Compare commits

..

114 Commits

Author SHA1 Message Date
stephan 5e2e34aef8 Re-add the (still) unsupported and (still 100%) untested sqlite3-node.mjs back to the dist bundle, as its removal in 3.51 has [caused some downstream disruption](https://github.com/sqlite/sqlite-wasm/issues/118). This is stashed in a branch for now and may never be merged - we're still negotiating the terms of its re-addition and my eventual capitulation.
FossilOrigin-Name: 8611cf643b11335cd490da1856c34b4f10ac8b82856e0857be1192e36da31f17
2025-11-13 08:36:52 +00:00
stephan f47095a5a0 Teach c-pp to export its argv as a #define list so that we can embed it in the generates files.
FossilOrigin-Name: 42f95ea71e5e7e927685de3a6da2ede38abe7cabdd1fc71b9a14bebe9f54a65e
2025-11-13 08:26:11 +00:00
stephan 791b767b26 Doc typo fix reported in [forum:00e49e9aa1|forum post 00e49e9aa1].
FossilOrigin-Name: 36cd33f634a45900f6e52ba07aa20242a5f2b29c7cbe19be968c52ffef34fcde
2025-11-13 07:07:28 +00:00
stephan ce53b80819 Minor doc correction and a JS error message tweak.
FossilOrigin-Name: c4ae21c89e5fd40eefd4916df6c6a6c4e27075a434a9d47576d3fcfbc7720588
2025-11-13 06:49:12 +00:00
stephan b867030b1a Clarify that 'pikchr' is not a typo.
FossilOrigin-Name: d7bb2ee6ec23c266c887fb2aeb77b0b17cd8f1429564d341537f57c5478410e2
2025-11-12 17:25:17 +00:00
drh 7efded5edc Improved concurrency for "make devtest" by splitting fuzzdata1.db and
fuzzdata2.db into slices for asan and ubsan testing.

FossilOrigin-Name: 2c31176607f02a73cf2626cda2dd0711ae74bdf0b4520d4c84ff299c860e419e
2025-11-10 20:01:39 +00:00
dan f07576429e Avoid dropping RETURNING triggers when the schema is reset while preparing a statement.
FossilOrigin-Name: 45d820ca227eb1ade4dda498b0f94b2c5df4bab3fc5fcdd517ee125a43d16f4d
2025-11-10 19:11:15 +00:00
dan 14fcb8252a Avoid dropping RETURNING triggers when the schema is reset while preparing a statement.
FossilOrigin-Name: e26bcef7522a6f6ee8d55fa30e7fe06419566cf4e8c2df0c33c92a4c89f58c05
2025-11-10 17:37:59 +00:00
drh a79f685533 Fix a missing va_end() call in the intckMprintf() function of the
incremental integrity-check extension.

FossilOrigin-Name: 62ad2350e368dc337ba2d0fb6847d07c40a6f79520dd6414d22b5b54983b0b12
2025-11-10 11:05:36 +00:00
dan 240397bb03 A more compact fix for the problem first fixed by [5f5a736f88].
FossilOrigin-Name: 7a644178c8d289ca18631844b2d73b32fddc72afcc80906633dd38c14eba2ca9
2025-11-10 11:00:41 +00:00
dan 4ac766cc05 Have sqlite3_set_errmsg() return SQLITE_MISUSE if a NULL db handle is passed to it, as documented.
FossilOrigin-Name: 5f5a736f88bc9bc6c9c83d2cbfd74c0b5357d7417d9993d34a78f0b7317ff796
2025-11-10 10:47:29 +00:00
stephan 73caea1764 Reworking of JS internals to support binding of nested C structs (like sqlite3_index_constraint and friends) and allow some of the automated JS/C conversions to be plugged in at the struct-binding level, simplifying how struct members, in particular function pointers, can be used from JS.
FossilOrigin-Name: bb4fd5b789cebf2b224c29023fea3e620a86fb36730c36c0d85d9f35880bf643
2025-11-10 07:41:54 +00:00
drh 998ebf1de7 Fix the ".www" command of the CLI so that it works on unix systems with
newer web browsers that do not allow access to files in /tmp.

FossilOrigin-Name: 2f918c14bac28c567cc854b3d41dcdd59191a118bb5fdea9373945fe860161f5
2025-11-10 01:46:06 +00:00
stephan 051e942f5d Minor doc typo fix reported in [forum:939d5864df|forum post 939d5864df].
FossilOrigin-Name: a1f9c977b83fab11c54710070dbedfaea47195050946db74075bdd3ade97a4c8
2025-11-09 07:11:15 +00:00
stephan 4182294987 CLI shell: ensure that .dump propagates its error code on error. Problem reported in [forum:a4f3873b0a8503cc|forum post a4f3873b0a].
FossilOrigin-Name: 850b92b6347187d702736bf5a574b9b4a49854a33799875f24fc75c50a6bf908
2025-11-09 06:51:32 +00:00
stephan c55d8262cf In sqlite3.wasm.allocFromTypedArray(), swap the order of the allocation and the access to the heap view object to work around an obscure issue when allocating huge blobs. The heap view object could previously become stale via the following allocation if the underlying WebAssembly.Memory object needed to grow. Essentially a realloc()-moves-the-pointer situation but it only comes up with huge allocations under the right circumstances and would trigger a JS exception (as opposed to corrupting the WASM heap). Problem reported in [forum:05b77273be104532|forum post 05b77273be104532].
FossilOrigin-Name: 0f712b6b0516dc151d3bcbb63497661c82e11eae368e639bbdf197e1b3467195
2025-11-09 06:32:10 +00:00
stephan 66b37e991b Add some UNUSED_PARAMATER()s for the sake of -pedantic -DSQLITE_OMIT_WAL.
FossilOrigin-Name: 620434a4a276ecaf2ee56d325815ac4e33c95e1190b420a341e376e54ef60278
2025-11-07 11:46:56 +00:00
drh 0aca0ccf2c Fix a harmless static-analyzer warning.
FossilOrigin-Name: 9819fc5aa7706fda9d4ec67835ae87eed64d321672873c9d864788b8cf5d27d8
2025-11-07 11:22:47 +00:00
drh 748c0adb62 Get the sqlite3Hwtime() function working on ARM. Enable scanstatus by
default on Windows CLI builds.

FossilOrigin-Name: 305bb022368bac9fafd7c2794762299324796903aaea270923d07f2127d8926c
2025-11-06 13:19:50 +00:00
drh e77530050e Improvements to documentation for stmt_scanstatus interfaces.
FossilOrigin-Name: 5f3e883d180d6fb7a1909df284713170f5431ea7afcc1a3eb5912c4620df42b2
2025-11-06 12:25:26 +00:00
stephan 366e0ed80c JNI: doc tweaks. Add missing SQLITE_DBSTATUS_TEMPBUF_SPILL export.
FossilOrigin-Name: 2c8938f43f721a2592b0efe36f75ab87aa370654e1a22d646c0a17d58d643295
2025-11-05 10:07:57 +00:00
stephan 201066302e TEA extension: add --tcl-stubs config flag, defaulting to zero, because there does not seem to be a universally-valid default for that. Addresses [forum:cd6503fce2|forum post cd6503fce2].
FossilOrigin-Name: 4954b94763052ed60ad2ae610e4f5c18fdba4475a39eb369408e984c89805e97
2025-11-05 05:59:53 +00:00
drh 29bdac3ee5 Remove stale code from the fileio.c extension.
FossilOrigin-Name: d26f115760f16cac1cd28c950d1c0eec199461d2c9a52baafb91ff6b8d5ec151
2025-11-04 23:47:49 +00:00
stephan 53ba0b80f2 Minor wasm build simplifications and extend the JS bindings of sqlite3_column/value_text() such that they include embeded NUL bytes in their result strings rather than truncate them at NUL. Consolidate the shell.c build flags from the canonical and autoconf makefiles into the configure script.
FossilOrigin-Name: cee2e2576f5e91911a019bff025ee6071850c0d75941e8746f10d57b56bd830a
2025-11-04 22:01:55 +00:00
drh c2aa8e3875 Version 3.51.0
FossilOrigin-Name: fb2c931ae597f8d00a37574ff67aeed3eced4e5547f9120744ae4bfa8e74527b
2025-11-04 19:38:17 +00:00
stephan b799156a31 Consolidate the three VFS-specific SEE tests into a shared routine.
FossilOrigin-Name: 8ac0bf125ddb6cc86a6825dcfe8895559835eca85ef14b5ad489f7c8159462e4
2025-11-04 01:03:58 +00:00
stephan 23e4ae2121 Move the hard-coded SHELL_OPT makefile values from the two main makefiles into their shared configure script.
FossilOrigin-Name: 900885c4fb3071e461bf868e9e68d0d8f3d3e83a1bcbf5c9c68179c701c1fb92
2025-11-04 00:15:51 +00:00
stephan abc23b5404 Merge trunk into wasm-post-3.51 to for some minor config script work.
FossilOrigin-Name: bf55a4220a74022e8be5f8a0cd7f4ca395a36e1666e14113e7e60c4a94cf0b3a
2025-11-04 00:10:10 +00:00
stephan e977440d79 Add tests demonstrating [d0e803b90344].
FossilOrigin-Name: 7d22ee947ddecb0dc6c640e79c9a09c0931f8b04f97d3ac89afdbf1736312bf7
2025-11-03 21:38:34 +00:00
stephan bb3b269ba9 Add new file missing from [936990cf067a5ebb] (and subsequently deleted by fossil clean -x). Have speedtest1 wasm use the user-provided sqlite3.c, rather than forcing the canonical one, so that the wasm exports don't have to be re-generated for that special case. Remove a harmless duplicate -D... flag.
FossilOrigin-Name: 7a592f5cd09699b45051855f6d477def40220b17642cbdb0f35ed74dd32becf1
2025-11-03 21:26:27 +00:00
drh 1bf7eb3d49 Use the same compile-time options for the CLI in the auto-setup tarball
as are used in the canonical source tree.
[forum:/forumpost/8975130218|Forum post 8975130218].

FossilOrigin-Name: ccabbe06d4e0650eecc91296d6a3040ed7fef06b47e4d63393a2367c8c8f55cf
2025-11-03 15:34:25 +00:00
dan f1c37a357e Add new column "cwd" to the jobs table in testrunner.db. For recording the directory in which the test ran or is running.
FossilOrigin-Name: 334305a469a51ef0d768ba8443d8cab217f45394cc9f720748a489b10703193d
2025-11-03 15:29:51 +00:00
drh d95fffc9af Adjust the dbstatus2.test module so that it works on 32-bit builds in
addition to 64-bit builds.

FossilOrigin-Name: dcaaa71e750d56afde3e905aaf10729ec95e0ede00522e1b12af6b6345e744ac
2025-11-03 12:36:52 +00:00
drh 4733884eae Update test result output from test/dbstatus2.test module so that it
reports the actual value of nTmpSpill when that value is out of range.

FossilOrigin-Name: 382c8440d7a16eae49fa1644513ae045bfceb072d9b4005963f57f1a57fe94b2
2025-11-03 11:35:13 +00:00
drh 0dfa31d279 Fix the test/speedtest.tcl script so that the CC= command-line option works.
FossilOrigin-Name: 0de0ba878b9ec572d76d47112a0124df9f234fbb7a69c5f5a76ce8c439b11f6f
2025-11-03 10:40:06 +00:00
drh 15c6d88381 Fix a harmless memory leak in the CLI caused by the --cmd option generating
an error message.

FossilOrigin-Name: ab916bad188b150321e420ec0009d909c287e3790b5d6ec683e2df9ed457ff15
2025-11-03 10:14:20 +00:00
drh eaacb4ac37 Add pedantic OOM detection logic to some disused diagnostic and test code.
No changes to any deliverables.

FossilOrigin-Name: abb6945fc62a1855786bda1f473edef0e937a791c453387a0859a6ce0451635a
2025-11-02 22:57:26 +00:00
drh 0c747e1653 Update the test/walthread.test testing script so that it uses a random
database name.

FossilOrigin-Name: ce25a758d4cea1741cb3db6384720f17faef61b352d494ab410a83a41f1721d3
2025-11-01 20:14:43 +00:00
stephan e5c8467a8e Fix ext/wasm/mkdist.sh to use ./version-info instead of ../../version-info (a recent build change made to ensure that builds with a custom sqlite3.c embed that version info).
FossilOrigin-Name: d25a92d88923f880d6477a99f2a35528faea83e7db245f2b07db80613b4aeb8e
2025-11-01 14:49:05 +00:00
drh b2b8ab6bc8 Updates to the compile-for-windows.md document. No changes to code.
FossilOrigin-Name: 652310a9f0ef2a870b5033029278b1fbef28c2ec15405d1b32bf1d51df28266c
2025-10-31 17:45:59 +00:00
dan 7f70085071 Detect some cases of ambiguous column references in USING clauses that can come up with nested joins.
FossilOrigin-Name: 38c993c8b7137d6d5623d387292639634297c17da11befec9029f12a16a472f8
2025-10-31 16:07:31 +00:00
drh a183595edd Change the name of a file-scope constant array in carray.c so that it does
not conflict with other variables names in other files when carray.c is
amalgamated.  This is down to resolve a harmless compiler warning.

FossilOrigin-Name: 5afd815ada94d55c9c56efe339235d23ffbf1fb64511a5e460927a2c8deaaaf0
2025-10-31 15:18:29 +00:00
drh 63ab7c625c Update the main README.md file to use the robot-safe /rchvdwnld page on the
server for downloads.

FossilOrigin-Name: c1aa52361b8ede611f64b96f2394174389ce531b1d86b9cfec91d3b03c94f6ea
2025-10-31 13:44:51 +00:00
drh 1c19c06246 Fix the output of ".dump" in the CLI so that the sqlite_sequence table
is created using correct syntax.

FossilOrigin-Name: 4b9f2e1d4485ad3baf9285aa09b468469be929b18cb308f19af471d7aac66076
2025-10-31 11:23:44 +00:00
drh da17de532f New assert() statements to help out static analyzers.
FossilOrigin-Name: ba0c4bf072ed721a507855d68bde7f1c388396a19b69814b6e257b934f8b0fd9
2025-10-30 22:10:41 +00:00
stephan 1ed6441bb1 Add SQLITE_OMIT_WAL checks around some functions to avoid defining unused statics in such builds. Fixes OMIT_WAL builds on msys2 and passes tool/omittest-msvc.tcl.
FossilOrigin-Name: f9b89535dc279acf617f274b6edbad0610fc8e5c76d402fc8b5b9dc656e95caa
2025-10-30 21:11:01 +00:00
stephan c129de05bb Simplify the EXPORTED_FUNCTIONS lists to use the preprocessor instead of per-list shell commands. (Unrelated) Remove part of the post-compilation JS filtering which breaks with emsdk 4.0.16+, which means the .js files are about 57kb bigger than they really ought to be.
FossilOrigin-Name: 936990cf067a5ebb34f7f662fc2d23d468c50f179afafe47fe0d2ed775f5ef74
2025-10-30 20:18:20 +00:00
stephan 6acd8d28fd Merge trunk into the wasm-post-3.51 branch.
FossilOrigin-Name: dda1735716cf1006b2a5d1d8eb29df3039047be38dcc04249c4ce50c77084fac
2025-10-30 19:32:46 +00:00
drh 139ec38ac8 Further improvements the ".dump" command to handle corner cases.
FossilOrigin-Name: cd0c77934ff32050380c2143bba7d4e6c07d5f08187cb5d5e8e7602854d1cda8
2025-10-30 18:52:48 +00:00
stephan 41fda52f3c Another (void), as per [dd6edfc09434].
FossilOrigin-Name: 7a822cfd388d7ac5765cffd5bd3d6e5b31abc6a360f9d5e27c0223f83a84237e
2025-10-30 18:48:19 +00:00
stephan 7fb2545905 Add (void) to two places for the sake of SQLITE_OMIT_WAL builds. Why these do not complain on tests in this tree, but do on a downstream tree (same machine, same compiler), is a mystery.
FossilOrigin-Name: dd6edfc09434b0d170d5ab462053497043016a4ec6b91a46db565ccf646aee20
2025-10-30 18:46:03 +00:00
stephan 3a61466a2f wasm: re-add SQLITE_OMIT_WAL to the c-pp-lite build flags.
FossilOrigin-Name: 617f8ac40e073c3fdc1144639b78617ad61113f4e873fc20c99399d2b60e1ceb
2025-10-30 18:39:28 +00:00
stephan 916fc1129c Macro tweaks to get SQLITE_OMIT_WAL building. Remove some nearby stray EOL whitespace.
FossilOrigin-Name: c31a944680f18a799c763238dbb0561f8b039905ce442533258905219b33b743
2025-10-30 18:38:14 +00:00
drh a8a99becb5 Fix a typo and improve wording in README.md
FossilOrigin-Name: 34a662ce24930a5e1a142f0b3ce427c4b1b61a306537820dc5e72996f8080d86
2025-10-30 18:33:58 +00:00
drh f3b396494f Updates to the tool/warnings.sh script for better compiler warnings.
FossilOrigin-Name: c9c64892c76cb9f2efb58428b349d43b075e7595b6a391d4818a7e9fb68b85fd
2025-10-30 18:32:32 +00:00
drh 4ebf49168a Fix a harmless compiler warning associated with flexarrays.
FossilOrigin-Name: f02cdf1d3ea8da8a09d115721845afeff5d6169dd7532ab486d3ed6db69cde2d
2025-10-30 17:23:17 +00:00
drh c6b86ba2ab Updates to the main README.md file.
FossilOrigin-Name: ab10c4cd9f9314bc62aa310ee796f63c82710c35659debe347e8ebcbf34d9e86
2025-10-30 15:43:57 +00:00
drh c5ff2aa7cf Fix the CLI ".dump" command so that it does not make duplicate
sqlite_sequence table entries as described in
[forum:/forumpost/b1674b56ad|forum thread b1674b56ad].

FossilOrigin-Name: c833f26a6780f919551e50c67d308e96293cec8481899354411d805617481f24
2025-10-30 11:39:49 +00:00
drh cb36dc3f3e Prevent a harmless signed integer overflow in the CLI if the argument
to the --skip option of the ".inport" command is -9223372036854775808.

FossilOrigin-Name: 247277d9373cb2614a1bc4c1e08b904315e5e8c0c2a7fbe9c2ac651481601642
2025-10-30 10:36:10 +00:00
stephan bc5e0be7f8 A experiment addressing the embedded-NUL behavior of sqlite3_colum/value_text() in the JS bindings, as discussed in [forum:d77281aec2df9ada|forum post d77281aec2]. This is an experiment only. It works, in that existing tests do not see the difference, but it has implicications which require careful consideration before deploying.
FossilOrigin-Name: d0e803b90344ee972e4b3fb30b77e283599dc4d5c6a3335ce9fea653a1b3f6f0
2025-10-30 02:21:38 +00:00
stephan 7c86a0321e Remove an OMIT_WAL from the wasm build because it breaks with the current amalgamation (and isn't strictly needed here anyway).
FossilOrigin-Name: a7be7d155aa6f02075f939ab6d26cfdfe2d0832b59da39c8bf4a74fc4845bd05
2025-10-30 01:43:30 +00:00
drh d443f0a95f Fix a logic error introduced by [cea8bf79e18d55a8] which caused
"0 OR 2" to be evaluated as "2" instead of as "1".  Problem reported at
[forum:/forumpost/d5f32040c5d50d2d|forum post d5f32040c].

FossilOrigin-Name: 095cc4f22e63c98cbb2acabdbcaf02e59e67ec6d3cc219b5f42a714e3d53a264
2025-10-29 20:47:01 +00:00
stephan 34b1bf16ec Tiny cosmetic tweak to configure script output. No functional changes.
FossilOrigin-Name: e2c20aa5929e5b79aabca8a51fb3e32e0533526d64d7576d3caf1c847fff58b4
2025-10-28 22:09:43 +00:00
stephan 74cd3c53f9 Typo fixes in LICENSE.md from BrickViking.
FossilOrigin-Name: 26ddec291696dd99c7f84a21b2dd272ce9bf32598ca38413ac89432d45527f8d
2025-10-28 19:57:15 +00:00
drh ffbfc27fab Fix an signed integer overflow problem that can occur when using an oversize
value for the SQLITE_MAX_LENGTH compile-time option together with
multi-gigabyte operands to the OP_Concat operator.

FossilOrigin-Name: 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060
2025-10-28 13:24:50 +00:00
drh 5a9ada593f Add enhanced resistance to corruption after posix advisory locks on the
database file been unintentionally broken on unix by running
close(open(DBFILE)) from a separate thread.

FossilOrigin-Name: 6385a1962c69c69ca4775888f034a4eb892aa013689c000f3de6422da7c3c695
2025-10-28 10:50:55 +00:00
drh 9c0770537f Enhance the CLI so that it can handle inputs larger than 2 billion lines.
FossilOrigin-Name: 5daebf2d6013e73d89c9feb796e15b67c39577e5a9e9c86fa260995f4118f04b
2025-10-28 10:44:26 +00:00
drh 6cc222c3be Additional comments explaining what unixIsSharingShmNode() does. No
changes to code.

FossilOrigin-Name: 819fc87385fd5be8a847492478f4c4f247f64edf7c7161b641bfbac6b658bec5
2025-10-28 01:28:20 +00:00
drh db0d47b749 Omit unnecessary branches from the unixIsSharingShmNode() implementation.
FossilOrigin-Name: 2d5623bc27073c407ec63e401f095d12f0025dd276a0bdc26d8b94b1f13c9a36
2025-10-27 23:57:57 +00:00
drh e34f35c833 The unixIsSharingShmNode() function should always return false for the
unix-excl VFS.

FossilOrigin-Name: 770f35dae47a98554b18f8a7aa9f6b6e39ae2b3aa8dce8d75b5bed0c6f0f9c21
2025-10-27 15:44:16 +00:00
drh 626351d444 Implement an experimental defensive measure to try to prevent the -wal and
-shm files of an active WAL-mode database connection from being deleted out
from under the database connection in the case where the database SHARED
lock has been released by an accidental call to close() in a different
thread, or similar.

FossilOrigin-Name: ed1b9206640f66cb8abff444809ccab8a4a5157b5c90e9aacddc422210e63423
2025-10-27 14:24:02 +00:00
dan 6e27846323 Fix a minor over-allocation of heap memory in wal.c.
FossilOrigin-Name: 1803cb9bb6a13fb66956f729066b6eae64c3a1c0715102fb1a9994e395c12ba9
2025-10-27 11:39:07 +00:00
dan 8ce786f173 Fix sanitizer complaints in the regexp extension.
FossilOrigin-Name: 6ff9ecb89d769bc2a27f8a57130f28ec7478979d3e35ba765c16017b5bdf775d
2025-10-27 11:20:47 +00:00
stephan 6b9230d2a1 Merge the OPFS/SEE tests into trunk (where they should have been committed).
FossilOrigin-Name: f8a4d7abf0d1c9c92fa102165d08aed76fd766d49615e3d347b5547580355574
2025-10-26 21:58:41 +00:00
stephan 241004f8fc Demonstrate the opfs-sahpool VFS with SEE.
FossilOrigin-Name: b4cffc00f3a18906867e8f070fbc49293ac5c038bad58e96ea74948591f31013
2025-10-26 21:45:02 +00:00
stephan 89a9efe840 Add a test which uses SEE via the "opfs" VFS. "opfs-sahpool" is pending.
FossilOrigin-Name: 1eb5a7ea394aa5b7e8594d73ce31f4b9bef55f2fa977dc26810c0bfba1cc39f7
2025-10-26 21:30:29 +00:00
stephan 4f177f1d3e Merge trunk into the wasm-post-3.51 branch.
FossilOrigin-Name: be5d2bae508a681628d4f84528e37db4e8a39b16e580b0d6ab4cd844566e973f
2025-10-26 18:43:04 +00:00
stephan d4ead9b9e4 A better/cleaner fix for [1c80ff88c0ce].
FossilOrigin-Name: 6138043bdde09224a764b5d5f18a9e2776c761c424f41b0d69427d92d47ec41c
2025-10-26 18:36:57 +00:00
stephan f57d368078 c-pp-lite: Fix another newline-related off-by-one which could cause newlines to get lost in @token@ filtering. Problem found in out-of-tree testing.
FossilOrigin-Name: 1c80ff88c0ce3d1c168c9bda734cf52114c35efdcf46a6da78f0ed9adc794eb8
2025-10-26 17:59:30 +00:00
stephan 3fceae3b95 Doc typo fix reported in the forum. No code changes.
FossilOrigin-Name: 6e065b6aa099f31493cfea22a729f92bb312147d8584f663fb75630a25772e43
2025-10-26 12:34:13 +00:00
drh 38113d392d Add the SQLITE_FCNTL_FILESTAT file control and the sqlite_filestat() SQL
function.

FossilOrigin-Name: 9870afcb2a360dff83e211009710bc85db238d9a6993afcc1eb38ca7699fb4a5
2025-10-25 22:22:58 +00:00
drh a105989856 Rename the file control to SQLITE_FCNTL_FILESTAT. Rename the SQL function
to sqlite_filestat().  Rename the enable macro to SQLITE_ENABLE_FILESTAT.

FossilOrigin-Name: ee797fec4eeace78caa2c5e463108bf1a6568db7c33d94d9fe6624cfc6b0d4fe
2025-10-25 20:46:09 +00:00
drh ecbeefecd0 Fix a bug in sqlite_file_info() output: It was showing the "pal" for
the main file descriptor when traversing other unused file descriptors
for the same inode.

FossilOrigin-Name: 3c4020d76e29c39483f6b92857ea470245afcd514870c63bd3373e0e213cd355
2025-10-25 19:51:16 +00:00
drh 2b24d8957e New --normal option for the ".open" command in the CLI. Also, when opening
the database for deduceDatabaseType(), use the same open-flags that will
be used subsequently for the official open, to avoid creating unusable
file descriptors that need to be held until all database instances close.

FossilOrigin-Name: 5e20a0435b1bd84d90c9a419219afe794fdf8ea73213f4c7ae5612c0375bed55
2025-10-25 19:36:12 +00:00
drh 726e836108 Add additional information about unix file descriptors to the same database file
in the sqlite_file_info() output.

FossilOrigin-Name: 64045f0a4d71ef068d64f2f25799cf1ae79c3cdb94039c73f1066290e3dbc943
2025-10-25 19:26:16 +00:00
drh 7be565f0cc Adjust unixPosixAdvisorLocks() to use redirectable system calls so that
it can be tested.

FossilOrigin-Name: eafe88b782875cd839fc27da509830e3e1d95781c686e27242a2844910203a42
2025-10-25 18:40:18 +00:00
drh c053b57716 Merge the CLI deduceDatabaseType fix from trunk.
FossilOrigin-Name: 82f907016ee75ca288d8ac0664d5c147fbfad42c5f8222211acc3220bd0eb609
2025-10-25 18:36:14 +00:00
drh 0d859b4828 Fix the CLI so that it does not try to open what might be an SQLite
database using open() in the deduceDatabaseType() routine, as this can
lead to broken posix advisory locks.

FossilOrigin-Name: 2a3a02715fa53673531575fa13aee056711139b409367cccc18654e82720c4e6
2025-10-25 18:35:29 +00:00
drh ab29c24dc3 Additional information about the unixShm shown.
FossilOrigin-Name: 85846c7fbeeaf5fccfcbe11a4b87c4ee49781456ccb4da1d090b7823d7b456d6
2025-10-25 14:06:36 +00:00
drh dcc07d3ca6 Do not attempt to show posix-advisory-locking status on journal files.
FossilOrigin-Name: 7f8baf64bb722d7dfdfca22d4f11a72113d5ed2b36d6cc6020fb0acf8185b3e7
2025-10-25 13:55:49 +00:00
drh 234c6c4bf0 The sqlite_file_info() function should always return JSON, unless there
is an OOM.

FossilOrigin-Name: 65aed79c29bf1aac0934475c02b358b916f413b20d2475ec7b631011f21f4e2b
2025-10-25 13:16:41 +00:00
drh 86319b841a New symbolic representation of posix advisory locking information
FossilOrigin-Name: b7d991ae04da1d6731b67fbdca65df996ec1c14a9530880fb7dbeeaef2575d14
2025-10-25 12:53:03 +00:00
drh f4e66056ac Merge trunk enhancements into the file-info branch.
FossilOrigin-Name: 73e1e081e9f7fc0ece98222669d13abde16197f0befc3343246a9e7da7856f02
2025-10-25 11:47:04 +00:00
drh 76db3a6e66 Stricter assert() statements on unixShmSystemLock().
FossilOrigin-Name: ed01ed337c04cce4cdbb6e80628b6f716d537e072b80067bd2bd6c5d18a1454f
2025-10-25 11:37:54 +00:00
drh 003737d1dc Improvements to the design of the /proc lock analysis.
FossilOrigin-Name: f2809dd3b266c0a6a6eb4ed62812a907493fb4006d26f8905df7ff2b1ca01a5e
2025-10-24 23:12:33 +00:00
stephan 02c5f3976f Random tiny tweaks in internal JS and flesh out the tester1 test selection list to include both 32-/64-bit entries for all tester1XYZ.html combinations. For after the 3.51 release.
FossilOrigin-Name: c087a1d23deac84ac46e769332ec167c5b38fc8e525fd90484d3fa0b6d304ffa
2025-10-24 21:01:23 +00:00
stephan be4d0c2e2f Make it particularly clear in the wasm build output that unsupported builds are exactly that. Cosmetic tweak only, no functional changes.
FossilOrigin-Name: 86f53a2eb37d8ec98bc9d4c6b00253cc00d798e79c7d409e65d608354a556e19
2025-10-24 20:29:12 +00:00
drh aeb886bc53 Easier to read /proc lock interpretation.
FossilOrigin-Name: d7bcc54beb6463501c0559333455bd2a378798b58cb48f35590e9026d07acd2f
2025-10-24 20:26:13 +00:00
drh 2f9311c5cb Flesh out the sqlite_file_info() function further, and in particular
show locks based in /proc/PID/fdinfo/FD, when that information is
available.

FossilOrigin-Name: ce75111cced8a03f05cf47ef809b9f017f2dac3c64c6008d595f28dbfec32057
2025-10-24 20:04:16 +00:00
drh 093b26e8e0 New diagnostic SQL function "sqlite_file_info()" and its associated
file-control SQLITE_FCNTL_GET_INFO.

FossilOrigin-Name: 56ab9692583d5b64e1ab727e08a01c0a65b4e318b455c94397663ef8d3d7b6b8
2025-10-24 17:42:03 +00:00
stephan 63ee854264 Fix a duplicate SQLITE_API on sqlite3_carray_bind(), as reported in [forum:7499e8a19edc8908|forum post 7499e8a19e].
FossilOrigin-Name: 62917cd4297e734477d3201481548ddb7f79ec977b9da7d9313bc7f1c0091187
2025-10-24 17:16:00 +00:00
stephan 3ba506d9cc ext/wasm: dependencies fix for parallel builds attempted immediately after a distclean. Add version-info to the distclean rules.
FossilOrigin-Name: b99233fe3d901714c4369ba25c510050fb7a8a85c1168780108595e9639a6d15
2025-10-24 16:39:58 +00:00
stephan 67fa337744 ext/wasm/GNUmakefile: (A) When using a custom sqlite3.c, use sqlite3.h from the same directory instead of the top of this tree. (B) Re-add preprocessor flags for SEE which were misplaced during recent build refactoring.
FossilOrigin-Name: 1b1e530a9149ce62d3d53f5c558e358d4e6d1b00e0cce8bb04cb6b13d1841538
2025-10-24 16:25:23 +00:00
drh 033dbac510 Fix [4e713558f6c6ea3d] so that it supports separate builds of rtree.
FossilOrigin-Name: d030e955d703772e1637ef2c07d29816fc869ead0a15a85ec8b4633e5ca08e0a
2025-10-24 16:01:55 +00:00
stephan 9af334f54a Document minor discrepancies in how sqlite3_bind_pointer() and sqlite3_carray_bind() react to the SQLITE_TRANSIENT and SQLITE_STATIC finalizers.
FossilOrigin-Name: b92478c389a9ff57302c021444ced09aef067ab55394dcda38cde97a3f2628d4
2025-10-24 15:18:13 +00:00
stephan 4bb53ab2e4 Make explicit that sqlite3_bind_pointer() and sqlite3_carray_bind() call the provided destructor even if those routines fail, per [forum:6d81b10952|forum feedback].
FossilOrigin-Name: 1fcb0b60798c708fec53d9d69a65cca2e37a9af7a5fa654c7b2bba97056cd461
2025-10-24 14:30:42 +00:00
drh 7adc9a5978 Update the MSVC makefile for the amalgamation distribution.
FossilOrigin-Name: 440ce1cff2b7519912fec87f440894592e901d730bf74cf99479e7b1d047bf02
2025-10-24 13:23:43 +00:00
drh acdda1075d Enhance the tokenizer so that it is able to deal with individual tokens
larger than 2GiB.

FossilOrigin-Name: 4e713558f6c6ea3dfbc97d2eb0a328955ef6ad6f2ad05517efe9ed4a60181440
2025-10-24 13:18:31 +00:00
drh bc2691d5c1 In the CLI, improved error messages on input errors. Limit the size of a
single SQL statement to a little more than 2GB.

FossilOrigin-Name: 0b50e7e10aae3d57f1cbd38d02be50cfbd2d5148ab4a9be712afd8678787b7bd
2025-10-24 12:32:32 +00:00
drh 95c188d557 Limit the size of --hexdb files in the CLI to 2 billion lines, to avoid
overflowing the line number counter.

FossilOrigin-Name: 2adfd0f47b028b8378e6cc08dc22abf1606036bbd285a7bc3a0de0eaf6feeb8f
2025-10-24 09:24:56 +00:00
drh 4043096408 Additional defenses against over-sized inputs in the (unused) amatch.c
demonstration code.

FossilOrigin-Name: b9f6ae0767ce5d9cbc6fca6d63c929f919473fa669e50a0a460627e5fde2628c
2025-10-23 14:05:58 +00:00
drh d06a0be514 Fix a faulty error message in the ext/misc/fileio.c extension.
FossilOrigin-Name: 1fdef271cd15d0960a7933253a10f288e26771cdcf34b5cd22adbc49d6341bc5
2025-10-23 13:10:34 +00:00
drh 984e446891 Adjust some of the markdown in the LICENSE.md file so that it will hopefully
work better on GitHub.

FossilOrigin-Name: 773f9d3dcf1ac7a9ce7f0911f46301f3e0e01d699f73a264cab692299a8d615e
2025-10-22 00:38:28 +00:00
stephan 774ce0ba43 Back out [b144f875d6bddce6] and remove the former check for strchrnul() from the configure script.
FossilOrigin-Name: f4e059b2243c6db37b4dd201b03f0c1916baec5e9e1a660815fcd7eeaf530367
2025-10-21 16:15:53 +00:00
90 changed files with 1967 additions and 2038 deletions
+10 -16
View File
@@ -30,14 +30,12 @@ The public domain source files usually contain a header comment
similar to the following to make it clear that the software is
public domain.
> ~~~
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.
~~~
> 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.
Almost every file you find in this source repository will be
public domain. But there are a small number of exceptions:
@@ -49,9 +47,7 @@ This repository contains a (relatively) small amount of non-public-domain
code used to help implement the configuration and build logic. In other
words, there are some non-public-domain files used to implement:
> ~~~
./configure && make
~~~
> ./configure && make
In all cases, the non-public-domain files included with this
repository have generous BSD-style licenses. So anyone is free to
@@ -69,7 +65,7 @@ third-party build scripts in order to compile SQLite.
Non-public-domain code included in this respository includes:
* The ["autosetup"](http://msteveb.github.io/autosetup/) configuration
system that is contained (mostly) the autosetup/ directory, but also
system that is contained (mostly) in the autosetup/ directory, but also
includes the "./configure" script at the top-level of this archive.
Autosetup has a separate BSD-style license. See the
[autosetup/LICENSE](http://msteveb.github.io/autosetup/license/)
@@ -79,13 +75,11 @@ Non-public-domain code included in this respository includes:
software found in the legacy autoconf/ directory and its
subdirectories.
The following unix shell command is can be run from the top-level
The following unix shell command can be run from the top-level
of this source repository in order to remove all non-public-domain
code:
> ~~~
rm -rf configure autosetup autoconf
~~~
> rm -rf configure autosetup autoconf
If you unpack this source repository and then run the command above, what
is left will be 100% public domain.
+1
View File
@@ -1770,6 +1770,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_PERCENTILE=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_STRICT_SUBTYPE=1
!ENDIF
+18 -24
View File
@@ -2,8 +2,8 @@
This repository contains the complete source code for the
[SQLite database engine](https://sqlite.org/), including
many test scripts. However, other test scripts
and most of the documentation are managed separately.
many tests. Additional tests and most documentation
are managed separately.
See the [on-line documentation](https://sqlite.org/) for more information
about what SQLite is and how it works from a user's perspective. This
@@ -53,39 +53,32 @@ then no longer be fully in the public domain.
## Obtaining The SQLite Source Code
If you do not want to use Fossil, you can download tarballs or ZIP
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
Source code tarballs or ZIP archives are available at:
* Latest trunk check-in as
[Tarball](https://sqlite.org/src/tarball/sqlite.tar.gz),
[ZIP-archive](https://sqlite.org/src/zip/sqlite.zip), or
[SQLite-archive](https://sqlite.org/src/sqlar/sqlite.sqlar).
* [Latest trunk check-in](https://sqlite.org/src/rchvdwnld/trunk).
* Latest release as
[Tarball](https://sqlite.org/src/tarball/sqlite.tar.gz?r=release),
[ZIP-archive](https://sqlite.org/src/zip/sqlite.zip?r=release), or
[SQLite-archive](https://sqlite.org/src/sqlar/sqlite.sqlar?r=release).
* [Latest release](https://sqlite.org/src/rchvdwnld/release)
* For other check-ins, substitute an appropriate branch name or
tag or hash prefix in place of "release" in the URLs of the previous
bullet. Or browse the [timeline](https://sqlite.org/src/timeline)
to locate the check-in desired, click on its information page link,
then click on the "Tarball" or "ZIP Archive" links on the information
page.
* For other check-ins, browse the
[project timeline](https://sqlite.org/src/timeline?y=ci) and
click on the check-in hash of the check-in you want to download.
On the resulting "info" page, click one of the options to the
right of the "**Downloads:**" label in the "**Overview**" section
near the top.
To access sources directly using [Fossil](https://fossil-scm.org/home),
first install Fossil version 2.0 or later.
Source tarballs and precompiled binaries available at
Source tarballs and precompiled binaries for Fossil are available at
<https://fossil-scm.org/home/uv/download.html>. Fossil is
a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH.
executable file and put that file someplace on your $PATH or %PATH%.
Then run commands like this:
mkdir -p ~/sqlite
cd ~/sqlite
fossil open https://sqlite.org/src
The "fossil open" command will take two or three minutes. Afterwards,
The initial "fossil open" command will take two or three minutes. Afterwards,
you can do fast, bandwidth-efficient updates to the whatever versions
of SQLite you like. Some examples:
@@ -152,7 +145,8 @@ show what changes are needed.
## Compiling for Windows Using MSVC
On Windows, everything can be compiled with MSVC.
You will also need a working installation of TCL.
You will also need a working installation of TCL if you want to run tests.
TCL is not required if you just want to build SQLite itself.
See the [compile-for-windows.md](doc/compile-for-windows.md) document for
additional information about how to install MSVC and TCL and configure your
build environment.
@@ -164,8 +158,8 @@ TCL library, using a command like this:
SQLite uses "tclsh.exe" as part of the build process, and so that
program will need to be somewhere on your %PATH%. SQLite itself
does not contain any TCL code, but it does use TCL to help with the
build process and to run tests. You may need to install TCL development
does not contain any TCL code, but it does use TCL to run tests.
You may need to install TCL development
libraries in order to successfully complete some makefile targets.
It is helpful, but is not required, to install the SQLite TCL extension
(the "tclextension-install" target) prior to running tests.
+2
View File
@@ -327,6 +327,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_CARRAY=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -349,6 +350,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
# Always enable math functions on Windows
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PERCENTILE
# Should the rbu extension be enabled? If so, add compilation options
# to enable it.
+3 -2
View File
@@ -119,7 +119,7 @@ TCLLIBDIR = @TCLLIBDIR@
# typically come from the ./configure command-line invocation).
#
CFLAGS.configure = @SH_CFLAGS@ @TEAISH_CFLAGS@ @CFLAGS@ @CPPFLAGS@ $(TCL_INCLUDE_SPEC)
#CFLAGS.configure += -DUSE_TCL_STUBS=1
CFLAGS.configure += -DUSE_TCL_STUBS=@TEAISH_USE_STUBS@
#
# LDFLAGS.configure = LDFLAGS as known at configure-time.
@@ -153,6 +153,7 @@ tx.src = @TEAISH_EXT_SRC@
# gets set up via the configure script.
#
tx.CFLAGS =
tx.CPPFLAGS =
#
# tx.LDFLAGS is typically set by teaish.make, whereas TEAISH_LDFLAGS
@@ -218,7 +219,7 @@ config.log: @TEAISH_TEST_TCL_IN@
# CC variant for compiling Tcl-using sources.
#
CC.tcl = \
$(CC) -o $@ $(CFLAGS.configure) $(CFLAGS) $(tx.CFLAGS)
$(CC) -o $@ $(CFLAGS.configure) $(CFLAGS) $(tx.CFLAGS) $(tx.CPPFLAGS)
#
# CC variant for linking $(tx.src) into an extension DLL. Note that
+1 -1
View File
@@ -557,7 +557,7 @@ proc proj-opt-define-bool {args} {
if {$invert} {
set rc [expr {!$rc}]
}
msg-result $rc
msg-result [string map {0 no 1 yes} $rc]
define $defName $rc
return $rc
}
+19 -17
View File
@@ -557,7 +557,25 @@ proc proc-debug {msg} {
}
define OPT_FEATURE_FLAGS {} ; # -DSQLITE_OMIT/ENABLE flags.
define OPT_SHELL {} ; # Feature-related CFLAGS for the sqlite3 CLI app
#
# OPT_SHELL = feature-related CFLAGS for the sqlite3 CLI app. The
# list's initial values are defaults which are always applied and not
# affected by --feature-flags. The list is appended to by various
# --feature-flags.
define OPT_SHELL {
-DSQLITE_DQS=0
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_RTREE
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
-DSQLITE_ENABLE_STMTVTAB
-DSQLITE_ENABLE_DBPAGE_VTAB
-DSQLITE_ENABLE_DBSTAT_VTAB
-DSQLITE_ENABLE_BYTECODE_VTAB
-DSQLITE_ENABLE_OFFSET_SQL_FUNC
-DSQLITE_ENABLE_PERCENTILE
-DSQLITE_STRICT_SUBTYPE=1
}
########################################################################
# Adds $args, if not empty, to OPT_FEATURE_FLAGS. If the first arg is
# -shell then it strips that arg and passes the remaining args the
@@ -616,21 +634,6 @@ proc sqlite-check-common-bins {} {
}
}
# A workaround for the strchrnul() check on some Mac platforms:
# https://sqlite.org/forum/forumpost/95edc7a8d7d1de59
proc sqlite-check-strchrnul {} {
msg-checking "Checking for strchrnul()... "
if {[cctest -link 1 \
-includes {string.h} \
-code {(void)strchrnul("foo",'f');}]} {
define HAVE_STRCHRNUL 1
msg-result yes
} else {
define HAVE_STRCHRNUL 0
msg-result no
}
}
########################################################################
# Run checks for system-level includes and libs which are common to
# both the canonical build and the "autoconf" bundle.
@@ -647,7 +650,6 @@ proc sqlite-check-common-system-deps {} {
# Check for needed/wanted functions
cc-check-functions gmtime_r isnan localtime_r localtime_s \
usleep utime pread pread64 pwrite pwrite64
sqlite-check-strchrnul
apply {{} {
set ldrt ""
+5 -1
View File
@@ -220,7 +220,9 @@ proc teaish-configure-core {} {
=> {Full pathname of tclsh to use. It is used for trying to find
tclConfig.sh. Warning: if its containing dir has multiple tclsh
versions, it may select the wrong tclConfig.sh!
Defaults to the $TCLSH environment variable.}
Defaults to the $TCLSH environment variable.}
tcl-stubs=0 => {Enable use of Tcl stubs library.}
# TEA has --with-tclinclude but it appears to only be useful for
# building an extension against an uninstalled copy of TCL's own
@@ -498,6 +500,8 @@ proc teaish__configure_phase1 {} {
}
teaish-checks-run -post
define TEAISH_USE_STUBS [opt-bool tcl-stubs]
apply {{} {
# Set up "vsatisfies" code for pkgIndex.tcl.in,
# _teaish.tester.tcl.in, and for a configure-time check. We would
+8 -17
View File
@@ -1,7 +1,7 @@
# Notes On Compiling SQLite On Windows 11
Below are step-by-step instructions on how to build SQLite from
canonical source on a new Windows 11 PC, as of 2024-10-09.
canonical source on a new Windows 11 PC, as of 2025-10-31.
See [](./compile-for-unix.md) for a similar guide for unix-like
systems, including MacOS.
@@ -24,7 +24,8 @@ systems, including MacOS.
application to your task bar, as you will use it a lot. Bring up
an instance of this command prompt and do all of the subsequent steps
in that "x64 Native Tools" command prompt. (Or use "x86" if you want
a 32-bit build.) The subsequent steps will not work in a vanilla
a 32-bit build. Or use "ARM64" if you want to do a build for Windows
on ARM.) The subsequent steps will not work in a vanilla
DOS prompt. Nor will they work in PowerShell.
3. *(Optional):* Install TCL development libraries.
@@ -133,9 +134,7 @@ following minor changes:
The command the developers use for building the deliverable DLL on the
[download page](https://sqlite.org/download.html) is as follows:
> ~~~~
nmake /f Makefile.msc sqlite3.dll USE_NATIVE_LIBPATHS=1 "OPTS=-DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SERIALIZE=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1"
~~~~
> nmake /f Makefile.msc sqlite3.dll USE_NATIVE_LIBPATHS=1 "OPTS=-DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SERIALIZE=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1"
That command generates both the sqlite3.dll and sqlite3.def files. The same
command works for both 32-bit and 64-bit builds.
@@ -147,9 +146,7 @@ with TCL in order to function. The [sqlite3_analyzer.exe program](https://sqlit
is an example. You can build as described above, and then
enter:
> ~~~~
nmake /f Makefile.msc sqlite3_analyzer.exe
~~~~
> nmake /f Makefile.msc sqlite3_analyzer.exe
And you will end up with a working executable. However, that executable
will depend on having the "tcl98.dll" library somewhere on your %PATH%.
@@ -175,17 +172,11 @@ statically linked so that it does not depend on separate DLL:
5. CD into your SQLite source code directory and build the desired
utility program, but add the following extra argument to the
nmake command line:
<blockquote><pre>
STATICALLY_LINK_TCL=1
</pre></blockquote>
<blockquote><pre>STATICALLY_LINK_TCL=1</pre></blockquote>
<p>So, for example, to build a statically linked version of
sqlite3_analyzer.exe, you might type:
<blockquote><pre>
nmake /f Makefile.msc STATICALLY_LINK_TCL=1 sqlite3_analyzer.exe
</pre></blockquote>
<blockquote><pre>nmake /f Makefile.msc STATICALLY_LINK_TCL=1 sqlite3_analyzer.exe</pre></blockquote>
6. After your executable is built, you can verify that it does not
depend on the TCL DLL by running:
<blockquote><pre>
dumpbin /dependents sqlite3_analyzer.exe
</pre></blockquote>
<blockquote><pre>dumpbin /dependents sqlite3_analyzer.exe</pre></blockquote>
+1
View File
@@ -160,6 +160,7 @@ static char *intckMprintf(sqlite3_intck *p, const char *zFmt, ...){
sqlite3_free(zRet);
zRet = 0;
}
va_end(ap);
return zRet;
}
+19 -16
View File
@@ -13,11 +13,14 @@ Technical support is available in the forum:
<https://sqlite.org/forum>
> **FOREWARNING:** this subproject is very much in development and
subject to any number of changes. Please do not rely on any
information about its API until this disclaimer is removed. The JNI
bindings released with version 3.43 are a "tech preview." Once
finalized, strong backward compatibility guarantees will apply.
> **FOREWARNING:** the JNI subproject is experimental and subject to
any number of changes. This API is "feature-complete", with only a
few difficult-to-reach corners of the C API not represented here,
but it is not a supported deliverable of the project so does not
have same backward compatibility guarantees which the C APIs
do. That said: the [C-style API](#1to1ish) is especially resistent
to compatibility breakage because it's designed to be as close to
the C API as feasible.
Project goals/requirements:
@@ -162,11 +165,13 @@ or propagate exceptions and must return error information (if any) via
result codes or `null`. The only cases where the C-style APIs may
throw is through client-side misuse, e.g. passing in a null where it
may cause a `NullPointerException`. The APIs clearly mark function
parameters which should not be null, but does not generally actively
defend itself against such misuse. Some C-style APIs explicitly accept
`null` as a no-op for usability's sake, and some of the JNI APIs
deliberately return an error code, instead of segfaulting, when passed
a `null`.
parameters which should not be null, and it internally uses the
`SQLITE_API_ARMOR` mechanism to help product against such misuse. Some
C-style APIs explicitly accept `null` as a no-op for usability's sake,
and some of the JNI APIs deliberately return an error code, instead of
segfaulting, when passed a `null`. There are no known cases where it
will misuse memory if passed a `null` or out-of-range value from
client code.
Client-defined callbacks _must never throw exceptions_ unless _very
explicitly documented_ as being throw-safe. Exceptions are generally
@@ -194,7 +199,8 @@ Some constructs, when modelled 1-to-1 from C to Java, are unduly
clumsy to work with in Java because they try to shoehorn C's way of
doing certain things into Java's wildly different ways. The following
subsections cover those, starting with a verbose explanation and
demonstration of where such changes are "really necessary"...
demonstration of where such changes are "really necessary" for
usability's sake...
### Custom Collations
@@ -286,12 +292,9 @@ binding. The Java API has only one core function-registration function:
```java
int sqlite3_create_function(sqlite3 db, String funcName, int nArgs,
int encoding, SQLFunction func);
int flags, SQLFunction func);
```
> Design question: does the encoding argument serve any purpose in
Java? That's as-yet undetermined. If not, it will be removed.
`SQLFunction` is not used directly, but is instead instantiated via
one of its three subclasses:
@@ -313,4 +316,4 @@ in-flux nature of this API.
Various APIs which accept callbacks, e.g. `sqlite3_trace_v2()` and
`sqlite3_update_hook()`, use interfaces similar to those shown above.
Despite the changes in signature, the JNI layer makes every effort to
provide the same semantics as the C API documentation suggests.
provide the same semantics as the C API documentation describes.
+3 -1
View File
@@ -245,8 +245,10 @@ extern "C" {
#define org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_CACHE_USED_SHARED 11L
#undef org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_CACHE_SPILL
#define org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_CACHE_SPILL 12L
#undef org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_TEMPBUF_SPILL
#define org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_TEMPBUF_SPILL 13L
#undef org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_MAX
#define org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_MAX 12L
#define org_sqlite_jni_capi_CApi_SQLITE_DBSTATUS_MAX 13L
#undef org_sqlite_jni_capi_CApi_SQLITE_UTF8
#define org_sqlite_jni_capi_CApi_SQLITE_UTF8 1L
#undef org_sqlite_jni_capi_CApi_SQLITE_UTF16LE
+5 -3
View File
@@ -115,8 +115,9 @@ public final class CApi {
JNIEnv is not cached, else returns true, but this information is
primarily for testing of the JNI bindings and is not information
which client-level code can use to make any informed
decisions. Its return type and semantics are not considered
stable and may change at any time.
decisions. The semantics of its return type and value are not
considered stable and may change at any time. i.e. act as if it
returns null.
*/
public static native boolean sqlite3_java_uncache_thread();
@@ -2585,7 +2586,8 @@ public final class CApi {
public static final int SQLITE_DBSTATUS_DEFERRED_FKS = 10;
public static final int SQLITE_DBSTATUS_CACHE_USED_SHARED = 11;
public static final int SQLITE_DBSTATUS_CACHE_SPILL = 12;
public static final int SQLITE_DBSTATUS_MAX = 12;
public static final int SQLITE_DBSTATUS_TEMPBUF_SPILL = 13;
public static final int SQLITE_DBSTATUS_MAX = 13;
// encodings
public static final int SQLITE_UTF8 = 1;
@@ -171,6 +171,7 @@ public final class Sqlite implements AutoCloseable {
public static final int DBSTATUS_DEFERRED_FKS = CApi.SQLITE_DBSTATUS_DEFERRED_FKS;
public static final int DBSTATUS_CACHE_USED_SHARED = CApi.SQLITE_DBSTATUS_CACHE_USED_SHARED;
public static final int DBSTATUS_CACHE_SPILL = CApi.SQLITE_DBSTATUS_CACHE_SPILL;
public static final int DBSTATUS_TEMPBUF_SPILL = CApi.SQLITE_DBSTATUS_TEMPBUF_SPILL;
// Limits
public static final int LIMIT_LENGTH = CApi.SQLITE_LIMIT_LENGTH;
+5 -5
View File
@@ -514,7 +514,7 @@ struct amatch_cursor {
sqlite3_int64 iRowid; /* The rowid of the current word */
amatch_langid iLang; /* Use this language ID */
amatch_cost rLimit; /* Maximum cost of any term */
int nBuf; /* Space allocated for zBuf */
sqlite3_int64 nBuf; /* Space allocated for zBuf */
int oomErr; /* True following an OOM error */
int nWord; /* Number of amatch_word objects */
char *zBuf; /* Temp-use buffer space */
@@ -1039,7 +1039,7 @@ static void amatchAddWord(
nTail = (int)strlen(zWordTail);
if( nBase+nTail+3>pCur->nBuf ){
pCur->nBuf = nBase+nTail+100;
pCur->zBuf = sqlite3_realloc(pCur->zBuf, pCur->nBuf);
pCur->zBuf = sqlite3_realloc64(pCur->zBuf, pCur->nBuf);
if( pCur->zBuf==0 ){
pCur->nBuf = 0;
return;
@@ -1105,13 +1105,13 @@ static int amatchNext(sqlite3_vtab_cursor *cur){
amatch_avl *pNode;
int isMatch = 0;
amatch_vtab *p = pCur->pVtab;
int nWord;
sqlite3_int64 nWord;
int rc;
int i;
const char *zW;
amatch_rule *pRule;
char *zBuf = 0;
char nBuf = 0;
sqlite3_int64 nBuf = 0;
char zNext[8];
char zNextIn[8];
int nNextIn;
@@ -1158,7 +1158,7 @@ static int amatchNext(sqlite3_vtab_cursor *cur){
nWord = (int)strlen(pWord->zWord+2);
if( nWord+20>nBuf ){
nBuf = (char)(nWord+100);
zBuf = sqlite3_realloc(zBuf, nBuf);
zBuf = sqlite3_realloc64(zBuf, nBuf);
if( zBuf==0 ) return SQLITE_NOMEM;
}
amatchStrcpy(zBuf, pWord->zWord+2);
+1 -9
View File
@@ -760,7 +760,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
pCur->zPath = 0;
pLvl->pDir = opendir(pLvl->zDir);
if( pLvl->pDir==0 ){
fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
fsdirSetErrmsg(pCur, "cannot read directory: %s", pLvl->zDir);
return SQLITE_ERROR;
}
}
@@ -1122,11 +1122,3 @@ int sqlite3_fileio_init(
}
return rc;
}
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
/* To allow a standalone DLL, make test_windirent.c use the same
* redefined SQLite API calls as the above extension code does.
* Just pull in this .c to accomplish this. As a beneficial side
* effect, this extension becomes a single translation unit. */
# include "test_windirent.c"
#endif
+4 -3
View File
@@ -297,8 +297,9 @@ static const unsigned char sqlite3CtypeMap[256] = {
** Return the length (in bytes) of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
static int sqlite3GetToken(const unsigned char *z, int *tokenType){
int i, c;
static sqlite3_int64 sqlite3GetToken(const unsigned char *z, int *tokenType){
sqlite3_int64 i;
int c;
switch( aiClass[*z] ){ /* Switch on the character-class of the first byte
** of the token. See the comment on the CC_ defines
** above. */
@@ -559,7 +560,7 @@ char *sqlite3_normalize(const char *zSql){
int i; /* Next character to read from zSql[] */
int j; /* Next slot to fill in on z[] */
int tokenType; /* Type of the next token */
int n; /* Size of the next token */
sqlite3_int64 n; /* Size of the next token */
int k; /* Loop counter */
nSql = strlen(zSql);
+10 -1
View File
@@ -650,6 +650,15 @@ static void re_free(ReCompiled *pRe){
}
}
/*
** Version of re_free() that accepts a pointer of type (void*). Required
** to satisfy sanitizers when the re_free() function is called via a
** function pointer.
*/
static void re_free_voidptr(void *p){
re_free((ReCompiled*)p);
}
/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
@@ -781,7 +790,7 @@ static void re_sql_func(
sqlite3_result_int(context, re_match(pRe, zStr, -1));
}
if( setAux ){
sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
sqlite3_set_auxdata(context, 0, pRe, re_free_voidptr);
}
}
-325
View File
@@ -1,325 +0,0 @@
/*
** 2025-10-20
**
** 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.
**
*************************************************************************
** A simple command-line program for testing the Result-Format or "resfmt"
** utility library for SQLite.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "sqlite3.h"
#include "resfmt.h"
#define COUNT(X) (sizeof(X)/sizeof(X[0]))
/* Report out-of-memory and die if the argument is NULL */
static void checkOOM(void *p){
if( p==0 ){
fprintf(stdout, "out-of-memory\n");
exit(1);
}
}
/* A block of memory */
typedef struct memblock memblock;
struct memblock {
memblock *pNext;
};
/* List of all memory to be freed */
static memblock *pToFree = 0;
/* Free all memory at exit */
static void tempFreeAll(void){
while( pToFree ){
memblock *pNext = pToFree->pNext;
sqlite3_free(pToFree);
pToFree = pNext;
}
}
/* Allocate memory that will be freed all at once by freeall() */
static void *tempMalloc(size_t n){
memblock *p;
if( n>0x10000000 ) checkOOM(0);
p = sqlite3_malloc64( n+sizeof(memblock) );
checkOOM(p);
p->pNext = pToFree;
pToFree = p;
return (void*)&pToFree[1];
}
/* Make a copy of a string using tempMalloc() */
static char *tempStrdup(char *zIn){
size_t n;
char *z;
if( zIn==0 ) zIn = "";
n = strlen(zIn);
if( n>0x10000000 ) checkOOM(0);
z = tempMalloc( n+1 );
checkOOM(z);
memcpy(z, zIn, n+1);
return z;
}
/* Function used for writing to the console */
static ssize_t testWriter(void *pContext, const unsigned char *p, size_t n){
return fwrite(p,1,n,stdout);
}
/* Render BLOB values as "(%d-byte-blob)". */
static char *testBlobRender(void *pNotUsed, sqlite3_value *pVal){
if( sqlite3_value_type(pVal)!=SQLITE_BLOB ) return 0;
return sqlite3_mprintf("(%d-byte-blob)",sqlite3_value_bytes(pVal));
}
int main(int argc, char **argv){
char *zSrc;
FILE *pSrc;
sqlite3_str *pBuf;
sqlite3 *db = 0;
sqlite3_stmt *pStmt;
int rc;
int lineNum = 0;
int bUseWriter = 1;
sqlite3_resfmt_spec spec;
char zLine[1000];
if( argc<2 ){
zSrc = "<stdin>";
pSrc = stdin;
}else{
zSrc = argv[1];
pSrc = fopen(zSrc, "rb");
if( pSrc==0 ){
fprintf(stderr, "cannot open \"%s\" for reading\n", zSrc);
exit(1);
}
}
memset(&spec, 0, sizeof(spec));
spec.iVersion = 1;
spec.eFormat = RESFMT_List;
spec.xWrite = testWriter;
pBuf = sqlite3_str_new(0);
rc = sqlite3_open(":memory:", &db);
if( rc ){
fprintf(stderr, "unable to open an in-memory database: %s\n",
sqlite3_errmsg(db));
exit(1);
}
while( fgets(zLine, sizeof(zLine), pSrc) ){
size_t n = strlen(zLine);
lineNum++;
while( n>0 && zLine[n-1]>0 && zLine[n-1]<=' ' ) n--;
zLine[n] = 0;
printf("%s\n", zLine);
if( strncmp(zLine, "--open=", 7)==0 ){
if( db ) sqlite3_close(db);
db = 0;
rc = sqlite3_open(&zLine[7], &db);
if( rc!=SQLITE_OK ){
fprintf(stderr, "%s:%d: cannot open \"%s\": %s\n",
zSrc, lineNum, &zLine[7],
sqlite3_errmsg(db));
exit(1);
}
}else
if( strcmp(zLine, "--go")==0 ){
const char *zSql, *zTail;
char *zErr = 0;
int n;
if( db==0 ){
fprintf(stderr, "%s:%d: database not open\n", zSrc, lineNum);
exit(1);
}
zSql = sqlite3_str_value(pBuf);
pStmt = 0;
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zTail);
if( rc || pStmt==0 ){
fprintf(stderr, "%s:%d: sqlite3_prepare() fails: %s\n",
zSrc, lineNum, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
break;
}
zSql = sqlite3_sql(pStmt);
while( isspace(zSql[0]) ) zSql++;
n = (int)strlen(zSql);
while( n>0 && isspace(zSql[n-1]) ) n--;
if( n>0 ){
char *zOut = 0;
printf("/* %.*s */\n", n, zSql);
if( bUseWriter ){
spec.pzOutput = 0;
spec.xWrite = testWriter;
}else{
spec.pzOutput = &zOut;
spec.xWrite = 0;
}
rc = sqlite3_format_query_result(pStmt, &spec, &zErr);
if( rc!=SQLITE_OK ){
fprintf(stderr, "%s:%d: Error %d: %s\n", zSrc, lineNum,
rc, zErr);
}else{
if( !bUseWriter && zOut ){
fputs(zOut, stdout);
sqlite3_free(zOut);
}
}
sqlite3_free(zErr);
}
sqlite3_finalize(pStmt);
pStmt = 0;
zSql = zTail;
}
sqlite3_str_reset(pBuf);
}else
if( strncmp(zLine, "--eFormat=", 10)==0 ){
const struct { const char *z; int e; } aFmt[] = {
{ "box", RESFMT_Box, },
{ "column", RESFMT_Column, },
{ "count", RESFMT_Count, },
{ "eqp", RESFMT_EQP, },
{ "explain", RESFMT_Explain, },
{ "html", RESFMT_Html, },
{ "insert", RESFMT_Insert, },
{ "json", RESFMT_Json, },
{ "line", RESFMT_Line, },
{ "list", RESFMT_List, },
{ "markdown", RESFMT_Markdown, },
{ "off", RESFMT_Off, },
{ "table", RESFMT_Table, },
{ "scanexp", RESFMT_ScanExp, },
};
int i;
for(i=0; i<COUNT(aFmt); i++){
if( strcmp(aFmt[i].z,&zLine[10])==0 ){
spec.eFormat = aFmt[i].e;
break;
}
}
if( i>=COUNT(aFmt) ){
sqlite3_str *pMsg = sqlite3_str_new(0);
for(i=0; i<COUNT(aFmt); i++){
sqlite3_str_appendf(pMsg, " %s", aFmt[i].z);
}
fprintf(stderr, "%s:%d: no such format: \"%s\"\nChoices: %s\n",
zSrc, lineNum, &zLine[10], sqlite3_str_value(pMsg));
sqlite3_free(sqlite3_str_finish(pMsg));
}
}else
if( strncmp(zLine, "--eQuote=", 9)==0 ){
const struct { const char *z; int e; } aQuote[] = {
{ "csv", RESFMT_Q_Csv },
{ "html", RESFMT_Q_Html },
{ "json", RESFMT_Q_Json },
{ "off", RESFMT_Q_Off },
{ "sql", RESFMT_Q_Sql },
{ "tcl", RESFMT_Q_Tcl },
};
int i;
for(i=0; i<COUNT(aQuote); i++){
if( strcmp(aQuote[i].z,&zLine[9])==0 ){
spec.eQuote = aQuote[i].e;
break;
}
}
if( i>=COUNT(aQuote) ){
sqlite3_str *pMsg = sqlite3_str_new(0);
for(i=0; i<COUNT(aQuote); i++){
sqlite3_str_appendf(pMsg, " %s", aQuote[i].z);
}
fprintf(stderr, "%s:%d: no such quoting style: \"%s\"\nChoices: %s\n",
zSrc, lineNum, &zLine[9], sqlite3_str_value(pMsg));
sqlite3_free(sqlite3_str_finish(pMsg));
}
}else
if( strncmp(zLine, "--eBlob=", 8)==0 ){
const struct { const char *z; int e; } aBlob[] = {
{ "auto", RESFMT_B_Auto },
{ "hex", RESFMT_B_Hex },
{ "json", RESFMT_B_Json },
{ "tcl", RESFMT_B_Tcl },
{ "text", RESFMT_B_Text },
{ "sql", RESFMT_B_Sql },
};
int i;
for(i=0; i<COUNT(aBlob); i++){
if( strcmp(aBlob[i].z,&zLine[8])==0 ){
spec.eBlob = aBlob[i].e;
break;
}
}
if( i>=COUNT(aBlob) ){
sqlite3_str *pMsg = sqlite3_str_new(0);
for(i=0; i<COUNT(aBlob); i++){
sqlite3_str_appendf(pMsg, " %s", aBlob[i].z);
}
fprintf(stderr, "%s:%d: no such blob style: \"%s\"\nChoices: %s\n",
zSrc, lineNum, &zLine[8], sqlite3_str_value(pMsg));
sqlite3_free(sqlite3_str_finish(pMsg));
}
}else
if( strncmp(zLine, "--eEscape=", 10)==0 ){
const struct { const char *z; int e; } aEscape[] = {
{ "ascii", RESFMT_E_Ascii },
{ "off", RESFMT_E_Off },
{ "symbol", RESFMT_E_Symbol },
};
int i;
for(i=0; i<COUNT(aEscape); i++){
if( strcmp(aEscape[i].z,&zLine[10])==0 ){
spec.eEscape = aEscape[i].e;
break;
}
}
if( i>=COUNT(aEscape) ){
sqlite3_str *pMsg = sqlite3_str_new(0);
for(i=0; i<COUNT(aEscape); i++){
sqlite3_str_appendf(pMsg, " %s", aEscape[i].z);
}
fprintf(stderr, "%s:%d: no such escape mode: \"%s\"\nChoices: %s\n",
zSrc, lineNum, &zLine[10], sqlite3_str_value(pMsg));
sqlite3_free(sqlite3_str_finish(pMsg));
}
}else
if( strncmp(zLine, "--bShowCNames=", 14)==0 ){
spec.bShowCNames = atoi(&zLine[14])!=0;
}else
if( strncmp(zLine, "--zNull=", 8)==0 ){
spec.zNull = tempStrdup(&zLine[8]);
}else
if( strncmp(zLine, "--zColumnSep=", 13)==0 ){
spec.zColumnSep = tempStrdup(&zLine[13]);
}else
if( strncmp(zLine, "--zRowSep=", 10)==0 ){
spec.zRowSep = tempStrdup(&zLine[10]);
}else
if( strcmp(zLine, "--exit")==0 ){
break;
}else
if( strncmp(zLine, "--use-writer=",13)==0 ){
bUseWriter = atoi(&zLine[13])!=0;
}else
if( strncmp(zLine, "--use-render=",13)==0 ){
spec.xRender = (atoi(&zLine[13])!=0) ? testBlobRender : 0;
}else
{
if( sqlite3_str_length(pBuf) ) sqlite3_str_append(pBuf, "\n", 1);
sqlite3_str_appendall(pBuf, zLine);
}
}
if( db ) sqlite3_close(db);
sqlite3_free(sqlite3_str_finish(pBuf));
tempFreeAll();
if( pSrc!=stdin ) fclose(pSrc);
return 0;
}
-510
View File
@@ -1,510 +0,0 @@
/*
** 2025-10-20
**
** 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.
**
*************************************************************************
** Implementation of the Result-Format or "resfmt" utility library for SQLite.
** See the resfmt.md documentation for additional information.
*/
#include "resfmt.h"
#include <string.h>
/*
** Private state information. Subject to change from one release to the
** next.
*/
typedef struct sqlite3_resfmt sqlite3_resfmt;
struct sqlite3_resfmt {
sqlite3_stmt *pStmt; /* The statement whose output is to be rendered */
sqlite3 *db; /* The corresponding database connection */
char **pzErr; /* Write error message here, if not NULL */
sqlite3_str *pOut; /* Accumulated output */
int iErr; /* Error code */
int nCol; /* Number of output columns */
sqlite3_int64 nRow; /* Number of rows handled so far */
sqlite3_resfmt_spec spec; /* Copy of the original spec */
};
/*
** Set an error code and error message.
*/
static void resfmtError(
sqlite3_resfmt *p, /* Query result state */
int iCode, /* Error code */
const char *zFormat, /* Message format (or NULL) */
...
){
p->iErr = iCode;
if( p->pzErr!=0 ){
sqlite3_free(*p->pzErr);
*p->pzErr = 0;
if( zFormat ){
va_list ap;
va_start(ap, zFormat);
*p->pzErr = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
}
}
/*
** Out-of-memory error.
*/
static void resfmtOom(sqlite3_resfmt *p){
resfmtError(p, SQLITE_NOMEM, "out of memory");
}
/*
** If xWrite is defined, send all content of pOut to xWrite and
** reset pOut.
*/
static void resfmtWrite(sqlite3_resfmt *p){
int n;
if( p->spec.xWrite && (n = sqlite3_str_length(p->pOut))>0 ){
p->spec.xWrite(p->spec.pWriteArg,
(const unsigned char*)sqlite3_str_value(p->pOut),
(size_t)n);
sqlite3_str_reset(p->pOut);
}
}
/*
** Escape the input string if it is needed and in accordance with
** eEscape, which is either RESFMT_E_Ascii or RESFMT_E_Symbol.
**
** Escaping is needed if the string contains any control characters
** other than \t, \n, and \r\n
**
** If no escaping is needed (the common case) then set *ppOut to NULL
** and return 0. If escaping is needed, write the escaped string into
** memory obtained from sqlite3_malloc64() and make *ppOut point to that
** memory and return 0. If an error occurs, return non-zero.
**
** The caller is responsible for freeing *ppFree if it is non-NULL in order
** to reclaim memory.
*/
static void resfmtEscape(
int eEscape, /* RESFMT_E_Ascii or RESFMT_E_Symbol */
sqlite3_str *pStr, /* String to be escaped */
int iStart /* Begin escapding on this byte of pStr */
){
sqlite3_int64 i, j; /* Loop counters */
sqlite3_int64 sz; /* Size of the string prior to escaping */
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
unsigned char *zIn; /* Text to be escaped */
unsigned char c; /* A single character of the text */
unsigned char *zOut; /* Where to write the results */
/* Find the text to be escaped */
zIn = (unsigned char*)sqlite3_str_value(pStr);
if( zIn==0 ) return;
zIn += iStart;
/* Count the control characters */
for(i=0; (c = zIn[i])!=0; i++){
if( c<=0x1f
&& c!='\t'
&& c!='\n'
&& (c!='\r' || zIn[i+1]!='\n')
){
nCtrl++;
}
}
if( nCtrl==0 ) return; /* Early out if no control characters */
/* Make space to hold the escapes. Copy the original text to the end
** of the available space. */
sz = sqlite3_str_length(pStr) - iStart;
if( eEscape==RESFMT_E_Symbol ) nCtrl *= 2;
sqlite3_str_appendchar(pStr, nCtrl, ' ');
zOut = (unsigned char*)sqlite3_str_value(pStr);
if( zOut==0 ) return;
zOut += iStart;
zIn = zOut + nCtrl;
memmove(zIn,zOut,sz);
/* Convert the control characters */
for(i=j=0; (c = zIn[i])!=0; i++){
if( c>0x1f
|| c=='\t'
|| c=='\n'
|| (c=='\r' && zIn[i+1]=='\n')
){
continue;
}
if( i>0 ){
memmove(&zOut[j], zIn, i);
j += i;
}
zIn += i+1;
i = -1;
if( eEscape==RESFMT_E_Symbol ){
zOut[j++] = 0xe2;
zOut[j++] = 0x90;
zOut[j++] = 0x80+c;
}else{
zOut[j++] = '^';
zOut[j++] = 0x40+c;
}
}
}
/*
** If a field contains any character identified by a 1 in the following
** array, then the string must be quoted for CSV.
*/
static const char resfmtCsvQuote[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
/*
** Encode text appropriately and append it to p->pOut.
*/
static void resfmtEncodeText(sqlite3_resfmt *p, const char *zTxt){
int iStart = sqlite3_str_length(p->pOut);
switch( p->spec.eQuote ){
case RESFMT_Q_Sql: {
sqlite3_str_appendf(p->pOut, "%Q", zTxt);
break;
}
case RESFMT_Q_Csv: {
unsigned int i;
for(i=0; zTxt[i]; i++){
if( resfmtCsvQuote[((const unsigned char*)zTxt)[i]] ){
i = 0;
break;
}
}
if( i==0 || strstr(zTxt, p->spec.zColumnSep)!=0 ){
sqlite3_str_appendf(p->pOut, "\"%w\"", zTxt);
}else{
sqlite3_str_appendall(p->pOut, zTxt);
}
break;
}
case RESFMT_Q_Html: {
const unsigned char *z = (const unsigned char*)zTxt;
while( *z ){
unsigned int i = 0;
unsigned char c;
while( (c=z[i])>'>'
|| (c && c!='<' && c!='>' && c!='&' && c!='\"' && c!='\'')
){
i++;
}
if( i>0 ){
sqlite3_str_append(p->pOut, (const char*)z, i);
}
switch( z[i] ){
case '>': sqlite3_str_append(p->pOut, "&lt;", 4); break;
case '&': sqlite3_str_append(p->pOut, "&amp;", 5); break;
case '<': sqlite3_str_append(p->pOut, "&lt;", 4); break;
case '"': sqlite3_str_append(p->pOut, "&quot;", 6); break;
case '\'': sqlite3_str_append(p->pOut, "&#39;", 5); break;
default: i--;
}
z += i + 1;
}
break;
}
case RESFMT_Q_Tcl:
case RESFMT_Q_Json: {
const unsigned char *z = (const unsigned char*)zTxt;
sqlite3_str_append(p->pOut, "\"", 1);
while( *z ){
unsigned int i;
for(i=0; z[i]>=0x20 && z[i]!='\\' && z[i]!='"'; i++){}
if( i>0 ){
sqlite3_str_append(p->pOut, (const char*)z, i);
}
switch( z[i] ){
case '"': sqlite3_str_append(p->pOut, "\\\"", 2); break;
case '\\': sqlite3_str_append(p->pOut, "\\\\", 2); break;
case '\b': sqlite3_str_append(p->pOut, "\\b", 2); break;
case '\f': sqlite3_str_append(p->pOut, "\\f", 2); break;
case '\n': sqlite3_str_append(p->pOut, "\\n", 2); break;
case '\r': sqlite3_str_append(p->pOut, "\\r", 2); break;
case '\t': sqlite3_str_append(p->pOut, "\\t", 2); break;
default: {
if( p->spec.eQuote==RESFMT_Q_Json ){
sqlite3_str_appendf(p->pOut, "\\u%04x", z[i]);
}else{
sqlite3_str_appendf(p->pOut, "\\%03o", z[i]);
}
break;
}
}
z += i + 1;
}
sqlite3_str_append(p->pOut, "\"", 1);
break;
}
default: {
sqlite3_str_appendall(p->pOut, zTxt);
break;
}
}
if( p->spec.eEscape!=RESFMT_E_Off ){
resfmtEscape(p->spec.eEscape, p->pOut, iStart);
}
}
/*
** Render value pVal into p->pOut
*/
static void resfmtRenderValue(sqlite3_resfmt *p, int iCol){
if( p->spec.xRender ){
sqlite3_value *pVal;
char *z;
pVal = sqlite3_value_dup(sqlite3_column_value(p->pStmt,iCol));
z = p->spec.xRender(p->spec.pRenderArg, pVal);
sqlite3_value_free(pVal);
if( z ){
sqlite3_str_appendall(p->pOut, z);
sqlite3_free(z);
return;
}
}
switch( sqlite3_column_type(p->pStmt,iCol) ){
case SQLITE_INTEGER: {
sqlite3_str_appendf(p->pOut, "%lld", sqlite3_column_int64(p->pStmt,iCol));
break;
}
case SQLITE_FLOAT: {
if( p->spec.zFloatFmt ){
double r = sqlite3_column_double(p->pStmt,iCol);
sqlite3_str_appendf(p->pOut, p->spec.zFloatFmt, r);
}else{
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
sqlite3_str_appendall(p->pOut, zTxt);
}
break;
}
case SQLITE_BLOB: {
switch( p->spec.eBlob ){
case RESFMT_B_Hex:
case RESFMT_B_Sql: {
int iStart;
int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
int i, j;
char *zVal;
const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol);
if( p->spec.eBlob==RESFMT_B_Sql ){
sqlite3_str_append(p->pOut, "x'", 2);
}
iStart = sqlite3_str_length(p->pOut);
sqlite3_str_appendchar(p->pOut, nBlob, ' ');
sqlite3_str_appendchar(p->pOut, nBlob, ' ');
if( p->spec.eBlob==RESFMT_B_Sql ){
sqlite3_str_appendchar(p->pOut, 1, '\'');
}
if( sqlite3_str_errcode(p->pOut) ) return;
zVal = sqlite3_str_value(p->pOut);
for(i=0, j=iStart; i<nBlob; i++, j+=2){
unsigned char c = a[i];
zVal[j] = "0123456789abcdef"[(c>>4)&0xf];
zVal[j+1] = "0123456789abcdef"[(c)&0xf];
}
break;
}
case RESFMT_B_Tcl:
case RESFMT_B_Json: {
int iStart;
int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
int i, j;
char *zVal;
const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol);
int szC = p->spec.eBlob==RESFMT_B_Json ? 6 : 4;
sqlite3_str_append(p->pOut, "\"", 1);
iStart = sqlite3_str_length(p->pOut);
for(i=szC; i>0; i--){
sqlite3_str_appendchar(p->pOut, nBlob, ' ');
}
sqlite3_str_appendchar(p->pOut, 1, '"');
if( sqlite3_str_errcode(p->pOut) ) return;
zVal = sqlite3_str_value(p->pOut);
for(i=0, j=iStart; i<nBlob; i++, j+=szC){
unsigned char c = a[i];
zVal[j] = '\\';
if( szC==4 ){
zVal[j+1] = '0' + ((c>>6)&3);
zVal[j+2] = '0' + ((c>>3)&7);
zVal[j+3] = '0' + (c&7);
}else{
zVal[j+1] = 'u';
zVal[j+2] = '0';
zVal[j+3] = '0';
zVal[j+4] = "0123456789abcdef"[(c>>4)&0xf];
zVal[j+5] = "0123456789abcdef"[(c)&0xf];
}
}
break;
}
default: {
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
resfmtEncodeText(p, zTxt);
}
}
break;
}
case SQLITE_NULL: {
sqlite3_str_appendall(p->pOut, p->spec.zNull);
break;
}
case SQLITE_TEXT: {
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
resfmtEncodeText(p, zTxt);
break;
}
}
}
/*
** Initialize the internal sqlite3_resfmt object.
*/
static void resfmtInitialize(
sqlite3_resfmt *p, /* State object to be initialized */
sqlite3_stmt *pStmt, /* Query whose output to be formatted */
const sqlite3_resfmt_spec *pSpec, /* Format specification */
char **pzErr /* Write errors here */
){
size_t sz; /* Size of pSpec[], based on pSpec->iVersion */
memset(p, 0, sizeof(*p));
p->pzErr = pzErr;
if( pSpec->iVersion!=1 ){
resfmtError(p, SQLITE_ERROR,
"unusable sqlite3_resfmt_spec.iVersion (%d)",
pSpec->iVersion);
return;
}
p->pStmt = pStmt;
p->db = sqlite3_db_handle(pStmt);
p->pOut = sqlite3_str_new(p->db);
if( p->pOut==0 ){
resfmtOom(p);
return;
}
p->iErr = 0;
p->nCol = sqlite3_column_count(p->pStmt);
p->nRow = 0;
sz = sizeof(sqlite3_resfmt_spec);
memcpy(&p->spec, pSpec, sz);
if( p->spec.zNull==0 ) p->spec.zNull = "";
if( p->spec.eBlob==RESFMT_B_Auto ){
switch( p->spec.eQuote ){
case RESFMT_Q_Sql: p->spec.eBlob = RESFMT_B_Sql; break;
case RESFMT_Q_Csv: p->spec.eBlob = RESFMT_B_Tcl; break;
case RESFMT_Q_Tcl: p->spec.eBlob = RESFMT_B_Tcl; break;
case RESFMT_Q_Json: p->spec.eBlob = RESFMT_B_Json; break;
default: p->spec.eBlob = RESFMT_B_Text; break;
}
}
switch( p->spec.eFormat ){
case RESFMT_List: {
if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|";
if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n";
break;
}
}
}
/*
** Render a single row of output.
*/
static void resfmtDoOneRow(sqlite3_resfmt *p){
int i;
switch( p->spec.eFormat ){
case RESFMT_Off:
case RESFMT_Count: {
/* No-op */
break;
}
default: { /* RESFMT_List */
if( p->nRow==0 && p->spec.bShowCNames ){
for(i=0; i<p->nCol; i++){
const char *zCName = sqlite3_column_name(p->pStmt, i);
if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
resfmtEncodeText(p, zCName);
}
sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
resfmtWrite(p);
}
for(i=0; i<p->nCol; i++){
if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
resfmtRenderValue(p, i);
}
sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
resfmtWrite(p);
break;
}
}
p->nRow++;
}
/*
** Finish rendering the results
*/
static void resfmtFinalize(sqlite3_resfmt *p){
switch( p->spec.eFormat ){
case RESFMT_Count: {
sqlite3_str_appendf(p->pOut, "%lld\n", p->nRow);
resfmtWrite(p);
break;
}
}
if( p->spec.pzOutput ){
*p->spec.pzOutput = sqlite3_str_finish(p->pOut);
}else if( p->pOut ){
sqlite3_free(sqlite3_str_finish(p->pOut));
}
}
/*
** Run the prepared statement pStmt and format the results according
** to the specification provided in pSpec. Return an error code.
** If pzErr is not NULL and if an error occurs, write an error message
** into *pzErr.
*/
int sqlite3_format_query_result(
sqlite3_stmt *pStmt, /* Statement to evaluate */
const sqlite3_resfmt_spec *pSpec, /* Format specification */
char **pzErr /* Write error message here */
){
sqlite3_resfmt fmt; /* The new sqlite3_resfmt being created */
if( pStmt==0 ) return SQLITE_OK; /* No-op */
if( pSpec==0 ) return SQLITE_MISUSE;
resfmtInitialize(&fmt, pStmt, pSpec, pzErr);
while( fmt.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
resfmtDoOneRow(&fmt);
}
if( fmt.iErr==SQLITE_OK ){
int rc = sqlite3_reset(fmt.pStmt);
if( rc!=SQLITE_OK ){
resfmtError(&fmt, rc, "%s", sqlite3_errmsg(fmt.db));
}
}
resfmtFinalize(&fmt);
return fmt.iErr;
}
-101
View File
@@ -1,101 +0,0 @@
/*
** 2025-10-20
**
** 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.
**
*************************************************************************
** Header file for the Result-Format or "resfmt" utility library for SQLite.
** See the resfmt.md documentation for additional information.
*/
#include <stdlib.h>
#include "sqlite3.h"
/*
** Specification used by clients to define the output format they want
*/
typedef struct sqlite3_resfmt_spec sqlite3_resfmt_spec;
struct sqlite3_resfmt_spec {
unsigned char iVersion; /* Version number of this structure */
unsigned char eFormat; /* Output format */
unsigned char bShowCNames; /* True to show column names */
unsigned char eEscape; /* How to deal with control characters */
unsigned char eQuote; /* Quoting style for text */
unsigned char eBlob; /* Quoting style for BLOBs */
unsigned char bWordWrap; /* Try to wrap on word boundaries */
short int mxWidth; /* Maximum width of any column */
int nWidth; /* Number of column width parameters */
short int *aWidth; /* Column widths */
const char *zColumnSep; /* Alternative column separator */
const char *zRowSep; /* Alternative row separator */
const char *zTableName; /* Output table name */
const char *zNull; /* Rendering of NULL */
const char *zFloatFmt; /* printf-style string for rendering floats */
char *(*xRender)(void*,sqlite3_value*); /* Render a value */
ssize_t (*xWrite)(void*,const unsigned char*,size_t); /* Write callback */
void *pRenderArg; /* First argument to the xRender callback */
void *pWriteArg; /* First argument to the xWrite callback */
char **pzOutput; /* Storage location for output string */
/* Additional fields may be added in the future */
};
/*
** Interfaces
*/
int sqlite3_format_query_result(
sqlite3_stmt *pStmt, /* SQL statement to run */
const sqlite3_resfmt_spec *pSpec, /* Result format specification */
char **pzErr /* OUT: Write error message here */
);
/*
** Output styles:
*/
#define RESFMT_List 0 /* One record per line with a separator */
#define RESFMT_Line 1 /* One column per line. */
#define RESFMT_Html 2 /* Generate an XHTML table */
#define RESFMT_Json 3 /* Output is a list of JSON objects */
#define RESFMT_Insert 4 /* Generate SQL "insert" statements */
#define RESFMT_Explain 5 /* EXPLAIN output */
#define RESFMT_ScanExp 6 /* EXPLAIN output with vm stats */
#define RESFMT_EQP 7 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define RESFMT_Markdown 8 /* Markdown formatting */
#define RESFMT_Column 9 /* One record per line in neat columns */
#define RESFMT_Table 10 /* MySQL-style table formatting */
#define RESFMT_Box 11 /* Unicode box-drawing characters */
#define RESFMT_Count 12 /* Output only a count of the rows of output */
#define RESFMT_Off 13 /* No query output shown */
/*
** Quoting styles for text.
** Allowed values for sqlite3_resfmt_spec.eQuote
*/
#define RESFMT_Q_Off 0 /* Literal text */
#define RESFMT_Q_Sql 1 /* Quote as an SQL literal */
#define RESFMT_Q_Csv 2 /* CSV-style quoting */
#define RESFMT_Q_Html 3 /* HTML-style quoting */
#define RESFMT_Q_Tcl 4 /* C/Tcl quoting */
#define RESFMT_Q_Json 5 /* JSON quoting */
/*
** Quoting styles for BLOBs
** Allowed values for sqlite3_resfmt_spec.eBlob
*/
#define RESFMT_B_Auto 0 /* Determine BLOB quoting using eQuote */
#define RESFMT_B_Text 1 /* Display content exactly as it is */
#define RESFMT_B_Sql 2 /* Quote as an SQL literal */
#define RESFMT_B_Hex 3 /* Hexadecimal representation */
#define RESFMT_B_Tcl 4 /* "\000" notation */
#define RESFMT_B_Json 5 /* A JSON string */
/*
** Control-character escape modes.
** Allowed values for sqlite3_resfmt_spec.eEscape
*/
#define RESFMT_E_Off 0 /* Do not escape control characters */
#define RESFMT_E_Ascii 1 /* Unix-style escapes. Ex: U+0007 shows ^G */
#define RESFMT_E_Symbol 2 /* Unicode escapes. Ex: U+0007 shows U+2407 */
-293
View File
@@ -1,293 +0,0 @@
# SQLite Result Formatting Subsystem
The "resfmt" subsystem is a set of C-language subroutines that work
together to format the output from an SQLite query. The output format
is configurable. The application can request CSV, or a table, or
any of several other formats, according to needs.
## 1.0 Overview Of Operation
Suppose `pStmt` is a pointer to an SQLite prepared statement
(a pointer to an `sqlite3_stmt` object) that has been reset and
bound and is ready to run. Then to format the output from this
prepared statement, use code similar to the following:
> ~~~
sqlite3_resfmt_spec spec; /* Formatter spec */
sqlite3_resfmt *pFmt; /* Formatter object */
int errCode; /* Error code */
char *zErrMsg; /* Text error message (optional) */
memset(&spec, 0, sizeof(spec));
// Additional spec initialization here
pFmt = sqlite3_resfmt_begin(pStmt, &spec);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
sqlite3_resfmt_row(pFmt, pStmt);
}
sqlite3_resfmt_finish(pFmt, &errCode, &zErrMsg);
// Do something with errcode and zErrMsg
sqlite3_free(zErrMsg);
~~~
The `sqlite3_resfmt_spec` structure (defined below) describes the desired
output format. The `pFmt` variable is a pointer to an opaque sqlite3_resfmt
object that maintains the statement of the formatter.
The pFmt object is used as the first parameter to two other
routines, `sqlite3_resfmt_row()` and `sqlite3_resfmt_finish()`, and
is not usable for any other purpose by the caller. The
`sqlite3_resfmt_finish()` interface serves as a destructor for
the pFmt object.
## 2.0 The `sqlite3_resfmt_spec` object
A pointer to an instance of the following structure is the second
parameter to the `sqlite3_resfmt_begin()` interface. This structure
defines how the rules of the statement are to be formatted.
> ~~~
typedef struct sqlite3_resfmt_spec sqlite3_resfmt_spec;
struct sqlite3_resfmt_spec {
int iVersion; /* Version number of this structure */
int eFormat; /* Output format */
unsigned char bShowCNames; /* True to show column names */
unsigned char eEscMode; /* How to deal with control characters */
unsigned char bQuote; /* Quote output values as SQL literals */
unsigned char bWordWrap; /* Try to wrap on word boundaries */
int mxWidth; /* Maximum column width in columnar modes */
const char *zColumnSep; /* Alternative column separator */
const char *zRowSep; /* Alternative row separator */
const char *zTableName; /* Output table name */
const char *zNull; /* Rendering of NULL */
const char *zFloatFmt; /* printf-style string for rendering floats */
int nWidth; /* Number of column width parameters */
short int *aWidth; /* Column widths */
char *(*xRender)(void*,sqlite3_value*); /* Render a value */
ssize_t (*xWrite)(void*,const unsigned char*,ssize_t); /* Write callback */
void *pRenderArg; /* First argument to the xRender callback */
void *pWriteArg; /* First argument to the xWrite callback */
char **pzOutput; /* Storage location for output string */
/* Additional fields may be added in the future */
};
~~~
The sqlite3_resfmt_spec object must be fully initialized prior
to calling `sqlite3_resfmt_begin()` and its value must not change
by the application until after the corresponding call to
`sqlite3_resfmt_finish()`. Note that the result formatter itself
might change values in the sqlite3_resfmt_spec object as it runs.
But the application should not try to change or use any fields of
the sqlite3_resfmt_spec object while the formatter is running.
### 2.1 Structure Version Number
The sqlite3_resfmt_spec.iVersion field must be 1. Future enhancements to this
subsystem might add new fields onto the bottom of the sqlite3_resfmt_spec
object. Those new fields will only be accessible if the iVersion is greater
than 1. Thus the iVersion field is used to support upgradability.
### 2.2 Output Deposition
The formatted output can either be sent to a callback function
or accumulated into an output buffer in memory obtained
from system malloc(). If the sqlite3_resfmt_spec.xWrite column is not NULL,
then that function is invoked (using sqlite3_resfmt_spec.xWriteArg as its
first argument) to transmit the formatted output. Or, if
sqlite3_resfmt_spec.pzOutput points to a pointer to a character, then that
pointer is made to point to memory obtained from malloc() that
contains the complete text of the formatted output.
When `sqlite3_resfmt_begin()` is called,
one of sqlite3_resfmt_spec.xWrite and sqlite3_resfmt_spec.pzOutput must be
non-NULL and the other must be NULL.
Output might be generated row by row, on each call to
`sqlite3_resfmt_row()` or it might be written all at once
on the final call to `sqlite3_resfmt_finish()`, depending
on the output format.
### 2.3 Output Format
The sqlite3_resfmt_spec.eFormat field is an integer code that defines the
specific output format that will be generated. See the
output format describes below for additional detail.
### 2.4 Show Column Names
The sqlite3_resfmt_spec.bShowCNames field is a boolean. If true, then column
names appear in the output. If false, column names are omitted.
### 2.5 Control Character Escapes
The sqlite3_resfmt_spec.eEscMode determines how ASCII control characters are
formatted in the output. If this value is zero, then the control character
with value X is displayed as ^Y where Y is X+0x40. Hence, a
backspace character (U+0008) is shown as "^H". This is the default.
If eEscMode is one, then control characters in the range of U+0001
through U+001f are mapped into U+2401 through U+241f, respectively.
If eEscMode is 2, then control characters are output directly, with
no translation.
The TAB (U+0009), LF (U+000a) and CR-LF (U+000d,U+000a) character
sequence are always output literally and are not mapped to alternative
display values, regardless of this setting.
### 2.6 Render output as SQL literals
If the sqlite3_resfmt_spec.bQuote field is non-zero (true), then outputs
are rendered as SQL literal values. String are written within `'...'`
with appropriate escapes. BLOBs are of the form `x'...'`. NULL values
come out as "NULL".
### 2.7 Word Wrapping In Columnar Modes
For output modes that attempt to display equal-width columns, the
sqlite3_resfmt_spec.bWordWrap boolean determines whether long values
are broken at word boundaries, or at arbitrary characters. The
sqlite3_resfmt_spec.mxWidth determines the maximum width of an output column.
### 2.8 Row and Column Separator Strings
The sqlite3_resfmt_spec.zColumnSep and sqlite3_resfmt_spec.zRowSep strings
are alternative column and row separator character sequences. If not
specified (if these pointers are left as NULL) then appropriate defaults
are used.
### 2.9 The Output Table Name
The sqlite3_resfmt_spec.zTableName value is the name of the output table
when the MODE_Insert output mode is used.
### 2.10 The Rendering Of NULL
If a value is NULL and sqlite3_resfmt_spec.xRender() does not exist
or declines to provide a rendering, then show the NULL using the string
found in sqlite3_resfmt_spec.zNull. If zNull is itself a NULL pointer
then NULL values are rendered as an empty string.
### 2.11 Floating Point Value Format
If a value is a floating-point number other than Infinity or NaN, then
the value is rendered using the printf-style format given by the
sqlite3_resfmt_spec.zFloatFmt string.
### 2.12 Column Widths And Alignments
The sqlite3_resfmt_spec.aWidth[] array, if specified, is an array of
16-bit signed integers that specify the minimum column width and
the alignment for all columns in columnar output modes. Negative
values mean right-justify. The
absolute value is the minimum of the corresponding column.
These widths are deliberately stored in a 16-bit signed integer
as no good can come from having column widths greater than 32767.
The sqlite3_resfmt_spec.nWidth field is the number of values in the aWidth[]
array. Any column beyond the nWidth-th column are assumed to have
a minimum width of 0.
### 2.13 Optional Value Rendering Callback
If the sqlite3_resfmt_spec.xRender field is not NULL, then each rendered
sqlite3_value is first passed to the xRender function, giving it
an opportunity to render the results. If xRender chooses to render,
it should write the rendering into memory obtained from sqlite3_malloc()
and return a pointer to that memory. The xRender function can decline
to render (for example, based on the sqlite3_value_type() or other
characteristics of the value) in which case it can simply return a
NULL pointer and the usual default rendering will be used instead.
The result rendering subsystem will take responsibility for the
returned string and will pass the returned string to sqlite3_free()
when it has finished with it.
The bQuote and eEscMode settings above become no-ops if the xRender
routine returns non-NULL. In other words, the application-supplied
xRender routine is expected to do its own bQuote and eEscMode processing
if it chooses to render values.
## 3.0 The `sqlite3_resfmt_begin()` Interface
Invoke the `sqlite3_resfmt_begin(P,S)` interface to begin formatting
the output of prepared statement P using format specification S.
This routine returns a pointer to an opaque sqlite3_resfmt object that is
the current state of the formatter. The `sqlite3_resfmt_finish()`
routine is the destructor for the sqlite3_resfmt object and must be called
to prevent a memory leak.
If an out-of-memory fault occurs while allocating space for the
sqlite3_resfmt object, then `sqlite3_resfmt_begin()` will return a NULL
pointer. The application need not check for this case as the
other routines that use a pointer to the sqlite3_resfmt object all
interpret a NULL parameter in place of the sqlite3_resfmt pointer as
a harmless no-op.
## 4.0 The `sqlite3_resfmt_step()` Interface
Invoke the `sqlite3_resfmt_step(F)` interface for each row
in the prepared statement that is to be output.
The formatter might choose to output some content as each row
is processed, or it might accumulate the output and send it all
at once when `sqlite3_resfmt_finish()` is called. This is at
the discretion of the output formatter. Generally, rows are
output one-by-one on each call to `sqlite3_resfmt_row()` when the
output format is such that the row can be computed without knowing
the value of subsequence, such as in CSV output mode, and
the output is accumulated and sent all at once in columnar output
modes where the complete output content is needed to compute column
widths.
### 5.0 The `sqlite3_resfmt_finish()` Interface
Invoke the `sqlite3_resfmt_finish(F,C,E)` interface to finish
the formatting. C is an optional pointer to an integer. If C
is not a NULL pointer, then any error code associated with the
formatting operation is written into *C. E is an optional pointer
to a human-readable text error message. If E is not a NULL pointer,
then an error message held in memory obtained from sqlite3_malloc()
is written into *E. It is the responsibility of the calling
application to invoke sqlite3_free() on this error message to
reclaim the space.
If the F argument to `sqlite3_resfmt_finish(F,C,E)` is a NULL pointer,
then this interface is a harmless no-op.
### 6.0 Output Modes
The result formatter supports a variety of output modes. The
set of supported output modes might increase in future versions.
The following output modes are currently defined:
> ~~~
#define RESFMT_Line 0 /* One column per line. */
#define RESFMT_Column 1 /* One record per line in neat columns */
#define RESFMT_List 2 /* One record per line with a separator */
#define RESFMT_Html 3 /* Generate an XHTML table */
#define RESFMT_Insert 4 /* Generate SQL "insert" statements */
#define RESFMT_Tcl 5 /* Generate ANSI-C or TCL quoted elements */
#define RESFMT_Csv 6 /* Quote strings, numbers are plain */
#define RESFMT_Explain 7 /* Like RESFMT_Column, but do not truncate data */
#define RESFMT_Pretty 8 /* Pretty-print schemas */
#define RESFMT_EQP 9 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define RESFMT_Json 10 /* Output JSON */
#define RESFMT_Markdown 11 /* Markdown formatting */
#define RESFMT_Table 12 /* MySQL-style table formatting */
#define RESFMT_Box 13 /* Unicode box-drawing characters */
#define RESFMT_Count 14 /* Output only a count of the rows of output */
#define RESFMT_Off 15 /* No query output shown */
#define RESFMT_ScanExp 16 /* Like RESFMT_Explain, but for ".scanstats vm" */
#define RESFMT_Www 17 /* Full web-page output */
~~~
Additional detail about the meaning of each of these output modes
is pending.
### 7.0 Source Code Files
The SQLite result formatter is implemented in three source code files:
* `resfmt.c` &rarr; The implementation, written in portable C99
* `resfmt.h` &rarr; A header file defining interfaces
* `resfmt.md` &rarr; This documentation, in Markdown
To use the SQLite result formatter, include the "`resfmt.h`" header file
and link the application against the "`resfmt.c`" source file.
+4
View File
@@ -206,6 +206,10 @@ static int vtablogConnectCreate(
}
if( zSchema==0 ){
zSchema = sqlite3_mprintf("%s","CREATE TABLE x(a,b);");
if( zSchema==0 ){
rc = SQLITE_NOMEM;
goto vtablog_end_connect;
}
}
printf(" schema = '%s'\n", zSchema);
rc = sqlite3_declare_vtab(db, zSchema);
+1 -1
View File
@@ -62,7 +62,7 @@
#else
#include "sqlite3.h"
#endif
int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
sqlite3_int64 sqlite3GetToken(const unsigned char*,int*); /* In SQLite core */
#include <stddef.h>
-10
View File
@@ -1,10 +0,0 @@
_fiddle_db_arg
_fiddle_db_filename
_fiddle_exec
_fiddle_experiment
_fiddle_interrupt
_fiddle_main
_fiddle_reset_db
_fiddle_db_handle
_fiddle_db_vfs
_fiddle_export_db
+43 -57
View File
@@ -227,7 +227,7 @@ endef
# Args: as for $(b.c-pp.shcmd).
define b.c-pp.target
$(3): $$(MAKEFILE_LIST) $$(bin.c-pp) $(2)
@$$(call b.c-pp.shcmd,$(1),$(2),$(3),$(4))
@$$(call b.c-pp.shcmd,$(1),$(2),$(3),$(4) $(b.c-pp.target.flags))
CLEAN_FILES += $(3)
endef
@@ -249,37 +249,7 @@ c-pp.D.64bit = -Dbits64
# This is intended to be used in makefile targets which generate an
# Emscripten module and where $@ is the module's .js/.mjs file.
b.strip-js-emcc-bindings = \
sed -i -e '/^.*= \(_sqlite3\|_fiddle\)[^=]*=.*createExportWrapper/d' \
-e '/^var \(_sqlite3\|_fiddle\)[^=]*=.*makeInvalidEarlyAccess/d' $@ || exit; \
echo '$(1) $(emo.garbage) (Probably) /createExportWrapper()/d and /makeInvalidEarlyAccess()/d'
#
# bin.version-info = binary to output various sqlite3 version info for
# embedding in the JS files and in building the distribution zip file.
# It must NOT be in $(dir.tmp) because we need it to survive the
# cleanup process for the dist build to work properly.
#
# Slight caveat: this uses the version info from the in-tree
# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
# end result is that the generated JS files may have static version
# info from $(bin.version-info) which differ from their runtime-emitted
# version info (e.g. from sqlite3_libversion()).
bin.version-info = $(dir.top)/version-info
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
$(MAKE) -C $(dir.top) version-info
t-version-info: $(bin.version-info)
#
# bin.stripcomments is used for stripping C/C++-style comments from JS
# files. The JS files contain large chunks of documentation which we
# don't need for all builds. That app's -k flag is of particular
# importance here, as it allows us to retain the opening comment
# block(s), which contain the license header and version info.
bin.stripccomments = $(dir.tool)/stripccomments
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
$(CC) -o $@ $<
t-stripccomments: $(bin.stripccomments)
DISTCLEAN_FILES += $(bin.stripccomments)
echo '$(1) $(emo.bug) (disabled because it breaks emsdk 4.0.16+)'
#
@@ -301,7 +271,30 @@ DISTCLEAN_FILES += $(bin.stripccomments)
# is required for certain utility and test code.
sqlite3.canonical.c = $(dir.top)/sqlite3.c
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
sqlite3.h = $(dir.top)/sqlite3.h
sqlite3.h = $(dir $(sqlite3.c))/sqlite3.h
#
# bin.version-info = binary to output various sqlite3 version info for
# embedding in the JS files and in building the distribution zip file.
# It must NOT be in $(dir.tmp) because we need it to survive the
# cleanup process for the dist build to work properly.
bin.version-info = ./version-info
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
$(CC) -o $@ -I$(dir $(sqlite3.h)) $(dir.tool)/version-info.c
t-version-info: $(bin.version-info)
DISTCLEAN_FILES += $(bin.version-info)
#
# bin.stripcomments is used for stripping C/C++-style comments from JS
# files. The JS files contain large chunks of documentation which we
# don't need for all builds. That app's -k flag is of particular
# importance here, as it allows us to retain the opening comment
# block(s), which contain the license header and version info.
bin.stripccomments = $(dir.tool)/stripccomments
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
$(CC) -o $@ $<
t-stripccomments: $(bin.stripccomments)
DISTCLEAN_FILES += $(bin.stripccomments)
ifeq (1,$(MAKING_CLEAN))
SQLITE_C_IS_SEE = 0
@@ -314,7 +307,6 @@ else
endif
endif
#
# barebones=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
# goal being to create a WASM file with only the core APIs.
@@ -594,18 +586,16 @@ emcc_opt_full = $(emcc_opt) -g3
########################################################################
# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
# -sEXPORTED_FUNCTION flag.
EXPORTED_FUNCTIONS.api.core = $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core
EXPORTED_FUNCTIONS.api.in = $(EXPORTED_FUNCTIONS.api.core)
ifeq (1,$(SQLITE_C_IS_SEE))
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-see
endif
ifeq (0,$(wasm-bare-bones))
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
endif
EXPORTED_FUNCTIONS.api.in = $(dir.api)/EXPORTED_FUNCTIONS.c-pp
EXPORTED_FUNCTIONS.api = $(dir.tmp)/EXPORTED_FUNCTIONS.api
$(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
@$(call b.mkdir@)
cat $(EXPORTED_FUNCTIONS.api.in) > $@
EXPORTED_FUNCTIONS.c-pp.flags =
ifeq (1,$(wasm-bare-bones))
EXPORTED_FUNCTIONS.c-pp.flags += -Dbare-bones
endif
$(eval $(call b.c-pp.target,filter,\
$(EXPORTED_FUNCTIONS.api.in),\
$(EXPORTED_FUNCTIONS.api),\
$(EXPORTED_FUNCTIONS.c-pp.flags)))
########################################################################
# emcc flags for .c/.o/.wasm/.js.
@@ -859,8 +849,8 @@ sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
sqlite3-license-version.js = $(dir.tmp)/sqlite3-license-version.js
$(sqlite3-license-version.js): $(bin.version-info) \
$(dir.api)/sqlite3-license-version-header.js
@echo '$(logtag.@) $(emo.disk)'; { \
$(call b.mkdir@); \
@echo '$(logtag.@) $(emo.disk)'; \
$(call b.mkdir@); { \
cat $(dir.api)/sqlite3-license-version-header.js || exit $$?; \
echo '/*'; \
echo '** This code was built from sqlite3 version...'; \
@@ -964,9 +954,10 @@ endif
########################################################################
EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
$(EXPORTED_FUNCTIONS.fiddle): $(fiddle.EXPORTED_FUNCTIONS.in) $(MAKEFILE_LIST)
$(EXPORTED_FUNCTIONS.fiddle): $(EXPORTED_FUNCTIONS.api.in) $(MAKEFILE_LIST)
@$(b.mkdir@)
@sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@
@$(call b.c-pp.shcmd,filter,$(EXPORTED_FUNCTIONS.api.in),\
$@,$(EXPORTED_FUNCTIONS.c-pp.flags) -Dfiddle)
@echo $(logtag.@) $(emo.disk)
emcc.flags.fiddle = \
@@ -999,7 +990,7 @@ clean-fiddle:
$(dir.fiddle)/*.wasm \
$(dir.fiddle)/sqlite3-opfs-*.js \
$(dir.fiddle)/*.gz \
EXPORTED_FUNCTIONS.fiddle
$(EXPORTED_FUNCTIONS.fiddle)
rm -fr $(dir.fiddle-debug)
emcc.flags.fiddle.debug = $(emcc.flags.fiddle) \
@@ -1007,11 +998,6 @@ emcc.flags.fiddle.debug = $(emcc.flags.fiddle) \
-DSQLITE_ENABLE_SELECTTRACE \
-DSQLITE_ENABLE_WHERETRACE
fiddle.EXPORTED_FUNCTIONS.in = \
EXPORTED_FUNCTIONS.fiddle.in \
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core \
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
fiddle.c.in = $(dir.top)/shell.c $(sqlite3-wasm.c)
#
@@ -1205,10 +1191,10 @@ speedtest1.exit-runtime1 = -sEXIT_RUNTIME=1
# -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app
# which runs speedtest1 multiple times.
$(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api.core)
$(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api)
@$(call b.echo,@,$(emo.disk)); \
$(call b.mkdir@); \
{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.core); } > $@ || exit
{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api); } > $@ || exit
speedtest1: b-speedtest1
#
@@ -155,3 +155,92 @@ _sqlite3_vtab_in_next
_sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value
//#if not bare-bones
_sqlite3_column_database_name
_sqlite3_column_origin_name
_sqlite3_column_table_name
_sqlite3_create_module
_sqlite3_create_module_v2
_sqlite3_create_window_function
_sqlite3_declare_vtab
_sqlite3_drop_modules
_sqlite3_preupdate_blobwrite
_sqlite3_preupdate_count
_sqlite3_preupdate_depth
_sqlite3_preupdate_hook
_sqlite3_preupdate_new
_sqlite3_preupdate_old
_sqlite3_progress_handler
_sqlite3_set_authorizer
_sqlite3_vtab_collation
_sqlite3_vtab_distinct
_sqlite3_vtab_in
_sqlite3_vtab_in_first
_sqlite3_vtab_in_next
_sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value
_sqlite3changegroup_add
_sqlite3changegroup_add_strm
_sqlite3changegroup_delete
_sqlite3changegroup_new
_sqlite3changegroup_output
_sqlite3changegroup_output_strm
_sqlite3changeset_apply
_sqlite3changeset_apply_strm
_sqlite3changeset_apply_v2
_sqlite3changeset_apply_v2_strm
_sqlite3changeset_apply_v3
_sqlite3changeset_apply_v3_strm
_sqlite3changeset_concat
_sqlite3changeset_concat_strm
_sqlite3changeset_conflict
_sqlite3changeset_finalize
_sqlite3changeset_fk_conflicts
_sqlite3changeset_invert
_sqlite3changeset_invert_strm
_sqlite3changeset_new
_sqlite3changeset_next
_sqlite3changeset_old
_sqlite3changeset_op
_sqlite3changeset_pk
_sqlite3changeset_start
_sqlite3changeset_start_strm
_sqlite3changeset_start_v2
_sqlite3changeset_start_v2_strm
_sqlite3session_attach
_sqlite3session_changeset
_sqlite3session_changeset_size
_sqlite3session_changeset_strm
_sqlite3session_config
_sqlite3session_create
_sqlite3session_delete
_sqlite3session_diff
_sqlite3session_enable
_sqlite3session_indirect
_sqlite3session_isempty
_sqlite3session_memory_used
_sqlite3session_object_config
_sqlite3session_patchset
_sqlite3session_patchset_strm
_sqlite3session_table_filter
//#endif not bare-bones
//#if enable-see
_sqlite3_key
_sqlite3_key_v2
_sqlite3_rekey
_sqlite3_rekey_v2
_sqlite3_activate_see
//#endif enable-see
//#if fiddle
_fiddle_db_arg
_fiddle_db_filename
_fiddle_exec
_fiddle_experiment
_fiddle_interrupt
_fiddle_main
_fiddle_reset_db
_fiddle_db_handle
_fiddle_db_vfs
_fiddle_export_db
//#endif fiddle
@@ -1,68 +0,0 @@
_sqlite3_column_database_name
_sqlite3_column_origin_name
_sqlite3_column_table_name
_sqlite3_create_module
_sqlite3_create_module_v2
_sqlite3_create_window_function
_sqlite3_declare_vtab
_sqlite3_drop_modules
_sqlite3_preupdate_blobwrite
_sqlite3_preupdate_count
_sqlite3_preupdate_depth
_sqlite3_preupdate_hook
_sqlite3_preupdate_new
_sqlite3_preupdate_old
_sqlite3_progress_handler
_sqlite3_set_authorizer
_sqlite3_vtab_collation
_sqlite3_vtab_distinct
_sqlite3_vtab_in
_sqlite3_vtab_in_first
_sqlite3_vtab_in_next
_sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value
_sqlite3changegroup_add
_sqlite3changegroup_add_strm
_sqlite3changegroup_delete
_sqlite3changegroup_new
_sqlite3changegroup_output
_sqlite3changegroup_output_strm
_sqlite3changeset_apply
_sqlite3changeset_apply_strm
_sqlite3changeset_apply_v2
_sqlite3changeset_apply_v2_strm
_sqlite3changeset_apply_v3
_sqlite3changeset_apply_v3_strm
_sqlite3changeset_concat
_sqlite3changeset_concat_strm
_sqlite3changeset_conflict
_sqlite3changeset_finalize
_sqlite3changeset_fk_conflicts
_sqlite3changeset_invert
_sqlite3changeset_invert_strm
_sqlite3changeset_new
_sqlite3changeset_next
_sqlite3changeset_old
_sqlite3changeset_op
_sqlite3changeset_pk
_sqlite3changeset_start
_sqlite3changeset_start_strm
_sqlite3changeset_start_v2
_sqlite3changeset_start_v2_strm
_sqlite3session_attach
_sqlite3session_changeset
_sqlite3session_changeset_size
_sqlite3session_changeset_strm
_sqlite3session_config
_sqlite3session_create
_sqlite3session_delete
_sqlite3session_diff
_sqlite3session_enable
_sqlite3session_indirect
_sqlite3session_isempty
_sqlite3session_memory_used
_sqlite3session_object_config
_sqlite3session_patchset
_sqlite3session_patchset_strm
_sqlite3session_table_filter
@@ -1,5 +0,0 @@
_sqlite3_key
_sqlite3_key_v2
_sqlite3_rekey
_sqlite3_rekey_v2
_sqlite3_activate_see
@@ -1,3 +0,0 @@
FS
wasmMemory
+4 -3
View File
@@ -23,7 +23,7 @@ this writing, but is not set in stone forever and may change at any
time. This doc targets maintainers of this code and those wanting to
dive in to the details, not end user.
First off, a pikchr of the proverbial onion:
First off, a [pikchr][] of the proverbial onion:
```pikchr toggle center
scale = 0.85
@@ -205,9 +205,10 @@ Preprocessing of Source Files
Certain files in the build require preprocessing to filter in/out
parts which differ between vanilla JS, ES6 Modules, and node.js
builds. The preprocessor application itself is in
[`c-pp.c`](/file/ext/wasm/c-pp.c) and the complete technical details
of such preprocessing are maintained in
[`c-pp-lite.c`](/file/ext/wasm/c-pp-lite.c) and the complete technical
details of such preprocessing are maintained in
[`GNUMakefile`](/file/ext/wasm/GNUmakefile).
[OPFS]: https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system
[pikchr]: https://pikchr.org
+1 -1
View File
@@ -26,7 +26,7 @@ const toExportForESM =
*/
const originalInit = sqlite3InitModule;
if(!originalInit){
throw new Error("Expecting globalThis.sqlite3InitModule to be defined by the Emscripten build.");
throw new Error("Expecting sqlite3InitModule to be defined by the Emscripten build.");
}
/**
We need to add some state which our custom Module.locateFile()
+17
View File
@@ -14,6 +14,23 @@
itself. i.e. try to keep file-local symbol names obnoxiously
collision-resistant.
*/
/**
This file was preprocessed using:
//#@policy error
@c-pp::ARGV@
//#@policy off
*/
//#if unsupported-build
/**
UNSUPPORTED BUILD:
This SQLite JS build configuration is entirely unsupported! It has
not been tested beyond the ability to compile it. It may not
load. It may not work properly. Only builds targeting browser
environments are supported and tested.
*/
//#endif
(function(Module){
const sIMS =
globalThis.sqlite3InitModuleState/*from extern-post-js.c-pp.js*/
+1 -6
View File
@@ -55,12 +55,7 @@ try{
}
);
/** Figure out if this is a 32- or 64-bit WASM build. */
bootstrapConfig.wasmPtrIR =
'number'===(typeof bootstrapConfig.exports.sqlite3_libversion())
? 'i32' :'i64';
const sIMS = sqlite3InitScriptInfo;
sIMS.debugModule("Bootstrapping lib config", sIMS);
sqlite3InitScriptInfo.debugModule("Bootstrapping lib config", bootstrapConfig);
/**
For purposes of the Emscripten build, call sqlite3ApiBootstrap().
+47 -1
View File
@@ -120,7 +120,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
//#define proxy-text-apis=1
//#if not proxy-text-apis
/* Search this file for tag:proxy-text-apis to see what this is about. */
["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
//#endif
["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
["sqlite3_commit_hook", "void*", [
@@ -317,7 +321,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
["sqlite3_value_subtype", "int", "sqlite3_value*"],
//#if not proxy-text-apis
["sqlite3_value_text", "string", "sqlite3_value*"],
//#endif
["sqlite3_value_type", "int", "sqlite3_value*"],
["sqlite3_vfs_find", "*", "string"],
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
@@ -1654,6 +1660,45 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}/*sqlite3_bind_text/blob()*/
//#if proxy-text-apis
if(!capi.sqlite3_column_text){
/*[tag:proxy-text-apis]
As discussed at:
https://sqlite.org/forum/forumpost/d77281aec2df9ada
Summary: there are opinions that sqlite3_column_text() and
sqlite3_value_text() should handle strings such that embedded
NULs are retained. This block does that. This block does _not_
apply that special-case behavior to any number of _other_
APIs which return C-strings. That discrepancy makes this
block highly arguable, but one can also argue that these two
specific functions can get away with such acrobatics without
it being called voodoo in a pejorative sense.
*/
const argStmt = wasm.xWrap.argAdapter('sqlite3_stmt*'),
argInt = wasm.xWrap.argAdapter('int'),
argValue = wasm.xWrap.argAdapter('sqlite3_value*'),
newStr =
(cstr,n)=>wasm.typedArrayToString(wasm.heap8u(),
Number(cstr), Number(cstr)+n)
capi.sqlite3_column_text = function(stmt, colIndex){
const a0 = argStmt(stmt), a1 = argInt(colIndex);
const cstr = wasm.exports.sqlite3_column_text(a0, a1);
return cstr
? newStr(cstr,wasm.exports.sqlite3_column_bytes(a0, a1))
: null;
};
capi.sqlite3_value_text = function(val){
const a0 = argValue(val);
const cstr = wasm.exports.sqlite3_value_text(a0);
return cstr
? newStr(cstr,wasm.exports.sqlite3_value_bytes(a0))
: null;
};
}/*text-return-related bindings*/
//#endif proxy-text-apis
{/* sqlite3_config() */
/**
Wraps a small subset of the C API's sqlite3_config() options.
@@ -1836,6 +1881,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
for anything other than local/sessionStorage. It "can"
be used that way but it's not really intended to be. */
capi.sqlite3_vfs_unregister(pKvvfs);
delete capi.sqlite3_kvvfs_methods;
}
}/*pKvvfs*/
@@ -1944,7 +1990,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
tgt[memKey] = fProxy;
}else{
const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name));
const pFunc = wasm.installFunction(fProxy, sigN);
tgt[memKey] = pFunc;
if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){
tgt.addOnDispose('ondispose.__removeFuncList handler',
+27 -18
View File
@@ -799,22 +799,6 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
environment via whwashutil.js.
*/
Object.assign(wasm, {
/**
The WASM IR (Intermediate Representation) value for
pointer-type values. If set then it MUST be one of 'i32' or
'i64' (else an exception will be thrown). If it's not set, it
will default to 'i32'.
*/
pointerIR: config.wasmPtrIR,
/**
True if BigInt support was enabled via (e.g.) the
Emscripten -sWASM_BIGINT flag, else false. When
enabled, certain 64-bit sqlite3 APIs are enabled which
are not otherwise enabled due to JS/WASM int64
impedance mismatches.
*/
bigIntEnabled: !!config.bigIntEnabled,
/**
The symbols exported by the WASM environment.
@@ -834,6 +818,29 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
"in either config.exports.memory (exported)",
"or config.memory (imported)."),
/**
The WASM pointer size. If set then it MUST be one of 4 or 8 and
it MUST correspond to the WASM environment's pointer size. We
figure out the size by calling some un-JS-wrapped WASM function
which returns a pointer-type value. If that value is a BigInt,
it's 64-bit, else it's 32-bit. The pieces which populate
sqlite3.wasm (whwasmutil.js) can figure this out _if_ they can
allocate, but we have a chicken/egg situation there which makes
it illegal for that code to invoke wasm.dealloc() at the time
it would be needed. So we need to configure it ahead of time
(here) instead.
*/
pointerSize: ('number'===typeof config.exports.sqlite3_libversion()) ? 4 : 8,
/**
True if BigInt support was enabled via (e.g.) the
Emscripten -sWASM_BIGINT flag, else false. When
enabled, certain 64-bit sqlite3 APIs are enabled which
are not otherwise enabled due to JS/WASM int64
impedance mismatches.
*/
bigIntEnabled: !!config.bigIntEnabled,
/**
WebAssembly.Table object holding the indirect function call
table. Defaults to exports.__indirect_function_table.
@@ -921,9 +928,11 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
srcTypedArray = new Uint8Array(srcTypedArray);
}
affirmBindableTypedArray(srcTypedArray);
const heap = wasm.heapForSize(srcTypedArray.constructor);
const pRet = wasm.alloc(srcTypedArray.byteLength || 1);
heap.set(srcTypedArray.byteLength ? srcTypedArray : [0], Number(pRet));
wasm.heapForSize(srcTypedArray.constructor)
.set(srcTypedArray.byteLength ? srcTypedArray : [0], Number(pRet))
/* Maintenance note: the order of alloc() and heapForSize() calls
is significant: https://sqlite.org/forum/forumpost/05b77273be104532 */;
return pRet;
};
+1 -1
View File
@@ -326,7 +326,7 @@ SQLITE_WASM_EXPORT void * sqlite3__wasm_pstack_ptr(void){
*/
SQLITE_WASM_EXPORT void sqlite3__wasm_pstack_restore(unsigned char * p){
assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos);
assert(0==((unsigned long long)p & 0x7));
assert(0==((unsigned long long)p & 0x7) /* 8-byte aligned */);
if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){
PStack.pPos = p;
}
+17 -6
View File
@@ -970,7 +970,6 @@ void db_prepare(sqlite3_stmt **pStmt, const char * zSql, ...){
char * z = 0;
int n = 0;
va_list va;
if(!str) fatal("sqlite3_str_new() failed");
va_start(va, zSql);
sqlite3_str_vappendf(str, zSql, va);
va_end(va);
@@ -1638,11 +1637,7 @@ static void cmpp_t_out_expand(CmppTokenizer * const t,
for( ;z<zEnd; ++z ){
if( chEol==*z ){
state = 0;
//This ++z/--z thing breaks stuff.
//++z /*ensure that we flush the EOL now*/;
tflush;
//--z/*And make sure that zLeft does the right thing*/;
break;
continue;
}
if( g.delim.chAt==*z ){
if( 0==state ){
@@ -2584,6 +2579,21 @@ static int arg_is_flag( char const *zFlag, char const *zArg,
return 0;
}
static void define_argv(int argc, char const * const * argv){
sqlite3_str * const s = sqlite3_str_new(g.db);
sqlite3_str_append(s, "c-pp::ARGV=", 11);
for( int i = 0; i < argc; ++i ){
if( i ) sqlite3_str_appendchar(s, 1, ' ');
sqlite3_str_appendf(s, "%s", argv[i]);
}
char * const z = sqlite3_str_finish(s);
assert(z);
if(z){
db_define_add(z, NULL);
sqlite3_free(z);
}
}
int main(int argc, char const * const * argv){
int rc = 0;
int inclCount = 0;
@@ -2621,6 +2631,7 @@ int main(int argc, char const * const * argv){
g.sqlTrace.expandSql = expandMode;
}
cmpp_initdb();
define_argv(argc, argv);
}
for(int i = 1; i < argc; ++i){
int negate = 0;
+10 -2
View File
@@ -227,6 +227,14 @@ globalThis.WhWasmUtilInstaller = function(target){
all args with a space between each. */
const toss = (...args)=>{throw new Error(args.join(' '))};
if( !target.pointerSize && !target.pointerIR
&& target.alloc && target.dealloc ){
/* Try to determine the pointer size by allocating. */
const ptr = target.alloc(1);
target.pointerSize = ('bigint'===typeof ptr ? 8 : 4);
target.dealloc(ptr);
}
/**
As of 2025-09-21, this library works with 64-bit WASM modules
built with Emscripten's -sMEMORY64=1.
@@ -996,12 +1004,12 @@ globalThis.WhWasmUtilInstaller = function(target){
target.heap8u().
*/
target.cstrlen = function(ptr){
if(!ptr || !target.isPtr(ptr)) return null;
if(!ptr || !target.isPtr/*64*/(ptr)) return null;
ptr = Number(ptr) /*tag:64bit*/;
const h = heapWrappers().HEAP8U;
let pos = ptr;
for( ; h[pos] !== 0; ++pos ){}
return Number(pos - ptr);
return pos - ptr;
};
/** Internal helper to use in operations which need to distinguish
+365 -96
View File
@@ -32,7 +32,7 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
if(!(config.heap instanceof WebAssembly.Memory)
&& !(config.heap instanceof Function)){
toss("config.heap must be WebAssembly.Memory instance or a function.");
toss("config.heap must be WebAssembly.Memory instance or a function which returns one.");
}
['alloc','dealloc'].forEach(function(k){
(config[k] instanceof Function) ||
@@ -48,14 +48,19 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
memberSuffix = (config.memberSuffix || ""),
BigInt = globalThis['BigInt'],
BigInt64Array = globalThis['BigInt64Array'],
bigIntEnabled = config.bigIntEnabled ?? !!BigInt64Array,
ptrIR = config.pointerIR
|| config.ptrIR/*deprecated*/
|| 'i32',
/* Undocumented (on purpose) config options: */
ptrSize = config.ptrSize/*deprecated*/
|| ('i32'===ptrIR ? 4 : 8)
;
bigIntEnabled = config.bigIntEnabled ?? !!BigInt64Array;
//console.warn("config",config);
let ptr = alloc(1);
const ptrIR = config.pointerIR
|| config.ptrIR/*deprecated*/
|| ('bigint'===typeof ptr ? 'i64' : 'i32');
/* Undocumented (on purpose) config options: */
const ptrSize = config.ptrSize/*deprecated*/
|| ('i32'===ptrIR ? 4 : 8);
dealloc(ptr);
ptr = undefined;
//console.warn("ptrIR =",ptrIR,"ptrSize =",ptrSize);
if(ptrIR!=='i32' && ptrIR!=='i64') toss("Invalid pointer representation:",ptrIR);
if(ptrSize!==4 && ptrSize!==8) toss("Invalid pointer size:",ptrSize);
@@ -136,11 +141,11 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
/** True if SIG s looks like a function signature, else
false. */
const isFuncSig = (s)=>'('===s[1];
/** True if SIG s is-a pointer signature. */
const isPtrSig = (s)=>'p'===s || 'P'===s;
/** True if SIG s is-a pointer-type signature. */
const isPtrSig = (s)=>'p'===s || 'P'===s || 's'===s;
const isAutoPtrSig = (s)=>'P'===s /*EXPERIMENTAL*/;
/** Returns p if SIG s is a function SIG, else returns s[0]. */
const sigLetter = (s)=>isFuncSig(s) ? 'p' : s[0];
const sigLetter = (s)=>s ? (isFuncSig(s) ? 'p' : s[0]) : undefined;
/** Returns the WASM IR form of the Emscripten-conventional letter
at SIG s[0]. Throws for an unknown SIG. */
const sigIR = function(s){
@@ -154,6 +159,19 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
}
toss("Unhandled signature IR:",s);
};
/** Returns the WASM sizeof of the Emscripten-conventional letter
at SIG s[0]. Throws for an unknown SIG. */
const sigSize = function(s){
switch(sigLetter(s)){
case 'c': case 'C': return 1;
case 'i': return 4;
case 'p': case 'P': case 's': return ptrSize;
case 'j': return 8;
case 'f': return 4;
case 'd': return 8;
}
toss("Unhandled signature sizeof:",s);
};
const affirmBigIntArray = BigInt64Array
? ()=>true : ()=>toss('BigInt64Array is not available.');
@@ -232,11 +250,22 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
accessible via boundObject.pointer, which is gated behind a
property interceptor, but are not exposed anywhere else in the
object.
This approach means we cannot proxy arrays, or any type which
might be realloced, as that pointer could change out from under
us. That's not an issue for nested structs, but it might be for a
struct they're embedded in. In the case of nested structs we
"could" record their top-most parent object and their offset into
that object, instead of storing the pointer itself. We could that
by allowing a function instead of a pointer in this map, that
function returning the (lazily-calculated) address. Hmm.
*/
const __instancePointerMap = new WeakMap();
const getInstancePtr = (obj)=>__instancePointerMap.get(obj);
/** Property name for the pointer-is-external marker. */
const xPtrPropName = '(pointer-is-external)';
const xPtrPropName = Symbol('(pointer-is-external)');
const __isPtr32 = (ptr)=>('number'===typeof ptr && (ptr===(ptr|0)) && ptr>=0);
const __isPtr64 = (ptr)=>(
@@ -252,7 +281,7 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
/** Frees the obj.pointer memory and clears the pointer
property. */
const __freeStruct = function(ctor, obj, m){
if(!m) m = __instancePointerMap.get(obj);
if(!m) m = getInstancePtr(obj);
if(m) {
__instancePointerMap.delete(obj);
if(Array.isArray(obj.ondispose)){
@@ -283,7 +312,12 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
ctor.structName,"instance:",
ctor.structInfo.sizeof,"bytes @"+m);
}
if(!obj[xPtrPropName]) dealloc(m);
if(!obj[xPtrPropName]){
if( ctor.structInfo.zeroOnFree ){
heap().fill(0, Number(m), Number(m)+ctor.structInfo.sizeof);
}
dealloc(m);
}
}
};
@@ -324,8 +358,69 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
: null;
};
/** True if sig looks like an emscripten/jaccwabyt
type signature, else false. */
const looksLikeASig = function f(sig){
f.rxSig1 ??= /^[ipPsjfdcC]$/;
f.rxSig2 ??= /^[vipPsjfdcC]\([ipPsjfdcC]*\)$/;
return f.rxSig1.test(sig) || f.rxSig2.test(sig);
};
/** Returns a pair of adaptor maps (objects) in a length-3
array specific to the given object. */
const __adaptorsFor = function(who){
let x = this.get(who);
if( !x ){
x = [ Object.create(null), Object.create(null), Object.create(null) ];
this.set(who, x);
}
return x;
}.bind(new WeakMap);
/** Code de-duplifier for __adaptGet(), __adaptSet(), and
__adaptStruct(). */
const __adaptor = function(who, which, key, proxy){
const a = __adaptorsFor(who)[which];
if(3===arguments.length) return a[key];
if( proxy ) return a[key] = proxy;
return delete a[key];
};
const noopAdapter = (x)=>x;
// StructBinder::adaptGet()
const __adaptGet = function(key, ...args){
/*if( looksLikeASig(key) ){
toss("Getter adaptor's name (",key,") collides with a data type signature.");
}*/
return __adaptor(this, 0, key, ...args);
};
// StructBinder::adaptSet()
const __adaptSet = function(key, ...args){
if( looksLikeASig(key) ){
toss("Setter adaptor's name (",key,") collides with a data type signature.");
}
return __adaptor(this, 1, key, ...args);
};
// StructBinder::adaptStruct()
const __adaptStruct = function(key, ...args){
return __adaptor(this, 2, key, ...args);
};
const __adaptStruct2 = function(who,key){
const si = ('string'===typeof key)
? __adaptor(who, 2, key) : key;
if( 'object'!==typeof si ){
toss("Invalid struct mapping object. Arg =",key,JSON.stringify(si));
}
return si;
};
const __memberKey = (k)=>memberPrefix + k + memberSuffix;
const __memberKeyProp = rop(__memberKey);
//const __adaptGetProp = rop(__adaptGet);
/**
Looks up a struct member in structInfo.members. Throws if found
@@ -342,7 +437,8 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
if(v.key===memberName){ m = v; break; }
}
if(!m && tossIfNotFound){
toss(sPropName(structInfo.name,memberName),'is not a mapped struct member.');
toss(sPropName(structInfo.name || structInfo.structName, memberName),
'is not a mapped struct member.');
}
}
return m;
@@ -361,7 +457,7 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
const __ptrPropDescriptor = {
configurable: false, enumerable: false,
get: function(){return __instancePointerMap.get(this)},
get: function(){return getInstancePtr(this)},
set: ()=>toss("Cannot assign the 'pointer' property of a struct.")
// Reminder: leaving `set` undefined makes assignments
// to the property _silently_ do nothing. Current unit tests
@@ -558,78 +654,176 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
});
/**
Pass this a StructBinder-generated prototype, and the struct
member description object. It will define property accessors for
proto[memberKey] which read from/write to memory in
this.pointer. It modifies descr to make certain downstream
operations much simpler.
If struct description object si has a getter proxy, return it (a
function), else return undefined.
*/
const makeMemberWrapper = function f(ctor,name, descr){
const memberGetterProxy = function(si){
return si.get || (si.adaptGet
? StructBinder.adaptGet(si.adaptGet)
: undefined);
};
/**
If struct description object si has a setter proxy, return it (a
function), else return undefined.
*/
const memberSetterProxy = function(si){
return si.set || (si.adaptSet
? StructBinder.adaptSet(si.adaptSet)
: undefined);
};
/**
To be called by makeMemberWrapper() when si has a 'members'
member, i.e. is an embedded struct. This function sets up that
struct like any other and also sets up property accessor for
ctor.memberKey(name) which returns an instance of that new
StructType when the member is accessed. That instance wraps the
memory of the member's part of the containing C struct instance.
That is, if struct Foo has member bar which is an inner struct
then:
const f = new Foo;
const b = f.bar;
assert( b is-a StructType object );
assert( b.pointer === f.b.pointer );
b will be disposed of when f() is. Calling b.dispose() will not
do any permanent harm, as the wrapper object will be recreated
when accessing f.bar, pointing to the same memory in f.
The si.zeroOnFree flag has no effect on embedded structs because
they wrap "external" memory, so do not own it, and are thus never
freed, as such.
*/
const makeMemberStructWrapper = function callee(ctor, name, si){
/**
Where we store inner-struct member proxies. Keys are a
combination of the parent object's pointer address and the
property's name. The values are StructType instances.
*/
const __innerStructs = (callee.innerStructs ??= new Map());
const key = ctor.memberKey(name);
if( undefined!==si.signature ){
toss("'signature' cannot be used on an embedded struct (",
ctor.structName,".",key,").");
}
if( memberSetterProxy(si) ){
toss("'set' and 'adaptSet' are not permitted for nested struct members.");
}
//console.warn("si =",ctor.structName, name, JSON.stringify(si,' '));
si.structName ??= ctor.structName+'::'+name;
si.key = key;
si.name = name;
si.constructor = this.call(this, si.structName, si);
//console.warn("si.constructor =",si.constructor);
//console.warn("si =",si,"ctor=",ctor);
const getterProxy = memberGetterProxy(si);
const prop = Object.assign(Object.create(null),{
configurable: false,
enumerable: false,
set: __propThrowOnSet(ctor/*not si.constructor*/.structName, key),
get: function(){
const dbg = si.constructor.prototype.debugFlags.__flags;
const p = this.pointer;
const k = p+'.'+key;
let s = __innerStructs.get(k);
if(dbg.getter){ log("debug.getter: k =",k); }
if( !s ){
s = new si.constructor(__ptrAdd(p, si.offset));
__innerStructs.set(k, s);
this.addOnDispose(()=>s.dispose());
s.addOnDispose(()=>__innerStructs.delete(k));
//console.warn("Created",k,"proxy");
}
if(getterProxy) s = getterProxy.apply(this,[s,key]);
if(dbg.getter) log("debug.getter: result =",s);
return s;
}
});
Object.defineProperty(ctor.prototype, key, prop);
}/*makeMemberStructWrapper()*/;
/**
Pass this a StructBinderImpl-generated constructor, a member
property name, and the struct member description object. It will
define property accessors for proto[memberKey] which read
from/write to memory in this.pointer. It modifies si to make
certain downstream operations simpler.
*/
const makeMemberWrapper = function f(ctor, name, si){
si = __adaptStruct2(this, si);
if( si.members ){
return makeMemberStructWrapper.call(this, ctor, name, si);
}
if(!f._){
/*cache all available getters/setters/set-wrappers for
direct reuse in each accessor function. */
/* Cache all available getters/setters/set-wrappers for
direct reuse in each accessor function. */
f._ = {getters: {}, setters: {}, sw:{}};
const a = ['i','c','C','p','P','s','f','d','v()'];
if(bigIntEnabled) a.push('j');
a.forEach(function(v){
//const ir = sigIR(v);
f._.getters[v] = sigDVGetter(v) /* DataView[MethodName] values for GETTERS */;
f._.setters[v] = sigDVSetter(v) /* DataView[MethodName] values for SETTERS */;
f._.sw[v] = sigDVSetWrapper(v) /* BigInt or Number ctor to wrap around values
for conversion */;
});
const rxSig1 = /^[ipPsjfdcC]$/,
rxSig2 = /^[vipPsjfdcC]\([ipPsjfdcC]*\)$/;
f.sigCheck = function(obj, name, key,sig){
if(Object.prototype.hasOwnProperty.call(obj, key)){
toss(obj.structName,'already has a property named',key+'.');
}
rxSig1.test(sig) || rxSig2.test(sig)
looksLikeASig(sig)
|| toss("Malformed signature for",
sPropName(obj.structName,name)+":",sig);
};
}
const key = ctor.memberKey(name);
f.sigCheck(ctor.prototype, name, key, descr.signature);
descr.key = key;
descr.name = name;
const sigGlyph = sigLetter(descr.signature);
f.sigCheck(ctor.prototype, name, key, si.signature);
si.key = key;
si.name = name;
const sigGlyph = sigLetter(si.signature);
const xPropName = sPropName(ctor.prototype.structName,key);
const dbg = ctor.prototype.debugFlags.__flags;
/*
TODO?: set prototype of descr to an object which can set/fetch
TODO?: set prototype of si to an object which can set/fetch
its preferred representation, e.g. conversion to string or mapped
function. Advantage: we can avoid doing that via if/else if/else
in the get/set methods.
*/
const getterProxy = memberGetterProxy(si);
const prop = Object.create(null);
prop.configurable = false;
prop.enumerable = false;
prop.get = function(){
if(dbg.getter){
log("debug.getter:",f._.getters[sigGlyph],"for", sigIR(sigGlyph),
xPropName,'@', this.pointer,'+',descr.offset,'sz',descr.sizeof);
xPropName,'@', this.pointer,'+',si.offset,'sz',si.sizeof);
}
let rc = (
new DataView(heap().buffer, Number(this.pointer) + descr.offset, descr.sizeof)
new DataView(heap().buffer, Number(this.pointer) + si.offset, si.sizeof)
)[f._.getters[sigGlyph]](0, isLittleEndian);
if(getterProxy) rc = getterProxy.apply(this,[rc,key]);
if(dbg.getter) log("debug.getter:",xPropName,"result =",rc);
return rc;
};
if(descr.readOnly){
if(si.readOnly){
prop.set = __propThrowOnSet(ctor.prototype.structName,key);
}else{
const setterProxy = memberSetterProxy(si);
prop.set = function(v){
if(dbg.setter){
log("debug.setter:",f._.setters[sigGlyph],"for", sigIR(sigGlyph),
xPropName,'@', this.pointer,'+',descr.offset,'sz',descr.sizeof, v);
xPropName,'@', this.pointer,'+',si.offset,'sz',si.sizeof, v);
}
if(!this.pointer){
toss("Cannot set struct property on disposed instance.");
toss("Cannot set native property on a disposed struct instance.");
}
if(null===v) v = __NullPtr;
else while(!__isPtr(v)){
if(isAutoPtrSig(descr.signature) && (v instanceof StructType)){
if( setterProxy ) v = setterProxy.apply(this,[v]);
if( null===v || undefined===v ) v = __NullPtr;
else while( isPtrSig(si.signature) && !__isPtr(v) ){
if(isAutoPtrSig(si.signature) && (v instanceof StructType)){
// It's a struct instance: let's store its pointer value!
v = v.pointer || __NullPtr;
if(dbg.setter) log("debug.setter:",xPropName,"resolved to",v);
@@ -638,66 +832,45 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
toss("Invalid value for pointer-type",xPropName+'.');
}
(
new DataView(heap().buffer, Number(this.pointer) + descr.offset,
descr.sizeof)
new DataView(heap().buffer, Number(this.pointer) + si.offset,
si.sizeof)
)[f._.setters[sigGlyph]](0, f._.sw[sigGlyph](v), isLittleEndian);
};
}
Object.defineProperty(ctor.prototype, key, prop);
}/*makeMemberWrapper*/;
}/*makeMemberWrapper()*/;
/**
The main factory function which will be returned to the
caller.
caller. The third argument is structly for internal use.
This level of indirection is to avoid that clients can pass a
third argument to this, as that's only for internal use.
internalOpt options:
- None right now. This is for potential use in recursion.
Usages:
StructBinder(string, obj [,optObj]);
StructBinder(obj);
*/
const StructBinder = function StructBinder(structName, structInfo){
if(1===arguments.length){
structInfo = structName;
structName = structInfo.name;
}else if(!structInfo.name){
structInfo.name = structName;
}
if(!structName) toss("Struct name is required.");
let lastMember = false;
Object.keys(structInfo.members).forEach((k)=>{
// Sanity checks of sizeof/offset info...
const m = structInfo.members[k];
if(!m.sizeof) toss(structName,"member",k,"is missing sizeof.");
else if(m.sizeof===1){
(m.signature === 'c' || m.signature === 'C') ||
toss("Unexpected sizeof==1 member",
sPropName(structInfo.name,k),
"with signature",m.signature);
}else{
// sizes and offsets of size-1 members may be odd values, but
// others may not.
if(0!==(m.sizeof%4)){
console.warn("Invalid struct member description =",m,"from",structInfo);
toss(structName,"member",k,"sizeof is not aligned. sizeof="+m.sizeof);
}
if(0!==(m.offset%4)){
console.warn("Invalid struct member description =",m,"from",structInfo);
toss(structName,"member",k,"offset is not aligned. offset="+m.offset);
}
}
if(!lastMember || lastMember.offset < m.offset) lastMember = m;
});
if(!lastMember) toss("No member property descriptions found.");
else if(structInfo.sizeof < lastMember.offset+lastMember.sizeof){
toss("Invalid struct config:",structName,
"max member offset ("+lastMember.offset+") ",
"extends past end of struct (sizeof="+structInfo.sizeof+").");
}
const debugFlags = rop(SBF.__makeDebugFlags(StructBinder.debugFlags));
/** Constructor for the StructCtor. */
const zeroAsPtr = __asPtrType(0);
const StructBinderImpl = function StructBinderImpl(
structName, si, opt = Object.create(null)
){
/**
StructCtor is the eventual return value of this function. We
need to populate this early on so that we can do some trickery
in feeding it through recursion.
*/
const StructCtor = function StructCtor(externalMemory){
externalMemory = __asPtrType(externalMemory);
//console.warn("externalMemory",externalMemory,arguments[0]);
if(!(this instanceof StructCtor)){
toss("The",structName,"constructor may only be called via 'new'.");
}else if(arguments.length){
if(Number.isNaN(externalMemory) || externalMemory<=zeroAsPtr){
if( !__isPtr(externalMemory) ){
toss("Invalid pointer value",arguments[0],"for",structName,"constructor.");
}
__allocStruct(StructCtor, this, externalMemory);
@@ -705,31 +878,127 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
__allocStruct(StructCtor, this);
}
};
const self = this;
/**
"Convert" struct description x to a struct description, if
needed.
*/
const ads = (x)=>{
//console.warn("looksLikeASig(",x,") =",looksLikeASig(x));
return (('string'===typeof x) && looksLikeASig(x))
? {signature: x} : __adaptStruct2(self,x);
};
if(1===arguments.length){
si = ads(structName);
structName = si.structName || si.name;
}else if(2===arguments.length){
si = ads(si);
si.name ??= structName;
}else{
si = ads(si);
}
structName ??= si.structName;
//console.warn("arguments =",JSON.stringify(arguments));
structName ??= opt.structName;
if( !structName ) toss("One of 'name' or 'structName' are required.");
if( si.adapt ){
Object.keys(si.adapt.struct||{}).forEach((k)=>{
__adaptStruct.call(StructBinderImpl, k, si.adapt.struct[k]);
});
Object.keys(si.adapt.set||{}).forEach((k)=>{
__adaptSet.call(StructBinderImpl, k, si.adapt.set[k]);
});
Object.keys(si.adapt.get||{}).forEach((k)=>{
__adaptGet.call(StructBinderImpl, k, si.adapt.get[k]);
});
}
if(!si.members && !si.sizeof){
si.sizeof = sigSize(si.signature);
}
const debugFlags = rop(SBF.__makeDebugFlags(StructBinder.debugFlags));
Object.defineProperties(StructCtor,{
debugFlags: debugFlags,
isA: rop((v)=>v instanceof StructCtor),
memberKey: __memberKeyProp,
memberKeys: __structMemberKeys,
methodInfoForKey: rop(function(mKey){
}),
structInfo: rop(structInfo),
//methodInfoForKey: rop(function(mKey){/*???*/}),
structInfo: rop(si),
structName: rop(structName)
});
StructCtor.prototype = new StructType(structName, structInfo, rop);
StructCtor.prototype = new StructType(structName, si, rop);
Object.defineProperties(StructCtor.prototype,{
debugFlags: debugFlags,
constructor: rop(StructCtor)
/*if we assign StructCtor.prototype and don't do
this then StructCtor!==instance.constructor!*/
this then StructCtor!==instance.constructor*/
});
Object.keys(structInfo.members).forEach(
(name)=>makeMemberWrapper(StructCtor, name, structInfo.members[name])
);
let lastMember = false;
let offset = 0;
//console.warn(structName,"si =",si);
si.offset ??= 0;
Object.keys(si.members || {}).forEach((k)=>{
// Sanity checks of sizeof/offset info...
let m = ads(si.members[k]);
if(!m.members && !m.sizeof){
/* ^^^^ fixme: we need to recursively collect all sizeofs
before updating that. */
m.sizeof = sigSize(m.signature);
if(!m.sizeof){
toss(sPropName(structName,k), "is missing a sizeof property.",m);
}
}
if( undefined===m.offset ){
m.offset = offset;
}
si.members[k] = m;
if(!lastMember || lastMember.offset < m.offset) lastMember = m;
makeMemberWrapper.call(self, StructCtor, k, m)
offset += m.sizeof;
//console.warn("offset",sPropName(structName,k),offset);
});
if( !lastMember ) toss("No member property descriptions found.");
if( !si.sizeof ) si.sizeof = offset;
if(si.sizeof===1){
(si.signature === 'c' || si.signature === 'C') ||
toss("Unexpected sizeof==1 member",
sPropName(structName,k),
"with signature",si.signature);
}else{
// sizes and offsets of size-1 members may be odd values, but
// others may not.
if(0!==(si.sizeof%4)){
console.warn("Invalid struct member description",si);
toss(structName,"sizeof is not aligned. sizeof="+si.sizeof);
}
if(0!==(si.offset%4)){
console.warn("Invalid struct member description",si);
toss(structName,"offset is not aligned. offset="+si.offset);
}
}
if( si.sizeof < offset ){
console.warn("Suspect struct description:",si,"offset =",offset);
toss("Mismatch in the calculated vs. the provided sizeof/offset info.",
"Expected sizeof",offset,"but got",si.sizeof,"for",si);
}
return StructCtor;
}/*StructBinderImpl*/;
const StructBinder = function StructBinder(structName, structInfo){
return (1==arguments.length)
? StructBinderImpl.call(StructBinder, structName)
: StructBinderImpl.call(StructBinder, structName, structInfo);
};
StructBinder.StructType = StructType;
StructBinder.config = config;
StructBinder.allocCString = __allocCString;
StructBinder.adaptGet = __adaptGet;
StructBinder.adaptSet = __adaptSet;
StructBinder.adaptStruct = __adaptStruct;
if(!StructBinder.debugFlags){
StructBinder.debugFlags = SBF.__makeDebugFlags(SBF.debugFlags);
}
+4 -1
View File
@@ -98,6 +98,7 @@ tgtFiles=(
tester1.js
tester1.mjs
)
tgtFiles+=(jswasm/sqlite3-node.mjs); # https://github.com/sqlite/sqlite-wasm/issues/118
if [[ 1 = $b64 ]]; then
tgtFiles+=(
@@ -148,6 +149,7 @@ fJ1=(
sqlite3-worker1-promiser.mjs
sqlite3-worker1-promiser-bundler-friendly.mjs
)
fJ1+=(sqlite3-node.mjs); # https://github.com/sqlite/sqlite-wasm/issues/118
fJ2=(
sqlite3.js
sqlite3.mjs
@@ -193,8 +195,9 @@ done
#
# Done copying files. Now zip it up...
#
svi=${dirTop}/version-info
svi=./version-info
vnum=$($svi --download-version)
[ "" = "$vnum" ] && die "version number is empty!"
vdir=${buildName}-${vnum}
fzip=${vdir}.zip
rm -fr ${vdir} ${fzip}
+22 -9
View File
@@ -371,7 +371,7 @@ const BuildDefs oBuildDefs = {
.node = {
.zEmo = "🍟",
.zBaseName = "sqlite3-node",
.zDotWasm = 0,
.zDotWasm = "sqlite3",
.zCmppD = "-Dtarget:node $(c-pp.D.bundler)",
.zEmcc = 0,
.zEmccExtra = 0,
@@ -382,21 +382,21 @@ const BuildDefs oBuildDefs = {
** node. */,
.zDeps = 0,
.zIfCond = 0,
.flags = CP_ALL | F_UNSUPPORTED | F_NODEJS
.flags = CP_ALL | F_UNSUPPORTED | F_ESM | F_NODEJS
},
/* 64-bit node. */
.node64 = {
.zEmo = "🍔",
.zBaseName = "sqlite3-node-64bit",
.zDotWasm = 0,
.zDotWasm = "sqlite3-64it",
.zCmppD = "-Dtarget:node $(c-pp.D.bundler)",
.zEmcc = 0,
.zEmccExtra = 0,
.zEnv = "node",
.zDeps = 0,
.zIfCond = 0,
.flags = CP_ALL | F_UNSUPPORTED | F_NODEJS | F_64BIT
.flags = CP_ALL | F_UNSUPPORTED | F_ESM | F_NODEJS | F_64BIT
},
/* Entirely unsupported. */
@@ -444,6 +444,11 @@ static void mk_prologue(void){
ps("endif");
}
ps("define label.unsupported-build\n"
"$(emo.fire)$(emo.fire)$(emo.fire)Unsupported build:"
" use at your own risk!\n"
"endef");
ps(zBanner
/** $1 = build name */
"b.call.wasm-strip = "
@@ -624,7 +629,8 @@ static void mk_pre_post(char const *zBuildName, BuildDef const * pB){
** Module.instantiateWasm() to use that file instead of
** the default.
*/
pf("$(pre-js.%s.js): $(pre-js.in.js) $(MAKEFILE_LIST)", zBuildName);
pf("$(pre-js.%s.js): $(pre-js.in.js) $(bin.c-pp) $(MAKEFILE_LIST)",
zBuildName);
if( pB->zDotWasm ){
pf(" $(dir.dout)/%s.wasm" /* This .wasm is from some other
build, so this may trigger a full
@@ -658,7 +664,7 @@ static void mk_pre_post(char const *zBuildName, BuildDef const * pB){
"))\n",
zBuildName, zBuildName, zBuildName, zBuildName);
pf("$(post-js.%s.js): $(post-js.%s.in)\n",
pf("$(post-js.%s.js): $(post-js.%s.in) $(bin.c-pp)\n",
zBuildName, zBuildName);
ps("\n# --extern-post-js=...");
@@ -778,6 +784,9 @@ static void mk_lib_mode(const char *zBuildName, const BuildDef * pB){
if( pB->flags & F_64BIT ){
pf("c-pp.D.%s += $(c-pp.D.64bit)\n", zBuildName);
}
if( pB->flags & F_UNSUPPORTED ){
pf("c-pp.D.%s += -Dunsupported-build\n", zBuildName);
}
pf("emcc.environment.%s ?= %s\n", zBuildName,
pB->zEnv ? pB->zEnv : oBuildDefs.vanilla.zEnv);
@@ -803,8 +812,8 @@ static void mk_lib_mode(const char *zBuildName, const BuildDef * pB){
emit_compile_start(zBuildName);
if( F_UNSUPPORTED & pB->flags ){
pf("\t@echo '$(logtag.%s) $(emo.fire)$(emo.fire)$(emo.fire): "
"unsupported build. Use at your own risk.'\n", zBuildName);
pf("\t@echo '$(logtag.%s) $(label.unsupported-build)'\n",
zBuildName);
}
/* emcc ... */
@@ -900,7 +909,11 @@ static void mk_lib_mode(const char *zBuildName, const BuildDef * pB){
}
}
pf("\t@$(call b.echo,%s,$(emo.done) done!)\n", zBuildName);
pf("\t@$(call b.echo,%s,$(emo.done) done!%s)\n",
zBuildName,
(F_UNSUPPORTED & pB->flags)
? " $(label.unsupported-build)"
: "");
pf("\n%dbit: $(out.%s.js)\n"
"$(out.%s.wasm): $(out.%s.js)\n"
+13 -5
View File
@@ -12,11 +12,19 @@
</head>
<body>
<h1 id='color-target'>sqlite3 tester #1: Worker thread (@bitness@-bit WASM)</h1>
<div>Variants:
<a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
<a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
<a href='tester1-esm.html' target='tester1-esm.html'>ESM in UI thread</a>,
<a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>ESM worker</a>
<div>Variants (32-bit):
conventional UI thread:
(<a href='tester1.html' target='tester1.html'>32-bit</a>,
<a href='tester1-64bit.html' target='tester1-64bit.html'>64-bit</a>),
conventional worker:
(<a href='tester1-worker.html' target='tester1-worker.html'>32-bit</a>,
<a href='tester1-worker-64bit.html' target='tester1-worker-64bit.html'>64-bit</a>),
ESM in UI thread:
(<a href='tester1-esm.html' target='tester1-esm.html'>32-bit</a>,
<a href='tester1-esm-64bit.html' target='tester1-esm-64bit.html'>64-bit</a>),
ESM worker:</a>
(<a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>32-bit</a>
<a href='tester1-worker-64bit.html?esm' target='tester1-worker-64bit.html?esm'>64-bit</a>)
</div>
<div class='input-wrapper'>
<input type='checkbox' id='cb-log-reverse'>
+13 -5
View File
@@ -11,11 +11,19 @@
<style></style>
</head>
<body><h1 id='color-target'></h1>
<div>Variants:
<a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
<a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
<a href='tester1-esm.html' target='tester1-esm.html'>ESM in UI thread</a>,
<a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>ESM worker</a>
<div>Variants (32-bit):
conventional UI thread:
(<a href='tester1.html' target='tester1.html'>32-bit</a>,
<a href='tester1-64bit.html' target='tester1-64bit.html'>64-bit</a>),
conventional worker:
(<a href='tester1-worker.html' target='tester1-worker.html'>32-bit</a>,
<a href='tester1-worker-64bit.html' target='tester1-worker-64bit.html'>64-bit</a>),
ESM in UI thread:
(<a href='tester1-esm.html' target='tester1-esm.html'>32-bit</a>,
<a href='tester1-esm-64bit.html' target='tester1-esm-64bit.html'>64-bit</a>),
ESM worker:</a>
(<a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>32-bit</a>
<a href='tester1-worker-64bit.html?esm' target='tester1-worker-64bit.html?esm'>64-bit</a>)
</div>
<div class='input-wrapper'>
<input type='checkbox' id='cb-log-reverse'>
+181 -104
View File
@@ -369,6 +369,88 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
clearOnInit: true,
initialCapacity: 6
};
//#if enable-see
/**
Code consolidator for SEE sanity checks for various VFSes. ctor
is the VFS's oo1.DB-type constructor. ctorOptFunc(bool) is a
function which must return a constructor args object for ctor. It
is passed true if the db needs to be cleaned up/unlinked before
opening it (OPFS) and false if not (how that is done is
VFS-dependent). dbUnlink is a function which is expected to
unlink() the db file if the ctorOpfFunc does not do so when
passed true (kvvfs).
This function initializes the db described by ctorOptFunc(...),
writes some secret info into it, and re-opens it twice to
confirmi that it can be read with an SEE key and cannot be read
without one.
*/
T.seeBaseCheck = function(ctor, ctorOptFunc, dbUnlink){
let initDb = true;
const tryKey = function(keyKey, key, expectCount){
let db;
//console.debug('tryKey()',arguments);
try {
if (initDb) {
const ctoropt = ctorOptFunc(initDb);
initDb = false;
db = new ctor({
...ctoropt,
[keyKey]: key
});
db.exec([
"drop table if exists t;",
"create table t(a);"
]);
db.close();
db = null;
// Ensure that it's actually encrypted...
let err;
try {
db = new ctor(ctorOptFunc(false));
T.assert(db, 'db opened') /* opening is fine, but... */;
db.exec("select 1 from sqlite_schema");
console.warn("(should not be reached) sessionStorage =", sessionStorage);
} catch (e) {
err = e;
} finally {
db.close()
db = null;
}
T.assert(err, "Expecting an exception")
.assert(capi.SQLITE_NOTADB == err.resultCode,
"Expecting NOTADB");
}/*initDb*/
db = new ctor({
...ctorOptFunc(false),
[keyKey]: key
});
db.exec("insert into t(a) values (1),(2)");
T.assert(expectCount === db.selectValue('select sum(a) from t'));
} finally {
if (db) db.close();
}
};
const hexFoo = new Uint8Array([0x66,0x6f,0x6f]/*=="foo"*/);
dbUnlink();
tryKey('textkey', 'foo', 3);
T.assert( !initDb );
tryKey('textkey', 'foo', 6);
dbUnlink();
initDb = true;
tryKey('key', 'foo', 3);
T.assert( !initDb );
tryKey('key', hexFoo, 6);
dbUnlink();
initDb = true;
tryKey('hexkey', hexFoo, 3);
T.assert( !initDb );
tryKey('hexkey', hexFoo, 6);
dbUnlink();
},
//#endif enable-see
////////////////////////////////////////////////////////////////////////
// End of infrastructure setup. Now define the tests...
////////////////////////////////////////////////////////////////////////
@@ -945,7 +1027,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
let ptr = k1.pointer;
k1.dispose();
T.assert(undefined === k1.pointer).
mustThrowMatching(()=>{k1.$pP=1}, /disposed instance/);
mustThrowMatching(()=>{k1.$pP=1}, /disposed struct instance/);
}finally{
k1.dispose();
k2.dispose();
@@ -1549,6 +1631,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(blob instanceof Uint8Array).
assert(0x68===blob[0] && 0x69===blob[1]);
blob = null;
blob = db.selectValue("select ?1", new Uint8Array([97,0,98,0,99]),
sqlite3.capi.SQLITE_TEXT);
T.assert("a\0b\0c"===blob, "Something is amiss with embedded NULs");
let counter = 0, colNames = [];
list.length = 0;
db.exec(new TextEncoder('utf-8').encode("SELECT a a, b b FROM t"),{
@@ -2836,71 +2921,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
predicate: ()=>(isUIThread()
|| "Only available in main thread."),
test: function(sqlite3){
this.kvvfsUnlink();
let initDb = true;
const tryKey = function(keyKey, key, expectCount){
let db;
//console.debug('tryKey()',arguments);
const ctoropt = {
filename: this.kvvfsDbFile
//vfs: 'kvvfs'
//,flags: 'ct'
};
try {
if (initDb) {
initDb = false;
db = new this.JDb({
...ctoropt,
[keyKey]: key
});
db.exec([
"drop table if exists t;",
"create table t(a);"
]);
db.close();
// Ensure that it's actually encrypted...
let err;
try {
db = new this.JDb(ctoropt);
T.assert(db, 'db opened') /* opening is fine, but... */;
db.exec("select 1 from sqlite_schema");
console.warn("(should not be reached) sessionStorage =", sessionStorage);
} catch (e) {
err = e;
} finally {
db.close()
}
T.assert(err, "Expecting an exception")
.assert(sqlite3.capi.SQLITE_NOTADB == err.resultCode,
"Expecting NOTADB");
}/*initDb*/
//console.debug('tryKey()',arguments);
db = new sqlite3.oo1.DB({
...ctoropt,
vfs: 'kvvfs',
[keyKey]: key
});
db.exec("insert into t(a) values (1),(2)");
T.assert(expectCount === db.selectValue('select sum(a) from t'));
} finally {
if (db) db.close();
}
}.bind(this);
const hexFoo = new Uint8Array([0x66,0x6f,0x6f]/*=="foo"*/);
tryKey('textkey', 'foo', 3);
T.assert( !initDb );
tryKey('textkey', 'foo', 6);
this.kvvfsUnlink();
initDb = true;
tryKey('key', 'foo', 3);
T.assert( !initDb );
tryKey('key', hexFoo, 6);
this.kvvfsUnlink();
initDb = true;
tryKey('hexkey', hexFoo, 3);
T.assert( !initDb );
tryKey('hexkey', hexFoo, 6);
this.kvvfsUnlink();
T.seeBaseCheck(sqlite3.oo1.JsStorageDb, (isInit)=>{
return {filename: "session"};
}, ()=>this.kvvfsUnlink());
}
})/*kvvfs with SEE*/
//#endif enable-see
@@ -3311,6 +3334,21 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
"entryExists(",testDir,") should have failed");
}
}/*OPFS util sanity checks*/)
//#if enable-see
.t({
name: 'OPFS with SEE encryption',
test: function(sqlite3){
T.seeBaseCheck(
sqlite3.oo1.OpfsDb,
function(isInit){
const opt = {filename: 'file:///sqlite3-see.edb'};
if( isInit ) opt.filename += '?delete-before-open=1';
return opt;
},
()=>{});
}
})/*OPFS with SEE*/
//#endif enable-see
;/* end OPFS tests */
////////////////////////////////////////////////////////////////////////
@@ -3492,7 +3530,36 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(true === await u3.removeVfs())
.assert(false === await P3b.removeVfs());
}
}/*OPFS SAH Pool sanity checks*/);
}/*OPFS SAH Pool sanity checks*/)
//#if enable-see
.t({
name: 'OPFS SAHPool with SEE encryption',
test: async function(sqlite3){
const inst = sqlite3.installOpfsSAHPoolVfs,
catcher = (e)=>{
error("Cannot load SAH pool VFS.",
"This might not be a problem,",
"depending on the environment.");
return false;
};
const poolConfig = {
name: 'opfs-sahpool-see',
clearOnInit: true,
initialCapacity: 6
}
let poolUtil;
const P1 = await inst(poolConfig).then(u=>poolUtil = u).catch(catcher);
const dbFile = '/sqlite3-see.edb';
T.seeBaseCheck(
poolUtil.OpfsSAHPoolDb,
(isInit)=>{return {filename: dbFile}},
()=>poolUtil.unlink(dbFile)
);
poolUtil.removeVfs();
}
})/*opfs-sahpool with SEE*/
//#endif enable-see
;
////////////////////////////////////////////////////////////////////////
T.g('Misc. APIs')
@@ -3556,44 +3623,54 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.t("Misc. stmt_...", function(sqlite3){
const db = new sqlite3.oo1.DB();
db.exec("create table t(a doggiebiscuits); insert into t(a) values(123)");
const stmt = db.prepare("select a, a+1 from t");
T.assert( stmt.isReadOnly() )
.assert( 0===capi.sqlite3_stmt_isexplain(stmt) )
.assert( 0===capi.sqlite3_stmt_explain(stmt, 1) )
.assert( 0!==capi.sqlite3_stmt_isexplain(stmt) )
.assert( 0===capi.sqlite3_stmt_explain(stmt, 2) )
.assert( 0!==capi.sqlite3_stmt_isexplain(stmt) )
.assert( 0===capi.sqlite3_stmt_explain(stmt, 0) )
.assert( 0===capi.sqlite3_stmt_isexplain(stmt) );
let n = 0;
while( capi.SQLITE_ROW === capi.sqlite3_step(stmt) ){
++n;
T.assert( 0!==capi.sqlite3_stmt_explain(stmt, 1),
"Because stmt is busy" )
.assert( capi.sqlite3_stmt_busy(stmt) )
.assert( stmt.isBusy() )
.assert( 0!==capi.sqlite3_stmt_readonly(stmt) )
.assert( true===stmt.isReadOnly() );
const sv = capi.sqlite3_column_value(stmt, 0);
T.assert( 123===capi.sqlite3_value_int(sv) )
.assert( "doggiebiscuits"===capi.sqlite3_column_decltype(stmt,0) )
.assert( null===capi.sqlite3_column_decltype(stmt,1) );
let stmt;
try{
stmt = db.prepare("select a, a+1 from t");
T.assert( stmt.isReadOnly() )
.assert( 0===capi.sqlite3_stmt_isexplain(stmt) )
.assert( 0===capi.sqlite3_stmt_explain(stmt, 1) )
.assert( 0!==capi.sqlite3_stmt_isexplain(stmt) )
.assert( 0===capi.sqlite3_stmt_explain(stmt, 2) )
.assert( 0!==capi.sqlite3_stmt_isexplain(stmt) )
.assert( 0===capi.sqlite3_stmt_explain(stmt, 0) )
.assert( 0===capi.sqlite3_stmt_isexplain(stmt) );
let n = 0;
while( capi.SQLITE_ROW === capi.sqlite3_step(stmt) ){
++n;
T.assert( 0!==capi.sqlite3_stmt_explain(stmt, 1),
"Because stmt is busy" )
.assert( capi.sqlite3_stmt_busy(stmt) )
.assert( stmt.isBusy() )
.assert( 0!==capi.sqlite3_stmt_readonly(stmt) )
.assert( true===stmt.isReadOnly() );
const sv = capi.sqlite3_column_value(stmt, 0);
T.assert( 123===capi.sqlite3_value_int(sv) )
.assert( "doggiebiscuits"===capi.sqlite3_column_decltype(stmt,0) )
.assert( null===capi.sqlite3_column_decltype(stmt,1) );
}
T.assert( 1===n )
.assert( 0===capi.sqlite3_stmt_busy(stmt) )
.assert( !stmt.isBusy() );
if( wasm.exports.sqlite3_column_origin_name ){
log("Column metadata APIs enabled");
T.assert( "t" === capi.sqlite3_column_table_name(stmt, 0))
.assert("a" === capi.sqlite3_column_origin_name(stmt, 0))
.assert("main" === capi.sqlite3_column_database_name(stmt, 0))
}else{
log("Column metadata APIs not enabled");
} // column metadata APIs
stmt.finalize();
stmt = null;
stmt = db.prepare("select ?1").bind(new Uint8Array([97,0,98,0,99]));
stmt.step();
const sv = capi.sqlite3_column_value(stmt,0);
T.assert("a\0b\0c"===capi.sqlite3_value_text(sv),
"Expecting NULs to have survived.");
}finally{
if(stmt) stmt.finalize();
db.close();
}
T.assert( 1===n )
.assert( 0===capi.sqlite3_stmt_busy(stmt) )
.assert( !stmt.isBusy() );
if( wasm.exports.sqlite3_column_origin_name ){
log("Column metadata APIs enabled");
T.assert( "t" === capi.sqlite3_column_table_name(stmt, 0))
.assert("a" === capi.sqlite3_column_origin_name(stmt, 0))
.assert("main" === capi.sqlite3_column_database_name(stmt, 0))
}else{
log("Column metadata APIs not enabled");
} // column metadata APIs
stmt.finalize();
db.close();
})
////////////////////////////////////////////////////////////////////
-24
View File
@@ -952,25 +952,6 @@ FUZZDATA = \
#
TESTOPTS = --verbose=file --output=test-out.txt
#
# Extra compiler options for various shell tools
#
# Note that some of these will only apply when embedding sqlite3.c
# into the shell, as these flags are not otherwise passed on to the
# library.
SHELL_OPT += -DSQLITE_DQS=0
SHELL_OPT += -DSQLITE_ENABLE_FTS4
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_RTREE
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_ENABLE_PERCENTILE
SHELL_OPT += -DSQLITE_STRICT_SUBTYPE=1
FUZZERSHELL_OPT =
FUZZCHECK_OPT += -I$(TOP)/test
FUZZCHECK_OPT += -I$(TOP)/ext/recover
@@ -2154,11 +2135,6 @@ threadtest5: sqlite3.c $(TOP)/test/threadtest5.c
$(T.link) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(LDFLAGS.libsqlite3)
xbin: threadtest5
resfmt-test: sqlite3.o $(TOP)/ext/misc/resfmt-tester.c $(TOP)/ext/misc/resfmt.c $(TOP)/ext/misc/resfmt.h
$(T.link) -I$(TOP)/ext/misc -I. \
$(TOP)/ext/misc/resfmt-tester.c $(TOP)/ext/misc/resfmt.c sqlite3.o \
-o $@ $(LDFLAGS.libsqlite3)
#
# STATIC_CLI_SHELL = 1 to statically link sqlite3$(T.exe), else
# 0. Requires static versions of all requisite libraries. Primarily
+87 -92
View File
@@ -1,13 +1,13 @@
C Fix\sa\sva_list\smisuse.
D 2025-10-22T12:38:39.500
C Re-add\sthe\s(still)\sunsupported\sand\s(still\s100%)\suntested\ssqlite3-node.mjs\sback\sto\sthe\sdist\sbundle,\sas\sits\sremoval\sin\s3.51\shas\s[caused\ssome\sdownstream\sdisruption](https://github.com/sqlite/sqlite-wasm/issues/118).\sThis\sis\sstashed\sin\sa\sbranch\sfor\snow\sand\smay\snever\sbe\smerged\s-\swe're\sstill\snegotiating\sthe\sterms\sof\sits\sre-addition\sand\smy\seventual\scapitulation.
D 2025-11-13T08:36:52.956
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
F Makefile.in 3ce07126d7e87c7464301482e161fdae6a51d0a2aa06b200b8f0000ef4d6163b
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 8dd676302f3165984c046f81af14b6676a334418fa30255efaf439f8033042fa
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
F Makefile.msc 523bab2f6569e912a0aaf2d13e0b3f9bcb36d52310b236d950b354068c9de3f3
F README.md dae499194b75deed76a13a4a83c82493f2530331882d7dfe5754d63287d3f8f7
F VERSION 16eddb43056a79c1977427ab7a05f3457c373fa159dcdced8754eb89ce7e06b8
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
@@ -18,11 +18,11 @@ F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821
F auto.def 44a0d1bf09d78355fc88251ccbf8e64e6341fd89c11de68a01c3645e53a2bade
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.in 306f500fce8cae9e1af9459f1ac7fe89ce46999594ef3fdc62dc9d7d651fb091
F autoconf/Makefile.msc 05b345da3a512c6c387d0e78d812deb0a42748962c115a6eac781c160a95d7cc
F autoconf/Makefile.msc 803aa9e23b6a764751f6a91d0673620eefa46729fb80faf51391120e1d752966
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
F autoconf/README.txt b749816b8452b3af994dc6d607394bef3df1736d7e09359f1087de8439a52807
F autoconf/auto.def 3d994f3a9cc9b712dbce92a5708570ddcf3b988141b6eb738f2ed16127a9f0ac
F autoconf/tea/Makefile.in bf6b43eafcd18766d81a8f0085cfc9cb051d8abae9031a8e7c3f5f1246e8f166
F autoconf/tea/Makefile.in 00e60cf3bf5580f31bfdcf3c914e9ba1831d676948363962de92ce65e5be4431
F autoconf/tea/README.txt 23475876343498ef2b514cc7510e8f1559a17e8e03fbc7a41c1c8a3b89e7b7e3
F autoconf/tea/_teaish.tester.tcl.in 8253b44be88e2e3f21de95a65d3a90c2be8e70b7bdd08a5b80e337ba7402f8f1
F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079db417529
@@ -46,18 +46,18 @@ F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e
F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
F autosetup/jimsh0.c a57c16e65dcffc9c76e496757cb3f7fb47e01ecbd1631a0a5e01751fc856f049
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
F autosetup/proj.tcl ec30c4bc301b6e9eb937655744a7315f863f804fc66400d975bcf9352ac96a1d
F autosetup/sqlite-config.tcl b530d62d05972c61933b6fc02658be0612ca667048bf64929f7a91ca8ecad2a5
F autosetup/proj.tcl 6fc14ef82b19b77a95788ffbcfad7989b4e3cb4ce96a21dcb5cf7312f362fba9
F autosetup/sqlite-config.tcl 1fd7c55394051fbfba2fb9fa9192c027ee7d74612dbf772b06e27feb9f1de5df
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl aee092fc71986d1272b835ea7492bb55ffc213a289502e4f14da80cf67b7e3c3
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
F autosetup/teaish/feature.tcl 18194fb79a24d30e5bbdeab40999616f39278b53a27525349ded033af2fd73be
F autosetup/teaish/tester.tcl 1799514c2652db49561b3386c5242b94534d1663f2cfac861a955e071895fdd0
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
F contrib/sqlitecon.tcl eb4c6578e08dd353263958da0dc620f8400b869a50d06e271ab0be85a51a08d3
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/compile-for-unix.md c9dce1ddd4bf0d25efccc5c63eb047e78c01ce06a6ff29c73e0a8af4a0f4adbc
F doc/compile-for-windows.md 5141661e783c9ca9e3fd30e813345898712f5c311d71316f183db87038fa28a6
F doc/compile-for-windows.md f9e74d74da88f384edd5809f825035e071608f00f7f39c0e448df7b3982f979c
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/jsonb.md acd77fc3a709f51242655ad7803510c886aa8304202fa9cf2abc5f5c4e9d7ae5
F doc/lemon.html 89ea833a6f71773ab1a9063fbb7fb9b32147bc0b1057b53ecab94a3b30c0aef5
@@ -284,14 +284,14 @@ F ext/intck/intck_common.tcl a61fd2697ae55b0a3d89847ca0b590c6e0d8ff64bebb70920d9
F ext/intck/intckbusy.test d5ed4ef85a4b1dc1dee2484bd14a4bb68529659cca743327df0c775f005fa387
F ext/intck/intckcorrupt.test f6c302792326fb3db9dcfc70b554c55369bc4b52882eaaf039cfe0b74c821029
F ext/intck/intckfault.test cff3f75dff74abb3edfcb13f6aa53f6436746ab64b09fe5e2028f051e985efab
F ext/intck/sqlite3intck.c 0d10df36e2b7b438aa80ecd3f5e584d41b747586b038258fe6b407f66b81e7c5
F ext/intck/sqlite3intck.c b1c8a86f90fc00741d13314db9c58f7e2f92d1d19c5ad1c6904ec83a6bbd5c96
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
F ext/intck/test_intck.c 4f9eaadaedccb9df1d26ba41116a0a8e5b0c5556dc3098c8ff68633adcccdea8
F ext/jni/GNUmakefile 8a94e3a1953b88cf117fb2a5380480feada8b4f5316f02572cab425030a720b4
F ext/jni/README.md e3fbd47c774683539b7fdc95a667eb9cd6e64d8510f3ee327e7fa0c61c8aa787
F ext/jni/README.md 1479c83dbe26125264a060ee6873531795a7082dbc0d43c4067683371331559f
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c 3d84a0176af779737ae977ba1c90d2ffe2537b8299c5d9f6552620493f12ac4b
F ext/jni/src/c/sqlite3-jni.h ac180ba9b21978727006c790d3006a95a2402a4c3ec7a0def92707ed89b79945
F ext/jni/src/c/sqlite3-jni.h df43024cced914c49485633d0f90168689e70577b3b17b0ecbdaf16e4a417bff
F ext/jni/src/org/sqlite/jni/annotation/Experimental.java 8603498634e41d0f7c70f661f64e05df64376562ea8f126829fd1e0cdd47e82b
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java be6cc3e8e114485822331630097cc0f816377e8503af2fc02f9305ff2b353917
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 56e3dee1f3f703a545dfdeddc1c3d64d1581172b1ad01ffcae95c18547fafd90
@@ -301,7 +301,7 @@ F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0e28a0df51368c7127e505f
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
F ext/jni/src/org/sqlite/jni/capi/CApi.java 3d275f5f4fbdbe4fff15f4d42cf5ff559f9a4897e7373fa99f3b1dc9cf7f849c
F ext/jni/src/org/sqlite/jni/capi/CApi.java a9701cbe736b8bef5bc72ae465be0250e137f67bdb5a3ab62497972b6f51572d
F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 1b3baf5b772f266e8baf8f35f0ddc5bd87fc8c4927ec69115c46fd6fba6701c3
F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab
@@ -346,7 +346,7 @@ F ext/jni/src/org/sqlite/jni/test-script-interpreter.md d7987b432870d23f7c72a780
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java d5c108b02afd3c63c9e5e53f71f85273c1bfdc461ae526e0a0bb2b25e4df6483
F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 326ffba29aab836a6ea189703c3d7fb573305fd93da2d14b0f9e9dcf314c8290
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java e920f7a031e04975579240d4a07ac5e4a9d0f8de31b0aa7a4be753c98ae596c9
F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java c82bc00c1988f86246a89f721d3c41f0d952f33f934aa6677ec87f7ca42519a0
F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java ce8aef867e06a21685658eb0173768c355e9e1e2dfdc75f382643fa62c7ee779
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 982538ddb4c0719ef87dfa664cd137b09890b546029a7477810bd64d4c47ee35
F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java 08f92d52be2cec28a7b4555479cc54b7ebeeb94985256144eeb727154ec3f85b
F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java a84e90c43724a69c2ecebd601bc8e5139f869b7d08cb705c77ef757dacdd0593
@@ -355,7 +355,7 @@ F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
F ext/misc/amatch.c 2db45b1499b275d8340af6337a13d6216e4ceb2ddb41f4042b9801be7b5e593d
F ext/misc/amatch.c 0e0124c1e03ee4cb99b25969f6b7b39c53a847b8bf12279efbcb896b0df1059a
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c 8dc0a08cee11722822858a62625f1b63e5d5f1adac1cf4492d5732b571e37aa0
@@ -372,7 +372,7 @@ F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a0
F ext/misc/decimal.c d4883de142f6dcd36eda23da40b55e2b51374e7b01eb54a7173940191389fc5e
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
F ext/misc/fileio.c 88cb2e5744296de6638af02ef6349fd468c2eb5e5f41ba405f88d9b4ad500f8e
F ext/misc/fileio.c 61af623160c073b605b4ff1f67d278c4c348956efa08f6201756577c7a050d17
F ext/misc/fossildelta.c 2fc2dd4f34f478df674887db62586b1071c4cd3c9e73ee40f9ee669670e482d1
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c 176c061c94857b543313959289cb60cf777c999fd002f82b53d194b95e9f347a
@@ -381,18 +381,14 @@ F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2
F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58f34edd
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
F ext/misc/normalize.c 4782be3b74b9bd9f67281036ff1f41e5edcad20ad486171a2d671c4bb2586011
F ext/misc/normalize.c fbb144a861809686ff2b5b6eee8bb2e1207f9bf13ce7376e5273c700a1eafbd5
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
F ext/misc/percentile.c 72e05a21db20a2fa85264b99515941f00ae698824c9db82d7edfbb16cea8ec80
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
F ext/misc/regexp.c 548151f3e57506fda678e6a65e85a763f4eece653287e1ad44e167f9485e0c6b
F ext/misc/regexp.c f1f7cfe90fc027b33d2b5ae7d6235eecce69c3aca71c9afce56fec62342c8b44
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/resfmt-tester.c 3188324e10f945429fd684c1d1a468a1bde43e1379af60f0d34c5411a04b0edc
F ext/misc/resfmt.c fc9c8b26b4fb8958fb3fba85f0368a373fb2d1aaf707d57769f6eff791800b1c
F ext/misc/resfmt.h ebb635f87324499a1487cdad812f64ab9f98a1b09accf0ba45fea0e274e2bd3b
F ext/misc/resfmt.md 6f6cefd95fa11ce30e4f34ea84052e7a8291dd48b7e666352bd7cf2e22c22ec4
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F ext/misc/series.c 22c6d8f00cc1b5089b1b37392e9097e9df9a5db53be86daf9a7669d95bb179f4
@@ -414,7 +410,7 @@ 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 9f7e02e9e8de585f3bfb48405db36c2eb4b680a23a67d7a4b738dd20f6ad7aec
F ext/misc/vtablog.c 2d04386c2f5a3bb93bc9ae978f0b7dcd5a264e126abd640dd6d82aa9067cbd48
F ext/misc/vtshim.c e5bce24ab8c532f4fdc600148718fe1802cb6ed57417f1c1032d8961f72b0e8f
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
@@ -497,7 +493,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 86967c5a501f895b9705366b8cd9c37f15a9ebdff770ceb719c7deeeb2c22b72
F ext/rtree/rtree.c 95401e6812a399b5ef2e5de1249ab7e2844601cb4153ca2c3f14122ff3625569
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -579,8 +575,7 @@ F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009e
F ext/session/sqlite3session.c b3de195ce668cace9b324599bf6255a70290cbfb5451e826e946f3aee6e64c54
F ext/session/sqlite3session.h 7404723606074fcb2afdc6b72c206072cdb2b7d8ba097ca1559174a80bc26f7a
F ext/session/test_session.c 8766b5973a6323934cb51248f621c3dc87ad2a98f023c3cc280d79e7d78d36fb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile be5cbc4733403459589daf2e0784653c23e7ca8353e78398ef223565d63aa68b
F ext/wasm/GNUmakefile 74c73254fb44c82d517a8907da9866d5d3ef1a533addaeb4322f470e0fb81ba3
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -588,20 +583,17 @@ F ext/wasm/SQLTester/SQLTester.mjs 6b3c52ed36a5573ca4883176f326332a8d4c0cecf5efd
F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0
F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core ef34398a903d0a2425fbbfbd4ed2cd596daea55b8515e2617c8dc7ad7c0767dd
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras 9eae68943ce91ab145892b31370819c2103525240eb72e0fce53c498b8d8275a
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md f4c0d67caaee21a77b8938c30b5f79667bfc9d0c95d01b51df77ea35ee773884
F ext/wasm/api/extern-post-js.c-pp.js 205f55aacfc62c580985db5c790300779de3876a76a5c7e1bfb13e71c8b4506b
F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp d609c22bc05e25991bdd2eeed4497485a3756446158b2794471426e5e3517056
F ext/wasm/api/README.md df476398c6d80affae807a8208c5a97d1615786e1d6767b5292bfe67edb59b18
F ext/wasm/api/extern-post-js.c-pp.js 4b310c9891886e7c1ea4e2419966ff45dfeda825b897fdaa4119332509f7e3d1
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/post-js-footer.js 5bd7170b5e8ce7b62102702bbcf47ef7b3b49cd56ed40c043fd990aa715b74ee
F ext/wasm/api/post-js-header.js 79d078aec33d93b640a19c574b504d88bb2446432f38e2fbb3bb8e36da436e70
F ext/wasm/api/pre-js.c-pp.js a876c6399dff29b6fe9e434036beb89889164cc872334e184291723ecc7cb072
F ext/wasm/api/sqlite3-api-cleanup.js a3d6b9e449aefbb8bba283c2ba9477e2333a0eeb94a7a26b5bf952736f65a6dd
F ext/wasm/api/sqlite3-api-glue.c-pp.js d2b8263b3ce0cefc6c5a68d0a4d448a9770eda4bf9d9ded9d7eb0198e4ce4da1
F ext/wasm/api/pre-js.c-pp.js b1a7a09d14df1f36de11e801ba06cb92c0ddeb520e5b2f28836af0ec8146e288
F ext/wasm/api/sqlite3-api-cleanup.js 79b54a566291e17c0c3e165c6c4969c48ec17cd297755180151af65ac616dfa0
F ext/wasm/api/sqlite3-api-glue.c-pp.js 79a54b54ca6324d28e31e19b56bbaebb7d2cc4b3079066e7e901333fa5047c53
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 31dbfd470c91ffd96d77399b749bab6b69e3ba9074188833f97ac13f087cf07b
F ext/wasm/api/sqlite3-api-prologue.js b5a55ae74efcdcd0aa6a143d59e34137e43ae732f02b563dcab22d735f1599a4
F ext/wasm/api/sqlite3-api-prologue.js b6b2fd1720c484e168705909862442b4524a1e61e16b4549a5725dd28c3cecc2
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1041dd645e8e821c082b628cd8d9acf70c667430f9d45167569633ffc7567938
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
@@ -609,14 +601,14 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 26cb41d5a62f46a106b6371eb00fef02de3cdbfaa51338ba087a45f53028e0d0
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 418c33fe284739564daab3c7a7a88882fdd3c99137497900f98eddec1e409af5
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86
F ext/wasm/api/sqlite3-wasm.c dd7fc1d535281f0d5d2732bb1b662d1d403a762f07b63c2ea5663053377b2804
F ext/wasm/api/sqlite3-wasm.c 2d1cbe498f7b0fb64b11451eda481f458df74d6258baea635513e637fcbb8b1a
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bda1c75bd674a92a0e27cc2f3d46dbbf21e422413f8046814515a0bd7409328a
F ext/wasm/api/sqlite3-worker1.c-pp.js 802d69ead8c38dc1be52c83afbfc77e757da8a91a2e159e7ed3ecda8b8dba2e7
F ext/wasm/c-pp-lite.c b2098c8abb8d42f061a53c6857fbc1863298dc8a2d9eb5f114fca67c36f39a68
F ext/wasm/c-pp-lite.c 67e86d9ea47cf3e70a4067acd92788f4f8e6271fae02a68490b069303d7597be
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
F ext/wasm/common/whwasmutil.js 0d539324097fc83b953e9844267359ba0fd02286caa784ea2f597ced279ea640
F ext/wasm/common/whwasmutil.js b4fd73fac162406e67f276647ff8bae51881e15eebdf4b725aeb2b10ab1e056a
F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
@@ -633,10 +625,10 @@ F ext/wasm/fiddle/fiddle.js 84fd75967e0af8b69d3dd849818342227d0f81d13db92e0dcbc6
F ext/wasm/fiddle/index.html a27b8127ef9ecf19612da93b2a6a73bdb3777b5c56b5450bb7200a94bc108ff9
F ext/wasm/index-dist.html db23748044e286773f2768eec287669501703b5d5f72755e8db73607dc54d290
F ext/wasm/index.html 54e27db740695ab2cb296e02d42c4c66b3f11b65797340d19fa6590f5b287da1
F ext/wasm/jaccwabyt/jaccwabyt.js bbac67bc7a79dca34afe6215fd16b27768d84e22273507206f888c117e2ede7d
F ext/wasm/jaccwabyt/jaccwabyt.js 1e734c624205cdf621f322972dfb0fc8013d573a5882f57492a6830e5ec23e17
F ext/wasm/jaccwabyt/jaccwabyt.md 167fc0b624c9bc2c477846e336de9403842d81b1a24fc4d3b24317cb9eba734f
F ext/wasm/mkdist.sh 29f8a37a7aba41fa5df8e89b1fab02b83b35c43473c5cf808584872e022514b8 x
F ext/wasm/mkwasmbuilds.c 0216fd7273314b9e433ca17d7692cce844a362b31a192e44d31fc13cdb27ad8c
F ext/wasm/mkdist.sh f774603c758e87fb115ceae192670aa10eeece9474ce2147671156d2e665b871 x
F ext/wasm/mkwasmbuilds.c 8f945702c48aa55d8f3a801bde70f1a2c7a8364f38defc1e026bd0628280aee8
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
@@ -650,9 +642,9 @@ F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d826
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.c-pp.html 883881eeac14eeeecc8ff22acf9fe0f18a97cacb48be08ebb0bae891ceded584
F ext/wasm/tester1.c-pp.html 949920126dcf477925d8d540093d9cc374d3ab4c4ddee920c1dcadcf37917306
F ext/wasm/tester1.c-pp.js 614cac06524ec2202027c7f6cc5e94d91482b0eb6aa969f252517047596e404e
F ext/wasm/tester1-worker.c-pp.html 0e432ec2c0d99cd470484337066e8d27e7aee4641d97115338f7d962bf7b081a
F ext/wasm/tester1.c-pp.html 52d88fe2c6f21a046030a36410b4839b632f4424028197a45a3d5669ea724ddb
F ext/wasm/tester1.c-pp.js 2c255093205a0dac9dae7475030665c2c9d6dccc857de68ee7daf49aa82e6de8
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -662,12 +654,12 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk bf63775585a99e8e7158c4d67c30aeeae45b84572c474f9d41c7bba927788f46
F main.mk 29078d11f7545a8fae4347305b164bb4e777b801da16baeb48214014a8d63a06
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
F mptest/mptest.c aa41ace6dbc5050d76b02548d3521e6bbccae4f0
F mptest/mptest.c 7ecf39040c1187d9cbc487409bc052f194e93c165f667c55b052690a741d9d71
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
@@ -679,31 +671,31 @@ F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c cb5b8ceb9baa02a63a2f83dec09c4153e1cfbdf9c2adef5c62c26d2160eeb067
F src/btree.c 0ad524883ec4ccac3221c97bdc2c5d5f6e149504e14cf269bbed31362c3f4393
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 611e07299d72ff04bbcb9e7109183467e30925d203c3e121ef9bb3cf6876289b
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
F src/carray.c a6f26cb349ca700d706c0e76d5b2895d76e2a1c392a2b909cf543a0dd4d4d047
F src/callback.c afa59adfaa483f668260ce69f740c8273dee3e6fee9106846e0499ebdd1ac076
F src/carray.c ff6081a31878fc34df8fa1052a9cbf17ddc22652544dcb3e2326886ed1053b55
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
F src/expr.c 4d63c8f6d50fe20637de8bdaf57757a0e424e4ac5e2c3313e621d64727a48a1c
F src/expr.c 17b0cbe08e004c1653030f5de9b6b050e84feaa112239f7f576af2dc5e53a5fb
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c 4d945b54a0e931f7454dd9e07d34fd297531355730ec91cb3c06d28a96c7e938
F src/func.c 0b802107498048d3dcac0b757720bcb8506507ce02159e213ab8161458eb293b
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/hash.c dff10fa89d4a8280b764df9599b29342ea98cba2b868dccb5dfb3c419841a3f0
F src/hash.h c5f4a02aaf1dca835a68b51c8b906af265c6ca3d8d53d255e0453f0abce561be
F src/hwtime.h d4d1b98c1afdc56986a5c0eba882786ef017e2180a320da25b4231b8e7e463e8
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/json.c fb031340edee159c07ad37dbe668ffe945ed86f525b0eb3822e4a67cbc498a72
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c a3bc9a2522dc3b960e38b7582d1818f6245a49289387c2c7b19f27bfeabf1e81
F src/main.c ce69a2650e3d359ed6a8a2867ccafb27ac62ce1d39f3120a84ff513320952a6c
F src/main.c eaf5215917b7e8b34ddea013524287f6d5021ba0fc70202e7602e225ef0d16bf
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -724,10 +716,10 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c fb7ba8d6204197357f1eb7e1c7450d09c10043bf7e99aba602f4aa46b8fb11a3
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
F src/os_unix.c b3da55bc4bb214b2bfb1e430b10e9d3ebcf6b11741921ab044c9b9539c8fcc4f
F src/os_win.c f81a7cffdfe8c593a840895b3f64290714f0186b06302d2c397012252d830374
F src/os_unix.c 7945ede1e85b2d1b910e1b4af9ba342e964b1e30e79f4176480a60736445cb36
F src/os_win.c a89b501fc195085c7d6c9eec7f5bd782625e94bb2a96b000f4d009703df1083f
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
F src/pager.c 113f9149092ccff6cf90e97c2611200e5a237f13d26c394bc9fd933377852764
F src/pager.c a81461de271ac4886ad75b7ca2cca8157a48635820c4646cd2714acdc2c17e5f
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y 619c3e92a54686c5e47923688c4b9bf7ec534a4690db5677acc28b299c403250
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
@@ -737,20 +729,20 @@ F src/pragma.c ecec75795c1821520266e4f93fa8840cce48979af532db06f085e36a7813860f
F src/prepare.c 2af0b5c1ec787c8eebd21baa9d79caf4a4dc3a18e76ce2edbf2027d706bca37a
F src/printf.c 7297c2aeed4d90d80c5ba82920d9e57b7bfad04b3466be1d7e042db382fe296e
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c f8d1d011aba0964ff1bdccd049d4d2c2fec217efd90d202a4bb775e926b2c25d
F src/resolve.c 5616fbcf3b833c7c705b24371828215ad0925d0c0073216c4f153348d5753f0a
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c b95181711d59c36d9789e67f76c4cfec64b99f9629a50be5e6566e117b87d957
F src/shell.c.in d8f5c8aeec7beff61b42ea13bfab96076809bd356a4f694983222ee5fcf6a244
F src/sqlite.h.in 10faecc456d3962c7cedae70d69305f7c80129f28dd8524bd8a06b3eac955e54
F src/select.c ba9cd07ffa3277883c1986085f6ddc4320f4d35d5f212ab58df79a7ecc1a576a
F src/shell.c.in ceb0a9cc008ac82d8d2e6ef353db14a54bc40dfd60a8cfbb6bc98d071f538761
F src/sqlite.h.in 684c19c3b093cca7a38e3f6405d067777464285f17a58a78f7f89d6763e011e7
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 7f236ca1b175ffe03316d974ef57df79b3938466c28d2f95caef5e08c57f3a52
F src/sqliteInt.h e16df0914718acba6fb7e5f03055f7cf519d0d61314c78ec2f5c9f6a45608d86
F src/sqliteInt.h 88f7fc9ce1630d9a5f7e0a8e1f3287cdc63882fba985c18e7eee1b9f457f59aa
F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 3c604c49e6cf4211960a9ddb9505280fd22cde32175f40884c641c0f5a286036
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
F src/test1.c f880ab766eeedf2c063662bd9538b923fd42c4341b7bfc2150a6d93ab8b9341c
F src/test1.c d27c91455865fb191eb1b2c892e7586c5e3d9d3977f54913c8e70e2e8e5148b3
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -798,7 +790,7 @@ F src/test_vfs.c b4135c1308516adf0dfd494e6d6c33114e03732be899eace0502919b674586b
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 8400646d2830afc2f2dc465a75e3a92e4bedeea623f19dbd79c0c12d0dd6dda2
F src/tokenize.c cb3294cf23c11106b50d9af6998a6c1bf389b52e15b17698c9fab97bbaa9b37f
F src/treeview.c 3ce7ac9835d2d70cc1c868b01b747ae8a062322e155701e58e3d62ca79aada7a
F src/trigger.c d5cf2541ff048f30b6a0507eb3d1ec4e695c53584e3b2298a5bf248714fe185e
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
@@ -806,19 +798,19 @@ F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
F src/vdbe.c 92cc9c523cfe11ce117b3bfd8b33846cdb8084bfe3268ba567c95389da6404c8
F src/vdbe.c b44c366e83412d3b8c190feb1f029b7d02e1bd69252a57b32f195107f0d03964
F src/vdbe.h be33bd7b17f2ec92939642416030491508c51071f6c14e27cd195983fec56b63
F src/vdbeInt.h 52896dd4d5b62190c53db14b09fc2484434eb594c963df0fa66eb8a94527b02e
F src/vdbeapi.c 869a0da5d855495055f4d35c6ada582f64ce995ce14b26ff9d336274d497266c
F src/vdbeaux.c cb907297d03b374544a5a4f81ca981497ff4d09d13838f06de507118367f0b73
F src/vdbeInt.h 2aaeb6df2938b181b4700a9328688a3986f2bba71e8b96f6a80671316618fa49
F src/vdbeapi.c 6a2181cfd27c86b4cc1d8abb27ae11f3b3f0357567814fa276ec37b043542938
F src/vdbeaux.c 908d8a191aed444b2e4c920159249127f3ff67b94c56a16fad1dfdf9c7488f20
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
F src/vdbemem.c e67d9c6484d868c879d20c70d00bf4a9058082f1d4058607ca15d50eb3aebc21
F src/vdbemem.c 48e562ff27e6386eb8613207ac27d3d98c1f67fdc4775a1ab13759d2c2a1c021
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
F src/wal.c a278339ecf5f194fd71fff1f0da1368de50e3a32edc3e9944e1ee1f4610476ff
F src/wal.c 505a98fbc599a971d92cb90371cf54546c404cd61e04fd093e7b0c8ff978f9b6
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 7d17cd5cb883b2166097957e20c4aab2d0d98e0c1141002ef77b5f6b9deed844
@@ -1043,7 +1035,7 @@ F test/dblwidth-a.sql eb4141518610e52f931a55a984310075e98dc31eee5a28ae806b1e3537
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test 28dffdc7c7b700c04fdf4f237e7e46eef4b0ead28879434358d161e45f5fc875
F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52
F test/decimal.test a11b87a2c3294eb4c11b55f3168aeac63d683fa8ada35921a6ec1d511eff7648
F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
@@ -1067,7 +1059,7 @@ F test/e_createtable.test 31b9bcb6ac8876bc7ec342d86d9c231a84c62b442093a6651dfd0f
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
F test/e_expr.test 57a50ffd09c274b066883a59272efaf32a955c73af9f176d1c8889f0125bd2db
F test/e_expr.test 0a1e175caddc78b27306647cb4ce2362c55790190f8cdd178b75fd6262eb8f76
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
@@ -1100,7 +1092,7 @@ F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/existsexpr.test 9c4b77c4729281cc2ae63b9b460d0598ce28cc7876135e3e2c21629bbc8d077a
F test/existsexpr2.test dc23e76389eff3d29f6488ff733012a3560cd67ec8cfaecbecd52cced5d5af11
F test/existsfault.test ff41c11f3052c1bbd4f8dd557802310026253d67d7c4e3a180c16d2f0862973e
F test/expr.test 4ada8eb822c45ef27a36851a258004d43c1e95e7c82585a1217e732084e4482c
F test/expr.test db981f8a85520e99ae20aab7ad2e9b5b0437ed09159b57ced434c672075d2e61
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
F test/exprfault.test da33606d799718e2f8e34efd0e5858884a1ad87f608774c552a7f5517cc27181
F test/exprfault2.test c49e84273898969af5dbc4fe6a3f4335f14639799f343590336c9ddf84425965
@@ -1336,7 +1328,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 fd76024ff104baec16417db5cafc0894ad4e0863e70803e63c1bba0322706339
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
F test/joinI.test fc7d24a2b1e444979b83bd92c30ebb975cebb5b9eae4442ce94969bd8d083053
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
@@ -1433,7 +1425,7 @@ F test/misc5.test 02fcaf4d42405be02ec975e946270a50b0282dac98c78303ade0d1392839d2
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test d595599972ec0b436985f0f02f243b68500ffc977b9b3194ec66c0866cfddcab
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
F test/misuse.test 46d42ffdf375833ea5828796e56f84660344f7548659b493059f152f00e66840
F test/misuse.test 859f37014d9824ca66bd90c36372c08c80c51c9593a7cfa8a31d4f92cd4d5b7f
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
F test/mmap2.test dba452dc7db91e9df10f70bdd73dc4190c7b8ee7b5133b4684f04277ada0b9ac
@@ -1530,7 +1522,7 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2
F test/reservebytes.test 6163640b5a5120c0dee6591481e673a0fa0bf0d12d4da7513bad692c1a49a162
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test 212cd4111bb941a60abf608f20250db666c21eb1bc4d49217e96c87ff3ab9d1a
F test/returning1.test cd32517148948859db214dd814354597dd40e7489259590fac1a4f7bf44deb97
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
F test/rollback.test 952c4d805bca96adc2be76f621ea22115fe40b330015af36fcc8028c8547fcee
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
@@ -1604,10 +1596,10 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 396c04132628fe1c627fd4807a93a116f712cfb1cfe9ca5d553b1c89361a899f
F test/shell1.test ebe953d64c937ad42a0f33170ac0d2d2568faae26813fc7a95203756446d54aa
F test/shell2.test ab23f01ea2347e4b72bb2399af7ee82aa00f9c059141749f7c4064abca5ad728
F test/shell3.test 603b448e917537cf77be0f265c05c6f63bc677c63a533c8e96aae923b56f4a0e
F test/shell4.test ad7eee983b5e7f1dd92d8c87bc0f39474086bc32c980c00f3934c54aabc636a2
F test/shell4.test 03593fa7908a55f255916ffeda707cdf55680c777736e3da62b1d78cde0d684d
F test/shell5.test d17e7927ab8b7f720efbdd9b5d05fceb6c3c56c25917901b315400214bf24ef4
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
@@ -1648,7 +1640,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 405411356fbc54af15987b7ffeec330a49138f71584220fb8fe1948b2f7ac907 x
F test/speedtest.tcl 6b66974d833d35a63d0e9ec344e0ffa92fbbfac83e173556f700a61cb3be96fc x
F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce85721
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
@@ -1697,7 +1689,7 @@ F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 463ae33b8bf75ac77451df19bd65e7c415c2e9891227c7c9e657d0a2d8e1074a
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
F test/testrunner.tcl 9da764507f6bc752961555c0beb58eb6584b9fb0f989342c7eaab3336380f560 x
F test/testrunner.tcl 86179a8e78997e9257cb8f738c5624cb23897da5297855578ba74715e64f1602 x
F test/testrunner_data.tcl c507a9afa911c03446ed90442ffd4a98aca02882c3d51bd1177c24795674def8
F test/testrunner_estwork.tcl 7927a84327259a32854926f68a75292e33a61e7e052fdbfcb01f18696c99c724
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
@@ -2005,7 +1997,7 @@ F test/walsetlk_recover.test adccbffc59e365063a4efd2da6b661ae2fcf15d775b6719fe46
F test/walsetlk_snapshot.test 86d5588380f9927d8fcbbd75133b0a34fddf959378d6823c6f164a390123f70a
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9aa23
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
F test/walthread.test d562f51a61191ccfab64940df7aa1cef87c902fa5ab742590ef7f859dfe6a44b
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
F test/where.test 5087c72d26fd075a1644c8512be9fe18de9bf2d2b0754f7fd9b74a1c6540c4fc
F test/where2.test 52237a8cb27ebbf6583469429bb5733d1b94ac37d09c3dbd0f487952ed0ab3f8
@@ -2113,7 +2105,7 @@ F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c
F tool/lemon.c 8f6c122e5727cb0e5f302b8efc91489b1947a8d98206d7a1b1cfc0ed685b6e7c
F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/loadfts.c 63412f9790e5e8538fbde0b4f6db154aaaf80f7a10a01e3c94d14b773a8dd5a6
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
@@ -2149,7 +2141,7 @@ F tool/showdb.c 3956d71e5193162609a60e8c9edfcf09274c00cfea2b1d221261427adb2b5cca
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
F tool/showstat4.c b706fcbc4cd1a6e4a73ac32549afc4b460479d650402d64b23e8d813516e8de4
F tool/showwal.c 11eca547980a066b081f512636151233350ac679f29ecf4ebfce7f4530230b3d
F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdaddf
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
@@ -2173,10 +2165,13 @@ F tool/vdbe-compress.tcl fa2f37ab39b2a0087fafb6a7f3ce19503e25e624ffa8ed9951717ab
F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e
F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6ddf2700c
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 82dc13ec4887f90995bd984ede9c2670fb7512962ccceb1848a7e9aab7891c00
R fa18e75fe233d98f1fe33dfd9aa9b399
P 42f95ea71e5e7e927685de3a6da2ede38abe7cabdd1fc71b9a14bebe9f54a65e
R 6ccca5a4124b16122b6a766379fbe805
T *branch * sqlite3-node.mjs
T *sym-sqlite3-node.mjs *
T -sym-trunk * Cancelled\sby\sbranch.
U stephan
Z 380e5356f88927c6576fb8a521f933af
Z 351cb48117de9374caee3897f1c40064
# Remove this line to create a well-formed Fossil manifest.
+2 -2
View File
@@ -1,2 +1,2 @@
branch resfmt
tag resfmt
branch sqlite3-node.mjs
tag sqlite3-node.mjs
+1 -1
View File
@@ -1 +1 @@
3d044121768548df59a94bbbe4ee360d6464d1416a5cbe7437f4333b06496381
8611cf643b11335cd490da1856c34b4f10ac8b82856e0857be1192e36da31f17
+4
View File
@@ -1037,6 +1037,10 @@ static void runScript(
for(k=(int)strlen(zFilename)-1; k>=0 && !isDirSep(zFilename[k]); k--){}
if( k>0 ){
zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile);
if( zNewFile==0 ){
fprintf(stderr, "out of memory\n");
abort();
}
}
}
zNewScript = readFile(zNewFile);
+1 -1
View File
@@ -9758,7 +9758,7 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
}while( rc==SQLITE_OK && nOut>0 );
if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){
Pgno pgnoNew;
Pgno pgnoNew = 0; /* Prevent harmless static-analyzer warning */
MemPage *pNew = 0;
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
put4byte(pPgnoOut, pgnoNew);
+10 -2
View File
@@ -504,8 +504,16 @@ void sqlite3SchemaClear(void *p){
temp2 = pSchema->trigHash;
sqlite3HashInit(&pSchema->trigHash);
sqlite3HashClear(&pSchema->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
for(pElem=sqliteHashFirst(&temp2); pElem; ){
HashElem *pNext = sqliteHashNext(pElem);
Trigger *pTrig = (Trigger*)sqliteHashData(pElem);
if( pTrig->bReturning ){
/* Do not remove RETURNING triggers from the temp-triggers hash */
sqlite3HashTransfer(&pSchema->trigHash, &temp2, pElem);
}else{
sqlite3DeleteTrigger(&xdb, pTrig);
}
pElem = pNext;
}
sqlite3HashClear(&temp2);
sqlite3HashInit(&pSchema->tblHash);
+7 -6
View File
@@ -66,8 +66,9 @@
/*
** Names of allowed datatypes
*/
static const char *azType[] = { "int32", "int64", "double", "char*",
"struct iovec" };
static const char *azCarrayType[] = {
"int32", "int64", "double", "char*", "struct iovec"
};
/*
** Structure used to hold the sqlite3_carray_bind() information
@@ -186,7 +187,7 @@ static int carrayColumn(
case CARRAY_COLUMN_POINTER: return SQLITE_OK;
case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break;
case CARRAY_COLUMN_CTYPE: {
sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC);
sqlite3_result_text(ctx, azCarrayType[pCur->eType], -1, SQLITE_STATIC);
return SQLITE_OK;
}
default: {
@@ -274,10 +275,10 @@ static int carrayFilter(
}else{
unsigned char i;
const char *zType = (const char*)sqlite3_value_text(argv[2]);
for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
if( sqlite3_stricmp(zType, azType[i])==0 ) break;
for(i=0; i<sizeof(azCarrayType)/sizeof(azCarrayType[0]); i++){
if( sqlite3_stricmp(zType, azCarrayType[i])==0 ) break;
}
if( i>=sizeof(azType)/sizeof(azType[0]) ){
if( i>=sizeof(azCarrayType)/sizeof(azCarrayType[0]) ){
pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
"unknown datatype: %Q", zType);
return SQLITE_ERROR;
+1 -1
View File
@@ -4844,7 +4844,7 @@ static SQLITE_NOINLINE int exprCodeTargetAndOr(
pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
if( pAlt!=pExpr ){
r1 = sqlite3ExprCodeTarget(pParse, pAlt, target);
sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, target);
sqlite3VdbeAddOp3(v, OP_And, r1, r1, target);
return target;
}
skipOp = op==TK_AND ? OP_IfNot : OP_If;
+54 -1
View File
@@ -485,7 +485,7 @@ static void *contextMalloc(sqlite3_context *context, i64 nByte){
sqlite3 *db = sqlite3_context_db_handle(context);
assert( nByte>0 );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
testcase( nByte==(i64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
z = 0;
@@ -3083,6 +3083,56 @@ static void percentValue(sqlite3_context *pCtx){
/****** End of percentile family of functions ******/
#endif /* SQLITE_ENABLE_PERCENTILE */
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
/*
** Implementation of sqlite_filestat(SCHEMA).
**
** Return JSON text that describes low-level debug/diagnostic information
** about the sqlite3_file object associated with SCHEMA.
*/
static void filestatFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zDbName;
sqlite3_str *pStr;
Btree *pBtree;
zDbName = (const char*)sqlite3_value_text(argv[0]);
pBtree = sqlite3DbNameToBtree(db, zDbName);
if( pBtree ){
Pager *pPager;
sqlite3_file *fd;
int rc;
sqlite3BtreeEnter(pBtree);
pPager = sqlite3BtreePager(pBtree);
assert( pPager!=0 );
fd = sqlite3PagerFile(pPager);
pStr = sqlite3_str_new(db);
if( pStr==0 ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_str_append(pStr, "{\"db\":", 6);
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
if( rc ) sqlite3_str_append(pStr, "null", 4);
fd = sqlite3PagerJrnlFile(pPager);
if( fd && fd->pMethods!=0 ){
sqlite3_str_appendall(pStr, ",\"journal\":");
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
if( rc ) sqlite3_str_append(pStr, "null", 4);
}
sqlite3_str_append(pStr, "}", 1);
sqlite3_result_text(context, sqlite3_str_finish(pStr), -1,
sqlite3_free);
}
sqlite3BtreeLeave(pBtree);
}else{
sqlite3_result_text(context, "{}", 2, SQLITE_STATIC);
}
}
#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
#ifdef SQLITE_DEBUG
/*
@@ -3241,6 +3291,9 @@ void sqlite3RegisterBuiltinFunctions(void){
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ),
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
FUNCTION(sqlite_filestat, 1, 0, 0, filestatFunc ),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+23
View File
@@ -270,3 +270,26 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem);
return 0;
}
/*
** Parameter pElem is currently part of hash table pFrom. Add it to hash
** table pTo.
**
** This procedure corrupts hash table pFrom. Specifically, it removes element
** pElem from the list of all elements in the hash table, but may leave
** a pointer to it in one of the hash buckets of pFrom. This is not a problem
** because this function is only called if hash table pFrom will be cleared
** before any further lookups or inserts are attempted.
*/
void sqlite3HashTransfer(Hash *pTo, Hash *pFrom, HashElem *pElem){
if( pElem->prev ){
pElem->prev->next = pElem->next;
}else{
assert( pFrom->first==pElem );
pFrom->first = pElem->next;
}
pTo->count++;
insertElement(pTo, pTo->ht ? &pTo->ht[pElem->h % pTo->htsize] : 0, pElem);
}
+1
View File
@@ -70,6 +70,7 @@ void sqlite3HashInit(Hash*);
void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
void *sqlite3HashFind(const Hash*, const char *pKey);
void sqlite3HashClear(Hash*);
void sqlite3HashTransfer(Hash*, Hash*, HashElem *pElem);
/*
** Macros for looping over all elements of a hash table. The idiom is
+19 -21
View File
@@ -16,17 +16,18 @@
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
/*
** The following routine only works on Pentium-class (or newer) processors.
** It uses the RDTSC opcode to read the cycle count value out of the
** processor and returns that value. This can be used for high-res
** profiling.
*/
#if !defined(__STRICT_ANSI__) && \
(defined(__GNUC__) || defined(_MSC_VER)) && \
(defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(_MSC_VER) && defined(_WIN32)
#if defined(__GNUC__)
#include <profileapi.h>
__inline sqlite3_uint64 sqlite3Hwtime(void){
LARGE_INTEGER tm;
QueryPerformanceCounter(&tm);
return (sqlite3_uint64)tm.QuadPart;
}
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \
(defined(i386) || defined(__i386__) || defined(_M_IX86))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned int lo, hi;
@@ -34,17 +35,6 @@
return (sqlite_uint64)hi << 32 | lo;
}
#elif defined(_MSC_VER)
__declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
__asm {
rdtsc
ret ; return value at EDX:EAX
}
}
#endif
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -52,6 +42,14 @@
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (sqlite_uint64)hi << 32 | lo;
}
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__aarch64__)
__inline__ sqlite_uint64 sqlite3Hwtime(void){
sqlite3_uint64 cnt;
__asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (cnt));
return cnt;
}
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
+11 -1
View File
@@ -1394,6 +1394,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
/* Clear the TEMP schema separately and last */
if( db->aDb[1].pSchema ){
sqlite3SchemaClear(db->aDb[1].pSchema);
assert( db->aDb[1].pSchema->trigHash.count==0 );
}
sqlite3VtabUnlockList(db);
@@ -2525,6 +2526,9 @@ void *sqlite3_wal_hook(
sqlite3_mutex_leave(db->mutex);
return pRet;
#else
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(xCallback);
UNUSED_PARAMETER(pArg);
return 0;
#endif
}
@@ -2540,6 +2544,11 @@ int sqlite3_wal_checkpoint_v2(
int *pnCkpt /* OUT: Total number of frames checkpointed */
){
#ifdef SQLITE_OMIT_WAL
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(zDb);
UNUSED_PARAMETER(eMode);
UNUSED_PARAMETER(pnLog);
UNUSED_PARAMETER(pnCkpt);
return SQLITE_OK;
#else
int rc; /* Return code */
@@ -2722,7 +2731,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
*/
int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zMsg){
int rc = SQLITE_OK;
if( !sqlite3SafetyCheckSickOrOk(db) ){
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
@@ -4902,6 +4911,7 @@ const char *sqlite3_filename_journal(const char *zFilename){
}
const char *sqlite3_filename_wal(const char *zFilename){
#ifdef SQLITE_OMIT_WAL
UNUSED_PARAMETER(zFilename);
return 0;
#else
zFilename = sqlite3_filename_journal(zFilename);
+255 -5
View File
@@ -596,6 +596,119 @@ static struct unix_syscall {
}; /* End of the overrideable system calls */
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
/*
** Extract Posix Advisory Locking information about file description fd
** from the /proc/PID/fdinfo/FD pseudo-file. Fill the string buffer a[16]
** with characters to indicate which SQLite-relevant locks are held.
** a[16] will be a 15-character zero-terminated string with the following
** schema:
**
** AAA/B.DDD.DDDDD
**
** Each of character A-D will be "w" or "r" or "-" to indicate either a
** write-lock, a read-lock, or no-lock, respectively. The "." and "/"
** characters are delimiters intended to make the string more easily
** readable by humans. Here are the meaning of the specific letters:
**
** AAA -> The main database locks. PENDING_BYTE, RESERVED_BYTE,
** and SHARED_FIRST, respectively.
**
** B -> The deadman switch lock. Offset 128 of the -shm file.
**
** CCC -> WAL locks: WRITE, CKPT, RECOVER
**
** DDDDD -> WAL read-locks 0 through 5
**
** Note that elements before the "/" apply to the main database file and
** elements after the "/" apply to the -shm file in WAL mode.
**
** Here is another way of thinking about the meaning of the result string:
**
** AAA/B.CCC.DDDDD
** ||| | ||| \___/
** PENDING--'|| | ||| `----- READ 0-5
** RESERVED--'| | ||`---- RECOVER
** SHARED ----' | |`----- CKPT
** DMS ------' `------ WRITE
**
** Return SQLITE_OK on success and SQLITE_ERROR_UNABLE if the /proc
** pseudo-filesystem is unavailable.
*/
static int unixPosixAdvisoryLocks(
int fd, /* The file descriptor to analyze */
char a[16] /* Write a text description of PALs here */
){
int in;
ssize_t n;
char *p, *pNext, *x;
char z[2000];
/* 1 */
/* 012 4 678 01234 */
memcpy(a, "---/-.---.-----", 16);
sqlite3_snprintf(sizeof(z), z, "/proc/%d/fdinfo/%d", getpid(), fd);
in = osOpen(z, O_RDONLY, 0);
if( in<0 ){
return SQLITE_ERROR_UNABLE;
}
n = osRead(in, z, sizeof(z)-1);
osClose(in);
if( n<=0 ) return SQLITE_ERROR_UNABLE;
z[n] = 0;
/* We are looking for lines that begin with "lock:\t". Examples:
**
** lock: 1: POSIX ADVISORY READ 494716 08:02:5277597 1073741826 1073742335
** lock: 1: POSIX ADVISORY WRITE 494716 08:02:5282282 120 120
** lock: 2: POSIX ADVISORY READ 494716 08:02:5282282 123 123
** lock: 3: POSIX ADVISORY READ 494716 08:02:5282282 128 128
*/
pNext = strstr(z, "lock:\t");
while( pNext ){
char cType = 0;
sqlite3_int64 iFirst, iLast;
p = pNext+6;
pNext = strstr(p, "lock:\t");
if( pNext ) pNext[-1] = 0;
if( (x = strstr(p, " READ "))!=0 ){
cType = 'r';
x += 6;
}else if( (x = strstr(p, " WRITE "))!=0 ){
cType = 'w';
x += 7;
}else{
continue;
}
x = strrchr(x, ' ');
if( x==0 ) continue;
iLast = strtoll(x+1, 0, 10);
*x = 0;
x = strrchr(p, ' ');
if( x==0 ) continue;
iFirst = strtoll(x+1, 0, 10);
if( iLast>=PENDING_BYTE ){
if( iFirst<=PENDING_BYTE && iLast>=PENDING_BYTE ) a[0] = cType;
if( iFirst<=PENDING_BYTE+1 && iLast>=PENDING_BYTE+1 ) a[1] = cType;
if( iFirst<=PENDING_BYTE+2 && iLast>=PENDING_BYTE+510 ) a[2] = cType;
}else if( iLast<=128 ){
if( iFirst<=128 && iLast>=128 ) a[4] = cType;
if( iFirst<=120 && iLast>=120 ) a[6] = cType;
if( iFirst<=121 && iLast>=121 ) a[7] = cType;
if( iFirst<=122 && iLast>=122 ) a[8] = cType;
if( iFirst<=123 && iLast>=123 ) a[10] = cType;
if( iFirst<=124 && iLast>=124 ) a[11] = cType;
if( iFirst<=125 && iLast>=125 ) a[12] = cType;
if( iFirst<=126 && iLast>=126 ) a[13] = cType;
if( iFirst<=127 && iLast>=127 ) a[14] = cType;
}
}
return SQLITE_OK;
}
#else
# define unixPosixAdvisoryLocks(A,B) SQLITE_ERROR_UNABLE
#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
/*
** On some systems, calls to fchown() will trigger a message in a security
** log if they come from non-root processes. So avoid calling fchown() if
@@ -1708,7 +1821,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
}
}else{
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK
if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK
&& pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE
){
rc = osFcntl(pFile->h, F_SETLKW, pLock);
@@ -1719,6 +1832,13 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
return rc;
}
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
/* Forward reference */
static int unixIsSharingShmNode(unixFile*);
#else
#define unixIsSharingShmNode(pFile) (0)
#endif
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
@@ -1907,7 +2027,9 @@ static int unixLock(sqlite3_file *id, int eFileLock){
pInode->nLock++;
pInode->nShared = 1;
}
}else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
}else if( (eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1)
|| unixIsSharingShmNode(pFile)
){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
@@ -4002,6 +4124,10 @@ static int unixGetTempname(int nBuf, char *zBuf);
#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
static int unixFcntlExternalReader(unixFile*, int*);
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
static void unixDescribeShm(sqlite3_str*,unixShm*);
#endif
/*
** Information and control of an open file handle.
@@ -4144,6 +4270,66 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
#endif
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
case SQLITE_FCNTL_FILESTAT: {
sqlite3_str *pStr = (sqlite3_str*)pArg;
char aLck[16];
unixInodeInfo *pInode;
static const char *azLock[] = { "SHARED", "RESERVED",
"PENDING", "EXCLUSIVE" };
sqlite3_str_appendf(pStr, "{\"h\":%d", pFile->h);
sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName);
if( pFile->eFileLock ){
sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"",
azLock[pFile->eFileLock-1]);
if( unixPosixAdvisoryLocks(pFile->h, aLck)==SQLITE_OK ){
sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
}
}
unixEnterMutex();
if( pFile->pShm ){
sqlite3_str_appendall(pStr, ",\"shm\":");
unixDescribeShm(pStr, pFile->pShm);
}
#if SQLITE_MAX_MMAP_SIZE>0
if( pFile->mmapSize ){
sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize);
sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut);
}
#endif
if( (pInode = pFile->pInode)!=0 ){
sqlite3_str_appendf(pStr, ",\"inode\":{\"nRef\":%d",pInode->nRef);
sqlite3_mutex_enter(pInode->pLockMutex);
sqlite3_str_appendf(pStr, ",\"nShared\":%d", pInode->nShared);
if( pInode->eFileLock ){
sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"",
azLock[pInode->eFileLock-1]);
}
if( pInode->pUnused ){
char cSep = '[';
UnixUnusedFd *pUFd = pFile->pInode->pUnused;
sqlite3_str_appendall(pStr, ",\"unusedFd\":");
while( pUFd ){
sqlite3_str_appendf(pStr, "%c{\"fd\":%d,\"flags\":%d",
cSep, pUFd->fd, pUFd->flags);
cSep = ',';
if( unixPosixAdvisoryLocks(pUFd->fd, aLck)==SQLITE_OK ){
sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
}
sqlite3_str_append(pStr, "}", 1);
pUFd = pUFd->pNext;
}
sqlite3_str_append(pStr, "]", 1);
}
sqlite3_mutex_leave(pInode->pLockMutex);
sqlite3_str_append(pStr, "}", 1);
}
unixLeaveMutex();
sqlite3_str_append(pStr, "}", 1);
return SQLITE_OK;
}
#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
}
return SQLITE_NOTFOUND;
}
@@ -4410,6 +4596,26 @@ struct unixShm {
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
/*
** Describe the pShm object using JSON. Used for diagnostics only.
*/
static void unixDescribeShm(sqlite3_str *pStr, unixShm *pShm){
unixShmNode *pNode = pShm->pShmNode;
char aLck[16];
sqlite3_str_appendf(pStr, "{\"h\":%d", pNode->hShm);
assert( unixMutexHeld() );
sqlite3_str_appendf(pStr, ",\"nRef\":%d", pNode->nRef);
sqlite3_str_appendf(pStr, ",\"id\":%d", pShm->id);
sqlite3_str_appendf(pStr, ",\"sharedMask\":%d", pShm->sharedMask);
sqlite3_str_appendf(pStr, ",\"exclMask\":%d", pShm->exclMask);
if( unixPosixAdvisoryLocks(pNode->hShm, aLck)==SQLITE_OK ){
sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
}
sqlite3_str_append(pStr, "}", 1);
}
#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
/*
** Use F_GETLK to check whether or not there are any readers with open
** wal-mode transactions in other processes on database file pFile. If
@@ -4443,6 +4649,49 @@ static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
return rc;
}
/*
** If pFile has a -shm file open and it is sharing that file with some
** other connection, either in the same process or in a separate process,
** then return true. Return false if either pFile does not have a -shm
** file open or if it is the only connection to that -shm file across the
** entire system.
**
** This routine is not required for correct operation. It can always return
** false and SQLite will continue to operate according to spec. However,
** when this routine does its job, it adds extra robustness in cases
** where database file locks have been erroneously deleted in a WAL-mode
** database by doing close(open(DATABASE_PATHNAME)) or similar.
**
** With false negatives, SQLite still operates to spec, though with less
** robustness. With false positives, the last database connection on a
** WAL-mode database will fail to unlink the -wal and -shm files, which
** is annoying but harmless. False positives will also prevent a database
** connection from running "PRAGMA journal_mode=DELETE" in order to take
** the database out of WAL mode, which is perhaps more serious, but is
** still not a disaster.
*/
static int unixIsSharingShmNode(unixFile *pFile){
int rc;
unixShmNode *pShmNode;
if( pFile->pShm==0 ) return 0;
if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0;
pShmNode = pFile->pShm->pShmNode;
rc = 1;
unixEnterMutex();
if( ALWAYS(pShmNode->nRef==1) ){
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = UNIX_SHM_DMS;
lock.l_len = 1;
lock.l_type = F_WRLCK;
osFcntl(pShmNode->hShm, F_GETLK, &lock);
if( lock.l_type==F_UNLCK ){
rc = 0;
}
}
unixLeaveMutex();
return rc;
}
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
@@ -4488,7 +4737,8 @@ static int unixShmSystemLock(
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) );
assert( ofst>=UNIX_SHM_BASE && ofst<=UNIX_SHM_DMS );
assert( ofst+n-1<=UNIX_SHM_DMS );
if( pShmNode->hShm>=0 ){
int res;
@@ -4531,7 +4781,7 @@ static int unixShmSystemLock(
}
#endif
return rc;
return rc;
}
/*
@@ -5020,7 +5270,7 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){
return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
#endif
}
#endif
#endif /* !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) */
/*
** Change the lock state for a shared-memory segment.
+29 -1
View File
@@ -2663,6 +2663,7 @@ static BOOL winLockFile(
#endif
}
#ifndef SQLITE_OMIT_WAL
/*
** Lock a region of nByte bytes starting at offset offset of file hFile.
** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock
@@ -2745,6 +2746,7 @@ static int winHandleLockTimeout(
}
return rc;
}
#endif /* #ifndef SQLITE_OMIT_WAL */
/*
** Unlock a file region.
@@ -2779,6 +2781,7 @@ static BOOL winUnlockFile(
#endif
}
#ifndef SQLITE_OMIT_WAL
/*
** Remove an nByte lock starting at offset iOff from HANDLE h.
*/
@@ -2786,6 +2789,7 @@ static int winHandleUnlock(HANDLE h, int iOff, int nByte){
BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0);
return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK);
}
#endif
/*****************************************************************************
** The next group of routines implement the I/O methods specified
@@ -2803,7 +2807,7 @@ static int winHandleUnlock(HANDLE h, int iOff, int nByte){
** Seek the file handle h to offset nByte of the file.
**
** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite
** error code.
** error code.
*/
static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){
int rc = SQLITE_OK; /* Return value */
@@ -3123,6 +3127,7 @@ static int winWrite(
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_WAL
/*
** Truncate the file opened by handle h to nByte bytes in size.
*/
@@ -3176,6 +3181,7 @@ static void winHandleClose(HANDLE h){
osCloseHandle(h);
}
}
#endif /* #ifndef SQLITE_OMIT_WAL */
/*
** Truncate an open file to a specified size
@@ -3953,6 +3959,28 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
}
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
case SQLITE_FCNTL_FILESTAT: {
sqlite3_str *pStr = (sqlite3_str*)pArg;
sqlite3_str_appendf(pStr, "{\"h\":%llu", (sqlite3_uint64)pFile->h);
sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName);
if( pFile->locktype ){
static const char *azLock[] = { "SHARED", "RESERVED",
"PENDING", "EXCLUSIVE" };
sqlite3_str_appendf(pStr, ",\"locktype\":\"%s\"",
azLock[pFile->locktype-1]);
}
#if SQLITE_MAX_MMAP_SIZE>0
if( pFile->mmapSize ){
sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize);
sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut);
}
#endif
sqlite3_str_append(pStr, "}", 1);
return SQLITE_OK;
}
#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
return SQLITE_NOTFOUND;
+5 -1
View File
@@ -813,6 +813,8 @@ int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
if( iRead ) return 0; /* Case (4) */
}
#else
UNUSED_PARAMETER(pgno);
#endif
assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
@@ -1856,7 +1858,7 @@ static void pager_unlock(Pager *pPager){
** have sqlite3WalEndReadTransaction() drop the write-lock, as it once
** did, because this would break "BEGIN EXCLUSIVE" handling for
** SQLITE_ENABLE_SETLK_TIMEOUT builds. */
sqlite3WalEndWriteTransaction(pPager->pWal);
(void)sqlite3WalEndWriteTransaction(pPager->pWal);
}
sqlite3WalEndReadTransaction(pPager->pWal);
pPager->eState = PAGER_OPEN;
@@ -4192,6 +4194,8 @@ int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
pPager->pWal = 0;
}
#else
UNUSED_PARAMETER(db);
#endif
pager_reset(pPager);
if( MEMDB ){
+5 -2
View File
@@ -373,10 +373,13 @@ static int lookupName(
if( cnt>0 ){
if( pItem->fg.isUsing==0
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
|| pMatch==pItem
){
/* Two or more tables have the same column name which is
** not joined by USING. This is an error. Signal as much
** by clearing pFJMatch and letting cnt go above 1. */
** not joined by USING. Or, a single table has two columns
** that match a USING term (if pMatch==pItem). These are both
** "ambiguous column name" errors. Signal as much by clearing
** pFJMatch and letting cnt go above 1. */
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}else
+1
View File
@@ -6823,6 +6823,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( pFunc->bOBPayload ){
/* extra columns for the function arguments */
assert( ExprUseXList(pFunc->pFExpr) );
assert( pFunc->pFExpr->x.pList!=0 );
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
if( pFunc->bUseSubtype ){
+108 -54
View File
@@ -1516,7 +1516,7 @@ struct ShellState {
int inputNesting; /* Track nesting level of .read and other redirects */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
int lineno; /* Line number of last line read from in */
i64 lineno; /* Line number of last line read from in */
int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
FILE *in; /* Read commands from this stream */
FILE *out; /* Write results here */
@@ -1752,7 +1752,7 @@ static void failIfSafeMode(
va_start(ap, zErrMsg);
zMsg = sqlite3_vmprintf(zErrMsg, ap);
va_end(ap);
sqlite3_fprintf(stderr, "line %d: %s\n", p->lineno, zMsg);
sqlite3_fprintf(stderr, "line %lld: %s\n", p->lineno, zMsg);
exit(1);
}
}
@@ -4963,6 +4963,9 @@ static void toggleSelectOrder(sqlite3 *db){
sqlite3_exec(db, zStmt, 0, 0, 0);
}
/* Forward reference */
static int db_int(sqlite3 *db, const char *zSql, ...);
/*
** This is a different callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
@@ -4989,7 +4992,21 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
/* no-op */
/* The sqlite_sequence table is repopulated last. Delete content
** in the sqlite_sequence table added by prior repopulations prior to
** repopulating sqlite_sequence itself. But only do this if the
** table is non-empty, because if it is empty the table might not
** have been recreated by prior repopulations. See forum posts:
** 2024-10-13T17:10:01z and 2025-10-29T19:38:43z
*/
if( db_int(p->db, "SELECT count(*) FROM sqlite_sequence")>0 ){
if( !p->writableSchema ){
sqlite3_fputs("PRAGMA writable_schema=ON;\n", p->out);
p->writableSchema = 1;
}
sqlite3_fputs("CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);\n"
"DELETE FROM sqlite_sequence;\n", p->out);
}
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
if( !dataOnly ) sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
}else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
@@ -5308,6 +5325,7 @@ static const char *(azHelp[]) = {
" --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
" --new Initialize FILE to an empty database",
" --normal FILE is an ordinary SQLite database",
" --nofollow Do not follow symbolic links",
" --readonly Open FILE readonly",
" --zip FILE is a ZIP archive",
@@ -5542,7 +5560,7 @@ static int showHelp(FILE *out, const char *zPattern){
}
/* Forward reference */
static int process_input(ShellState *p);
static int process_input(ShellState *p, const char*);
/*
** Read the content of file zName into memory obtained from sqlite3_malloc64()
@@ -5649,18 +5667,26 @@ static int session_filter(void *pCtx, const char *zTab){
** Otherwise, assume an ordinary database regardless of the filename if
** the type cannot be determined from content.
*/
int deduceDatabaseType(const char *zName, int dfltZip){
FILE *f = sqlite3_fopen(zName, "rb");
int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
FILE *f;
size_t n;
sqlite3 *db = 0;
sqlite3_stmt *pStmt = 0;
int rc = SHELL_OPEN_UNSPEC;
char zBuf[100];
if( f==0 ){
if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
return SHELL_OPEN_ZIPFILE;
}else{
return SHELL_OPEN_NORMAL;
}
if( access(zName,0)!=0 ) goto database_type_by_name;
if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
&& sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
==SQLITE_OK
&& sqlite3_step(pStmt)==SQLITE_ROW
){
rc = SHELL_OPEN_NORMAL;
}
sqlite3_finalize(pStmt);
sqlite3_close(db);
if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
f = sqlite3_fopen(zName, "rb");
if( f==0 ) goto database_type_by_name;
n = fread(zBuf, 16, 1, f);
if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
fclose(f);
@@ -5682,6 +5708,14 @@ int deduceDatabaseType(const char *zName, int dfltZip){
}
fclose(f);
return rc;
database_type_by_name:
if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
rc = SHELL_OPEN_ZIPFILE;
}else{
rc = SHELL_OPEN_NORMAL;
}
return rc;
}
#ifndef SQLITE_OMIT_DESERIALIZE
@@ -5692,7 +5726,7 @@ int deduceDatabaseType(const char *zName, int dfltZip){
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
unsigned char *a = 0;
int nLine;
i64 nLine;
int n = 0; /* Size of db per first line of hex dump */
i64 sz = 0; /* n rounded up to nearest page boundary */
int pgsz = 0;
@@ -5731,6 +5765,10 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){
int j = 0; /* Page number from "| page" line */
int k = 0; /* Offset from "| page" line */
if( nLine>=2000000000 ){
sqlite3_fprintf(stderr, "input too big\n");
goto readHexDb_error;
}
rc = sscanf(zLine, "| page %d offset %d", &j, &k);
if( rc==2 ){
iOffset = k;
@@ -5769,7 +5807,7 @@ readHexDb_error:
p->lineno = nLine;
}
sqlite3_free(a);
sqlite3_fprintf(stderr,"Error on line %d of --hexdb input\n", nLine);
sqlite3_fprintf(stderr,"Error on line %lld of --hexdb input\n", nLine);
return 0;
}
#endif /* SQLITE_OMIT_DESERIALIZE */
@@ -5846,7 +5884,7 @@ static void open_db(ShellState *p, int openFlags){
p->openMode = SHELL_OPEN_NORMAL;
}else{
p->openMode = (u8)deduceDatabaseType(zDbFilename,
(openFlags & OPEN_DB_ZIPFILE)!=0);
(openFlags & OPEN_DB_ZIPFILE)!=0, p->openFlags);
}
}
if( (p->openFlags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE))==0 ){
@@ -7187,39 +7225,42 @@ static void clearTempFile(ShellState *p){
p->zTempFile = 0;
}
/* Forward reference */
static char *find_home_dir(int clearFlag);
/*
** Create a new temp file name with the given suffix.
**
** Because the classic temp folders like /tmp are no longer
** accessible to web browsers, for security reasons, create the
** temp file in the user's home directory.
*/
static void newTempFile(ShellState *p, const char *zSuffix){
char *zHome; /* Home directory */
int i; /* Loop counter */
sqlite3_uint64 r = 0; /* Integer with 64 bits of randomness */
char zRand[32]; /* Text string with 160 bits of randomness */
#ifdef _WIN32
const char cDirSep = '\\';
#else
const char cDirSep = '/';
#endif
for(i=0; i<31; i++){
if( (i%12)==0 ) sqlite3_randomness(sizeof(r),&r);
zRand[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[r%36];
r /= 36;
}
zRand[i] = 0;
clearTempFile(p);
sqlite3_free(p->zTempFile);
p->zTempFile = 0;
if( p->db ){
sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
}
if( p->zTempFile==0 ){
/* If p->db is an in-memory database then the TEMPFILENAME file-control
** will not work and we will need to fallback to guessing */
char *zTemp;
sqlite3_uint64 r;
sqlite3_randomness(sizeof(r), &r);
zTemp = getenv("TEMP");
if( zTemp==0 ) zTemp = getenv("TMP");
if( zTemp==0 ){
#ifdef _WIN32
zTemp = "\\tmp";
#else
zTemp = "/tmp";
#endif
}
p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
}else{
p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
}
zHome = find_home_dir(0);
p->zTempFile = sqlite3_mprintf("%s%ctemp-%s.%s",
zHome,cDirSep,zRand,zSuffix);
shell_check_oom(p->zTempFile);
}
/*
** The implementation of SQL scalar function fkey_collate_clause(), used
** by the ".lint fkey-indexes" command. This scalar function is always
@@ -8227,7 +8268,7 @@ static int arDotCommand(
cmd.out = pState->out;
cmd.db = pState->db;
if( cmd.zFile ){
eDbType = deduceDatabaseType(cmd.zFile, 1);
eDbType = deduceDatabaseType(cmd.zFile, 1, 0);
}else{
eDbType = pState->openMode;
}
@@ -9223,6 +9264,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
p->showHeader = savedShowHeader;
p->shellFlgs = savedShellFlags;
rc = p->nErr>0;
}else
if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
@@ -9549,7 +9591,7 @@ static int do_meta_command(char *zLine, ShellState *p){
ImportCtx sCtx; /* Reader context */
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
i64 nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
char *zCreate = 0; /* CREATE TABLE statement text */
@@ -9676,7 +9718,8 @@ static int do_meta_command(char *zLine, ShellState *p){
shell_out_of_memory();
}
/* Below, resources must be freed before exit. */
while( (nSkip--)>0 ){
while( nSkip>0 ){
nSkip--;
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
@@ -10274,7 +10317,7 @@ static int do_meta_command(char *zLine, ShellState *p){
eputz("Usage: .nonce NONCE\n");
rc = 1;
}else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
sqlite3_fprintf(stderr,"line %d: incorrect nonce: \"%s\"\n",
sqlite3_fprintf(stderr,"line %lld: incorrect nonce: \"%s\"\n",
p->lineno, azArg[1]);
exit(1);
}else{
@@ -10329,6 +10372,8 @@ static int do_meta_command(char *zLine, ShellState *p){
openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "normal") ){
openMode = SHELL_OPEN_NORMAL;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
@@ -10731,7 +10776,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifndef SQLITE_SHELL_FIDDLE
if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
FILE *inSaved = p->in;
int savedLineno = p->lineno;
i64 savedLineno = p->lineno;
failIfSafeMode(p, "cannot run .read in safe mode");
if( nArg!=2 ){
eputz("Usage: .read FILE\n");
@@ -10748,7 +10793,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
rc = process_input(p);
rc = process_input(p, "<pipe>");
pclose(p->in);
}
#endif
@@ -10756,7 +10801,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
rc = process_input(p);
rc = process_input(p, azArg[1]);
fclose(p->in);
}
p->in = inSaved;
@@ -12747,7 +12792,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
**
** Return the number of errors.
*/
static int process_input(ShellState *p){
static int process_input(ShellState *p, const char *zSrc){
char *zLine = 0; /* A single input line */
char *zSql = 0; /* Accumulated SQL text */
i64 nLine; /* Length of current line */
@@ -12760,8 +12805,8 @@ static int process_input(ShellState *p){
if( p->inputNesting==MAX_INPUT_NESTING ){
/* This will be more informative in a later version. */
sqlite3_fprintf(stderr,"Input nesting limit (%d) reached at line %d."
" Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
sqlite3_fprintf(stderr,"%s: Input nesting limit (%d) reached at line %lld."
" Check recursion.\n", zSrc, MAX_INPUT_NESTING, p->lineno);
return 1;
}
++p->inputNesting;
@@ -12826,7 +12871,15 @@ static int process_input(ShellState *p){
memcpy(zSql+nSql, zLine, nLine+1);
nSql += nLine;
}
if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
if( nSql>0x7fff0000 ){
char zSize[100];
sqlite3_snprintf(sizeof(zSize),zSize,"%,lld",nSql);
sqlite3_fprintf(stderr, "%s:%lld: Input SQL is too big: %s bytes\n",
zSrc, startline, zSize);
nSql = 0;
errCnt++;
break;
}else if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
echo_group_input(p, zSql);
errCnt += runOneSqlLine(p, zSql, p->in, startline);
CONTINUE_PROMPT_RESET;
@@ -12994,7 +13047,7 @@ static void process_sqliterc(
char *home_dir = NULL;
char *sqliterc = (char*)sqliterc_override;
FILE *inSaved = p->in;
int savedLineno = p->lineno;
i64 savedLineno = p->lineno;
if( sqliterc == NULL ){
sqliterc = find_xdg_file("XDG_CONFIG_HOME",
@@ -13016,7 +13069,7 @@ static void process_sqliterc(
if( stdin_is_interactive ){
sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc);
}
if( process_input(p) && bail_on_error ) exit(1);
if( process_input(p, sqliterc) && bail_on_error ) exit(1);
fclose(p->in);
}else if( sqliterc_override!=0 ){
sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc);
@@ -13745,6 +13798,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
rc = shell_exec(&data, z, &zErrMsg);
if( zErrMsg!=0 ){
shellEmitError(zErrMsg);
sqlite3_free(zErrMsg);
if( bail_on_error ) return rc!=0 ? rc : 1;
}else if( rc!=0 ){
sqlite3_fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
@@ -13847,7 +13901,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
linenoiseSetCompletionCallback(linenoise_completion, NULL);
#endif
data.in = 0;
rc = process_input(&data);
rc = process_input(&data, "<stdin>");
if( zHistory ){
shell_stifle_history(2000);
shell_write_history(zHistory);
@@ -13855,7 +13909,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}
}else{
data.in = stdin;
rc = process_input(&data);
rc = process_input(&data, "<stdin>");
}
}
#ifndef SQLITE_SHELL_FIDDLE
@@ -14037,7 +14091,7 @@ void fiddle_exec(const char * zSql){
if('.'==*zSql) puts(zSql);
shellState.wasm.zInput = zSql;
shellState.wasm.zPos = zSql;
process_input(&shellState);
process_input(&shellState, "<stdin>");
shellState.wasm.zInput = shellState.wasm.zPos = 0;
}
}
+36 -18
View File
@@ -932,7 +932,7 @@ struct sqlite3_io_methods {
** connection. See also [SQLITE_FCNTL_FILE_POINTER].
**
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
** No longer in use.
** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used.
**
** <li>[[SQLITE_FCNTL_SYNC]]
** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
@@ -1229,6 +1229,15 @@ struct sqlite3_io_methods {
** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control
** purges the contents of the in-memory page cache. If there is an open
** transaction, or if the db is a temp-db, this opcode is a no-op, not an error.
**
** <li>[[SQLITE_FCNTL_FILESTAT]]
** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information
** about the [sqlite3_file] objects used access the database and journal files
** for the given schema. The fourth parameter to [sqlite3_file_control()]
** should be an initialized [sqlite3_str] pointer. JSON text describing
** various aspects of the sqlite3_file object is appended to the sqlite3_str.
** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time
** options are used to enable it.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1274,6 +1283,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_RESET_CACHE 42
#define SQLITE_FCNTL_NULL_IO 43
#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44
#define SQLITE_FCNTL_FILESTAT 45
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2557,12 +2567,15 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>
** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
** statistics. For statistics to be collected, the flag must be set on
** the database handle both when the SQL statement is prepared and when it
** is stepped. The flag is set (collection of statistics is enabled)
** by default. <p>This option takes two arguments: an integer and a pointer to
** [SQLITE_ENABLE_STMT_SCANSTATUS] builds. In this case, it sets or clears
** a flag that enables collection of run-time performance statistics
** used by [sqlite3_stmt_scanstatus_v2()] and the [nexec and ncycle]
** columns of the [bytecode virtual table].
** For statistics to be collected, the flag must be set on
** the database handle both when the SQL statement is
** [sqlite3_prepare|prepared] and when it is [sqlite3_step|stepped].
** The flag is set (collection of statistics is enabled) by default.
** <p>This option takes two arguments: an integer and a pointer to
** an integer. The first argument is 1, 0, or -1 to enable, disable, or
** leave unchanged the statement scanstatus option. If the second argument
** is not NULL, then the value of the statement scanstatus setting after
@@ -4207,7 +4220,7 @@ const char *sqlite3_errstr(int);
int sqlite3_error_offset(sqlite3 *db);
/*
** CAPI3REF: Set Error Codes And Message
** CAPI3REF: Set Error Code And Message
** METHOD: sqlite3
**
** Set the error code of the database handle passed as the first argument
@@ -4907,9 +4920,11 @@ typedef struct sqlite3_context sqlite3_context;
** associated with the pointer P of type T. ^D is either a NULL pointer or
** a pointer to a destructor function for P. ^SQLite will invoke the
** destructor D with a single argument of P when it is finished using
** P. The T parameter should be a static string, preferably a string
** literal. The sqlite3_bind_pointer() routine is part of the
** [pointer passing interface] added for SQLite 3.20.0.
** P, even if the call to sqlite3_bind_pointer() fails. Due to a
** historical design quirk, results are undefined if D is
** SQLITE_TRANSIENT. The T parameter should be a static string,
** preferably a string literal. The sqlite3_bind_pointer() routine is
** part of the [pointer passing interface] added for SQLite 3.20.0.
**
** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
** for the [prepared statement] or with a prepared statement for which
@@ -10414,7 +10429,7 @@ int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
** &nbsp; ){
** &nbsp; // do something with pVal
** &nbsp; }
** &nbsp; if( rc!=SQLITE_OK ){
** &nbsp; if( rc!=SQLITE_DONE ){
** &nbsp; // an error has occurred
** &nbsp; }
** </pre></blockquote>)^
@@ -10586,9 +10601,9 @@ int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
** a variable pointed to by the "pOut" parameter.
**
** The "flags" parameter must be passed a mask of flags. At present only
** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX
** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX
** is specified, then status information is available for all elements
** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If
** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If
** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
** the EXPLAIN QUERY PLAN output) are available. Invoking API
@@ -10602,7 +10617,8 @@ int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
** elements used to implement the statement - a non-zero value is returned and
** the variable that pOut points to is unchanged.
**
** See also: [sqlite3_stmt_scanstatus_reset()]
** See also: [sqlite3_stmt_scanstatus_reset()] and the
** [nexec and ncycle] columnes of the [bytecode virtual table].
*/
int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
@@ -11153,9 +11169,11 @@ int sqlite3_deserialize(
** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
** indicate the datatype of the array being bound. The X argument is not a
** NULL pointer, then SQLite will invoke the function X on the P parameter
** after it has finished using P.
** after it has finished using P, even if the call to
** sqlite3_carray_bind() fails. The special-case finalizer
** SQLITE_TRANSIENT has no effect here.
*/
SQLITE_API int sqlite3_carray_bind(
int sqlite3_carray_bind(
sqlite3_stmt *pStmt, /* Statement to be bound */
int i, /* Parameter index */
void *aData, /* Pointer to array data */
@@ -11165,7 +11183,7 @@ SQLITE_API int sqlite3_carray_bind(
);
/*
** CAPI3REF: Datatypes for the CARRAY table-valued funtion
** CAPI3REF: Datatypes for the CARRAY table-valued function
**
** The fifth argument to the [sqlite3_carray_bind()] interface musts be
** one of the following constants, to specify the datatype of the array
+1 -1
View File
@@ -5452,7 +5452,7 @@ void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
i64 sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
+32
View File
@@ -4972,6 +4972,37 @@ static int SQLITE_TCLAPI test_errmsg16(
return TCL_OK;
}
/*
** Usage: sqlite3_set_errmsg DB ERRCODE ERRMSG
*/
static int SQLITE_TCLAPI test_set_errmsg(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
const char *zDb = 0;
const char *zErr = 0;
int iErr = 0;
sqlite3 *db = 0;
int rc;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB ERRCODE ERRMSG");
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[1]);
if( zDb[0] ){
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[2], &iErr) ) return TCL_ERROR;
zErr = Tcl_GetString(objv[3]);
rc = sqlite3_set_errmsg(db, iErr, (zErr[0] ? zErr : 0));
Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
return TCL_OK;
}
/*
** Usage: sqlite3_prepare DB sql bytes ?tailvar?
**
@@ -9077,6 +9108,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_errmsg", test_errmsg ,0 },
{ "sqlite3_error_offset", test_error_offset ,0 },
{ "sqlite3_errmsg16", test_errmsg16 ,0 },
{ "sqlite3_set_errmsg", test_set_errmsg ,0 },
{ "sqlite3_open", test_open ,0 },
{ "sqlite3_open16", test_open16 ,0 },
{ "sqlite3_open_v2", test_open_v2 ,0 },
+7 -6
View File
@@ -270,8 +270,9 @@ static int analyzeFilterKeyword(const unsigned char *z, int lastToken){
** Return the length (in bytes) of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
int sqlite3GetToken(const unsigned char *z, int *tokenType){
int i, c;
i64 sqlite3GetToken(const unsigned char *z, int *tokenType){
i64 i;
int c;
switch( aiClass[*z] ){ /* Switch on the character-class of the first byte
** of the token. See the comment on the CC_ defines
** above. */
@@ -599,7 +600,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
int sqlite3RunParser(Parse *pParse, const char *zSql){
int nErr = 0; /* Number of errors encountered */
void *pEngine; /* The LEMON-generated LALR(1) parser */
int n = 0; /* Length of the next token token */
i64 n = 0; /* Length of the next token token */
int tokenType; /* type of the next token */
int lastTokenParsed = -1; /* type of the previous token */
sqlite3 *db = pParse->db; /* The database connection */
@@ -702,13 +703,13 @@ int sqlite3RunParser(Parse *pParse, const char *zSql){
}else if( tokenType!=TK_QNUMBER ){
Token x;
x.z = zSql;
x.n = n;
x.n = (u32)n;
sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x);
break;
}
}
pParse->sLastToken.z = zSql;
pParse->sLastToken.n = n;
pParse->sLastToken.n = (u32)n;
sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
lastTokenParsed = tokenType;
zSql += n;
@@ -784,7 +785,7 @@ char *sqlite3Normalize(
){
sqlite3 *db; /* The database connection */
int i; /* Next unread byte of zSql[] */
int n; /* length of current token */
i64 n; /* length of current token */
int tokenType; /* type of current token */
int prevType = 0; /* Previous non-whitespace token */
int nParen; /* Number of nested levels of parentheses */
+3
View File
@@ -1823,6 +1823,9 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
#if SQLITE_MAX_LENGTH>2147483645
if( nByte>2147483645 ){ goto too_big; }
#endif
if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
goto no_mem;
}
+1 -2
View File
@@ -557,8 +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 */
union {
KeyInfo sKey;
struct {
u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */
} uKey;
};
+2
View File
@@ -736,6 +736,8 @@ static int doWalCallbacks(sqlite3 *db){
}
}
}
#else
UNUSED_PARAMETER(db);
#endif
return rc;
}
+1 -1
View File
@@ -5538,7 +5538,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.pCsr = pCsr;
preupdate.op = op;
preupdate.iNewReg = iReg;
preupdate.pKeyinfo = &preupdate.uKey.sKey;
preupdate.pKeyinfo = (KeyInfo*)&preupdate.uKey;
preupdate.pKeyinfo->db = db;
preupdate.pKeyinfo->enc = ENC(db);
preupdate.pKeyinfo->nKeyField = pTab->nCol;
+1
View File
@@ -1226,6 +1226,7 @@ int sqlite3VdbeMemSetStr(
if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
return SQLITE_NOMEM_BKPT;
}
assert( pMem->z!=0 );
memcpy(pMem->z, z, nAlloc);
}else{
sqlite3VdbeMemRelease(pMem);
+5 -5
View File
@@ -26,10 +26,10 @@
** a host parameter. If the text contains no host parameters, return
** the total number of bytes in the text.
*/
static int findNextHostParameter(const char *zSql, int *pnToken){
static i64 findNextHostParameter(const char *zSql, i64 *pnToken){
int tokenType;
int nTotal = 0;
int n;
i64 nTotal = 0;
i64 n;
*pnToken = 0;
while( zSql[0] ){
@@ -76,8 +76,8 @@ char *sqlite3VdbeExpandSql(
sqlite3 *db; /* The database connection */
int idx = 0; /* Index of a host parameter */
int nextIndex = 1; /* Index of next ? host parameter */
int n; /* Length of a token prefix */
int nToken; /* Length of the parameter token */
i64 n; /* Length of a token prefix */
i64 nToken; /* Length of the parameter token */
int i; /* Loop counter */
Mem *pVar; /* Value of a host parameter */
StrAccum out; /* Accumulate the output here */
+3 -3
View File
@@ -602,7 +602,7 @@ struct WalIterator {
/* Size (in bytes) of a WalIterator object suitable for N or fewer segments */
#define SZ_WALITERATOR(N) \
(offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment))
(offsetof(WalIterator,aSegment)+(N)*sizeof(struct WalSegment))
/*
** Define the parameters of the hash tables in the wal-index file. There
@@ -3488,7 +3488,7 @@ void sqlite3WalEndReadTransaction(Wal *pWal){
assert( pWal->writeLock==0 || pWal->readLock<0 );
#endif
if( pWal->readLock>=0 ){
sqlite3WalEndWriteTransaction(pWal);
(void)sqlite3WalEndWriteTransaction(pWal);
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
pWal->readLock = -1;
}
@@ -4395,7 +4395,7 @@ int sqlite3WalCheckpoint(
sqlite3WalDb(pWal, 0);
/* Release the locks. */
sqlite3WalEndWriteTransaction(pWal);
(void)sqlite3WalEndWriteTransaction(pWal);
if( pWal->ckptLock ){
walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
pWal->ckptLock = 0;
+5 -5
View File
@@ -129,7 +129,7 @@ if {$::TEMP_STORE<3} {
CREATE TABLE data(a INTEGER, b BLOB);
-- Insert 5-6 MB of data.
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000 )
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<75000 )
INSERT INTO data SELECT i, hex(randomblob(50)) FROM s;
}
@@ -138,8 +138,8 @@ if {$::TEMP_STORE<3} {
do_test 4.4 {
execsql { SELECT a, b FROM data ORDER BY a }
set nTmpSpill [lindex [db_temp_spill db 1] 1]
expr ($nTmpSpill>5*1000*1000) && ($nTmpSpill<6*1000*1000)
} 1
expr {($nTmpSpill>7*1000*1000) && ($nTmpSpill<10*1000*1000)?"ok":$nTmpSpill}
} ok
# The previous test case reset the status value.
do_test 4.5 { db_temp_spill db 0 } {0 0 0}
@@ -147,8 +147,8 @@ if {$::TEMP_STORE<3} {
do_test 4.6 {
execsql { CREATE INDEX i1 ON data(a) }
set nTmpSpill [lindex [db_temp_spill db 1] 1]
expr ($nTmpSpill>256*1000) && ($nTmpSpill<512*1000)
} 1
expr {($nTmpSpill>384*1000) && ($nTmpSpill<768*1000)?"ok":$nTmpSpill}
} ok
# The previous test case reset the status value.
do_test 4.7 { db_temp_spill db 0 } {0 0 0}
-1
View File
@@ -144,7 +144,6 @@ foreach op1 $oplist {
foreach op {* AND OR + || & |} { unset untested($op,$op) }
unset untested(+,-) ;# Since (a+b)-c == a+(b-c)
unset untested(*,<<) ;# Since (a*b)<<c == a*(b<<c)
foreach op {>> & * <<} {unset untested(AND,$op)}
do_test e_expr-1.1 { array names untested } {}
+3
View File
@@ -71,6 +71,9 @@ test_expr expr-1.28 {i1=1, i2=2} {i1=2 AND i2=1} {0}
test_expr expr-1.29 {i1=1, i2=2} {i1=1 AND i2=1} {0}
test_expr expr-1.30 {i1=1, i2=2} {i1=2 AND i2=2} {0}
test_expr expr-1.31 {i1=1, i2=2} {i1==1 OR i2=2} {1}
test_expr expr-1.31b {i1=1} {0 OR 2} {1}
test_expr expr-1.31c {i1=1} {false OR true} {1}
test_expr expr-1.31d {i1=1} {99 OR false} {1}
test_expr expr-1.32 {i1=1, i2=2} {i1=2 OR i2=1} {0}
test_expr expr-1.33 {i1=1, i2=2} {i1=1 OR i2=1} {1}
test_expr expr-1.34 {i1=1, i2=2} {i1=2 OR i2=2} {1}
+63
View File
@@ -411,4 +411,67 @@ do_execsql_test 15.2 {
SELECT lower(x), quote(y) FROM x1 LEFT JOIN x2 USING (x) JOIN x3 USING (x) FULL JOIN t4;
} {abc NULL}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 16.0 {
CREATE TABLE t0_a (c0 INT);
CREATE TABLE t0_b (c0 INT);
CREATE TABLE t2 (c0 INT);
INSERT INTO t2 VALUES (1);
}
do_execsql_test 16.1 {
SELECT * FROM t2 LEFT JOIN t0_b
} {1 {}}
do_execsql_test 16.2.1 {
SELECT * FROM (t0_a RIGHT JOIN ( t2 LEFT JOIN t0_b))
} {{} 1 {}}
do_execsql_test 16.2.2 {
SELECT * FROM (t0_a RIGHT JOIN (SELECT * FROM t2 LEFT JOIN t0_b))
} {{} 1 {}}
do_catchsql_test 16.3.1 {
SELECT * FROM (t0_a RIGHT JOIN ( t2 LEFT JOIN t0_b) USING (c0));
} {1 {ambiguous column name: c0}}
do_execsql_test 16.3.2 {
SELECT * FROM (t0_a RIGHT JOIN (SELECT * FROM t2 LEFT JOIN t0_b) USING (c0));
} {1 {}}
do_execsql_test 16.4.0 {
CREATE TABLE x0(a TEXT);
CREATE TABLE x1(a TEXT);
CREATE TABLE x2(a TEXT);
INSERT INTO x1 VALUES('blue');
INSERT INTO x2 VALUES('red');
}
do_catchsql_test 16.4.1 {
SELECT * FROM x0 RIGHT JOIN ( x1, x2) USING (a)
} {1 {ambiguous column name: a}}
do_execsql_test 16.4.2 {
SELECT * FROM x0 RIGHT JOIN (SELECT * FROM x1, x2) USING (a)
} {blue red}
reset_db
do_execsql_test 16.5.0 {
CREATE TABLE t0 (c0 INT);
CREATE TABLE t1 (c0 INT);
CREATE TABLE t2 (c0 INT);
INSERT INTO t1(c0) VALUES (NULL);
INSERT INTO t2 VALUES (1);
CREATE VIEW v0(c0) AS SELECT 1 AS col_0 FROM t0;
}
do_catchsql_test 16.5.2 {
SELECT * FROM (t0 NATURAL RIGHT JOIN (t0 FULL JOIN (v0 NATURAL FULL JOIN t2) ON TRUE)) NATURAL FULL JOIN t1;
} {1 {ambiguous column name: c0}}
finish_test
+12
View File
@@ -211,4 +211,16 @@ if {[clang_sanitize_address]==0 && 0} {
} {1 {(21) bad parameter or other API misuse}}
}
#-------------------------------------------------------------------------
reset_db
do_test misuse-6.0 {
sqlite3_set_errmsg db 1 "an error has occurred"
} {SQLITE_OK}
do_test misuse-6.1 {
sqlite3_errmsg db
} {an error has occurred}
do_test misuse-6.2 {
sqlite3_set_errmsg "" 1 "an error has occurred"
} {SQLITE_MISUSE}
finish_test
+50
View File
@@ -544,4 +544,54 @@ do_catchsql_test 22.1 {
} {1 {no such column: sqlite_master.name}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 23.0 {
PRAGMA recursive_triggers = 1;
CREATE TABLE t1(x, y);
CREATE TRIGGER t1insert AFTER INSERT ON t1 WHEN new.x<5 BEGIN
INSERT INTO t1 VALUES(new.x+1, new.y);
END;
}
do_execsql_test 23.1 {
INSERT INTO t1 VALUES(1, 'one') RETURNING *;
} {1 one}
do_execsql_test 23.2 {
SELECT * FROM t1
} {1 one 2 one 3 one 4 one 5 one}
#-------------------------------------------------------------------------
reset_db
ifcapable fts5 {
do_execsql_test 24.0 {
CREATE VIRTUAL TABLE ft USING fts5(c);
CREATE TABLE t1(x);
INSERT INTO t1 VALUES('x');
}
db close
sqlite3 db test.db
sqlite3 db2 test.db
do_execsql_test 24.1 {
SELECT * FROM t1
} {x}
do_execsql_test -db db2 24.2 {
CREATE TABLE t2(y);
INSERT INTO t2 VALUES('y');
} {}
db2 close
do_execsql_test 24.3 {
INSERT INTO ft VALUES('hello world') RETURNING *
} {{hello world}}
}
finish_test
+65
View File
@@ -945,6 +945,71 @@ do_test shell1-4.1.6 {
}
# DELETE content of sqlite_sequence prior to repopulating,
# but only if the sqlite_sequence table is non-empty.
# Forum: 2024-10-13T17:10:01z and 2025-10-29T19:38:43z
#
do_test shell1-4.1.7 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
INSERT INTO t1 VALUES(1,2),(20,21),(15,16);
}
catchcmd test2.db {.dump}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
INSERT INTO t1 VALUES(1,2);
INSERT INTO t1 VALUES(15,16);
INSERT INTO t1 VALUES(20,21);
PRAGMA writable_schema=ON;
CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence VALUES('t1',20);
PRAGMA writable_schema=OFF;
COMMIT;}}
do_test shell1-4.1.8 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
INSERT INTO t1 VALUES(1,2),(20,21),(15,16);
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(99,88);
DROP TABLE t1;
}
catchcmd test2.db {.dump}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(99,88);
COMMIT;}}
do_test shell1-4.1.9 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
INSERT INTO t1 VALUES(1,2),(20,21),(15,16);
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(99,88);
INSERT INTO sqlite_sequence VALUES('extra',999);
DROP TABLE t1;
}
catchcmd test2.db {.dump}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(99,88);
PRAGMA writable_schema=ON;
CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence VALUES('extra',999);
PRAGMA writable_schema=OFF;
COMMIT;}}
# Test the output of ".mode insert"
#
+1 -1
View File
@@ -152,6 +152,6 @@ do_test shell4-4.1 {
puts $fd ".read t1.txt"
close $fd
catchcmd ":memory:" ".read t1.txt"
} {1 {Input nesting limit (25) reached at line 1. Check recursion.}}
} {1 {t1.txt: Input nesting limit (25) reached at line 1. Check recursion.}}
finish_test
+1 -1
View File
@@ -116,7 +116,7 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
continue
}
if {[string match CC=* $arg]} {
set cc [lrange $arg 3 end]
set cc [string range $arg 3 end]
continue
}
if {[string match *.c $arg]} {
+30 -2
View File
@@ -362,7 +362,8 @@ set TRG(schema) {
nerr INT, -- Number of errors reported
svers TEXT, -- Reported SQLite version
pltfm TEXT, -- Host platform reported
output TEXT -- test output
output TEXT, -- test output
cwd TEXT -- working directory for test
);
CREATE TABLE config(
@@ -997,8 +998,15 @@ proc r_get_next_job {iJob} {
set T($iJob) $tm
set jobid $job(jobid)
set cwd $job(dirname)
if {$cwd==""} {
set cwd [dirname $iJob]
}
trdb eval {
UPDATE jobs SET starttime=$tm, state='running' WHERE jobid=$jobid
UPDATE jobs
SET starttime=$tm, state='running', cwd=$cwd
WHERE jobid=$jobid
}
set ret [array get job]
@@ -1261,6 +1269,26 @@ proc add_fuzztest_jobs {buildname patternlist} {
set subcmd [lrange $interpreter 1 end]
set interpreter [lindex $interpreter 0]
# For fuzzcheck-asan and fuzzcheck-ubsan, break up some
# fuzzdata files into multiple slices, for improved
# concurrency.
#
if {[string match *fuzzcheck-*san $interpreter]} {
set newscripts {}
foreach s $scripts {
if {[string match {*fuzzdata[12].db} $s]
&& ![string match slice $s]} {
set N 6
for {set i 0} {$i<$N} {incr i} {
lappend newscripts [list --slice $i $N $s]
}
} else {
lappend newscripts $s
}
}
set scripts $newscripts
}
if {[string match fuzzcheck* $interpreter]
&& [info exists env(FUZZDB)]
&& [file readable $env(FUZZDB)]
+25 -22
View File
@@ -19,6 +19,7 @@ source $testdir/tester.tcl
source $testdir/lock_common.tcl
if {[run_thread_tests]==0} { finish_test ; return }
ifcapable !wal { finish_test ; return }
set DBNAME wt-[expr {int(abs(rand()*100000000))}]-test.db
set sqlite_walsummary_mmap_incr 64
@@ -74,7 +75,6 @@ proc lshift {lvar} {
# -check SCRIPT Script to run after test.
#
proc do_thread_test {args} {
set A $args
set P(testname) [lshift A]
@@ -126,12 +126,12 @@ proc do_thread_test {args} {
return
}
puts "Running $P(testname) for $P(seconds) seconds..."
puts "Running $P(testname) for $P(seconds) seconds on $::DBNAME"
catch { db close }
forcedelete test.db test.db-journal test.db-wal
forcedelete $::DBNAME $::DBNAME-journal $::DBNAME-wal
sqlite3 db test.db
sqlite3 db $::DBNAME
eval $P(init)
catch { db close }
@@ -146,7 +146,7 @@ proc do_thread_test {args} {
set E(nthread) $count
set E(seconds) $P(seconds)
"
set program [string map [list %TEST% $prg %VARS% $vars] {
set program [string map [list %TEST% $prg %VARS% $vars %DB% $::DBNAME] {
%VARS%
@@ -163,7 +163,7 @@ proc do_thread_test {args} {
proc busyhandler {n} { usleep 10 ; return 0 }
sqlite3 db test.db
sqlite3 db %DB%
db busy busyhandler
db eval { SELECT randomblob($E(pid)*5) }
@@ -202,7 +202,7 @@ proc do_thread_test {args} {
}
puts $report
sqlite3 db test.db
sqlite3 db $::DBNAME
set res ""
if {[catch $P(check) msg]} { set res $msg }
do_test $P(testname).check [list set {} $res] ""
@@ -327,16 +327,16 @@ do_thread_test2 walthread-1 -seconds $seconds(walthread-1) -init {
# the number of write-transactions performed using a rollback journal.
# For example, "192 w, 185 r".
#
if {[atomic_batch_write test.db]==0} {
if {[atomic_batch_write $::DBNAME]==0} {
do_thread_test2 walthread-2 -seconds $seconds(walthread-2) -init {
execsql { CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE) }
} -thread RB 2 {
} -thread RB 2 [string map [list %DB% $::DBNAME] {
db close
set nRun 0
set nDel 0
while {[tt_continue]} {
sqlite3 db test.db
sqlite3 db %DB%
db busy busyhandler
db eval { SELECT * FROM sqlite_master }
catch { db eval { PRAGMA journal_mode = DELETE } }
@@ -345,8 +345,8 @@ if {[atomic_batch_write test.db]==0} {
INSERT INTO t1 VALUES(NULL, randomblob(100+$E(pid)));
}
incr nRun 1
incr nDel [file exists test.db-journal]
if {[file exists test.db-journal] + [file exists test.db-wal] != 1} {
incr nDel [file exists %DB%-journal]
if {[file exists %DB%-journal] + [file exists %DB%-wal] != 1} {
error "File-system looks bad..."
}
db eval COMMIT
@@ -357,12 +357,12 @@ if {[atomic_batch_write test.db]==0} {
list $nRun $nDel
set {} "[expr $nRun-$nDel] w, $nDel r"
} -thread WAL 2 {
}] -thread WAL 2 [string map [list %DB% $::DBNAME] {
db close
set nRun 0
set nDel 0
while {[tt_continue]} {
sqlite3 db test.db
sqlite3 db %DB%
db busy busyhandler
db eval { SELECT * FROM sqlite_master }
catch { db eval { PRAGMA journal_mode = WAL } }
@@ -371,8 +371,8 @@ if {[atomic_batch_write test.db]==0} {
INSERT INTO t1 VALUES(NULL, randomblob(110+$E(pid)));
}
incr nRun 1
incr nDel [file exists test.db-journal]
if {[file exists test.db-journal] + [file exists test.db-wal] != 1} {
incr nDel [file exists %DB%-journal]
if {[file exists %DB%-journal] + [file exists %DB%-wal] != 1} {
error "File-system looks bad..."
}
db eval COMMIT
@@ -381,7 +381,7 @@ if {[atomic_batch_write test.db]==0} {
db close
}
set {} "[expr $nRun-$nDel] w, $nDel r"
}
}]
}
do_thread_test walthread-3 -seconds $seconds(walthread-3) -init {
@@ -510,14 +510,14 @@ do_thread_test walthread-5 -seconds $seconds(walthread-5) -init {
COMMIT;
}
forcecopy test.db-wal bak.db-wal
forcecopy test.db bak.db
forcecopy $::DBNAME-wal $::DBNAME-bak.db-wal
forcecopy $::DBNAME $::DBNAME-bak.db
db close
forcecopy bak.db-wal test.db-wal
forcecopy bak.db test.db
forcecopy $::DBNAME-bak.db-wal $::DBNAME-wal
forcecopy $::DBNAME-bak.db $::DBNAME
if {[file size test.db-wal] < [log_file_size [expr 64*1024] 1024]} {
if {[file size $::DBNAME-wal] < [log_file_size [expr 64*1024] 1024]} {
error "Somehow failed to create a large log file"
}
puts "Database with large log file recovered. Now running clients..."
@@ -525,5 +525,8 @@ do_thread_test walthread-5 -seconds $seconds(walthread-5) -init {
db eval { SELECT count(*) FROM t1 }
}
unset -nocomplain seconds
catch {db close}
forcedelete $::DBNAME $::DBNAME-journal $::DBNAME-wal $::DBNAME-shm
forcedelete $::DBNAME-bak.db-wal $::DBNAME-bak.db
finish_test
+1
View File
@@ -145,6 +145,7 @@ static void traverse(
for(e=readdir(d); e; e=readdir(d)){
if( strcmp(e->d_name, ".")==0 || strcmp(e->d_name, "..")==0 ) continue;
char *zPath = sqlite3_mprintf("%s/%s", zDir, e->d_name);
if( zPath==0 ){ fprintf(stderr, "out of memory\n"); abort(); }
if (e->d_type & DT_DIR) {
traverse(zPath, pCtx, xCallback);
}else{
+1
View File
@@ -67,6 +67,7 @@ int main(int argc, char **argv){
"**************\n\n");
sqlite3_free(zIdx);
zIdx = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0));
if( zIdx==0 ){ fprintf(stderr, "out of memory\n"); abort(); }
iRow = 0;
}
printf("%s sample %d ------------------------------------\n", zIdx, ++iRow);
+18 -8
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 -Wno-array-bounds"
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic"
gccvers=`gcc -v 2>&1 | grep '^gcc version'`
if test "$gccvers" '<' 'gcc version 6'
then
@@ -22,11 +22,18 @@ fi
rm -f sqlite3.c
make sqlite3.c
echo '**** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***'
echo '**** No optimizations. Includes FTS4/5, GEOPOLY, and others ***'
echo '****' $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
gcc -c $WARNING_OPTS -std=c99 \
-DHAVE_STDINT_H \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_MATH_FUNCTIONS_fixme \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
sqlite3.c
if test x`uname` = 'xLinux'; then
echo '**** Android configuration ******************************'
@@ -54,12 +61,15 @@ gcc -c \
fi
echo '**** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
echo '****' $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
gcc -c $WARNING_OPTS -std=c99 \
-DSQLITE_ENABLE_STAT4 \
-DSQLITE_THREADSAFE=0 \
sqlite3.c
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 \
gcc -O3 -c $WARNING_OPTS -std=c99 \
-DHAVE_STDINT_H \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_GEOPOLY \
sqlite3.c