Compare commits

...

466 Commits

Author SHA1 Message Date
dan 799e743333 Updates to the mktoolzip.tcl to work on win32.
FossilOrigin-Name: 166b775bb523362ffe17722ce175278726303c319fbe7e4a1e9291736db38a5d
2023-10-25 20:08:21 +00:00
drh 47a484d8ed Add an ALWAYS on branch that was made always-true by the DISTINCT ORDER BY
fix.

FossilOrigin-Name: c29ebcb0be8e969c359c077bd4ce752a9c952d2659062868f12efdd2cc77186d
2023-10-25 15:30:11 +00:00
drh 8f99cb9ad6 When doing a DISTINCT aggregate that contains an ORDER BY, only the
arguments to the aggregate need to be distinct, not the ORDER BY terms.

FossilOrigin-Name: d2dbbdf7194bab4e5e3b74d3dbffb012a335829824c775c72dd7347c013d2125
2023-10-25 14:54:16 +00:00
drh a9a7d118f6 Fix the amalgamation generator so that when it is reporting the Fossil
version number in the header comment of the amalgamation, it does not
elide the first hex digit of the version hash.

FossilOrigin-Name: cc66f526bd58c110cac027583f636099fa05b2b56d7ea9807b554cd950c1bf3c
2023-10-25 12:58:06 +00:00
drh 9f20bde65a Enhance the new xIntegrity method of the sqlite3_module object with new
parameters that provide the name of the table being checked and
a flag to indicate a "quick_check".  Based on feedback in
[forum:/forumpost/965c0d02ea|forum post 965c0d02ea].

FossilOrigin-Name: bc8afa3f15954bb35f65dbf940bf069de5e14d333036676c24430cf17b658d05
2023-10-25 10:37:11 +00:00
drh f4154879eb Implement check-in [477577120b897bf1] differently, so as not to disrupt
non-standard build configuration. See
[forum:/forumpost/c11523ca2df50293|forum post c11523ca2df50293].

FossilOrigin-Name: 50448fe4fdc8fd93303fe26bdcd885ecc606080c8e66e69d5be8dac28a77492b
2023-10-24 19:56:57 +00:00
drh 85b1f5c2f6 Test cases for COLLATE and NULLS FIRST/LAST in the ORDER BY for an
aggregate function.

FossilOrigin-Name: 641f928feb8b6cfd64cb03992bc18c1653960b6eaeb35145d17df494727c7a11
2023-10-24 17:45:11 +00:00
drh 9d486435f1 New #ifdefs to fix certain compile-time options.
FossilOrigin-Name: 688c6279ef1d4ff8d58e83a1c73ca0221ab8570a7cd89459946a86afdad6ec1c
2023-10-24 16:16:27 +00:00
dan 3da982635c Fix a problem with the fts5 highlight() and snippet() functions when used with tokenizers like "trigram" that output overlapping tokens. Forum post [forum:/forumpost/63735293ec|63735293ec].
FossilOrigin-Name: e952db86faaafd2ef8558175ebcae6834d0b0002813cc78c7ae7da713604cbec
2023-10-24 16:06:56 +00:00
dan d548f74024 Fix a problem with the fts5 highlight() and snippet() functions when used with tokenizers like "trigram" that output overlapping tokens. Forum post [forum:/forumpost/63735293ec|63735293ec].
FossilOrigin-Name: d570aa02f79b1d7d3889e33f9eebab1b7edcf5231b1357451eed9a538607de54
2023-10-24 15:53:02 +00:00
larrybr bdcae89358 Spelling improvements, in comments only
FossilOrigin-Name: 9ee25eeaf17124dbe34b961384e74c1ae239ee1798bb01907938600ed6b4066f
2023-10-24 15:11:55 +00:00
larrybr da67619d97 Spelling improvements, in comments only
FossilOrigin-Name: 65bcc583784476f8cc52dfe72ecc52df93d0ec5817c313ad7a83905c0047dd8c
2023-10-24 15:07:28 +00:00
drh c0ba6a97ec Fix various harmless scan-build warnings.
FossilOrigin-Name: 54be9af4469d7e31ee852f67e5aa32996557c10de654a60103fd165d2fedf311
2023-10-24 11:06:44 +00:00
drh eb9882d7d1 Fix a harmless compiler warning in the expert extension.
FossilOrigin-Name: 0c4907ddf9abd1ebfef31c1a53d702c4dcaa015c0032b8b52774c9e260b6cfd7
2023-10-24 09:57:54 +00:00
drh 13e69440fb Fix a minor typo in the previous.
FossilOrigin-Name: 9d388267e4e6724e2df333fe09d509e87defcfe984c5c2ebe031152d320812d0
2023-10-23 23:34:53 +00:00
drh 043768ce5a Add notes on how to build a statically linked version of sqlite3_analyzer.exe.
FossilOrigin-Name: 99ce9939c861ecc07877e640f75d395afb6502130bf4b5ccea8b98a80a1569ce
2023-10-23 23:34:24 +00:00
drh 811bece3f7 Add the sqlite3res file to the Windows build of sqldiff.exe so that the
resulting binary shows the SQLite icon.

FossilOrigin-Name: c696a4963bdd010c8161acbf7601078313e7da5ebb3f60381a489a70e5728dea
2023-10-23 19:51:16 +00:00
dan 4fecc81e20 Avoid attempting to delete a file while it is open in test script sessionalter.test.
FossilOrigin-Name: f20b4a96f747adeb2ed486f06dd7d911f0f24b37df87dcd32d2c3e4b687da9a6
2023-10-23 15:30:38 +00:00
dan 2db02ec245 Revert an earlier change that considered passing a NULL callback to sqlite3_preupdate_hook() to be a misuse. This is required to clear the preupdate hook altogether.
FossilOrigin-Name: 1bf6f0f3bb54933e4e6c730554144934f73a7fac87c97a916b275afd7379f397
2023-10-23 15:24:44 +00:00
drh 8c86f56e90 New test cases for PRAGMA integrity_check against FTS4 and FTS5 tables.
FossilOrigin-Name: 3950d20c3a4433543546ce4495ae07aab3d6cefb163b1f30813a9776c5b962e8
2023-10-23 15:23:10 +00:00
dan fd05978a1e Fix mutex1.test to take into account that the prng mutex is not (as of [c84e4483cb4]) taken when writing a header to an in-memory journal.
FossilOrigin-Name: c9e37417fcc41f1e975290bf583113ff8f4144c056e8fcd9fafcb432c1a26b18
2023-10-23 14:24:09 +00:00
drh 45b2e946cc Improved error messages for the xIntegrity method in FTS3/4 and FTS5.
FossilOrigin-Name: df69abc0823f4dd9c051f8d5993d2f447ee0dadab5cef73d670107b1071db255
2023-10-23 13:46:22 +00:00
drh bd8941a4f8 Fix sqlite3ExprDup() alignment assertions so that they work on 32-bit
platforms.

FossilOrigin-Name: 143f95efc7114455b1920f1d2f9a867392740f608d1dda4306005f01238103f8
2023-10-23 12:16:27 +00:00
drh f49d52d642 Temporarily disable the ext/expert/expert1-6.0 test, which does not work
on my configurations.

FossilOrigin-Name: a41b903d0fe489d20c4a7118a2c91f7c8a78568ce552225f64c2945bb811ea16
2023-10-23 11:41:41 +00:00
dan 3f81c3264a Add an SQLITE_OMIT_VIRTUALTABLE block around the new vtab code in "PRAGMA integrity_check".
FossilOrigin-Name: ab99eb2b6c50f4f0bb42918b9bdda37e2ef9316bed07de18fa4bd373c49a8b00
2023-10-23 11:34:24 +00:00
dan 06700d77c2 Add missing test file fts3fault3.test. Should have been part of [7f41d700].
FossilOrigin-Name: 92e64ab63a78445fe20863f9679c55a630a2295ff10c4ce33eab6dfaeef09622
2023-10-23 11:18:13 +00:00
larrybr 47b496868c Merge fixes for expert handling of UDFs and other UD-whatevers.
FossilOrigin-Name: b5d7d07df58bb8e4013b4047e4019b96e506e8ef03ca0abfc9aae06a122b353a
2023-10-23 02:08:34 +00:00
drh aa040d891f Fix the shell1.test test so to align with the new behavior imposed by
[bce807cd48763273] - that backslash escapes only work without quoted arguments
in dot-commands of the CLI.

FossilOrigin-Name: 0db82b4281a0e0d5e365553df11e0347f60c00c861c0fb96227059edff3a0ef6
2023-10-23 02:01:14 +00:00
larrybr 81be0d26bb Clear some picky warnings, sync w/trunk.
FossilOrigin-Name: ee58425904b36319e016dc69bb5f141bb3565b1723a97490a4b2cfa16b89fbdf
2023-10-23 01:55:35 +00:00
drh 5e6dde3b35 Fix [f5c01676fd281e93] so that it always preserves 8-byte alignment for Expr
objects.  Add new assert() statement to verify this.

FossilOrigin-Name: 678a9728dc6b88d8ef924c86603056df18204bc9a9c4776b9baffd7c5b10c5f2
2023-10-22 23:44:32 +00:00
drh a63539143d Do not do backslash excape processing on any unquoted strings in dot-commands
in the CLI - on Windows or on posix-like systems either one.  This brings the
processing into alignment with the documentation, allows backslash-delimited
filenames on Windows (as long as they are unquoted), and causes the CLI to work
the same with regard to backslash escapes on both Windows and posix.

FossilOrigin-Name: bce807cd4876327396b4ffcdf77f6931dd3bbd3314336eedf38bcf01d17af32c
2023-10-22 17:27:55 +00:00
stephan 28f45b1ab1 JNI: improve UB protections in sqlite3_bind_blob/text/text16().
FossilOrigin-Name: 5c8383210a87d7f9d37a27053b5b1b6f41794fa8612826c68c1ca49c495cbd97
2023-10-22 12:33:05 +00:00
stephan 6e4ef06ca1 Add missing ScalarFunction.java to JNI build.
FossilOrigin-Name: b8258103fb433d9f5cfa15661b5edf4e60128fb4161d8a18e5cc3253e5aed72b
2023-10-22 11:11:54 +00:00
drh 06f4dc7edb In the CLI, do not translate unquoted backslash escapes on dot-commands
as that can damage filename arguments.

FossilOrigin-Name: 4a0e2c6e17eefb296b7e91a13305b2260d6eb869a37bc5e5b79edaf3c19c810a
2023-10-21 22:31:00 +00:00
drh d2c737f2e4 Remove a branch that cannot affect the outcome from FkNoAction processing in
fkey.c.  Replace it with an assert().

FossilOrigin-Name: 023a9dbe83c0042e9d500e3ae6c0592a468982e4ac278d08c9201967506c7555
2023-10-21 20:34:57 +00:00
drh 76bd238a66 Replace the patch at [5cb61c6788d7c017] with a better way to avoid failing
PRAGMA integrity_check if a module implementation is not loaded, as the use
of suppressErr can lead to problems.

FossilOrigin-Name: be5737ee4f4f1d5f8b3126f6eb70210bf3d8b1cdaef51aae818eaaba43ccf722
2023-10-21 20:03:44 +00:00
dan ef6bf1bbe5 Fix a problem allowing a COMMIT following an OOM to cause fts3/4 corruption.
FossilOrigin-Name: 7f41d7006db4225cf9b3d197d3a76842778669ac079e76361214a8023c9976e6
2023-10-21 18:12:07 +00:00
drh da4cfde031 Add the SQLITE_TESTCTRL_FK_NO_ACTION test control. Make it available in the
CLI.  Fix a minor problems with SQLITE_CHANGESETAPPLY_FKNOACTION in sessions.

FossilOrigin-Name: 91b64c6a70744704fc3285be7d8d46ba679ea5f0f69bd77b0e093eeb7447947d
2023-10-21 16:33:20 +00:00
drh 5c8cfe9617 Extra comment on the implementation of SQLITE_TESTCTRL_FK_NO_ACTION,
warning about the need to reset the schema in order for the setting change
to take full effect.

FossilOrigin-Name: a50a333ae11ba5d92f432108308ac0bec9afb00f466b78c8d3f3aa7e2851ef21
2023-10-21 16:25:44 +00:00
dan fcef73a787 Add missing "finish_test" to sessionnoact.test.
FossilOrigin-Name: 9a1d37f5479adedb93f40e8189ad0efa891a438805d80774ee992d4dfd71150f
2023-10-21 15:21:06 +00:00
dan ca9dc173a2 Fix a problem with SQLITE_CHANGESETAPPLY_FKNOACTION and the foreign-key-trigger-cache.
FossilOrigin-Name: 95304ec6c9654b4366dc58ae263270cb42861cb5017174936f816922b5eb61e6
2023-10-21 15:04:24 +00:00
drh 51b358e5e5 Add SQLITE_TESTCTRL_FK_NO_ACTION.
FossilOrigin-Name: 563cf5f782cdddbbd7f727c65118edfd109aeb731c8aaf0d6ee5ee7030e61ea9
2023-10-21 12:54:37 +00:00
drh a35a54b824 Adjust an EXPLAIN QUERY PLAN output in scanstatus2.test to account for a
different loop order taken due to the removal of the view-scan optimization.

FossilOrigin-Name: 9deb8b6915e794bf9c5de88f2727ef9857351eaf905f8ab56754bc4d399c88b4
2023-10-21 11:43:54 +00:00
drh 813159e2ea Compress the content of the status line in testrunning.tcl so that all the
same status information appears but with less punctuation and with "zero"
values omitted, so that the status line will fit comfortably on an 80-column
terminal window.

FossilOrigin-Name: 966351311682a319ec796c07d407ce90cd1aa0cea9e904ba1085a4ebadbdf925
2023-10-21 11:34:59 +00:00
drh 531ca6058e Create the new string_agg(X,Y) aggregate function which is an alias for
the two-argument group_concat(X,Y) function, for compatibility with
SQL-Server and PostgreSQL.

FossilOrigin-Name: a3b3df8a9e43f1880a904b76027db56ed504a84622831c96ba1962a19bbed762
2023-10-21 11:13:47 +00:00
drh 266e5d034b Avoid an unnecessary malloc() for the page usage bitmap when running
a partial integrity_check.

FossilOrigin-Name: 2904fcbeebba9189cebc48e58d12fc46f78ee23d8c4d46644606691f8cabb80c
2023-10-21 11:06:03 +00:00
drh 51bb5dec6c Fix a test case broken by the previous check-in.
FossilOrigin-Name: 1e61864c3bffec133632f4575d59d11936e8bafc089c4d84a129dcaf7e9b6d7d
2023-10-21 11:00:57 +00:00
drh d5e040b6f0 Add string_agg(X,Y) as an alias for group_concat(X,Y), for compatibility
with SQLServer and PG.

FossilOrigin-Name: b91c19bf2680f60d7826ab5d9e7902e2dc2a55d847bbea565a6489d47f2cc8f1
2023-10-20 20:19:30 +00:00
dan 71bae9f19f Fix a problem allowing a COMMIT following an OOM to cause fts5 corruption.
FossilOrigin-Name: fba3129d1362dd3ee04d61cb3d3c48518cd98dde3febc85298f411776d60073e
2023-10-20 19:59:12 +00:00
drh 81656b15c9 Fix PRAGMA integrity_check so that it does not raise an error if the
schema contains a CREATE VIRTUAL TABLE that does not have its module
loaded.

FossilOrigin-Name: 5cb61c6788d7c0170b587e4667ee57d588c991a9901951762e33b97c6a135a82
2023-10-20 19:06:04 +00:00
drh e98f62fb3f Omit some redundant calls to strlen() used to find the size of
Expr.u.zToken in sqliteExprDup().  This inefficiency was seen while working
on the previous check-in, and I thought it best to fix it while it was
fresh in mind.

FossilOrigin-Name: b7a84eff5dcdf5b2ff81331097cdc64d0c5d16a4ae224320f39b64541ec72dc7
2023-10-20 18:09:08 +00:00
drh ab3eb5b770 Improvements to the sqlite3ExprDup() logic for faster performance and better
run-time error detection.  This check-in fixes the 5x oversize memory allocation
bug from [f371e4c0f8ea73ae] as well as all other known issues that result from
handing the ORDER BY clause of an aggregate function off of the pLeft pointer
of the Expr object.

FossilOrigin-Name: f5c01676fd281e938181b846dd2024d050f597dc6a7a91928beab9d8553dfdb5
2023-10-20 17:15:15 +00:00
dan 17c3408e0e Add the SQLITE_CHANGESETAPPLY_FKNOACTION flag to sqlite3session.h, for passing to sqlite3changeset_apply_v2() to cause all foreign key constraints to behave as if they were declared NO ACTION.
FossilOrigin-Name: fc9f82ea084159eaf3dd1757b96d17d1201b00c4e06455a7dcd8067172b25f28
2023-10-20 17:06:39 +00:00
drh 90e4a3b7fc Simplifications and optimizations to the Expr object duplication logic.
The 5x multiplier crutch from [f371e4c0f8ea73ae] is still present.  More
fixes are still needed.

FossilOrigin-Name: 56142a78163b755f16afc05201f623a7a19d9a4b0620a67f7fa20d2a965a288d
2023-10-20 15:47:30 +00:00
drh 0a261eb4bb Omit an unused constant from sessionfuzz.c to prevent a compiler warning.
FossilOrigin-Name: a0cf7e24f928183866ac54f0d6cd83c859d487a19dc87572ab0188d90d2ff87d
2023-10-20 14:05:26 +00:00
stephan 11223e0cff Correct the opfs-sahpool VFS's xGetLastError() method to return the previous error code, not 0, on success.
FossilOrigin-Name: 95a1dde63117d696323c775580b9c04f044a5b8d609e9174b739ac03ecc1336c
2023-10-20 12:23:49 +00:00
drh d707e012f0 Use sqlite3ParserAddCleanup() instead of calling sqlite3ExprListDelete()
directly when disposing of an unused ORDER BY in an aggregate function,
to avoid disrupting ALTER TABLE data structures.

FossilOrigin-Name: d083e42086733ecd79aba8c268e020b01782bfe1cfa9684ce1c277af9c8bf92a
2023-10-20 10:18:03 +00:00
drh dcf76a8bbd Remove a faulty assert() that was added just a few check-ins ago by
[8b6fffb552c30f9c].

FossilOrigin-Name: 18e7c826f08bce51719ef045daa60200b33790f2fe312c6853f9ef6c7e9d5030
2023-10-19 20:06:20 +00:00
drh 5f53f85e22 For TK_ORDER expression nodes to always be full-size.
FossilOrigin-Name: a5c73b46f4772f214ffbfa31cb87dce82ebd690addabef539bd09def26b7744d
2023-10-19 19:57:57 +00:00
drh 5080397e67 Fix an adverse interaction between the new aggregate ORDER BY logic and the
expression compressor.

FossilOrigin-Name: f371e4c0f8ea73aee9ea0645f396e3da20f1eb97be34c83de9d94c9cbb959934
2023-10-19 19:19:59 +00:00
drh d8b840a4f4 In the TreeView logic (used for debugging only) do not show unnecessary fields
of the Window object when a function has a FILTER.

FossilOrigin-Name: d2c6b82c346dbf39e07f09d187e4a8216a56caa7df3dcfafc82e32f676a1db8a
2023-10-19 19:08:33 +00:00
dan ee3c55471c Fix an fts3 problem caused by reducing the page size using the undocumented "nodesize" option, then running an incremental-merge.
FossilOrigin-Name: 2875dcb1ac86db2704ad377d719f308c8837e196b49c98b20ceda1324f2d27ea
2023-10-19 18:23:17 +00:00
drh 4e254641ff Simplify the Expr compression logic slightly by adding the new EP_FullSize
property to expressions that are exceptions to the rule and should not be
compressed.

FossilOrigin-Name: d5ae82ec52eafed5e3dc8c9d99685f6523fce7d973ef7e8d9d75ed9b8912426a
2023-10-19 18:07:58 +00:00
drh 0588385799 Simplification to sqlite3GetVarint32() to avoid confusing gcov.
FossilOrigin-Name: 89862c51ad9715bedf5b029db484602e740f0db7404970d482ce503c1b9a0ed2
2023-10-19 13:35:22 +00:00
drh 11877c6ba4 Fix an error in a debugging routine used inside of testcase(). Does not
appear in production.  Problem discovered by scan-build.

FossilOrigin-Name: c6c9d7ed6dbc71b998aeaaa1bdeb36b1bb9b902f9d6088ad36db29f8ea8b7ef6
2023-10-19 13:00:41 +00:00
drh 266178f369 New assert() statements to help verify correctness of the ORDER BY aggregate
code.

FossilOrigin-Name: 8b6fffb552c30f9cbf7102c2e26a7b486c4c9edd9f494d803de7004db3018277
2023-10-19 12:36:59 +00:00
drh 519017f25a Fix the sqlite3ReferencesSrcList() routine so that it recognizes columns
in the ORDER BY clause of an aggregate.  Fixes a problem with
[634286828dad873d] discoverd by dbsqlfuzz.

FossilOrigin-Name: 3d26f1aaa4876f21f2c3abf13bbc37933c8f32471153e29019880cc9530cb011
2023-10-19 12:12:49 +00:00
drh d9451051f1 Add support for ORDER BY on the argument list of aggregate functions.
FossilOrigin-Name: 634286828dad873dba244751441aa729cd37b6ed5899fa5875643d4af03c006c
2023-10-19 01:26:34 +00:00
drh 0b633640fa Merge the latest changes from trunk.
FossilOrigin-Name: d18bc400146812c8c5048af7eaf4a5371ddd80fc9ce895d253b6114b9eae7fc3
2023-10-19 01:09:49 +00:00
drh 69ff726d4d Fix a false-positive in run-time error checking.
FossilOrigin-Name: cd63eec0758960d9ee63d7b964ec62e2bd622f8c94a58bd9556046381ffa18d0
2023-10-19 00:25:35 +00:00
drh d05e54efff Changes for test coverage.
FossilOrigin-Name: ddfa09c6031afd4391a9888381bf09214cd542a826b431eeb1537a070f65c5f9
2023-10-18 23:48:24 +00:00
drh 42f5ea354e Test case for alter column that is used in the ORDER BY of an aggregate.
FossilOrigin-Name: 648ddb3a8eb358fc6c95aaa561ae68476c77996abda23890054ac07166278cef
2023-10-18 22:53:22 +00:00
drh ce51b31367 Deal with an OOM condition while processing aggregate ORDER BYs.
FossilOrigin-Name: b6d44427ec0184880ad14919667e2f526777c5085ffa636f6734cb5951a31225
2023-10-18 22:27:59 +00:00
drh 20b95f8d3f Make sure all terms of the ORDER BY within an aggregate go through aggregate
analysis.  Do not attach an aggregate ORDER BY to a window function.

FossilOrigin-Name: 16f3805514a741405f70e0ee3b5a6b67720bc75719372e82daa4136fe411ea2b
2023-10-18 22:03:48 +00:00
drh 49dc1be96f Basic test cases.
FossilOrigin-Name: 6cccf86c362631ada0c6cbaf661520648f8bbf7ae2b137b3d7d959647387e5c2
2023-10-18 19:44:59 +00:00
drh 0021079ceb Fix one minor error in order to get all legacy tests to pass.
FossilOrigin-Name: 5a885139c433a143302ab43dc5aaac1fed9db61548b4ff7d4b19b3a6a46c8fcc
2023-10-18 19:07:45 +00:00
drh 59a0d0bbf9 ORDER BY on aggregates seem to work, at least for simple smoke tests. Lots
more testing is needed though.  Surely there are many bugs.

FossilOrigin-Name: 64c12a835b6f1df8f2f5f4a41de083f6b3fc7f8030042c6aac0082382cd9cc4d
2023-10-18 18:11:11 +00:00
drh db19f48b69 Basic error checking. Resolve symbols in the aggregate ORDER BY expressions.
FossilOrigin-Name: c83a53a574d312130d1238c05ffa449d8bed2535d5ef5b5d9cf02f894494cca4
2023-10-18 13:58:31 +00:00
drh f8202f1ff3 Enhance the parser so that it can accept an ORDER BY clause on a function
invocation.  For this incremental check-in, the ORDER BY clause is currently
ignored.

FossilOrigin-Name: 3a98ff24bf468ed42d410a9a12d9f9b2ca154c7babe99fd6bc6f7b0565e0d132
2023-10-18 13:18:52 +00:00
stephan 0b4de1acac JS: replace one errant reference to 'self' with 'globalThis' and remove a separate dead-code 'self' reference.
FossilOrigin-Name: da1a47932ea96755b1e11fc2547ce11780b87846af6885857318ff18f1e62c31
2023-10-17 23:35:47 +00:00
drh 43dc31cf1f Fix a harmless compiler warning about variant types for a pointer function.
FossilOrigin-Name: 37ff0d8e7f91c32e8c53bb015280be47c66bf599281b640a8d3fd41335b55289
2023-10-17 19:33:52 +00:00
drh 6db4e5ed4c Make a new branch in the SqlExec opcode reachable by tests.
FossilOrigin-Name: 023ad470b68b7c09e159244493a6d0285d706efdecd8719a71e6885509d4750c
2023-10-17 18:59:13 +00:00
drh 42b49a3138 Omit an unreachable branch when SQLITE_ENABLE_API_ARMOR is not defined.
FossilOrigin-Name: 5f8b807b568f4f9ec65f1c924e0e1ac2f996f405e045204145ad7116be7580ee
2023-10-17 18:28:27 +00:00
drh 4c827feba1 Changes to sqlite3IntFloatCompare() in an attempt to better measure
branch coverage in the face of aggressive compiler optimization.

FossilOrigin-Name: 5781d043ffeccda03357ee530564987443dc1deb6111a4028701b4a98fdfe16d
2023-10-17 17:53:46 +00:00
drh 52d934e316 Fix a JSON bug introduced by the optimization of [df099ad713011b67] and
first appearing in 3.43.0.  The problem occurs when doing a JSON_EXTRACT()
on an array element that was added by JSON_SET() without first reparsing.
Reported by [forum:/forumpost/fc0e3f1e2a|forum post fc0e3f1e2a].

FossilOrigin-Name: e5099c549a1d8959d4015516f090b8e6438e517a64b20651175bf5413d94fb58
2023-10-17 13:41:41 +00:00
drh 5e0b11bda7 Enhance the documentation of sqlite3_deserialize() to make it clear that
the input database may not be in WAL mode.
[forum:/forumpost/a7e272cee9ac469f|Forum post a7e272cee9ac469f]

FossilOrigin-Name: e754789971e019647e7068f76dc6f9778675e4849fe51d8b25b39d3edf2379e5
2023-10-17 11:57:36 +00:00
drh 11095bcb89 When an I/O or similar error occurs during a transaction with
journal_mode=MEMORY, attempt to rollback before closing the journal, as
all rollback information is forgotten when a memory rollback journal is
closed.

FossilOrigin-Name: 1d67f75de259e5a26b751a50432822a268ebe367cda6510891ab81a15e5daa1c
2023-10-17 10:47:42 +00:00
stephan b866f98346 Harden API_ARMOR checks for sqlite3_stmt_scanstatus_v2().
FossilOrigin-Name: d3f38e813ba3b887e973af034713cd58fdfbe07da375b154accc7b5790cfaeda
2023-10-17 02:15:49 +00:00
stephan 08747d44a2 JNI: add aggregate function support to the wrapper1 API.
FossilOrigin-Name: 15b28b340a5c5efdbfe3fbed16ee0b699561edaeebb77446addf2374bdf9357e
2023-10-16 16:04:23 +00:00
stephan 626d0a9fda JNI: add scalar UDF support to the wrapper1 API.
FossilOrigin-Name: a850535766d2243d9475e1523c753615875a2da9c9d82a41a9fb61b141c6334a
2023-10-16 14:31:13 +00:00
stephan f2d7e961d9 JNI: initial draft (untested - requires more infrastructure first) of a UDF argument/result-handling interface which completely hides the C-style API from the client.
FossilOrigin-Name: 43b10a5cf9cb8be53d62914f340d533e60a70bf4caa8b9b91c0f867fa0f70493
2023-10-16 13:04:42 +00:00
stephan 7e540e5a2c JNI: cleanups in Tester2 and update the jar makefile target to account for [9fcdf96adca2].
FossilOrigin-Name: abc82bf4b800dde1b6e6172c7be816edb391fdbed5dbd2749f54623fdf3bf8e6
2023-10-16 10:38:34 +00:00
stephan 22fd153e43 JNI: move the C-style API parts into the capi subpackage and the higher-level wrapper into (tentatively) wrapper1, so that CApi.java can support multiple independent higher-level wrappers without name collisions, and CApi can be made public but have the option to be elided from wrapper-level javadocs for wrappers which do not wish to expose it.
FossilOrigin-Name: 9fcdf96adca25cc2d2f4b75ec4eea94254fb9671c5ba63b88213d7f62dedff1b
2023-10-16 10:27:19 +00:00
stephan 19179722d6 JNI: after calling a Java-side UDF, zero-out the pointer of the Java-side sqlite3_context and sqlite3_value array entries to avoid misbehavior if a client makes the mistake of holding a reference to one of those objects.
FossilOrigin-Name: 9fc3104f76a83d600beb11d91feb97bcea8bc7f7cda8cd73e7a6b81fbba879df
2023-10-16 08:10:11 +00:00
stephan f83a4d850c JNI: do not expose SQLITE_OPEN_... flags which are specific to VFSes.
FossilOrigin-Name: 2b4e53d8be42a3bc098317abd8bb58b8ddc25094d80787f784bbc896f4f7b976
2023-10-16 08:05:51 +00:00
stephan 24f6baca16 Change 3 instance of #if SQLITE_ENABLE_API_ARMOR to #ifdef for consistency with how it is normally used.
FossilOrigin-Name: dd766eeb59fec71627dd8ad8f120875b96fda455c6401e5671e086b785e2b2bc
2023-10-15 13:36:21 +00:00
stephan 5698e62f9e JNI: enable all optional components in the default build and fix a test broken by an option toggle.
FossilOrigin-Name: 5586a9df58a400c20a6815e8b0fbc7a7c49e5ef89daf92c452f1990586ca78ae
2023-10-15 13:32:38 +00:00
stephan 29aeb620e7 Correct non-void return from sqlite3_preupdate_hook() when API_ARMOR is enabled. Broken by [6cb77503484e].
FossilOrigin-Name: 40f5906f48d3f1f44d54e5b271fe04e7082166e50e3ed250bb57a4760f112e8a
2023-10-15 13:25:39 +00:00
stephan 6089e5bfcb Add coverage of more functions to SQLITE_ENABLE_API_ARMOR builds.
FossilOrigin-Name: 6cb77503484e104a51f08690974d6e19c336ab5467d327f84be1d042615f008c
2023-10-15 12:11:10 +00:00
stephan 8a273bb6e8 JNI: extend [baf220e78a46246c47] to include macro-generated sqlite3_value_...() bindings.
FossilOrigin-Name: ad34b2542e330c22fcf331810ab43e66346b1bad8de1a3989e6208cfa0fc2f92
2023-10-14 20:44:13 +00:00
stephan 4b1e42ef94 JNI: make the sqlite3_value_...() family of bindings resistent to NULL arguments.
FossilOrigin-Name: baf220e78a46246c476cd429ac131698db5fa66f62fb5725d4f736fe5246283c
2023-10-14 20:34:40 +00:00
drh d718bde6da Do not allow an ALTER TABLE ADD COLUMN on a STRICT table if the added column
contains a DEFAULT clause that would violate the type of the added column.

FossilOrigin-Name: 75b075863eaa56e36635a1d27740d37de8600ba92099b3fad9378a1e6ce12c0e
2023-10-14 20:24:52 +00:00
stephan eb62ccdab5 Add API_ARMOR support to the scanstatus family of functions.
FossilOrigin-Name: 2f3101f016d5f8d954a262befdf5e0f938a223e444bc534e1d3655b733f4663d
2023-10-14 20:01:55 +00:00
drh 153790d9ae The rtreecheck() SQL function should not invoke BEGIN or COMMIT as this
causes issues for statement transactions.

FossilOrigin-Name: b7b2e30b570efda338c62e88446dedb6667640f33855b2422ad20c7b569b025a
2023-10-14 17:14:53 +00:00
stephan 4213cc78cd JNI: add a missing result code check to sqlite3_bind_value(stmt, null).
FossilOrigin-Name: f1a357f42de58927c33e7047dc4417e3b9549d7529625f30c583e66b7d603b00
2023-10-14 16:57:48 +00:00
stephan a9000d424e JNI: add missing sqlite3_bind_value() and minor memory-safety-related cleanups.
FossilOrigin-Name: 3900031763abf4b2aab7b57e886cc407571d0d5928b74f24dcea8fb7371655af
2023-10-14 16:56:12 +00:00
stephan c76e450908 Add API_ARMOR support to the sqlite3_result_...() family of functions and sqlite3_bind_zeroblob64().
FossilOrigin-Name: afabe3e35a66625527e2881749cdb6e13300888ab57bc0f05889d0e3ee203d73
2023-10-14 16:29:36 +00:00
stephan 7a54b12695 More API_ARMOR additions.
FossilOrigin-Name: 78ebf838f645742f87733665cd72af736df345683b27377a2c8310c893b1769d
2023-10-14 14:53:18 +00:00
stephan a17f63290c Add column name to API_ARMOR check in sqlite3_blob_open() to avoid a null-pointer deref.
FossilOrigin-Name: 0114a6622afc4588c47e98d804340449417b603dc4831513eab4d8e4ccb15d42
2023-10-14 13:24:30 +00:00
stephan 067a13c395 Revert [f6cd88e6b234] - the NULL callback case is perfectly legal.
FossilOrigin-Name: 718ab67607895176e529eb7469832d262a347d030e83e7ee66d3b4704bf933de
2023-10-14 12:45:11 +00:00
stephan 6d035d481f Bring JNI-side sqlite3_last_insert_rowid() and sqlite3_table_column_metadata() in line with the core's NULL handling.
FossilOrigin-Name: c2afc1c2a2fc9bdf3d7b7701004e0fa40965cf8c6b7cf44b46f2ca37cfa1d2aa
2023-10-14 12:40:57 +00:00
stephan eaebd7fb6a Extend API_ARMOR checks on sqlite3_commit/rollback_hook() to include a check for the callback pointer.
FossilOrigin-Name: f6cd88e6b234560f729ff00da86144a0121ad96d5a07d227c9ffa3f43c22f72d
2023-10-14 12:20:55 +00:00
stephan 2ba1acce81 Add missing JNI bindings for sqlite3_db_readonly() and sqlite3_db_name(). Code-adjacent tweaks for the API_ARMOR audit.
FossilOrigin-Name: e5eace747ae656f1e05a346e53a2827242e57107567d2c3470e292cf0b40858d
2023-10-14 12:19:59 +00:00
drh c84a0b2195 Bug fix in sqlite3_analyzer: for databases larger than 1GiB, take into
account the lock-byte page when calculating the number of freelist pages.

FossilOrigin-Name: 26a909cdd32afee0f15968ca6f611eb259373b2a2195d0b3d47cfba103f1e6d6
2023-10-14 10:54:37 +00:00
drh 9132b8816a Earlier detection of a host of errors in CREATE TABLE, such the CREATE TABLE
statement itself fails, rather than generating an error on the first attempted
use of the created table.

FossilOrigin-Name: 348fa7aaf7958b3fb689ed023d946064ae8d92718a497a346e95114a2410cbf5
2023-10-13 22:19:23 +00:00
drh cc67a62fa0 Apply the correct affinity to DEFAULT values that are TRUE or FALSE.
FossilOrigin-Name: 4958db70c8103e249748fdeffc35f1c385e2e550e8a48697b82fcd797f3016be
2023-10-13 19:41:20 +00:00
drh 6f12e51313 Do not allow triggers on shadow tables under defensive mode.
FossilOrigin-Name: 44b932ff16e35814febd842d11215cf243393f173aade33ceded473598221e88
2023-10-13 18:29:18 +00:00
dan d7cdfe74f6 Fix an fts5 problem caused by a 'rebuild' followed by a DELETE in secure-delete mode.
FossilOrigin-Name: 18be505c628d9b13431ca6cfe822d4aeae119c53ae08aef26a67f310a8bd7bd3
2023-10-13 15:59:11 +00:00
drh af527231c1 Immediately fail a CREATE TABLE statement that attempts to create a
table that has a generated column loop.  Legacy allows the table to be
created but the table would not be usable for anything.

FossilOrigin-Name: 3237bf964117c1ef71143042837ef21872bb3d04bfd682075672e768953ec802
2023-10-13 13:49:46 +00:00
drh 9817065340 Actually prevent PRAGMA writable_schema=ON from being set in defensive mode,
rather than just preventing it from functioning.

FossilOrigin-Name: 2b574d9e7e922d0961ea27bfc0148d3098157ff8d4feefba469489c81d43f3e0
2023-10-13 12:57:23 +00:00
stephan 7dc0cc45f3 Round one of an audit for SQLITE_ENABLE_API_ARMOR for functions exposed by JNI and those functions missing armor, as [forum:5e3fc453a69b49ca|reported in several forum posts].
FossilOrigin-Name: 8c25c4b18ad07861bf0e47f99f3db04b569b9b859ad0690602f748ddf3576939
2023-10-13 12:48:35 +00:00
larrybr 99d43979d3 Avoid potential overflow in hex(). [forum:/forumpost/7ac0c9c5ea|See forum post 7ac0c9c5ea.]
FossilOrigin-Name: 2e968114fd0e60eebcc088dec02684e10b06ac1ec42d6bedb5287362f5cbf032
2023-10-13 01:39:47 +00:00
drh 5dc4a405c5 Make sure virtual tables have been connected before trying to invoke
the xIntegrity method during PRAGMA integrity_check.

FossilOrigin-Name: 4a4eccb681741917c6771101d4e329f91eae9b035f4d345218e522bb55fff6da
2023-10-12 20:51:17 +00:00
dan 3046039309 Fix a problem with an fts5 secure-delete on a rowid/term pair that follows a legacy delete of the same pair.
FossilOrigin-Name: 579aea0c28e01a79620ac758edc02db3a01baaa073e7773b8f0b6f610479520b
2023-10-12 19:46:58 +00:00
drh 4b136ed70a Enable SQLITE_VTAB_INNOCUOUS for FTS3, FTS5, and RTREE.
FossilOrigin-Name: f34c533b6c1f8ef3f69c75c1039406c12751cdde1fbdcb4d9776b24455facf8a
2023-10-12 18:46:27 +00:00
dan a11499a156 Add test case for [29937081].
FossilOrigin-Name: d3b983edf7164d30ddb8b4b745a3feff9737149d85b1c428d6ad488ac6a1960a
2023-10-12 18:09:27 +00:00
drh 5d9a6c6734 Make sure the journal file is closed when transitioning into MEMORY journal
mode, to avoid an assertion fault in the new sqlite3_randomness() avoidance
code added by [c84e4483cb44f827].

FossilOrigin-Name: 29937081a986d88f495ad48748c35ff5829f0ac31dd4ad3e48d180ae2fcb9a0c
2023-10-12 17:41:18 +00:00
larrybr 35d6c24fd5 CLI to check for rare prepare failures. [forum:/forumpost/5be6395182|See forum post 5be6395182.]
FossilOrigin-Name: 286d1e8012a5f5d9e1fe6dce1a732f725b8a1837f66daf6aefb792e19e96f2d4
2023-10-12 15:12:38 +00:00
stephan 6a0f297da9 Unconditionally force use of SQLITE_ENABLE_API_ARMOR in the WASM and JNI builds. Their corresponding test suites still work.
FossilOrigin-Name: c11394b50d0687b6d6abad9c80d5cd3cdce77e9b9c278f40601c460f463744a1
2023-10-11 20:37:42 +00:00
drh ac4aea5102 Fix the use of an uninitialized value that occurs when doing a json_insert()
of a string value that contains embedded U+0000 characters.

FossilOrigin-Name: d3c0cbb90966316be9cd25e3edb501da42731e8a83c13227b90ce17d3975a2c3
2023-10-11 17:24:31 +00:00
stephan 582d65cce3 Add (prepare, step, reset, finalize) parts of the JNI level-2 stmt wrapper and associated tests.
FossilOrigin-Name: a7082f186f2b9b6666bbc65f2eadeb74d91fa0a681e3b2468b261ffd322bd249
2023-10-11 13:52:05 +00:00
drh 58c7b770de Simplification to sqlite3ApiExit(). Generates identical machine code, but
easier for humans to read.

FossilOrigin-Name: 793bbfa5af9721bc3a61e8e5eda46dfce2f5ff3f223a7564c9e1b09f11e53cb3
2023-10-11 13:34:18 +00:00
drh 853fb5e723 Fix a bug in the mkautoconfamal.sh script, introduced by check-in [3308fdda4b81c110]
so that the "snapshot-tarball" and "amalgamation-tarball" makefile targets
work again when run from outside of the source tree.

FossilOrigin-Name: 65ccf5fef812d43aed9e00af36c90e1a499d197e30148753790445e25ee1324c
2023-10-10 15:33:05 +00:00
stephan 0b29d37ef9 Start adding tests for the second JNI layer.
FossilOrigin-Name: 0177f4dfe8a5c03c1d5dd279c6babe5a87b596c2351373f845b89fc6abf7947b
2023-10-10 12:16:04 +00:00
drh aaf1341dcd Use snprintf() in place of sprintf() in a debugging function in the CLI.
FossilOrigin-Name: 5e5e4d2b4958c329578d1e5af4ed25c1b774f0ed2d15fa6747d7d7fbbba4fa46
2023-10-09 22:45:10 +00:00
dan 6c96bf2c3f Avoid calling sqlite3_randomness and taking the PRNG mutex when writing a journal header in "journal_mode=memory" mode.
FossilOrigin-Name: c84e4483cb44f827416d8caafa22f076b2f31b2024fe8c5b5bcb0c9955149d11
2023-10-09 17:54:34 +00:00
drh 01a5a19919 Add a TCL script that does various verification checks on the source tree
to make sure that generated code has been updated correctly.

FossilOrigin-Name: 1f1a358af77f4386f98010eeae8487e6d39548a6dfe58c2664552490e7661122
2023-10-09 14:56:15 +00:00
drh 7e60f6dbf1 Fix a compiler warning caused by the previous check-in.
FossilOrigin-Name: 7e8768bf8b4002b1c287f2bc95262548e2ae81b437936154f2bb1ea1f739a904
2023-10-09 14:47:25 +00:00
drh 50da20d5b1 Turn on SEH by default when building using MSVC.
FossilOrigin-Name: f57e8275cf1ab3ad8027044cda0893282d1c403a5aa9fabbb1c7de280597b5cd
2023-10-09 14:05:21 +00:00
drh faef28e6bd Fix a potential UAF caused by JSON parser cache spill.
[forum:/forumpost/b25edc1d46|Forum post b25edc1d46].

FossilOrigin-Name: a163fecca90cab9d1b7bf8ebac78d498775eed7b6d81e7920e3401633c3a4b60
2023-10-09 12:46:53 +00:00
stephan 66dacae4c3 Flesh out the error state captured by SqliteException.java. Doc additions.
FossilOrigin-Name: 5c5397ff15543f4b3620244d9e57e15708eafcab1d42c9f87b4a60f0c01e8858
2023-10-09 12:45:28 +00:00
drh 4a11142072 Fix harmless compiler warning in the test module for sessions.
FossilOrigin-Name: 3d5ec99397c183cfb8c5d31e1967e0df8a4d6edbea92bbdf728571e3a6a36d68
2023-10-09 12:39:59 +00:00
stephan c8f829cdac Add JNI Sqlite and SqliteException classes. Add Tester2.java as the main test app for the high-level API.
FossilOrigin-Name: 6acf52be7abce8dcf434c5ebf0d5e88859b033e6418077846247ecf00ccf9381
2023-10-09 11:46:32 +00:00
stephan fd013682d6 Minor JNI doc and public/private cleanups.
FossilOrigin-Name: c49d36ece283274963ce2e5a4db1e8f586dffa22e47f4adb93c625f918c3fd5d
2023-10-09 10:44:10 +00:00
stephan 68585ea342 Rename SQLite3Jni to CApi to (A) reduce name prefix collisions with incoming classes and (B) align with its counterpart in the JS build. Remove the Canonical annotation because (A) the new code separation will inherently make that distinction and (B) the line between truly canonical and semi-canonical (e.g. differing in signature overloads) is blurry enough that consistent use of that annocation is becoming an unnecessary burden.
FossilOrigin-Name: ca216b4486aff7d206ebfc3a5e84d48919c282425d4313396bc19313ffca8a0e
2023-10-09 10:30:54 +00:00
dan 3b381b4afc Fix a problem with sqlite3changegroup_schema() and patchsets.
FossilOrigin-Name: c4ab4200dc2538e1132d87d70fd309b26b0da8a918fede1cb09b567ea40ec889
2023-10-07 17:29:10 +00:00
dan 4bdcfc6666 Add the sqlite3changegroup_schema() API. To allow changegroup objects to upgrade the schema of a changeset/patchset under some circumstances.
FossilOrigin-Name: 03f9e50b15c9c2fb4636dee24c1491c45322578b9fed08c6f4360be07c5c3830
2023-10-07 16:32:02 +00:00
dan 18efe17553 Fix a problem with the changes on this branch and tables that use an implicit primary key.
FossilOrigin-Name: 1f9d10235ff32e72074be695049567135b02e681068ce117b66adc14a6214449
2023-10-07 16:07:02 +00:00
drh 8f0634549c Add a test case to prevent a regression of the leak fixed in the previous
trunk check-in.

FossilOrigin-Name: f99ff655d09763c4a22d065041644ece793d84c82c644931e89ccf50c4f4564a
2023-10-07 08:15:47 +00:00
drh 43e232dc47 Fix a resource leak: sqlite3_blob_reopen() was failing to invoke the
xDel() distructor on a register when it sets that register to the new
rowid.  This was never a problem prior to the large-column cache of
[771fe35074b50b8d] as that destructor was always a no-op.
dbsqlfuzz cd96368deaece480fb94d42427dde053737a650e.

FossilOrigin-Name: 545edd5ecf20a7feb99dc5ce6f338fa1f172c2e17b240cbede497f0729dbd3d7
2023-10-07 08:00:54 +00:00
dan 83e43dc757 Add missing source code comments and fix other issues with the new code on this branch.
FossilOrigin-Name: df39fbe9ab87937beb77af353cd55602290b185e222e0a92a3ebf9a9a0b9e2e7
2023-10-06 20:39:42 +00:00
dan 9fc208aada Update this branch with latest changes from the trunk.
FossilOrigin-Name: 897e926a5eaa0eab7e09e5003e4c15c974897be298a18ae85345962dc3f410a1
2023-10-06 19:46:19 +00:00
dan 53e91a5e22 Add tests for the sqlite3changegroup_schema() API.
FossilOrigin-Name: 5dab481c101b1523b1cfde92678cbc654ea26d946bf29da372d71c1f89cbaf46
2023-10-06 19:01:43 +00:00
drh 00eee7a786 Remove an unused parameter from the recomputeColumnsNotIndexed() routine in
order to squash a harmless compiler warning.

FossilOrigin-Name: 9bf4bfd68080367b58594e0d44b110b3ee9766420f648537fd7bc638dacefb72
2023-10-06 12:55:53 +00:00
drh 1935887a68 Ensure that all fields of static sqlite3_module objects are explicitly
initialized, in order to hush-up nuisance compiler warnings.

FossilOrigin-Name: f3b3d712d6e58b1cb8fdebd2b6b3125080b6b3ac8c7c849a8cc1e5e778d62fe7
2023-10-06 12:51:05 +00:00
drh 03f7e42538 Remove and unused static variable from shell.c.in in order to silence a
harmless compiler warning.

FossilOrigin-Name: 477577120b897bf15edc2a85e220d5c64a1d5a245354939269f6753d8140ac95
2023-10-06 12:22:14 +00:00
drh 568643fd15 Increase the size of some variables associated with the PMA sorter in order
to avoid any possibility of a signed integer overflow.
[https://bugs.chromium.org/p/chromium/issues/detail?id=1489025|Chromium fuzzer issue 1489025].

FossilOrigin-Name: dc3be3af471d90dd810c1e2cc59e83cf6a57f01971b1258ea0da402e4d577ef2
2023-10-06 12:15:01 +00:00
dan 16381d062a Add the sqlite3changegroup_schema() API. To allow changegroups to handle differences in schema created by ALTER TABLE ADD COLUMN.
FossilOrigin-Name: 309deee2dd8dd07623fce79f6bb62d5279d140dd0be3b34bc42af20b0507726b
2023-10-05 19:09:23 +00:00
drh 5d9446d100 Improved detection of corrupt databases in balance_nonroot().
dbsqlfuzz d1cf013c50a620b68c2a5bd240d29afd65e5f58e.

FossilOrigin-Name: a2464bbb825b5976ef974a2e6c17ea150f5e6fcd0dd0f144b9f9c1c22a9c9c82
2023-10-05 11:06:10 +00:00
stephan a357bdbfc4 Do not squelch exceptions from SAHPool VFS importDb() - rethrow them. Problem reported in [forum:c80fc578809b80a3|forum post c80fc578809b80a3].
FossilOrigin-Name: 325bcdea4a436e514d83095d3893caf07a714b718e1b643507179b101c108e3b
2023-10-05 11:04:49 +00:00
drh 3a3912f21c Remove a stray blank line from the beginning of btree.c. No functional
code changes.

FossilOrigin-Name: c89983dcfc208faa86b31717144c069572598e9770228264d69a044a84bde277
2023-10-05 10:35:51 +00:00
dan 6d8e91be9d Allow a session object to generate a changeset, even if columns were added to one of the tables using ALTER TABLE ADD COLUMN while the changeset was being collected.
FossilOrigin-Name: a3f435eccf3a2aa11cb7420e94af5efcdfa04e9c169c5aaf61fa5cdcb165ceef
2023-10-04 21:15:24 +00:00
drh 10e751937c The Makefile distinguishes between tcl8.4 and tcl8.5. Some makefile targets
require tcl8.5, but others (ex: "sqlite3.c", "shell.c", and "sqlite3") require
only tcl8.4.

FossilOrigin-Name: 770308db9776b8c0a70b8807463e89a9eddfe5552e25e67324cd303dc974f50e
2023-10-04 12:49:08 +00:00
drh 57996f53e4 Modify the main makefile so that it fails with an error if the tclsh found
by ./configure is not tclsh 8.5 or later.
[forum:/forumpost/4380363682708ece|Forum post 4380363682708ece].

FossilOrigin-Name: 1765f3b5a00a8ca20a7b9e18ac7f9d7de0679470b234b83aea83aa5b4d4d34e6
2023-10-04 11:52:44 +00:00
stephan 4f65a3cec9 JNI: when fetching text-or-blob/length pairs, fetch the text-or-blob first, then the length, as the API docs suggest.
FossilOrigin-Name: e4f9d3946fa570bccea2de17c5536901bdabd46cfe25678fdd37ba0e2bfd99b1
2023-10-02 17:12:16 +00:00
drh 51e3f7a1c3 Fix the length of the string in the new concat() and concat_ws() functions.
FossilOrigin-Name: 325243226520376f4a142864ae3fb98866f25bff4dc50a6b648ef98428a7169f
2023-10-02 17:06:28 +00:00
drh 43d71eb892 Remove an ALWAYS() from a branch that can in fact be false following an OOM
fault.

FossilOrigin-Name: 3a1feb1c469d3dd50e2558581199b16bfd59b9d5bcb0de5f1a8f0ec30a17b4d1
2023-10-02 15:56:37 +00:00
stephan 041fb16631 Pointer-casting-related fixes for JNI on 32-bit ARM (pi4 armv7l).
FossilOrigin-Name: 54441039ae3ebe39e42f008f77ce1be117cbda6daeed8b01739ad42a3c1f0754
2023-10-02 14:44:28 +00:00
stephan dc13d74140 Add JNI binding for sqlite3_normalized_sql().
FossilOrigin-Name: 2532e5662a2bbb3e6b4c4be3fad035734b684bdf59b178cb64b444ca6d8b956b
2023-10-01 12:15:38 +00:00
stephan ec15e551f9 Make JNI binding of sqlite3_value_frombind() return boolean instead of int and add tests for it.
FossilOrigin-Name: 906e2ed3e9647f5c2355e9fea2beee141767cae7016da9fa1fe88283726b9369
2023-10-01 11:53:40 +00:00
stephan f046b82324 Fix JNI binding to compile without SQLITE_ENABLE_PREUPDATE_HOOK. Add build option to disable all optional ENABLE flags.
FossilOrigin-Name: c04022b7407f77eaf0175e831ebcd6bbdc0af1cef0d42c5c11102aa8484f24ca
2023-09-30 17:08:29 +00:00
stephan d1878bed86 Make all SQLite3Jni methods which take a void-pointer-as-long-int argument explicitly package-private, as they're always for internal use only even if SQLite3Jni is eventually made public.
FossilOrigin-Name: 5e387275f69ab2d3159b4b67b8cbfc6270410b61e5ac1f988616e8d051f6572e
2023-09-30 16:19:57 +00:00
stephan 41c6232e54 JNI: rename sqlite3_errmsg16() to sqlite3_errmsg(), as the 16 suffix is superfluous there.
FossilOrigin-Name: df25b21689de84b7b8c940df39461d3d88f592f0ba2dddcfcbb0bebcea6ee7da
2023-09-30 14:48:21 +00:00
stephan 0018ef15a3 Expose sqlite3_stmt_busy() to JNI.
FossilOrigin-Name: 5733aa5fe341d50b84baebd8803a86e381bb95959a8bc733b8fff6fd4e732867
2023-09-30 14:34:55 +00:00
stephan 8f43696c8a Correct an undefined-value deref in the JS bindings, triggered by passing invalid args and then tripping over an undefined value while trying to report that. Reported in [forum:dd42df144651d779|forum post dd42df144651d779].
FossilOrigin-Name: fd4632540717c4771ac9ae1fe4400091a2cd0553639bf809abaf4ecbc54de4f0
2023-09-30 13:13:23 +00:00
stephan 9ac7e2d0fc Make (almost) all SQLite3Jni.sqlite3_... members public but make the SQLite3Jni class package-private, which has the same foot-protection effect but makes it much simpler to patch SQLite3Jni to publicize the interface later. Remove some of the extraneous foot-shooting protection from indidivual functions, in lieu moving it to the still-pending higher-level interfaces.
FossilOrigin-Name: 082b86683e77b2d4a30e1515552f52511324ef97c43b622b4dab7975ae9fbd7d
2023-09-30 10:59:18 +00:00
stephan 008b62f1ae Merge in and close jni-ptr-passing branch. The remaining pointer-passing adaptation can be done incrementally without affecting the interface.
FossilOrigin-Name: 7927c42410ba0d5fc8e6e08caaa5cbaaeb359869f17d1afaa082f1aa47fdb2fc
2023-09-30 10:37:36 +00:00
stephan d1ce2755f0 Make all native JNI sqlite3_...() bindings package-private as a foot-shooting protective measure (higher-level pre-native-call argument validation is largely pending). Move SQLTester.java and TesterFts5.java into the org.sqlite.jni package so that they can access the being-tested methods.
FossilOrigin-Name: ec82f7251acab7df40755ef5f456f36fe49b59e63a20be59bd610fc4280ba8cd
2023-09-30 10:31:56 +00:00
stephan ebce46f02f More work towards the new pointer-passing mechanism in JNI, and code-adjacent cleanups.
FossilOrigin-Name: 6c63987e893357dc8b10decaa96c30fb37b75481640a303e77a0d8224354491e
2023-09-30 09:41:58 +00:00
dan bee5657042 Add test case to ensure the assert() removed by [f090af77] no longer fails.
FossilOrigin-Name: 615ab71761754b072439f92e73fdb98c916b820937bcca8904f4be34936d5f9c
2023-09-29 15:56:40 +00:00
drh 8be48440b6 Remove an incorrect assert().
FossilOrigin-Name: f090af775f6d2ce8b50850f5c9e33546bcb9cff5467d99ca210530cb7ca83d5b
2023-09-29 15:53:55 +00:00
stephan 83f62816f8 JNI: correct a NullPointerException triggered via SQLTester.
FossilOrigin-Name: 0a873de76c0cbcd8e2eda3f0508e427f1dcb32b01798687c0545acfe10102179
2023-09-28 20:34:28 +00:00
larrybr d93cfa2831 Clarify serialization API doc w.r.t. buffer validity and usage, instigated by [forum:/forumpost/8922e2ad2ad41205|forum post 8922e2ad2ad41205]. No code changes.
FossilOrigin-Name: b488b9fb71652eca90d2bf73d32f3d748badf517859dc833c58e021b0e017194
2023-09-28 15:00:25 +00:00
stephan 0dabcd139d Adapted the JNI bindings for the sqlite3_value_...() and (pre)update hook APIs to the new pointer-passing mechanism.
FossilOrigin-Name: 4182f0275d5d65e04a130eeef4d44642a5ffeeb4b84430d240ea2605345f1404
2023-09-28 11:19:37 +00:00
stephan 5d1448d08a Convert the remaining macro-generated JNI bindings to the new pointer-passing mechanism.
FossilOrigin-Name: 250fd6ae806cf705c0f29ad30ad8fb885b12590848e7adae63bc21d874c6d3bd
2023-09-28 10:50:26 +00:00
stephan 50b2a41330 Convert the macro-generated JNI bindings which take a db pointer to the new pointer-passing mechanism.
FossilOrigin-Name: 5f47fb77db4ee77afc541e680559ad88e66ba7fd04b830e70f8be92cf8d0a60c
2023-09-28 10:27:01 +00:00
stephan 1d74432fef Adapted JNI sqlite3_blob_...() and sqlite3_close...() to the new pointer-passing mechanism.
FossilOrigin-Name: 0b22c8ef93e5ccd45316099fb8575e27620158b1992c0c70fe0348cfc10147f8
2023-09-27 14:41:49 +00:00
stephan a917ee7056 Adapt JNI sqlite3_bind_...() bindings to the new pointer-passing method and correct the mapping of sqlite3_bind_zeroblob64() to use zeroblob64() instead of zeroblob(). Related internal API renaming.
FossilOrigin-Name: 980d559fff6e55d1e2ef39f242a8a09313a936cfb141807db475bcceff924869
2023-09-27 11:01:32 +00:00
stephan 9afd67cce7 Add missing license headers to JNI annotation classes and extend the definition of @NotNull to include 0L as the equivalent of null to account for the current rework of how pointers are passed from Java to C.
FossilOrigin-Name: bccdfeb9efde20410bde545893fb98ce5c0c4d04a8e7797b868ba8994120e1db
2023-09-27 10:29:07 +00:00
stephan 4632f91403 Rework the JNI sqlite3_backup APIs to the new pointer-passing approach.
FossilOrigin-Name: 48aeb1e2cdeb4aec85c4f63a1f809215cd4b473791169e72b5ddf6d6bdc2f7b7
2023-09-27 09:58:36 +00:00
stephan 36f60e6c1a Start reworking JNI methods such that they pass void pointers from Java to C instead of passing their strongly-typed wrappers, as that is reportedly significantly faster than passing the wrapper objects to C and extracting the pointers there. There are still many, many functions left to rework for this.
FossilOrigin-Name: 66c814dd473731703ee00e1ff610acfdccf09d1b87dd2355795ed697d4ed5d3e
2023-09-26 21:37:52 +00:00
drh 61df55d0be Fix harmless compiler warnings in the testfixture testing utility.
FossilOrigin-Name: 5a39a02d2dfd9ed6171cd0bd434b2bc268d0ed8ead6e1a396d1603266d9493ef
2023-09-26 21:22:46 +00:00
stephan e81d229fb7 JNI: implement AutoCloseable for the sqlite3 and sqlite3_stmt classes, and adjust a few tests to use it. Override Object.finalize() for sqlite3 class but not sqlite3_stmt (where it triggers a JVM crash for as-yet-unknown reasons).
FossilOrigin-Name: b633d8bbdbd43464ee03058c273e5188117b9538ed5d5148a1a3851e4adf6410
2023-09-26 19:49:35 +00:00
drh 0e224d93ea Fix yet another assert() in the partial-index constant value optimization.
FossilOrigin-Name: f459d0806cf044fd07743e4c91d0a5a6ddf45b3b41004bde4278f190d99a4cf5
2023-09-26 19:38:24 +00:00
dan 1c67749166 Remove a NEVER() from a condition in the partial-index constant value optimization that can sometimes be true.
FossilOrigin-Name: 63aea8c3e0605edcf49ad1e5ce1a56d2690dcb8c4857043997545daab46ca035
2023-09-26 19:26:47 +00:00
drh a6e7202677 Remove unreachable code from the partial-index constant value optimization
([8d4160910d651246]).

FossilOrigin-Name: 7ad38254c37153efa72291d09800693ca60894359548eda877d59defa8c70d49
2023-09-26 14:57:30 +00:00
stephan 6f737371c0 Remove some outdated JNI docs.
FossilOrigin-Name: 2ca5cbbb2a8ee94fe9f4888dea695a4429aefa17611fd9ebe59bf4866290ab0c
2023-09-26 09:46:04 +00:00
stephan efa8369214 Minor JNI doc updates. No code changes.
FossilOrigin-Name: 63687cc659f06a1f6aa9d4496ef01d9f0adbee6184b8e265fb8feec1ad30449b
2023-09-26 07:43:51 +00:00
dan 47b427423d In partial index scans, if the WHERE clause implies a constant value for a table column, replace occurences of that table column with the constant. This increases the likelihood of the partial index being a covering index.
FossilOrigin-Name: 8d4160910d6512469cb0a060b89c2509dde1c8e33d9358034d7fb39cd494eabe
2023-09-25 17:46:02 +00:00
dan 1b96f9167f Another very minor tweak to code on this branch to save cycles.
FossilOrigin-Name: 2c805dc68112db7f06aea56a731a33e046e876851bdda3e725ba96f6da1bf2ee
2023-09-25 17:21:53 +00:00
dan cf0906575d Change the order of an if..else... in new code to make it slightly faster.
FossilOrigin-Name: f80dc64483a54a488e507da140836261ae1b864577cc95d8e869919d5a25e73c
2023-09-25 15:25:49 +00:00
drh cc11526e22 Enable -Wall for the compiler on --enable-debug builds.
FossilOrigin-Name: 63a7b521390001939909d43d908af78f7df7cb92272d2b74f038da918c2bef05
2023-09-25 14:20:07 +00:00
dan 873849b81e Fix a bad interaction between LEFT JOIN, bloom filters and partial indexes.
FossilOrigin-Name: 5775f92b31f0539c66d37e50689bec17a82c0e857a781331c03e34bc18157087
2023-09-25 11:12:39 +00:00
larrybr 1da3215d65 Cause sqlite3_exper_new() to replicate UDFs and custom collations early enough to appear in virtual column expressions during schema copy. [forum:/forumpost/e030aa4b3a|forum post e030aa4b3a]
FossilOrigin-Name: 8fc2c45558a826a84e6f7e98564573da125a5e2d5c635a85bdeba2abe29fbfa1
2023-09-25 00:39:43 +00:00
larrybr 16096e6bd1 Make expert changes acceptable to C89.
FossilOrigin-Name: a4f03c22ec13d2f9769ac655ad77ccd906ab8c0ee32df37139bd998c234a7a0f
2023-09-24 22:51:56 +00:00
larrybr e5adfb1a5f Merge expert changes to accept UDFs and custom collations.
FossilOrigin-Name: 8ead1b5ed6693c0e3c30428033049c95a1fe636d1d1eff1734d0a896b5ff1f5a
2023-09-24 19:47:37 +00:00
larrybr 5918adb374 Add minimal exercise of expert acceptance of UDFs and custom collations.
FossilOrigin-Name: 0f6bbb79cbb52f5ddf38840898ab6789a4e108353918296df20b332117e6a148
2023-09-24 19:38:22 +00:00
larrybr 7ecef617ee Sync w/trunk prior to merge back.
FossilOrigin-Name: 2d290854cd9b6cef70b53c28745e1ccee5b5443378407bfc726e452e7e7a0a95
2023-09-24 19:28:07 +00:00
stephan a2ead23868 Resolve the JNI FTS5 test5() failure and remove some nearby dead code.
FossilOrigin-Name: 5655c51f103c6dfade799ffb5ca2eb21b4360ada598741f373c952ae732535aa
2023-09-24 19:13:31 +00:00
larrybr a25d478ea8 Give expert ability to deal with custom collations.
FossilOrigin-Name: ac1dc1b6ded0e43acb5b2b707110f767f7bdb5cecdb6b28a982db174ae233d37
2023-09-24 19:00:00 +00:00
dan af7cce98c5 Add extra tests for changes on this branch.
FossilOrigin-Name: cb45f5b070cfdbb4358e8e909b0b34d658b5925db06e282b38046298a159c545
2023-09-23 21:31:40 +00:00
dan 7a9bbfe1fa Avoid an error when parsing a schema that contains indexes with WHERE clauses containing unknown collation sequences.
FossilOrigin-Name: d5dd39e37ab994ce5d75688a40c6494c17807431529e85eb2b11d58f367fe232
2023-09-23 19:25:03 +00:00
dan c18c7523a4 Fix a failing assert() caused by changes on this branch.
FossilOrigin-Name: d0e21f20bd8643d21c4b88fb75b83939d68e9b7118f7289a164656f11d2ee555
2023-09-23 18:52:22 +00:00
drh 9f811a35b8 Fix a harmless compiler warning.
FossilOrigin-Name: 7c4210253b660b385d14de3ae7ab30f038036308e1164ec17b40e2805b9b2235
2023-09-23 18:49:30 +00:00
dan 2d3c5385bf Add extra tests for the fts5 xPhraseQuery API.
FossilOrigin-Name: b5edea16317ccc896394011f45442af44d5ea1041b6abfe152c90412c78bfc5b
2023-09-23 15:34:02 +00:00
stephan 6c248201b1 Resolve the JNI FTS5 test5() crash, caused by two unrelated typos in JNI callback signature strings. That test now fails with an expected-vs-got mismatch but no longer dies in the native code.
FossilOrigin-Name: 0233f310bf6bbb84f76b25205af160951e0bf6d8b2f1bca4537384af4fe47e58
2023-09-23 06:50:19 +00:00
stephan 8a67a46340 Remove an invalid optimization from JNI code and add a missing check check for Java-side exception.
FossilOrigin-Name: b8151f879718f7e30520f7e5ae04bd6724ae98af067be097b1a00df2175a038a
2023-09-23 06:37:18 +00:00
dan bd42642431 In partial index scans, if the WHERE clause implies a constant value for a table column, replace occurences of that table column with the constant. This increases the likelihood of the partial index being a covering index.
FossilOrigin-Name: 66ed7abdfa228abde2052e3988589371f0e49b11582b1b4a83255d2df3a0aefa
2023-09-22 20:21:27 +00:00
larrybr 163af02aca Give expert ability to deal with UDFs.
FossilOrigin-Name: 3406b05b4f57901f64f9b5fc83fe0250b827ae7f342c2026818dab0840aafd23
2023-09-22 14:20:45 +00:00
dan 8aaf63c6ac Add extra tests for java Fts5ExtensionApi API.
FossilOrigin-Name: f9d62b853ce8bfbfdc9f137e984e7a1b51d70e88c38b136b4fad1e8ae6ee8913
2023-09-18 20:42:06 +00:00
dan 876f09b560 Extra tests for java Fts5ExtensionApi interface.
FossilOrigin-Name: c923893f3604b278277de1bb919ef713bf7a4296b7ff71451cfe19bc2ff03190
2023-09-18 18:12:03 +00:00
drh 38119058aa Remove a NEVER() in btree.c that could actually be reached, with the approriate
database corruption.

FossilOrigin-Name: d1fd00e0875f881cacdc581a75215ec1872a81969ac07b8ebe3aaa707a9a3640
2023-09-17 16:36:22 +00:00
dan f99a27fab9 Fix resolution of "rowid" and similar identifiers in queries that use nested joins.
FossilOrigin-Name: 37ec43d92bde13efc71fa57ff5e59c4a95b9054c298f844aefeb06d4a91ad0d4
2023-09-16 18:18:57 +00:00
dan 2599705105 Enable "OR IGNORE" support via SQLITE_VTAB_CONSTRAINT_SUPPORT for internal-content (not contentless or external-content) fts5 tables.
FossilOrigin-Name: c362bde4f4b8489947f080154d7fddcfd6e8e21d742a483c496fb7fbe59969d2
2023-09-16 17:11:44 +00:00
drh a91fe45339 Add a NEVER() to an unreachable branch.
FossilOrigin-Name: 6b6eb38979d68c06e382620c8813d6b67a3de02c4a7a029c84f924b9a2e380c6
2023-09-16 16:39:27 +00:00
drh 5bd96b2446 Fix minor code indentation inconsistencies. No function changes.
FossilOrigin-Name: 05107a0ae1456b746d3119af68d39532fad23a7eef88c09a9ef46ab7f8da4b9d
2023-09-16 16:23:20 +00:00
drh 5ddf0cbe25 Fix a harmless compiler warning.
FossilOrigin-Name: 9e9ff4ca3a205d0b599634782a5ad389fbe4823663550f48c54ca35dbc660dc7
2023-09-16 16:12:10 +00:00
dan 2e8edc1d45 Further tests and assert() statements for the change on this branch.
FossilOrigin-Name: 1c202d540ac362bfc747a9f8472e83c9d7614e38467f8b48787a669fb34664ba
2023-09-16 14:42:18 +00:00
dan 63702bccaa Fix resolution of unqualified "rowid" identifiers in queries with nested joins.
FossilOrigin-Name: bbcbd3d537d6790373d97f59386b8ce7fa2177db572af0f1babe058a76e25cc3
2023-09-15 20:57:05 +00:00
drh 124a6aa7d5 Simplifications and performance optimizations for the RTree extension.
FossilOrigin-Name: 04a333f5faf6b90592f1f69889ac6c28949955e186f39037cd639480b06feae8
2023-09-15 20:28:27 +00:00
drh ef2056e533 Drop support for the view-scan optimization (check-in [609fbb94b8f01d67]) as
it was causing multiple performance regressions.  In its place, reduce the
estimated row count for DISTINCT subsqueries by a factor of 8.

FossilOrigin-Name: f911f1c4977fbcae041243955cf2b98d8cc8baa337885a69be0f2b9bd2efa6f3
2023-09-15 19:51:18 +00:00
drh 58c10d9469 Minor simplification to the DISTINCT output row count change.
FossilOrigin-Name: 0738386d7c505a98768ddaff7ff1fc76f115882d92d6f84bf136b4aa2caad8b8
2023-09-15 19:27:36 +00:00
drh c09701db9b Do not reduce subquery output row count estimates due to DISTINCT until
after the decision of whether or not to use an index for ORDER BY has been
made.

FossilOrigin-Name: 27390051e86ad86fb35219329d359be9e83073f59782631af7fc519225e10565
2023-09-15 19:00:47 +00:00
dan 81b70d97eb Allow expressions like "<tbl>.rowid" to refer to implicit rowid columns of tables in nested FROM clauses.
FossilOrigin-Name: 59a1bbc69f5dbb33418fa4b383393fb13a46bc1e531577da8ad54ae2fad5a10e
2023-09-15 18:36:51 +00:00
drh 20220d4682 Experimental: Assume that a DISTINCT clause on a subquery reduces the number
of rows returned by that subquery by a factor of 8.

FossilOrigin-Name: 5a940e47d501f23347eaf084f4820e064e93665d19c8938c80715b71006ede8b
2023-09-15 16:15:33 +00:00
drh 658096e124 The view-scan optimization was added to enhance the performance of one specific
query, but it causes performance regressions on a host of others.  Disable it
(at least temporarily) in order to try to find an alternative way of fixing the
one specific query that it was created to fix - an alternative way that does
not cause performance problems for other unrelated queries.

FossilOrigin-Name: d9625a9eafe88859c3255849ee750cc6322d5a13ddad45107f9b2085c20eff50
2023-09-15 14:06:44 +00:00
drh 581b229362 Do not try to convert a double into an unsigned 64-bit integer, as that does
not work on all platforms.  A double can only be converted into a signed
64-bit integer.

FossilOrigin-Name: ce339046416e9ddeffe77f71a8bfb8c5b302160c3207f919aebd62902618ed59
2023-09-15 10:24:29 +00:00
dan c9823e3960 Tests for java versions of Fts5ExtensionApi.xSetAuxdata() and xGetAuxdata().
FossilOrigin-Name: 858fa236f8b673eb03cf2242e8202cd33ae1f13a43b59bdbb2eecdb21d42ef55
2023-09-14 20:56:42 +00:00
stephan a0f878959f JNI: move XTokenizeCallback interface out of the Fts5 object - that level of indirection is a holdover from when those classes were in the core package.
FossilOrigin-Name: 385ec08570451c0be212677d1b681c13d225dc690965effa2293e64cb3d56023
2023-09-14 20:02:49 +00:00
dan 93717c2306 Add a few more tests for Fts5ExtensionApi methods.
FossilOrigin-Name: 4ce2a7e8ed0f2859efc1038fd0812bc2b667be1479f45c081deccc2cf188c807
2023-09-14 20:01:18 +00:00
dan 9ba2d13ed3 Add a test for the java version of Fts5ExtensionApi.xRowid().
FossilOrigin-Name: 227facf879d2ade348cdb51f5b50ba2f95b8621acc0cf7a5fed4a310b4c76baa
2023-09-14 17:42:34 +00:00
drh e744f66008 According to [forum:/forumpost/9f6db917e1|forum post 9f6db917e1], older
MSVC compilers are unable to convert a double directly into an unsigned
long long int, but must first go through a signed long long int.  Work
around this by restricting the range of doubles that are converted into
long long integers so that only the lower 63 bits are used.

FossilOrigin-Name: 0ab05871ba36e2a0eddfbc700c1d39891c54c453727a4effcdac3327efec163b
2023-09-14 16:45:46 +00:00
drh e68decd54c Document the use of OPFLAG_ISNOOP as the P2 argument on OP_Delete. No
functional code changes.

FossilOrigin-Name: d88f41b2cf2b721170d2428a50b717976091389d9a07d0ffa15c3323b0eaad37
2023-09-14 16:02:56 +00:00
dan 82cdf4987d Avoid a segfault in test program showdb.c that could occur when analyzing a corrupt db.
FossilOrigin-Name: 6bf3e90687d48243544cc07baa01cb1b25ee0b77c59437f96c8da8e5d8b8095e
2023-09-14 14:05:51 +00:00
drh 60e53c57cf Improve the sqlite3IntFloatCompare() routine so that it is testable.
FossilOrigin-Name: bb221381fa38db5be1222d89c567a9bca0e6c441e26a8c797bd326b263556afb
2023-09-14 13:10:17 +00:00
drh dc03af67a4 Do not set the global bUseLongDouble flag based purely on sizeof(long double)
being more than 8.  That is a necessary but not sufficient condition to use
the long double routines.  Instead, do a run-time test to verify that long
double really does provide extra precision.

FossilOrigin-Name: aa999d490b743f455f2fb6c41009098330380f0bc2e9b1c28fbc82141a9138ce
2023-09-14 10:46:50 +00:00
drh 647e3ed2ba Reduce the number of calls to sqlite3_mprintf() made by RTree.
FossilOrigin-Name: f158b7d4917e0951fbb86a6f438abcb618d8602566fa54bf04c05a37f3a73513
2023-09-14 01:46:57 +00:00
stephan 595c3ecc94 JNI: enable the fts5-customization bits by default but elide them from the docs until it's clearer where they're headed. Unrelated minor doc tweaks.
FossilOrigin-Name: 21adb1aef24398fba918a5e1479ce2b6fd7e86d87eb9f2bea86a0eb43e8809c2
2023-09-13 21:32:20 +00:00
drh 23164c984e Improved comments on the hasHighPrecisionDouble() routine. No changes to
the underlying code.

FossilOrigin-Name: 810c635ce063d873e969bf83339c654f6008e84ce8a61f0ffc61806e98d13dde
2023-09-13 20:35:04 +00:00
drh 5b5d4492f2 Determine at start time whether or not the underlying hardware supports
high-precision long double computations.

FossilOrigin-Name: 9a854b919667e0e679a259542b2ee444ee416dbd73ecd9458f6ced35d9d3f264
2023-09-13 20:06:46 +00:00
drh 7de8ae22f7 Omit the Reinsert algorithm from RTree. This causes most benchmarks to run
faster, at the expense of having a slightly less dense and hence larger index
(example: 33 entries/node versus 34 entries/node).

FossilOrigin-Name: b3049a1d3dbdd63c471499c2f6b417655defe9ad90228e7cc722f5be877aae01
2023-09-13 17:30:12 +00:00
stephan 1eca330a08 Doc corrections for the previous checkin.
FossilOrigin-Name: 9ea0a9f39d03707d251af5af08d1ba94958704ba74019d7e8823ccd21936023c
2023-09-13 17:16:25 +00:00
stephan 181063d477 Add JNI sqlite3_prepare_multi(), based on feedback.
FossilOrigin-Name: fa1c1534724b03debc83ae35c2fadab83faf4b4e62b91981fed103888de41396
2023-09-13 17:11:32 +00:00
drh f9967cb302 Performance optimization to cellContains() in RTREE.
FossilOrigin-Name: 43cde22bf3f36687df231eddf642581d1d4f4102ad8568d31f5b2ff0302ca800
2023-09-13 14:07:07 +00:00
drh cdae00b3e8 In the ChooseLeaf algorithm of RTREE, do an initial pass through the cells
of a node looking for solutions that involve no cell enlargement.  Only look
for the minimum cell enlargement if the enlargement is non-zero for all cells.
This results in a performance improvement by reducing the number of calls
to cellUnion().

FossilOrigin-Name: 59f0e239d19393190911ea3bd89b5a24be0d85d64ccf51906efc9537ad5d7298
2023-09-13 13:12:08 +00:00
drh 386e359044 Reduce the number of calls to cellArea() in the ChooseLeaf() algorithm of
rtree.

FossilOrigin-Name: c633fe6be0edc07a0aa1ac819d58b6c629b7c95b47b63516ae1b0a937f6a2b89
2023-09-13 12:06:02 +00:00
drh f4ae37ca44 Remove unused variable from the ChooseLeaf algorithm in r-tree.
FossilOrigin-Name: fb2e4a8067edc29ba64973820f265b21dfee0d32f4d675d32100d5eef93c2830
2023-09-13 11:36:44 +00:00
dan fef1c11f92 Replace an if() condition in fts5 that is always true with an assert().
FossilOrigin-Name: 2170312c8d7f076cbb8319227de3fac981432dae186bc1928cd217e41119b580
2023-09-13 11:24:58 +00:00
larrybr 111815609c CLI .import to accept EOF in lieu of record terminator on last field of CSV (with multiple field records), per RFC 4180. [forum:5b21c25bdfa|forum post 5b21c25bdfa]
FossilOrigin-Name: 6f7842f577a28df1f809cd4bae9e8eafa26f2b54a25a1362ebbdebf5026be57c
2023-09-12 23:21:39 +00:00
dan 12439f9c16 Fix a use-after-free error in fts5 that could occur when querying the "rank" column immediately after another connection changes its definition. [forum:a2dd636330|forum post a2dd636330].
FossilOrigin-Name: cb54c2da52d3175844127ead41cfed18793e91ea52e02af2d57c1d17b4312437
2023-09-12 18:36:46 +00:00
stephan 0148013416 Clarify some metrics output in Tester1.java.
FossilOrigin-Name: 4ae7199a82f0b6e0f5575e39d8bd454e527ab949f0c59b773a44a078c65c5676
2023-09-12 17:49:25 +00:00
stephan 18e143d1d5 Re-add the fts5 decls to sqlite3-jni.h, removed in a rebuild without fts5 enabled. Need a better solution for this problem.
FossilOrigin-Name: 6f269790a09350f49103bb0925e2a78a1f9b7a8aad84408eabbb8d64ef79d551
2023-09-12 17:06:51 +00:00
stephan 09d72e4a6e Rename JNI sqlite3_errmsg() to sqlite3_errmsg16() for overall constency with the text()/text16() family of functions.
FossilOrigin-Name: c4a8d8a5711bd2abeaf1c31046784d1bccff4b98e96522250866d1ee8ec6a9fe
2023-09-12 17:03:40 +00:00
stephan 1110f8ffcd JNI readme fix.
FossilOrigin-Name: 7dde000efcf170c33701947d1aab71bb45b2b0ae8646ee41bb2b2adbee56d1e6
2023-09-12 16:33:57 +00:00
drh 50925d23ab 64-bit builds on Windows default to using UTF-8 output (as if the -utf8
command-line option had been specified.)  32-bit builds continue to use
Windows code pages.  There is also a new -no-utf8 command-line option to
force the use of legacy code pages.

FossilOrigin-Name: d8c7560e8822f336e8c4b300eb1f2e55203fdf9e756d2e8af719563235f79ebc
2023-09-12 14:36:07 +00:00
drh 09e96ea731 Show the "(utf8)" tag on the CLI banner in Windows if in UTF8 mode.
FossilOrigin-Name: 822699a4d9756ec68f17d6e06da7f994730bcf5c7d69ca15e9131721c4ff3b19
2023-09-12 14:09:45 +00:00
drh ceeb9eeaac Add the -no-utf8 option to the Windows CLI to cause UTF-8 mode to be omitted.
FossilOrigin-Name: 4cb799c690986b8bd38d07461998824fa53418f7fe31f59d0bf38cae328d9b89
2023-09-11 20:09:05 +00:00
drh 17ca53da26 Make the -utf8 option the default behavior in the CLI on Windows for 64-bit
builds.

FossilOrigin-Name: 8b3c306def81546c5987f0f245d2bf3960218254c2833e9c27cd242e9118db62
2023-09-11 20:02:38 +00:00
drh 833ed7ee64 Refuse to build amalgamation-tarball and snapshot-tarball if the TEA version
number disagrees with ./VERSION.

FossilOrigin-Name: 3308fdda4b81c110ba4a66d0b325e7653c2f8155e7864aeb78991ed1da061836
2023-09-11 15:27:27 +00:00
stephan 5c3a25b450 Merge in JNI's significant divergence since it adopted sqlite3_client_data().
FossilOrigin-Name: e8e07dbbeaa7799eb0b90726e18e994aaf8c8d316ab4bdb06da732bc51cf0919
2023-09-11 15:20:15 +00:00
drh a9d788f08f Add support for the sqlite3_get_clientdata() and sqlite3_set_clientdata()
interfaces, to better support JNI.

FossilOrigin-Name: 9806c0dd2802d68b67c25c4f3347ed532f9a98b051e775d34e9182dd2f099891
2023-09-11 14:55:05 +00:00
stephan 7fa8d65539 Roll back [84e38341aeab] because a direct pointer comparison is ill-advised when the client-data string is dynamically allocated.
FossilOrigin-Name: 7b884832b71c23e62ba3c0d53f7c89199734c351f909d84ac19ac18c7ddccbd8
2023-09-10 10:56:28 +00:00
dan ef2e43304e Remove out-of-date comment regarding use of Parse.pConstExpr.
FossilOrigin-Name: 71548f72ad578db3d6ee409956386ace23ab2258d37cdc29ef2fb126e48f1ee3
2023-09-09 17:53:55 +00:00
stephan 8f825a7a1b In the JNI build, emit a reminder to not check in the javac-generated sqlite3-jni.h when FTS5 is disabled because changes in that feature flag result in unnecessary and large diffs in checked-in generated code.
FossilOrigin-Name: caceb52fb58f924e7cbbebac05e7fd7822b7f6f56a3f834392d2be801bf04633
2023-09-09 11:20:35 +00:00
stephan 8ea10ea520 Disable FTS5 in the JNI build by default until it can be thoroughly tested. This is mainly so that the public-facing javadoc does not include it.
FossilOrigin-Name: 6f25f02b70f561864264a71a85cb5efa05550743371fd655804033ea08d00f33
2023-09-09 07:52:05 +00:00
dan 1b2d170a8f Add extra tests for [4b60a1c3].
FossilOrigin-Name: 6357491bd1b97f7abddf1a83860f3763cd870033bddc74bd9994a6440fe8c762
2023-09-08 19:18:02 +00:00
dan 410acf6944 Fix a problem with fts5 secure-delete mode causing fts5 to corrupt its records.
FossilOrigin-Name: 4b60a1c358c966f161601e749ccb0a7c5f4126e20350f4d6c83b6f35841fbe0a
2023-09-08 18:34:42 +00:00
dan fb77b3ed3f Add -DSQLITE_OMIT_LOOKASIDE=1 to the "Sanitize" configuration in testrunner_data.tcl.
FossilOrigin-Name: a917ebf17b27951d1c6906e9068e816ef29861701f2e8f4f1a13acce5737f680
2023-09-07 17:54:12 +00:00
drh 8525e2d931 Enhance the ./configure script and its associated Makefile.in so that the
--with-linenoise=DIR argument cause the linenoise command-line editing
library located in directory DIR to be linked with the sqlite3 CLI.

FossilOrigin-Name: 6c7822b554c01f01e3e02a385b3370313022b16ba8d932c2ba5d3c3be61361fe
2023-09-07 16:53:30 +00:00
dan 09f1652f36 Fix a buffer overread in the sessions extension that could occur when processing a corrupt changeset.
FossilOrigin-Name: 0e4e7a05c4204b47a324d67e18e76d2a98e26b2723d19d5c655ec9fd2e41f4b7
2023-09-07 13:53:09 +00:00
drh 0a4c31d87b Fix a harmless compiler warning in the sqldiff.c utility.
FossilOrigin-Name: e6390a656713b855258277b65066d2a701cedd05981f1672c9acc2d6dc37d032
2023-09-07 13:48:42 +00:00
drh 6e2b63893c Add the "tool-zip" makefile target with the intention of using it to build
the "sqlite-tool-*.zip" deliverables.
deliverables.

FossilOrigin-Name: 06e4af492d669bb45c00b1b876cd82ec8813ac9ed580eb1dddd18147f7fbe7f6
2023-09-07 13:43:46 +00:00
drh dd69129f2a Fix a problem with the new xIntegrity method for virtual tables, and also fix
a bad assert() in FTS3 that was found by the new xIntegrity method.

FossilOrigin-Name: 52bbf44f2d9addc2b5f68b0fe33542470852310ce3a283e2c7ff4c52831d0ed1
2023-09-07 02:13:01 +00:00
drh 93b461ff00 Add documentation to sqlite3_get/set_clientdata() to make it clear that these
are security-sensitive interfaces that should not be exposed to potential
attackers.

FossilOrigin-Name: 2837061d66672a0a73c3fd2ff35ce0e1a66ee6d5365be25d4cc0ccba170c3665
2023-09-06 17:07:53 +00:00
drh d4bb0896d4 Add the xIntegrity method to the sqlite3_module object, thus enabling
PRAGMA integrity_check to operate on virtual tables.  Make use of this
new method in the FTS3/4, FTS5, and RTREE virtual tables.

FossilOrigin-Name: 2f08e7d233b6ddc28b61f0d17ae9b815a91c3c6e080862ce009dc0ad73c64cf5
2023-09-06 16:51:13 +00:00
drh 9e5d21092d Fix unreachable branches.
FossilOrigin-Name: f00fc16394427f25249dd58c25a9115fef1ae389e232d574b4e91db2e7f8c04d
2023-09-06 16:22:48 +00:00
drh d5ab4dd9e4 Change the xIntegrity virtual table method signature so that it returns
an integer error code and writes the error message into a parameter.

FossilOrigin-Name: f1d4024a8ca06cf954aaf1f612684d1a5d28492bde757695db3f22c50c649709
2023-09-06 14:00:01 +00:00
drh 961c2a9f36 Add the xIntegrity method to the sqlite3_module object. Implement this
method in RTREE, FTS3/4, and FTS5 so that "PRAGMA integrity_check" also
verifies the correctness of shadow tables associated with those virtual
tables.

FossilOrigin-Name: 17bede8cdefd968210dd8a5a2617acbe12ba2c99fdd5e88c5def8665e7bec2d7
2023-09-06 12:52:00 +00:00
stephan 7c1588b3ad Move Java-side FTS5 bits into the fts5 subpackage to (A) make it easy to optionally bundle it (or not) and (B) set a precedent for puting extension APIs in their own package.
FossilOrigin-Name: 4c773e1f331cd5854d4c6e8825197933c0bb6827b7437e56ac0ad650d1ddf55e
2023-09-06 07:39:25 +00:00
stephan f31b9fcf86 Java FTS5 API renaming, for consistency.
FossilOrigin-Name: 5e4cc9f386364858c6457c40f13f01e1826a59086aa7f0fa10244ea846f5acfd
2023-09-06 06:54:25 +00:00
drh 5a05a68315 Fix a few SQLITE_MISUSE returns so that they call sqlite3MisuseError().
FossilOrigin-Name: 93f74490faf8cc07e107afdab6737c6e5141ae1f01a05142bfcede2dd1b2ba4e
2023-09-05 15:03:23 +00:00
dan dd24b1c8a1 Add tests for, and source code comments to, fts5. No changes to code.
FossilOrigin-Name: b12afff4efe4de84388d102060e8c312abd2f9eca8270b3c0f01ac6d1f2e329a
2023-09-04 16:48:31 +00:00
drh 25a6e6ec8b Do not make assumptions about the byteorder of PowerPC processors.
FossilOrigin-Name: 4a2498fed4c5436fbcd4179db85e2741fdab37d42b0eebf12f41ec4573ce2c61
2023-09-04 12:50:17 +00:00
stephan 0c072b698b In JNI routines which set an OutputPointer.value, always do so, even on error, for consistency.
FossilOrigin-Name: d0df62f0af19a69f7ceb3ad1dceda0d8cc2ca5016a6e2a3a1e36356424c3ca49
2023-09-04 06:15:37 +00:00
stephan 3aeb58c90c Remove several unnececessary functions.
FossilOrigin-Name: 84433c72b0b08e7906ef87758caffe98f95df812945a7aea675bbc20791e33c0
2023-09-04 05:58:13 +00:00
stephan 4eaf5883b3 Move an internal utility class out of the public Java API.
FossilOrigin-Name: 8e1ae3197a62796565b7260b230057bdb3f136edd00a83f8a63532d44d386243
2023-09-04 05:34:30 +00:00
stephan 411d9e7b2e Expose sqlite3_bind_parameter_name() to JNI. Extend the definition of null for the @NotNull annotation, to consider closed/finalized Java-side handles wrapping C-side resources as null for its purposes.
FossilOrigin-Name: fc34e2bfa4a2255f019a2514367e58596837289de49f7fab87279c8b40c7f119
2023-09-04 04:23:31 +00:00
stephan 14412e9526 Add the missing sqlite3_blob_read() to [9a9945c405cf]. Elaborate on the definition of the @NotNull annotation.
FossilOrigin-Name: 85952b4a52a09e9da35754c1a1ec70b1bf277296011a2d37ac536b33437223d7
2023-09-03 14:41:13 +00:00
stephan 805e8c96b9 Expose the sqlite3_blob_...() APIs to JNI.
FossilOrigin-Name: 9a9945c405cfe9b6bf399655f498457da66b06c8b92014510ab9fb83fbb1c7d4
2023-09-03 14:13:29 +00:00
stephan 7dfacc9f96 Expose sqlite3_system_errno() to JNI.
FossilOrigin-Name: bac54da29c19ef5e0a76599b5d10b377ecd7b391a651af99526529df16a83c7d
2023-09-03 12:46:09 +00:00
stephan 286f30f85c Expose sqlite3_stmt_status() to JNI.
FossilOrigin-Name: d266acc23ecb7e76c8c68c6e89a76e6f3054f33f0262e60e06b258db5a5e2ccd
2023-09-03 12:32:09 +00:00
stephan 1943356268 Expose sqlite3_randomness() to JNI.
FossilOrigin-Name: de9692242132b8f2c92ef4acb08dd3063327b18666cbb17c4f1153dee9146eaf
2023-09-03 12:17:34 +00:00
stephan 83a8b6dd82 Expose sqlite3_get/set_auxdata() to JNI.
FossilOrigin-Name: 0de3271717e0298070097d7ea0ecb996d2e95cf65384e494515a554d0a1dffed
2023-09-03 11:58:33 +00:00
stephan e30436b605 Expose sqlite3_get_autocommit() to JNI.
FossilOrigin-Name: 67391c6588c71af411767d1e4b63c5041a8a9e669102da318e3482ccfc9d9bb9
2023-09-03 11:16:48 +00:00
stephan ce9902f8c2 Remove some unnecessary code.
FossilOrigin-Name: c7f9bbbbf0252c9749450e3ec994bf5ac945bd62428657ddff469291a0fd4b0d
2023-09-03 11:08:31 +00:00
stephan 54021c3bd0 Add a couple more sqlite3_backup tests.
FossilOrigin-Name: 5c2cf89d2c3ae5fc31b5e311bc2f2c1fef0037bdb0dff48c0a2a6bb6610e0215
2023-09-03 10:36:21 +00:00
stephan 24a689cf01 Export the sqlite3_backup_...() APIs to JNI.
FossilOrigin-Name: 865a3df5d550f6f4edbf95854750706e4e747d8f1825ae73d300b8e31934959b
2023-09-03 10:23:03 +00:00
stephan 2966b85df3 Export the sqlite3_keyword_...() family of functions to JNI.
FossilOrigin-Name: bd554db39159d8a538ce913d55285e3c417db8823c717a3e34bfa0678de42be7
2023-09-03 09:28:45 +00:00
drh d3c5471a9a Performance optimization to the OP_MakeRecord opcode.
FossilOrigin-Name: 2aef9af3dd493a82ba090ccb8ab1b8974349392ec3f1c35db7a3dbbec41b5c51
2023-09-02 19:35:15 +00:00
stephan de4d1c357f Add sqlite3_config(SQLITE_CONFIG_LOG) support to Java and correct clearing of SQLITE_CONFIG_SQLLOG. Correct missing names in propagated UDF exception messages.
FossilOrigin-Name: 652e2e82100ac3d8238d15ef6d43de4162fd02d695db4936ad5706fe4f2d7dc3
2023-09-02 14:36:41 +00:00
stephan 7d31de600b Expose sqlite3_complete() to JNI. Slightly widen the definition of "canonical" for the purposes of the @Canonical annotation. Add a few new tests.
FossilOrigin-Name: a59fe0cd9552128ca4186f4e66f0d188f2a57c7647f43828e42cb95801f350ce
2023-09-02 12:53:25 +00:00
stephan 216433636d Duplicate code consolidation.
FossilOrigin-Name: a1872ae959cca11d5d8bc224aaeb0b53e772d999df9924b2e9ea84ceedb99148
2023-09-02 11:26:36 +00:00
stephan 70b58fc119 Remove a superfluous level of indirection in the JNI internals.
FossilOrigin-Name: 8dca6f7660c15eacbda20da1c66c9ef1de36864f78750658226b1a7baf22b726
2023-09-02 10:18:10 +00:00
stephan 63f4a9c4db Further JNI cleanups.
FossilOrigin-Name: 30e38173c3ece0c9f8e7a9710f46cb5e8e8ef101c04531318a7adb070242f5dd
2023-09-02 08:51:14 +00:00
stephan 21d4f0cc7b Optimize sqlite3_get/set_clientdata() for the presumably common case of a static string pointer.
FossilOrigin-Name: 84e38341aeab4fd51690e8536d0101d00e3fb11cc50ebcff05ed219c98328872
2023-09-02 08:04:56 +00:00
stephan 49a40ef6d2 Add a timer to the JS SQLTester app to warn if it appears that loading the module has failed, which is commonly caused by the test scripts not being compiled.
FossilOrigin-Name: f9c1f9cad1ad22f689a4afa13d59bf9969ddaed6624cbc16cb1bf5d1fd0c8a5b
2023-09-01 17:51:09 +00:00
stephan a5f425cc6e Correct a Tester1.java test which inadvertently created a spurious db file in the current dir. Unrelated minor cleanups.
FossilOrigin-Name: 016bbdadbf9f95cef185d2606c23e3b3c724586fcca470e11e6fbdbaefd75c79
2023-09-01 16:28:46 +00:00
stephan 4ea63e5609 Make the JNI-internal metrics opt-in rather than opt-out so client builds won't have them by default. Unrelated doc tweaks.
FossilOrigin-Name: aa72d25a22c80a7a376127266b8923f0661147c8bc483baa327230364851a255
2023-09-01 14:20:39 +00:00
stephan d086065644 Make JNI interfaces of sqlite3_column/value_text() match the C ones better. Internal JNI cleanups and simplifications.
FossilOrigin-Name: eb24f97253d9c8e7c728c2ac67a0824b10ca67362ac4f8abb94d5d3c54c58c5b
2023-09-01 13:27:59 +00:00
stephan dba0ceea60 Second half of [1c532e80].
FossilOrigin-Name: 8ca1d815a57be1fade59fb8ea5705c27b10294e4959c8a9c624f1623df6a5f63
2023-09-01 11:10:09 +00:00
stephan f551aa4e80 In the OPFS VFS' importDb() methods, overwrite the header bytes 18 and 19 with 1 instead of 0. Both seem to work, but 1 is correct.
FossilOrigin-Name: 1c532e807bf8466b67d9600ab9630a6736de77259e9a71ac435641715ee0e04b
2023-09-01 11:05:22 +00:00
stephan 7862e19468 Remove some newly-dead code.
FossilOrigin-Name: dc0fa76b395c5e352116dc33cc1b455e5e9c9f01c285af52ccba4d37e4453b87
2023-09-01 10:37:15 +00:00
stephan 03ca59afb9 Expose sqlite3_limit() to JNI and remove the all SQLITE_ macros from the Java interface which are not directly exposed to client-level C code (SQLITE_MAX_... and SQLITE_THREADSAFE_...).
FossilOrigin-Name: 5fe5b0a585dbfa06cfca1fea40aea5ea3ccfe8295f41306ad2d5b851ace27203
2023-09-01 10:32:31 +00:00
stephan 55171a75ef JNI build improvements. Rename a Java class. Get the jar target working again.
FossilOrigin-Name: d086b7844cace5c997261c97565aeef62aaeeef727ccc7e83f17c54d6217b779
2023-09-01 09:43:56 +00:00
stephan a4b47b034c Expose sqlite3_stmt_explain(), sqlite3_stmt_isexplain(), and sqlite3_stmt_readonly() to JNI.
FossilOrigin-Name: 208b786afe16eafaf0ce791f319a5e05f733a7b71ce1c542e1b83481b013ec38
2023-09-01 06:50:17 +00:00
stephan 0d3f0a9c11 Export sqlite3_txn_state() to JNI.
FossilOrigin-Name: d732f71d0a292dbb493f79f7c6ecd8a4effbfbc91453b1c54bdd9becf2d75bdb
2023-08-31 19:35:59 +00:00
stephan 63e7ed3b44 Minor JNI cleanups.
FossilOrigin-Name: 2e2bb841ef8b53266ec48d8c3408d6396f29f17922e858eac1b4f12f4adeb05e
2023-08-31 18:34:43 +00:00
dan 8628c10e27 Do not disable unused columns in a UNION ALL sub-query if any component of the sub-query is DISTINCT.
FossilOrigin-Name: c84d5602ac9bfb4f12c3cf62033af616e51913c26877d1a0761363a625295f53
2023-08-31 18:00:10 +00:00
stephan 062bafb851 Add convenience overloads of JNI sqlite3_table_column_metadata() to simplify usage.
FossilOrigin-Name: faf4e6d398f444d970be8b1364c984c67ccbc5f8a27f3aa93f05b8a8de7bec9b
2023-08-31 15:24:46 +00:00
stephan 0c2ba994d2 Export sqlite3_(db_)free_memory() and sqlite3_table_column_metadata() to JNI. Further internals renaming for consistency and legibility.
FossilOrigin-Name: 7c86aa3400ed591d38c1828f366f4b5de97954c2b301919d3f06d9c2d3d7d1f2
2023-08-31 14:57:01 +00:00
drh 3823208d5b Use mutexes to make sqlite3_set_clientdata() and sqlite3_get_clientdata()
threadsafe.

FossilOrigin-Name: 443ea20ddb0f3bf5d77ef59cd4678f0e32d7da328002bb44d6fc080a53a37e29
2023-08-30 18:51:26 +00:00
stephan 7fc4223411 Replace JNI's per-db-instance state tracking with the new sqlite3_set/get_clientdata().
FossilOrigin-Name: e7c11d34ee2eebdca4d9db1496bbb4152e4c62745c083ad5e0337733e8d1254e
2023-08-30 18:45:42 +00:00
drh a7ec1f9a1b Fix a bug in json_array_length() introduced in version 3.43.0 by
check-in [df099ad713011b67].  If the JSON input comes from json_remove(),
the removed array entries are still counted as part of the array length.

FossilOrigin-Name: 69a635958a4a14187e88dd297df8978a4805b1b0c7bff3ec29d5632c0f68d889
2023-08-30 18:19:40 +00:00
drh d25d938877 Remove another unreachable branch in the sqlite3_set_clientdata() logic.
FossilOrigin-Name: 57e31e6b10b2aa68b6039914d191819bae0aa60999a99d5ef23ca18128b72e0e
2023-08-30 17:41:55 +00:00
drh a5af4a6614 Remove an unreachable branch, and improve documentation of
sqlite3_set_clientdata().

FossilOrigin-Name: 565c68adee64b6c838f2fcb162485b6cfe9a976adb79de4370be98fcd4af2baf
2023-08-30 17:14:12 +00:00
drh 7bb5a6db40 Fix the AVG() and TOTAL() functions (after the SUM() fix of [77d3dcd283595c52])
so that they work with infinitites.  Fixes a bug introduced by check-in.
[c63e26e705f5e967].  Bug reported by
[forum:/forumpost/8960fb40cc|forum post 8960fb40cc].

FossilOrigin-Name: 6df6f17ccb404c648076ccff4200d0eb5437f0e3e82424bf3da5ea682b107bb4
2023-08-30 16:03:27 +00:00
stephan 85a05d895a Further tweaking in both SQLTesters.
FossilOrigin-Name: 46b0eb98e7a56cc188836c46f4289de6281f80e6bc6eb33e0aa9133a0f86f00c
2023-08-30 15:51:42 +00:00
drh adf54de51e Fix to the sqlite3_get_clientdata() interface.
FossilOrigin-Name: 937cd1762b36d48d9e7bafe42e99e524c9b5528d39f64521bce2f81d9c887db8
2023-08-30 15:42:41 +00:00
drh 10deb35995 New experimental API for attaching client data to a database connection.
FossilOrigin-Name: d542837fdb42ebe810fc99225860d2cc7e6dd829a635bde820a09beff6bcb481
2023-08-30 15:20:15 +00:00
stephan 8dd07389ac When a JS SQLTester script throws, report the exception details back to the UI regardless of whether it's fatal.
FossilOrigin-Name: 273d3b05f630d399d42914e95c416b107b4746bbef129cfba9d00fd921666261
2023-08-30 14:20:02 +00:00
stephan 24c32c2e39 Add a JS implementation of Java's SQLTester.
FossilOrigin-Name: b530792a514d95c4e8f93cf2170d9fc4de367055fa1704fc171551c946024fa9
2023-08-30 13:07:35 +00:00
stephan e621556724 Add a UI, of sorts, to the JS SQLTester.
FossilOrigin-Name: 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c
2023-08-30 11:54:43 +00:00
stephan ac5e1f82ce Add a mechanism with which to import external SQLTester scripts into the JS testing tool.
FossilOrigin-Name: bb08ba020ce1d86ca6aa92f43d5ae915f67d08fa73120e1f603d150e76166624
2023-08-30 00:22:54 +00:00
stephan 4f1387e9ab Add directives support to JS SQLTester comparable to the Java impl. This brings the two to feature parity.
FossilOrigin-Name: 7cef4a8300826adbdcb3b205e134a4272b12b4aa7dbee97731ac12282a4a9f06
2023-08-29 21:30:37 +00:00
stephan 267c44771f More fleshing out of JS SQLTester.
FossilOrigin-Name: 8c503dfb9fa15389613a819fcc1792e23d3c05f99a9f450f82eac5125298726f
2023-08-29 20:44:40 +00:00
stephan aa15047796 JS SQLTestRunner can now run the Java impl's core-most sanity tests, missing only support for directives.
FossilOrigin-Name: 5e798369375ce1b0c9cdf831f835d931fbd562ff7b4db09a06d1bdca2ac1b975
2023-08-29 20:01:01 +00:00
drh a910f3f1c5 New conversion letters added to strftime(): %e, %k, %I, %l, %R, %P, %p, %T, %u.
FossilOrigin-Name: 058722b2d0b995195a8ce3effe9722ae1c18cb1e7a520b481030da0bd579fe41
2023-08-29 18:28:08 +00:00
stephan 69a55ca17d Get the JS SQLTester command handlers in place sans those which have to run SQL.
FossilOrigin-Name: d21b1217964a53f33b7ba3958b34aa8560dff8ede33e66f54aa0afbab7099ec3
2023-08-29 15:39:57 +00:00
drh 9d6acd960f Change the version number to 3.44.0 to begin the next development
cycle.  (Should have done this a few check-ins ago.)

FossilOrigin-Name: 253fe4a45decdcc4180c5aeccaf4cd0d1325a0f6df0913b0e6721ea3e26b4fe2
2023-08-29 15:38:54 +00:00
drh e1e67abc5c Add support for the CONCAT() and CONCAT_WS() SQL functions, modeled after
the PostgreSQL behavior.

FossilOrigin-Name: 0b434ca7aa19eff4ad134a8c6f88f6a7ccab88864faa55e93579a2462d8ac3bc
2023-08-29 15:24:41 +00:00
stephan 0fc20a32c0 Get the basic parsing pieces and command dispatching in place in the JS SQLTester.
FossilOrigin-Name: 8fcc2a553c1e26734902bbdee0c38183ee22b7b5c75f07405529bb79db34145a
2023-08-29 13:28:36 +00:00
stephan 524ddc940d Init bits of a port of Java's SQLTester to JS. Far from complete.
FossilOrigin-Name: 60eec5ceda80c64870713df8e9aeabeef933c007f2010792225a07d5ef36baef
2023-08-29 11:22:45 +00:00
dan b44b802378 Change a variable from "int" to "i64" to make it easier to prove that it cannot overflow.
FossilOrigin-Name: 00a8b3a263f3537588063ce42fad6e21fa343dad850b086d0929ed1617eb44fc
2023-08-29 10:50:11 +00:00
stephan d10ed826eb Remove some dead code. Add a skeleton SQLTester script for fts5.
FossilOrigin-Name: 6c83e31fa96f65b61377c0c801cc32b3c8ca27a0c8442f860364bec258c003cb
2023-08-29 00:10:31 +00:00
stephan 4e379078e7 Factor out a superfluous struct member.
FossilOrigin-Name: 76d3911c370b3dc02d119045003f87ad20a6efd9f7a44d4feb59b7c801ac8981
2023-08-28 23:18:19 +00:00
stephan 924c4545d3 Further minor internal JNI simplifications.
FossilOrigin-Name: 1808d12ee0d1f1e5ee49d48c699ca10c4f822989ac9b4ac08f2b861513ee5997
2023-08-28 22:52:04 +00:00
stephan fa23b4fc61 Improve threadability of the JNI collation-related bindings and add infrastructure for similar cases.
FossilOrigin-Name: f02dad66b965b9e3c504001e9603af8f74977f151bede9db369f88e86a4aeb00
2023-08-28 21:27:32 +00:00
stephan a08f737503 Correct JNI mapping of collations to be 1-db-to-many-collations.
FossilOrigin-Name: b927b0f5a68684b0a9799396d153bf1e2306351e8039c2bacb3d5b2056a0634f
2023-08-28 20:21:56 +00:00
dan 35c7f538e9 Updates to testrunner.tcl so that it runs fuzztest using multiple jobs.
FossilOrigin-Name: ceeabe9f8b31a30c65147fd270b92d43c7842247548cee9de165113991f6c2cf
2023-08-28 20:14:19 +00:00
dan ecdc5b3e6f Fix the "sdevtest" testrunner.tcl command so that it correctly enables asan on windows.
FossilOrigin-Name: 6463192369ff22eb15d4e34590ef55cd8a6f2501227835664816277806bf961b
2023-08-28 20:02:59 +00:00
dan 9b0e9f9089 Fixes for testrunner.tcl on windows.
FossilOrigin-Name: 26ae090889640bfcf02a6dd5aa58044edd4d0708a11d8e005149f1a3c8495bba
2023-08-28 18:15:14 +00:00
dan d7def73c97 Another fix for valgrind permutation. Remove the "copydir" table column - just add a [cp] or [copy] command to the test script where this functionality is required.
FossilOrigin-Name: 448b9a575e66960a0885864f88b99b6ea15655c77a42eef956c09c8dc70e539a
2023-08-28 16:28:00 +00:00
stephan ece2d7f2be Remove a pair of what are arguably unnecessary mutex locks (and often hit). More JNI-internal cleanups.
FossilOrigin-Name: ecf07a0144dc6402b1e0924b1775d99dc465b27aa86a2718cac60a9b4c974312
2023-08-28 16:22:31 +00:00
stephan 8d64c12a10 Update tool/mkctimec.tcl to account for [fe7365254d343e].
FossilOrigin-Name: 349aac7e8d513bc420e8948b84cf715e454443439fdcd5aff0f2b13815a9cbb3
2023-08-28 16:05:19 +00:00
drh 57b1800773 Add support for the -DSQLITE_EXTRA_AUTOEXT=name compile-time option.
[forum:/forumpost/00829394c74a670f|forum thread 00829394c74a670f].

FossilOrigin-Name: fe7365254d343ed03e11a4e9cad7f0e5d5182b9220c6fde6d30e434ebdaba2af
2023-08-28 15:58:00 +00:00
stephan 25e7d8af75 Duplicate code consolidation.
FossilOrigin-Name: 71f239747c7934310dedf9fc0cbf84fbeeed53808234067147335c12396849a1
2023-08-28 14:59:27 +00:00
stephan bdb149d063 Move a metrics counter so that it can be used to indirectly witness the race condition fix from [f5274e00f17d58e0] by recording varying final values for that metric across consecutive multi-threaded test runs.
FossilOrigin-Name: 54d2209d24547dbb05e7c12daa27211593c34de8005e8adba0989b8d219f5f3b
2023-08-28 13:18:46 +00:00
stephan 4e9b48cfc4 Resolve a JNI-side race condition. Removed a now-extraneous struct member. Internal API renaming for consistency.
FossilOrigin-Name: f5274e00f17d58e075f90ae5c1d4b38933da315e51592171fa35bcbd67b40b2a
2023-08-28 13:06:26 +00:00
drh bd953dfcad Fix an issue with infinity handling by the SUM() function that goes back
to the extended-precision SUM() enhancement of
[check-in c63e26e705f5e967].  Problem reported by
[forum:/forumpost/1c06ddcacc86032a|forum post 1c06ddcacc86032a].

FossilOrigin-Name: 77d3dcd283595c52f24c07fc59ba60c9133b71c440cf3f799cf48c907c6fae3e
2023-08-28 12:20:18 +00:00
stephan 0d066bc8a6 Resolve a condition which could cause an is-interrupted db to call its progress callback.
FossilOrigin-Name: a0d0f1aafc6086726131dff5e6628f2771c20db3122a53bdbb82945ab5d326d1
2023-08-28 12:06:38 +00:00
dan f98612b1c5 Fix the valgrind permutation on this branch.
FossilOrigin-Name: ccbf06760e8377f9209ba3fd4895a25fe1a5ea688c384bf357e765b6a2b4c2f7
2023-08-28 11:22:33 +00:00
stephan f0e9e59d8d Further JNI cleanups and javadoc additions.
FossilOrigin-Name: c393b1c9f5639c259406e587b3e08efdc1962203001823747681379ffc54fc10
2023-08-28 11:10:13 +00:00
stephan 2597ec6385 Lots of javadoc-related tweaks.
FossilOrigin-Name: cfe06f90e2c0231efded98767ef3cc646d3a7daa34d77b62b7c04b5aae9448fd
2023-08-28 07:28:36 +00:00
stephan 23dfa67c1e Correct a package renaming bug in the previous check-in and start applying the @Canonical annotation to functions to distinguish canonical API functions and Java-specific APIs.
FossilOrigin-Name: 8a016006805b08b72bfc4093c795d8cd8d7fe72f8ae234c175a8b7be3a841cbf
2023-08-28 05:48:34 +00:00
stephan b041f8ffdd Move the JNI annotations into the annotation subpackage.
FossilOrigin-Name: e4dedf90a92a069daef967dfe975469bf8ec7883c44c95e73345d4eded48e996
2023-08-28 05:39:05 +00:00
stephan 56d3b21317 Resolve a makefile bug which causes sqlite3-worker1-bundler-friendly.mjs to be built incorrectly. Reported in [forum:a874e435cf4690c1|forum post a874e435cf4690c1].
FossilOrigin-Name: 9d68c7ef103b9b51ed35fb91e62351eb6c62ad63ab03ac456ff9787cc83f10ab
2023-08-28 04:59:16 +00:00
stephan 5020ddc243 Reimplement JNI's sqlite3_value_text() as a native instead of a Java-side proxy. Unrelated minor simplifications.
FossilOrigin-Name: 401dd6ee283a4e7da2e50175a1b58e6a83afb0ea2d3b6cf80c7c621e17bcce98
2023-08-27 15:15:46 +00:00
stephan 0639c58836 Generic cleanups in Tester1.java.
FossilOrigin-Name: fbc1b6310b01f4f79439bb6ce59b2aaabd126da7201f36d4fc5d7ef95118a494
2023-08-27 14:47:45 +00:00
stephan 5575d6421b Remove JNI sqlite3_column_java_object(), as the protection rules of sqlite3_values makes it impossible to implement safely. Add JNI sqlite3_bind_java_object().
FossilOrigin-Name: 29bd4a23a4afd96b2cc06d2b91a4f30c0bbf2347af0b0d18f8d4cf8aafa63160
2023-08-27 13:43:45 +00:00
stephan 88bd53dfd0 Correct the signature mismatch between JNI sqlite3_column/value_text16() and add related tests.
FossilOrigin-Name: 77f6e70f17c0cb6d031f983c458c9ec2e88d92b4716397533a029af39da2d128
2023-08-27 11:28:57 +00:00
stephan 95f5d85d4a Make JNI sqlite3_trace_v2() thread-safe. Re-add a piece removed in [bae4d022aad9b] to work around a JVM crash which is unpredictably triggered by its substitute. Fix the THREADMODE=0 JNI build. Further internal API simplifications.
FossilOrigin-Name: 3f9f7a9cb08b0687ad206605a5109306762df9ae8bdeab2d8d60bf9373c9ad32
2023-08-27 10:40:00 +00:00
stephan 32a79760b5 Factor out an unnecessary struct member. JNI sqlite3_shutdown() now frees up the various object-recycling bins. Doc touchups.
FossilOrigin-Name: bae4d022aad9bbeb78cb027ecad799af87afe331e697add44ec22297c873141d
2023-08-27 09:12:50 +00:00
stephan 60aca33a8b Factor out a superfluous JNI class. Doc and code style cleanups.
FossilOrigin-Name: 0f37f27148dfa93ecc42381ad3455a9059285d1af2df027429044942dc4d861b
2023-08-27 08:10:59 +00:00
stephan 0f4bf3435a JNI code reorgs and simplify the failing-alloc interface a bit.
FossilOrigin-Name: deed5797de65a25896e991a441f0d05eb92662536296485920fb081e84ad5d32
2023-08-27 07:26:33 +00:00
stephan c7e7c88873 Apply the JNI OOM checks to memory returned by JDK APIs, as distinct from our APIs.
FossilOrigin-Name: 1ff78582bfd934e0c76464b5f23ed9bf09a3491b145e0ca34acb6e59c4f53995
2023-08-26 22:34:26 +00:00
stephan 0deaea218d Eliminate a superfluous JNI-internal middle-man class.
FossilOrigin-Name: daede0f801f59d6501a863c4688e4635b34171e98b56b8ab4432c779113f1997
2023-08-26 21:13:57 +00:00
dan 1f1169ad09 Updates to testrunner.tcl so that it runs "make fuzztest" using multiple jobs.
FossilOrigin-Name: 7596ea7074e0ac73312586ed3d28cdacf97f54b8af73f804cbc8066c94d4b4ef
2023-08-26 21:04:54 +00:00
stephan 506a8b52f3 Whether or not OOM is always fatal in JNI is now a compile-time option.
FossilOrigin-Name: 320a34c080d8bc1feae1578697923dfa7c4144b78de36f704c24cc4a4ce9d535
2023-08-26 21:02:50 +00:00
stephan 6428cd18d6 Correct a string length misuse in JNI sqlite3_result_error() in an OOM case. Unrelated minor JNI cleanups.
FossilOrigin-Name: 4252f56f3d8574b7b43306440726daf3b5f5500d5d9105784b2f82753e7c71dd
2023-08-26 19:34:49 +00:00
stephan 6a1ebbdb90 Remove a bunch of commented-out debug output.
FossilOrigin-Name: b49488481e2952294960bb0ee971f6eca126c19d68ef92152894aa28393e6865
2023-08-26 18:15:33 +00:00
stephan 220b6145f5 Re-order some out-of-order JNI APIs. Correct JNI sqlite3_open_v2() behavior in a particular OOM condition.
FossilOrigin-Name: 49d3be002ce5e594027f47a3ba448f0c21ec68b416b8df997497753f53e3ca52
2023-08-26 18:01:36 +00:00
stephan 2a6835fe0c Two significant typo fixes for [1a30919bfbb686].
FossilOrigin-Name: 6a6ee6dd54ec1a1dc7fb7d2f331951525d394a8362aef911f62878ac3961898f
2023-08-26 17:36:15 +00:00
stephan 3cb610c010 Bind sqlite3_db_handle() to JNI.
FossilOrigin-Name: 1a30919bfbb686464e8020e684120d22dd2375b910a17446b75452fda96a7449
2023-08-26 17:30:14 +00:00
stephan 2a0dc4895b Correct a potential duplicate xDestroy() being triggered for Java-side collations.
FossilOrigin-Name: 25331172f78544f7f23ad7821cbf065589f6d02706184d4c83fe3988452dac5d
2023-08-26 16:55:27 +00:00
stephan fec793dd8a Recycle per-UDF JNI state.
FossilOrigin-Name: cf406528eb86d8d0d55a468b2c4ec32a11a4947f45c4bbabdde8742ae199ce1f
2023-08-26 16:29:48 +00:00
stephan a7da592bd7 Code consolidation cleanups.
FossilOrigin-Name: d6b5ecd28740c2c5d21797fce9fe137c8a83f702f22901720cc6e8b1b42af001
2023-08-26 14:55:44 +00:00
stephan acfbe5284e Add -sqllog flag to the JNI 'tests' target because it hits APIs which are otherwise not tested.
FossilOrigin-Name: cc3153ed341f59262485c3541a8879c4e86520c8a10f4ce819344a88099e7d0e
2023-08-26 12:19:51 +00:00
stephan 3ff458d61e JNI internal cleanups and docs.
FossilOrigin-Name: b7b26bfb4f86e0b8aaabab258ccb0713737ffd4ecd3156d6a83a4f9a1d25edf6
2023-08-26 11:57:34 +00:00
stephan d9cf47e377 Remove the Java BusyHandler.xDestroy() method - it should not have had one. Eliminate the last of the potentially-significant MUTF-8 cases.
FossilOrigin-Name: c852f1ebbde273c3d28fe5aff0bf73cfc06b41dd371a94d7520536dc7a1dbcc1
2023-08-26 10:51:19 +00:00
stephan 6f8f587d2f Improve threading support for all types of JNI-side callback hooks, making them safe to invoke if another thread is busy replacing them.
FossilOrigin-Name: f2af7bbf493fe28d92fc9c77425f8bb9d48c02af9a5eabceb0365c705651e114
2023-08-26 10:20:38 +00:00
stephan 25033b6b3b Move the 3 Java SQLFunction subclasses from inner classes to package scope.
FossilOrigin-Name: 21fd47a68db9df1828f4cc4131d326a193b5751d56a40ae77ed0a78dc0621af1
2023-08-25 16:43:51 +00:00
stephan 9fed4aab77 Missed a straggler when renaming Java classes in [8ca528006533ac1]. Document threading limitations.
FossilOrigin-Name: 5786b95f5d09b4462aff0fdeac37992a2b64c47b004d18960f51e4e6a5796106
2023-08-25 16:26:16 +00:00
stephan a5f09eb29d Hopefully the last major API rename in the JNI bits: rename all lower_camel_case classes which do not have direct counterparts in the C API to UpperCamelCase, as that's more idiomatic. Java types which reflect C-style types are unaffected.
FossilOrigin-Name: 8ca528006533ac152e9b322e421cf5d339414c77332d9836a9ff429b793d0d2d
2023-08-25 14:17:36 +00:00
stephan ad818380cc More Java API renaming for consistency.
FossilOrigin-Name: 4e457778de189d8393e88f399dc521c8a5ad4ddd80a5fd69295bcb104fac5cbf
2023-08-25 13:23:45 +00:00
stephan a899186c86 Re-enable SQLITE_THREADSAFE=0 in the JNI build and add multitest target which builds and runs the tests in all 3 threading modes.
FossilOrigin-Name: 6b1c816f6aae9face07ed7ead969257cf915c21ff9cdad9a21b7cf0e7496e09e
2023-08-25 12:29:59 +00:00
stephan 0199669fa1 Code restructuring. Force SQLITE_THREADSAFE in JNI builds for the time being, as threadsafe==0 leads to as-yet-mysterious JNI-level reference errors.
FossilOrigin-Name: 5a099caa2c21bec647f0a521e7f5d0d1cc2f96d388d3d6c53d5ec80947f33e8d
2023-08-25 11:32:56 +00:00
dan 35f9b1719b Remove incorrect (but harmless) dependency on source code file "sessionfuzz-data1.db" from main.mk and Makefile.in.
FossilOrigin-Name: 17d56c0207f63614b34ef3594d06602ab7a6e85604f3589b30aa79316f1744ee
2023-08-25 11:06:26 +00:00
stephan 5ecb51c260 Only build in the JNI-side metrics tracking in SQLITE_DEBUG builds.
FossilOrigin-Name: 646e7fc3b5ba81c207f013c9a06781986138379f20e787320a811ba3ed5489dc
2023-08-25 04:27:17 +00:00
stephan aec1361a2b Javadoc and internal API cleanups.
FossilOrigin-Name: 10a43cba9bb2c23b5f31b31fcac81be34acec1940cca47d0b8e5a5ccbf1aa8eb
2023-08-25 04:02:33 +00:00
stephan 5276552083 Replace all of the JNI XyzHook/Handler classes with snake_cased ones which follow unified naming conventions to make them easier to apply.
FossilOrigin-Name: 76e62a381249b3b4262b22bdffe7fc2816c820115c9df266956ab8817b127aca
2023-08-25 02:57:30 +00:00
stephan 44b4b8260f javadoc additions.
FossilOrigin-Name: bedf33d403677d243a1505ce549166850ab55671700b143278db5feb84883ab3
2023-08-25 00:27:28 +00:00
stephan 3401736694 Re-frame the incongruous SQLite3Jni.uncacheThread() API as sqlite3_java_uncache_thread().
FossilOrigin-Name: 7232b033954fae40df3db43e489e0e5a703c03308f500a1ae36fd9d707632d7f
2023-08-24 22:28:44 +00:00
stephan 70dcc2822d Update some outdated JNI docs and account for a function renamed earlier this evening.
FossilOrigin-Name: 3f684ef5018116f4be46a07779451c8983ac87a5db182477f71ee7bf28287a04
2023-08-24 21:45:30 +00:00
stephan 0f0bf3ff9e Do not pre-allocate sqlite3_aggregate_context() for Java UDFs, as it unduly complicates UDF initialization.
FossilOrigin-Name: e8308f0c6ec2d8999c8a2502fb130cb3501ba326f23f71f2cd8d452debae79b5
2023-08-24 21:31:56 +00:00
dan 36018803d6 Add doc/testrunner.md, for documenting the testrunner.tcl script.
FossilOrigin-Name: 9c69a28401c7273823f2c2b291fd417febeb278afb9ce085a4b944505ca13d23
2023-08-24 19:08:50 +00:00
stephan eef599dbd4 More code legibility and style improvements in the JNI pieces. Start work on a javadoc build.
FossilOrigin-Name: 62b404d62fd62f4d220838b59c9f38a71afa2d4a8c3af0a5c9495fa7020972cf
2023-08-24 18:43:25 +00:00
stephan e336d92688 Doc, code style, and legibility cleanups.
FossilOrigin-Name: cf185bcd25629d882a030b8b87048179a120ab1f84aa1d68b279c499dbdf0dba
2023-08-24 17:25:05 +00:00
stephan cf8a93f804 Doc style fixes.
FossilOrigin-Name: 862f9828e078ae138c3533658c45e4c45155975794e752b9b3a71a693842f37a
2023-08-24 15:42:08 +00:00
stephan e6c299a5c8 Add a new non-goal to the JNI README.md.
FossilOrigin-Name: 53000cdae9b265752f8d8616679da621a571a6590c6eaeca23cf87a0e13aa4c4
2023-08-24 15:11:28 +00:00
stephan 8e52281659 Merge the jni-threading branch into trunk, eliminating the JNI API's prior threading limitations.
FossilOrigin-Name: 3739c8aa7080d8e1044ca51ab7b699b50da4d29620b35acfcea2745059b65bac
2023-08-24 14:49:29 +00:00
stephan 49ca4d20fa Merge into trunk improvements made to the wasm APIs which were too late for 3.43.
FossilOrigin-Name: ac9da5c79a4f56d25202d50974e16e2a463d77c99b1907aee2605d5a3e50a565
2023-08-24 14:43:30 +00:00
stephan e7a4685837 Correct JNI layer's misuse of an sqlite3-internal error-reporting API (no mutex held). Style cleanups. Eliminate lookups of per-thread state by approximately 85% across the test suite.
FossilOrigin-Name: 1f46ba8d3bc61af771c1e33d09ad25f0da4fc4f915f7a9f6223ebfd99526d81d
2023-08-24 14:31:36 +00:00
stephan 6043947eee Ensure that db mutex is held when using sqlite3ErrorWithMessage() to avoid a potential assertion in debug builds.
FossilOrigin-Name: b8f6a50a4bf9478324f0272d79f2fe6992a49b753e79e39a268c6afb261bb01e
2023-08-24 14:17:30 +00:00
stephan bfdc7ab5a7 Add more JNI docs, tests, and a handful of Java-side overloads.
FossilOrigin-Name: d19a431facbde6a6b960664674753ee85d2c051a76109ce7db0b079c65fbdea0
2023-08-24 11:57:51 +00:00
stephan 8cafdfa916 JNI cleanups regarding building with certain features disabled.
FossilOrigin-Name: a9e6d5158b8a4a6b8554a5f8f0a35785ee450d42ea877275dc27085e89716c18
2023-08-23 17:52:51 +00:00
stephan 1c3bf8a3e1 Remove unnecessary jclass-type struct members.
FossilOrigin-Name: d67255f7251cc5d1d27d77d4c84ff216e2da71202db989718189a6b4beff1cd0
2023-08-23 17:15:48 +00:00
stephan 495046ef88 Add a note to the JNI README explaining why the Java API has callback names like xFunc() and xPreUpdate().
FossilOrigin-Name: 415447a310f6a7d06b4aa9ef51f110cf8e2ef9545c69cb5983c367c50fe641d2
2023-08-23 13:36:27 +00:00
stephan bea9ed0f1f Bind sqlite3_preupdate_hook() and friends to JNI.
FossilOrigin-Name: d0c425b5c1d3aac5ead18a501a3760b4506d68d373cb3be484247042cf2fa8d4
2023-08-23 13:17:37 +00:00
stephan 4e97ab4296 Bind a subset of sqlite3_config() to JNI: threading modes and sqllog.
FossilOrigin-Name: fce8ecaf7f2e69a168978e6993e58c452c45f76c39da33f2869c9d947c16cab1
2023-08-23 10:36:12 +00:00
stephan 4c8ef3894e Numerous minor cleanups and code style conformance improvements.
FossilOrigin-Name: 6c92d884920e4ace54913fc60ceef6e43a4351f45a4cb3c4a0ed3d29d544a31b
2023-08-23 09:05:16 +00:00
stephan 336bc8a281 Improve C-side exception handling from Java-side UDF callbacks.
FossilOrigin-Name: aebbc24afb339ed07b7cd767fbc0d25f3e9c3d9bb5ef3d1c10b04b605c7261bc
2023-08-23 00:17:28 +00:00
stephan d53565b4f8 Minor Tester1.java cleanups.
FossilOrigin-Name: 70d936953ba55cfed32efe7e3a9d4b71da9a7ffc8818b6540471e0bf311bc688
2023-08-22 23:00:44 +00:00
stephan 3600976bf1 Fix Tester1 so that exceptions triggered via threads are not silently ignored. Disable auto-extension tests in multi-thread mode because concurrent threads rightfully interfere with that.
FossilOrigin-Name: 56b2a077ace6e6ad5834e1a597b710f212a5b7d5db5b9a27a41f2aa0f6952c55
2023-08-22 22:13:08 +00:00
stephan d1c7216b2f More work on the JNI multi-threaded test runner.
FossilOrigin-Name: 9a74ad716bded1e14333bf7c72392916f800d58a96240eabe4988ca5fc9e8752
2023-08-22 20:10:28 +00:00
stephan 87bb103038 Disassociate JNI db handles from the thread that created them, as it's no longer relevant.
FossilOrigin-Name: 8b78b737e66a399b04e555a8197f63a73198a4105cb2f37ffd5b0e6014302caf
2023-08-22 18:36:30 +00:00
stephan c675add616 Correct JNI binding of sqlite3_shutdown() to clean up all cached JNIEnv objects.
FossilOrigin-Name: 02e868690f97ca728b0f2dd018aa79a9d13c85dd85b164caa895d319ae8f3ff5
2023-08-22 17:51:57 +00:00
stephan a7e3a1c09b JNI internal cleanups and correct two leaked db handles in test code.
FossilOrigin-Name: f927a30b5bba35991f472084ebaf02779e84c343a4e84f0efb3df7679ff212f8
2023-08-22 17:36:59 +00:00
stephan 9828aa223a Move the JNI per-thread cache of NativePointerHolder refs into global space. This allows better-targeted mutex locks and incidentally eliminates the lagginess and post-run hangs in Tester1's multi-thread mode (presumably caused by deadlocks).
FossilOrigin-Name: e209f56a9745695aadc04418c7bebe62b79e38e5aee26c3248a30f73bfa460c2
2023-08-22 15:30:35 +00:00
stephan 0a102087d8 Move most of the per-JNIEnv global Java class refs into the global state, saving a bit of per-thread overhead.
FossilOrigin-Name: 7342bf578790e1a87c128a7c1c7745fe2e7c442890370feb160d406597d4d8ec
2023-08-22 11:34:34 +00:00
stephan 484f9bed4e Minor JNI cleanups.
FossilOrigin-Name: b88910aaaaaaa0936974379bb3eb8a5a3a634395b14e67cc9030f8a520f471f1
2023-08-21 23:45:19 +00:00
stephan 1089277105 JNI cleanups.
FossilOrigin-Name: 0a84131008a2e7886dac64a3545dea634811f6eac2b90885ec9c61ed1e6544c3
2023-08-19 14:49:08 +00:00
stephan 6f92f35449 Merge trunk into jni-threading branch.
FossilOrigin-Name: 8254479c6ff1ea3cc9e56de1698db8405c03da90b9bf4c401182e47e0842baf8
2023-08-19 12:34:23 +00:00
stephan bfa486d5fc JNI doc additions.
FossilOrigin-Name: 0c7ac34f30e1f7e35a2ac4e5e55e5f24857b24afa81a7abecba60f1c9c68b9ff
2023-08-19 12:32:00 +00:00
stephan 187da43379 JNI test code cleanups.
FossilOrigin-Name: e202b6e69da8cced114d027cf2e91a04dfdd50b601b3274214783f7d750c558c
2023-08-19 11:52:36 +00:00
stephan 8d9179bd07 Minor JNI cleanups.
FossilOrigin-Name: 1cecb9e0383aa78c491f9ba88c831a88b4b2d40ceef1b87be494b6ddc0789e41
2023-08-19 11:26:52 +00:00
stephan 3cf6c0f276 Add multi-thread run mode to JNI Tester1. It works but hangs on exit sometimes for Java reasons as yet not understood.
FossilOrigin-Name: bdbaf7a4534f40e550b646979e67e7b7731566bb5a2631ed376ac85a9bec40a7
2023-08-19 10:43:05 +00:00
stephan 46d677e713 Replace JNI::NewStringUTF() for the remaining cases where output may be incompatible with MUTF-8. It is now only used when we know the output to be plain ASCII.
FossilOrigin-Name: 2d955eef25ab116c487ebc34c6f2d2836d310af239ef1993f5aeee5a3f68d590
2023-08-19 08:22:34 +00:00
stephan 656f6c0c80 Improve exception handling in OpfsDb.importDb().
FossilOrigin-Name: a4eedd63b58f5c273b671f687cb68a32259963dbb053a710770383c735fb7f26
2023-08-18 14:41:21 +00:00
stephan ccbfe97cd5 Extend the importDb() method of both OPFS VFSes to (A) support reading in an async streaming fashion via a callback and (B) automatically disable WAL mode in the imported db.
FossilOrigin-Name: 9b1398c96a4fd0b59e65faa8d5c98de4129f0f0357732f12cb2f5c53a08acdc2
2023-08-18 14:16:26 +00:00
stephan 383df02b16 Remove some obsolete JNI-internal docs.
FossilOrigin-Name: 00a2a3736a6dcde81d920815520040f3c47f965165e7128ca1f4062e6ec7c17c
2023-08-17 22:04:07 +00:00
stephan 6c5f96fc4d Tighten up the JNI auto-ext handling.
FossilOrigin-Name: c09c8d05a20d916a9d9304eeea723ef7666a862a9e53f5feeeb1b03f9153d4b2
2023-08-17 13:13:22 +00:00
stephan 1dcb246988 Minor internal JNI cleanups and fixes.
FossilOrigin-Name: 0e9437de026cbfb333b90bb3400f1c015f85d49d73a25ad1000623216b88bfa0
2023-08-17 12:44:52 +00:00
stephan 0fa2545e7f Remove the FIXME markers related to threading. Code style cleanups.
FossilOrigin-Name: 154ab26dc6ba2d1fd976e8fe6dc1b1a06c734f7e9a276a3edc5c2f30b0d6d36a
2023-08-17 10:49:06 +00:00
stephan 95484726f6 Add SQLITE_EXTRA_AUTOEXT, similar to SQLITE_EXTRA_INIT but adds a builtin auto-extension provided by the client. Suggestion from [forum:00829394c74a670f| forum post 00829394c74a670f].
FossilOrigin-Name: 423e77277a61d7febf4c3fc737981fa22a82b5c774a8ada5375a01a0611535b2
2023-08-17 09:49:53 +00:00
stephan abfe646c12 Add note about the current threading limitation to ext/jni/README.md. No code changes.
FossilOrigin-Name: 653ed92dc39185cdedfab3ea518bc7ec2d2826120e5fa4cbdee3343301396184
2023-08-15 13:01:20 +00:00
stephan 6b51e35a9b Minor reshaping of Tester1 moving towards making a multi-threaded run mode.
FossilOrigin-Name: f104c14c26c123ee78c09fc1bc59efb8668dc624da05c1d8dbeaf3c9dd02a393
2023-08-15 09:26:47 +00:00
stephan 39c3f5f363 Remove a piece of stray debug output. No functional changes.
FossilOrigin-Name: 00ac653562a66aad3112ea322d08be68e05e6bf7413c814dd3f81bf850fcf43b
2023-08-15 09:16:41 +00:00
stephan 9019e2e667 Bring handling of the Java auto-ext handler more in line with the core in terms of locking and mutability during traversal. This removes the explicit synchronous requirement from the Java open() and auto-ext bindings.
FossilOrigin-Name: 42994b952e092ae4fa319395208622e887387ca3ff8ac57961c824a6c272bf0e
2023-08-14 17:12:55 +00:00
stephan 24b4cdd8d3 Remove some obsolete, commented-out makefile code. No functional or build changes.
FossilOrigin-Name: ea574cd5de6dbc7db2f4cffe0b6c83c795c4ba634ae1984e5c95bb3529daa5bb
2023-08-14 14:21:28 +00:00
stephan 7f2dea75ad More work on the JNI-specific mutexes. Rework the NativePointerHolder cache lookup to be slightly simpler and O(1) instead of O(N).
FossilOrigin-Name: c84ded0e59aea4861d72b53b4b40cf580747c0f6ca58c334a996f1a825276cb5
2023-08-14 13:27:40 +00:00
stephan d518e94adb JNI-internal docs and removal of obsolete code.
FossilOrigin-Name: b62d93258b6a661f3a9b61468b3b641c14faf2d2196f78aca95fe14de43c9444
2023-08-14 08:28:46 +00:00
stephan 6a1ed4c811 Internal API renaming for clarity's sake.
FossilOrigin-Name: 911e4fc5aaf9478214095a65f74af3ebca883922c36cf7a8d911116c42cf9de8
2023-08-13 20:58:12 +00:00
stephan 88381e53fc Add a mutex for auto-extensions, tied in to the open() process since that's the route into auto-extensions.
FossilOrigin-Name: 8da97e0db4eeacf91aa6fd909fd7cb73b050d194dfc7739a502b55f7eca6d7b1
2023-08-13 12:40:27 +00:00
stephan 4b4a911c5f Add some docs and metrics for the new mutex internals.
FossilOrigin-Name: 33d1780b43182d2574adbc1928707af825c485c99762738e58bc6d7c6c52ac6a
2023-08-13 10:28:35 +00:00
stephan 71e5694cd5 An initial attempt at protecting the JNI global state via mutexes at the C level instead of relying on Java's synchronized keyword. It seems to work but increases the run time of the single-threaded batch tester by roughly 3 times.
FossilOrigin-Name: c64e6a52ac79164be37fe643a4a39bd187af198a379410def8b8419f7c2224d4
2023-08-13 09:53:27 +00:00
stephan 0c07549fd6 Bind sqlite3_interrupt() and sqlite3_is_interrupted() to JNI but with caveats regarding mutexing of the JNIEnv cache. Add a loud warning to the JNI 'dist' target that it should be built with JDK8 (a.k.a. Java 1.8) for compatibility reasons.
FossilOrigin-Name: fbf99a2423dd20e4544bdeea85f714e9368ce3b92fefe97efb39a0fb4a557abe
2023-08-12 23:47:58 +00:00
301 changed files with 24041 additions and 10524 deletions
+51 -23
View File
@@ -57,6 +57,7 @@ LIBTCL = @TCL_LIB_SPEC@
#
READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@
READLINE_FLAGS += -DHAVE_EDITLINE=@TARGET_HAVE_EDITLINE@
READLINE_FLAGS += -DHAVE_LINENOISE=@TARGET_HAVE_LINENOISE@
# The library that programs using readline() must link against.
#
@@ -765,13 +766,22 @@ mptest: mptester$(TEXE)
$(MPTEST2) --journalmode DELETE
has_tclsh84:
sh $(TOP)/tool/cktclsh.sh 8.4 $(TCLSH_CMD)
touch has_tclsh84
has_tclsh85:
sh $(TOP)/tool/cktclsh.sh 8.5 $(TCLSH_CMD)
touch has_tclsh85
# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system. Some of the C source code and header
# files are automatically generated. This target takes care of
# all that automatic generation.
#
.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c
.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl has_tclsh84 fts5.c
rm -rf tsrc
mkdir tsrc
cp -f $(SRC) tsrc
@@ -781,15 +791,15 @@ mptest: mptester$(TEXE)
cp fts5.c fts5.h tsrc
touch .target_source
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS)
cp tsrc/sqlite3ext.h .
cp $(TOP)/ext/session/sqlite3session.h .
sqlite3r.h: sqlite3.h
sqlite3r.h: sqlite3.h has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) --enable-recover >sqlite3r.h
sqlite3r.c: sqlite3.c sqlite3r.h
sqlite3r.c: sqlite3.c sqlite3r.h has_tclsh84
cp $(TOP)/ext/recover/sqlite3recover.c tsrc/
cp $(TOP)/ext/recover/sqlite3recover.h tsrc/
cp $(TOP)/ext/recover/dbdata.c tsrc/
@@ -804,7 +814,7 @@ tclsqlite3.c: sqlite3.c
echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/split-sqlite3c.tcl
# Rule to build the amalgamation
@@ -1092,10 +1102,10 @@ tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la
# Rules to build opcodes.c and opcodes.h
#
opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl
opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl has_tclsh84
cat parse.h $(TOP)/src/vdbe.c | $(TCLSH_CMD) $(TOP)/tool/mkopcodeh.tcl >opcodes.h
# Rules to build parse.c and parse.h - the outputs of lemon.
@@ -1106,10 +1116,10 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE)
cp $(TOP)/src/parse.y .
./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) -S parse.y
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
sqlite3rc.h: $(TOP)/src/sqlite3.rc $(TOP)/VERSION
sqlite3rc.h: $(TOP)/src/sqlite3.rc $(TOP)/VERSION has_tclsh84
echo '#ifndef SQLITE_RESOURCE_VERSION' >$@
echo -n '#define SQLITE_RESOURCE_VERSION ' >>$@
cat $(TOP)/VERSION | $(TCLSH_CMD) $(TOP)/tool/replace.tcl exact . , >>$@
@@ -1145,7 +1155,7 @@ SHELL_SRC = \
$(TOP)/ext/recover/sqlite3recover.h \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
@@ -1233,7 +1243,7 @@ fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon$(BEXE)
fts5parse.h: fts5parse.c
fts5.c: $(FTS5_SRC)
fts5.c: $(FTS5_SRC) has_tclsh84
$(TCLSH_CMD) $(TOP)/ext/fts5/tool/mkfts5c.tcl
cp $(TOP)/ext/fts5/fts5.h .
@@ -1267,7 +1277,7 @@ TESTFIXTURE_SRC1 = sqlite3.c
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c
TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
testfixture$(TEXE): $(TESTFIXTURE_SRC)
testfixture$(TEXE): has_tclsh85 $(TESTFIXTURE_SRC)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
@@ -1291,11 +1301,17 @@ fulltestonly: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/full.test
# Fuzz testing
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
#
# WARNING: When the "fuzztest" target is run by the testrunner.tcl script,
# it does not actually run this code. Instead, it schedules equivalent
# commands. Therefore, if this target is updated, then code in
# testrunner_data.tcl (search for "trd_fuzztest_data") must also be updated.
#
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE)
./fuzzcheck$(TEXE) $(FUZZDATA)
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE)
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
@@ -1312,17 +1328,23 @@ testrunner: testfixture$(TEXE)
# Runs both fuzztest and testrunner, consecutively.
#
devtest: testfixture$(TEXE) fuzztest testrunner
devtest: srctree-check testfixture$(TEXE) fuzztest testrunner
mdevtest:
mdevtest: srctree-check has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest
sdevtest:
sdevtest: has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest
# Validate that various generated files in the source tree
# are up-to-date.
#
srctree-check: $(TOP)/tool/srctree-check.tcl
$(TCLSH_CMD) $(TOP)/tool/srctree-check.tcl
# Testing for a release
#
releasetest: testfixture$(TEXE)
releasetest: srctree-check testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release
# Minimal testing that runs in less than 3 minutes
@@ -1333,7 +1355,7 @@ quicktest: ./testfixture$(TEXE)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: fuzztest sourcetest $(TESTPROGS) tcltest
test: srctree-check fuzztest sourcetest $(TESTPROGS) tcltest
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
@@ -1351,13 +1373,13 @@ smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
shelltest: $(TESTPROGS)
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in has_tclsh85
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in has_tclsh85
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
sqltclsh$(TEXE): sqltclsh.c
@@ -1376,7 +1398,7 @@ CHECKER_DEPS =\
$(TOP)/ext/misc/btreeinfo.c \
$(TOP)/ext/repair/sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
sqlite3_checker.c: $(CHECKER_DEPS) has_tclsh85
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
sqlite3_checker$(TEXE): sqlite3_checker.c
@@ -1462,6 +1484,11 @@ amalgamation-tarball: sqlite3.c sqlite3rc.h
snapshot-tarball: sqlite3.c sqlite3rc.h
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot
# Build a ZIP archive containing various command-line tools.
#
tool-zip: testfixture sqlite3 sqldiff sqlite3_analyzer tool/mktoolzip.tcl
./testfixture $(TOP)/tool/mktoolzip.tcl
# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
@@ -1537,6 +1564,7 @@ clean:
rm -f threadtest5
rm -f src-verify
rm -f custom.rws
rm -f has_tclsh84 has_tclsh85
distclean: clean
rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \
@@ -1581,7 +1609,7 @@ fiddle: sqlite3.c shell.c
@echo 'Updating custom dictionary from tool/custom.txt'
aspell --lang=en create master ./custom.rws < $<
misspell: ./custom.rws
misspell: ./custom.rws has_tclsh84
$(TCLSH_CMD) ./tool/spellsift.tcl ./src/*.c ./src/*.h ./src/*.in
#
+11 -7
View File
@@ -52,8 +52,8 @@ MINIMAL_AMALGAMATION = 0
USE_STDCALL = 0
!ENDIF
# Set this non-0 to use structured exception handling (SEH) for WAL mode
# in the core library.
# Use the USE_SEH=0 option on the nmake command line to omit structured
# exception handling (SEH) support. SEH is on by default.
#
!IFNDEF USE_SEH
USE_SEH = 1
@@ -403,10 +403,11 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
!ENDIF
# Should structured exception handling (SEH) be enabled for WAL mode in
# the core library?
# the core library? It is on by default. Only omit it if the
# USE_SEH=0 option is provided on the nmake command-line.
#
!IF $(USE_SEH)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1
!IF $(USE_SEH)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_OMIT_SEH=1
!ENDIF
# These are the "extended" SQLite compilation options used when compiling for
@@ -1819,8 +1820,8 @@ $(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLIT
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
# <<mark>>
sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
@@ -2466,6 +2467,9 @@ extensiontest: testfixture.exe testloadext.dll
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl
.\testfixture.exe $(TOP)\tool\mktoolzip.tcl
coretestprogs: $(TESTPROGS)
testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe
+1 -1
View File
@@ -1 +1 @@
3.43.0
3.44.0
+6 -5
View File
@@ -52,8 +52,8 @@ MINIMAL_AMALGAMATION = 0
USE_STDCALL = 0
!ENDIF
# Set this non-0 to use structured exception handling (SEH) for WAL mode
# in the core library.
# Use the USE_SEH=0 option on the nmake command line to omit structured
# exception handling (SEH) support. SEH is on by default.
#
!IFNDEF USE_SEH
USE_SEH = 1
@@ -325,10 +325,11 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
!ENDIF
# Should structured exception handling (SEH) be enabled for WAL mode in
# the core library?
# the core library? It is on by default. Only omit it if the
# USE_SEH=0 option is provided on the nmake command-line.
#
!IF $(USE_SEH)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1
!IF $(USE_SEH)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_OMIT_SEH=1
!ENDIF
# These are the "extended" SQLite compilation options used when compiling for
+1 -1
View File
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
# so that we create the export library with the dll.
#-----------------------------------------------------------------------
AC_INIT([sqlite],[3.43.0])
AC_INIT([sqlite],[3.44.0])
#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
Vendored
+48 -24
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.43.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.44.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.43.0'
PACKAGE_STRING='sqlite 3.43.0'
PACKAGE_VERSION='3.44.0'
PACKAGE_STRING='sqlite 3.44.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -776,6 +776,7 @@ OPT_FEATURE_FLAGS
HAVE_ZLIB
USE_AMALGAMATION
TARGET_DEBUG
TARGET_HAVE_LINENOISE
TARGET_HAVE_EDITLINE
TARGET_HAVE_READLINE
TARGET_READLINE_INC
@@ -903,6 +904,7 @@ enable_editline
enable_readline
with_readline_lib
with_readline_inc
with_linenoise
enable_debug
enable_amalgamation
enable_load_extension
@@ -1470,7 +1472,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.43.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.44.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1535,7 +1537,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.43.0:";;
short | recursive ) echo "Configuration of sqlite 3.44.0:";;
esac
cat <<\_ACEOF
@@ -1587,6 +1589,7 @@ Optional Packages:
(tclConfig.sh)
--with-readline-lib specify readline library
--with-readline-inc specify readline include paths
--with-linenoise=DIR source directory for linenoise library
Some influential environment variables:
CC C compiler command
@@ -1665,7 +1668,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.43.0
sqlite configure 3.44.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2084,7 +2087,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.43.0, which was
It was created by sqlite $as_me 3.44.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3942,13 +3945,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3945: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3948: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3948: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3951: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3951: output\"" >&5)
(eval echo "\"\$as_me:3954: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5154,7 +5157,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5157 "configure"' > conftest.$ac_ext
echo '#line 5160 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6679,11 +6682,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6682: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6685: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6686: \$? = $ac_status" >&5
echo "$as_me:6689: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7018,11 +7021,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7021: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7024: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7025: \$? = $ac_status" >&5
echo "$as_me:7028: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7123,11 +7126,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7126: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7129: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7130: \$? = $ac_status" >&5
echo "$as_me:7133: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7178,11 +7181,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7181: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7184: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7185: \$? = $ac_status" >&5
echo "$as_me:7188: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9558,7 +9561,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9561 "configure"
#line 9564 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9654,7 +9657,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9657 "configure"
#line 9660 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11245,6 +11248,27 @@ fi
fi
fi
# Check whether --with-linenoise was given.
if test "${with_linenoise+set}" = set; then :
withval=$with_linenoise; with_linenoise=$withval
else
with_linenoise="no"
fi
if test "x$with_linenoise" != "xno"; then
TARGET_HAVE_READLINE=0
TARGET_HAVE_EDITLINE=0
TARGET_HAVE_LINENOISE=1
TARGET_READLINE_INC="-I${with_linenoise}"
TARGET_READLINE_LIBS="${with_linenoise}/linenoise.c"
echo "using linenoise source code at ${with_linenoise}"
else
TARGET_HAVE_LINENOISE=0
echo "not using linenoise"
fi
@@ -11321,7 +11345,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build type" >&5
$as_echo_n "checking build type... " >&6; }
if test "${enable_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
$as_echo "debug" >&6; }
else
@@ -12457,7 +12481,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.43.0, which was
This file was extended by sqlite $as_me 3.44.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12523,7 +12547,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.43.0
sqlite config.status 3.44.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+18 -1
View File
@@ -598,11 +598,28 @@ if test x"$with_readline" != xno; then
TARGET_HAVE_READLINE=1
fi
fi
AC_ARG_WITH([linenoise],
[AS_HELP_STRING([--with-linenoise=DIR],[source directory for linenoise library])],
[with_linenoise=$withval],
[with_linenoise="no"])
if test "x$with_linenoise" != "xno"; then
TARGET_HAVE_READLINE=0
TARGET_HAVE_EDITLINE=0
TARGET_HAVE_LINENOISE=1
TARGET_READLINE_INC="-I${with_linenoise}"
TARGET_READLINE_LIBS="${with_linenoise}/linenoise.c"
echo "using linenoise source code at ${with_linenoise}"
else
TARGET_HAVE_LINENOISE=0
echo "not using linenoise"
fi
AC_SUBST(TARGET_READLINE_LIBS)
AC_SUBST(TARGET_READLINE_INC)
AC_SUBST(TARGET_HAVE_READLINE)
AC_SUBST(TARGET_HAVE_EDITLINE)
AC_SUBST(TARGET_HAVE_LINENOISE)
##########
# Figure out what C libraries are required to compile programs
@@ -615,7 +632,7 @@ AC_SEARCH_LIBS(fdatasync, [rt])
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[enable debugging & verbose explain]))
AC_MSG_CHECKING([build type])
if test "${enable_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall"
AC_MSG_RESULT([debug])
else
TARGET_DEBUG="-DNDEBUG"
+52 -1
View File
@@ -16,7 +16,7 @@ canonical source on a new Windows 11 PC, as of 2023-08-16:
a 32-bit build.) The subsequent steps will not work in a vanilla
DOS prompt. Nor will they work in PowerShell.
3. Install TCL development libraries. This note assumes that you wil
3. Install TCL development libraries. This note assumes that you will
install the TCL development libraries in the "`c:\Tcl`" directory.
Make adjustments
if you want TCL installed somewhere else. SQLite needs both the
@@ -83,3 +83,54 @@ following minor changes:
<ul>
<li> `set PATH=c:\tcl32\bin;%PATH%`
</ul>
## Statically Linking The TCL Library
Some utility programs associated with SQLite need to be linked
with TCL in order to function. The [sqlite3_analyzer.exe program](https://sqlite.org/sqlanalyze.html)
is an example. You can build as described above, and then
enter:
> ~~~~
nmake /f Makefile.msc sqlite3_analyzer.exe
~~~~
And you will end up with a working executable. However, that executable
will depend on having the "tcl86.dll" library somewhere on your %PATH%.
Use the following steps to build an executable that has the TCL library
statically linked so that it does not depend on separate DLL:
1. Use the appropriate "Command Prompt" window - either x86 or
x64, depending on whether you want a 32-bit or 64-bit executable.
2. Untar the TCL source tarball into a fresh directory. CD into
the "win/" subfolder.
3. Run: `nmake /f makefile.vc OPTS=nothreads,static shell`
4. CD into the "Release*" subfolder that is created (note the
wildcard - the full name of the directory might vary). There
you will find the "tcl86s.lib" file. Copy this file into the
same directory that you put the "tcl86.lib" on your initial
installation. (In this document, that directory is
"`C:\Tcl32\lib`" for 32-bit builds and
"`C:\Tcl\lib`" for 64-bit builds.)
5. CD into your SQLite source code directory and build the desired
utility program, but add the following extra arguments to the
nmake command line:
<blockquote><pre>
CCOPTS="-DSTATIC_BUILD" LIBTCL="tcl86s.lib netapi32.lib user32.lib"
</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 CCOPTS="-DSTATIC_BUILD" LIBTCL="tcl86s.lib netapi32.lib user32.lib" 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>
+284
View File
@@ -0,0 +1,284 @@
# The testrunner.tcl Script
# 1. Overview
testrunner.tcl is a Tcl script used to run multiple SQLite tests using
multiple jobs. It supports the following types of tests:
* Tcl test scripts.
* Tests run with [make] commands. Specifically, at time of writing,
[make fuzztest], [make mptest], [make sourcetest] and [make threadtest].
testrunner.tcl pipes the output of all tests and builds run into log file
**testrunner.log**, created in the cwd directory. Searching this file for
"failed" is a good way to find the output of a failed test.
testrunner.tcl also populates SQLite database **testrunner.db**. This database
contains details of all tests run, running and to be run. A useful query
might be:
```
SELECT * FROM script WHERE state='failed'
```
Running the command:
```
./testfixture $(TESTDIR)/testrunner.tcl status
```
in the directory containing the testrunner.db database runs various queries
to produce a succinct report on the state of a running testrunner.tcl script.
Running:
```
watch ./testfixture $(TESTDIR)/testrunner.tcl status
```
in another terminal is a good way to keep an eye on a long running test.
Sometimes testrunner.tcl uses the [testfixture] binary that it is run with
to run tests (see "Binary Tests" below). Sometimes it builds testfixture and
other binaries in specific configurations to test (see "Source Tests").
# 2. Binary Tests
The commands described in this section all run various combinations of the Tcl
test scripts using the [testfixture] binary used to run the testrunner.tcl
script (i.e. they do not invoke the compiler to build new binaries, or the
[make] command to run tests that are not Tcl scripts). The procedure to run
these tests is therefore:
1. Build the "testfixture" (or "testfixture.exe" for windows) binary using
whatever method seems convenient.
2. Test the binary built in step 1 by running testrunner.tcl with it,
perhaps with various options.
The following sub-sections describe the various options that can be
passed to testrunner.tcl to test binary testfixture builds.
## 2.1. Organization of Tcl Tests
Tcl tests are stored in files that match the pattern *\*.test*. They are
found in both the $TOP/test/ directory, and in the various sub-directories
of the $TOP/ext/ directory of the source tree. Not all *\*.test* files
contain Tcl tests - a handful are Tcl scripts designed to invoke other
*\*.test* files.
The **veryquick** set of tests is a subset of all Tcl test scripts in the
source tree. In includes most tests, but excludes some that are very slow.
Almost all fault-injection tests (those that test the response of the library
to OOM or IO errors) are excluded. It is defined in source file
*test/permutations.test*.
The **full** set of tests includes all Tcl test scripts in the source tree.
To run a "full" test is to run all Tcl test scripts that can be found in the
source tree.
File *permutations.test* defines various test "permutations". A permutation
consists of:
* A subset of Tcl test scripts, and
* Runtime configuration to apply before running each test script
(e.g. enabling auto-vacuum, or disable lookaside).
Running **all** tests is to run all tests in the full test set, plus a dozen
or so permutations. The specific permutations that are run as part of "all"
are defined in file *testrunner_data.tcl*.
## 2.2. Commands to Run Tests
To run the "veryquick" test set, use either of the following:
```
./testfixture $TESTDIR/testrunner.tcl
./testfixture $TESTDIR/testrunner.tcl veryquick
```
To run the "full" test suite:
```
./testfixture $TESTDIR/testrunner.tcl full
```
To run the subset of the "full" test suite for which the test file name matches
a specified pattern (e.g. all tests that start with "fts5"), either of:
```
./testfixture $TESTDIR/testrunner.tcl fts5%
./testfixture $TESTDIR/testrunner.tcl 'fts5*'
```
To run "all" tests (full + permutations):
```
./testfixture $TESTDIR/testrunner.tcl all
```
<a name=binary_test_failures></a>
## 2.3. Investigating Binary Test Failures
If a test fails, testrunner.tcl reports name of the Tcl test script and, if
applicable, the name of the permutation, to stdout. This information can also
be retrieved from either *testrunner.log* or *testrunner.db*.
If there is no permutation, the individual test script may be run with:
```
./testfixture $PATH_TO_SCRIPT
```
Or, if the failure occured as part of a permutation:
```
./testfixture $TESTDIR/testrunner.tcl $PERMUTATION $PATH_TO_SCRIPT
```
TODO: An example instead of "$PERMUTATION" and $PATH\_TO\_SCRIPT?
# 3. Source Code Tests
The commands described in this section invoke the C compiler to build
binaries from the source tree, then use those binaries to run Tcl and
other tests. The advantages of this are that:
* it is possible to test multiple build configurations with a single
command, and
* it ensures that tests are always run using binaries created with the
same set of compiler options.
The testrunner.tcl commands described in this section may be run using
either a *testfixture* (or testfixture.exe) build, or with any other Tcl
shell that supports SQLite 3.31.1 or newer via "package require sqlite3".
TODO: ./configure + Makefile.msc build systems.
## Commands to Run SQLite Tests
The **mdevtest** command is equivalent to running the veryquick tests and
the [make fuzztest] target once for each of two --enable-all builds - one
with debugging enabled and one without:
```
tclsh $TESTDIR/testrunner.tcl mdevtest
```
In other words, it is equivalent to running:
```
$TOP/configure --enable-all --enable-debug
make fuzztest
make testfixture
./testfixture $TOP/test/testrunner.tcl veryquick
# Then, after removing files created by the tests above:
$TOP/configure --enable-all OPTS="-O0"
make fuzztest
make testfixture
./testfixture $TOP/test/testrunner.tcl veryquick
```
The **sdevtest** command is identical to the mdevtest command, except that the
second of the two builds is a sanitizer build. Specifically, this means that
OPTS="-fsanitize=address,undefined" is specified instead of OPTS="-O0":
```
tclsh $TESTDIR/testrunner.tcl sdevtest
```
The **release** command runs lots of tests under lots of builds. It runs
different combinations of builds and tests depending on whether it is run
on Linux, Windows or OSX. Refer to *testrunner\_data.tcl* for the details
of the specific tests run.
```
tclsh $TESTDIR/testrunner.tcl release
```
## Running ZipVFS Tests
testrunner.tcl can build a zipvfs-enabled testfixture and use it to run
tests from the Zipvfs project with the following command:
```
tclsh $TESTDIR/testrunner.tcl --zipvfs $PATH_TO_ZIPVFS
```
This can be combined with any of "mdevtest", "sdevtest" or "release" to
test both SQLite and Zipvfs with a single command:
```
tclsh $TESTDIR/testrunner.tcl --zipvfs $PATH_TO_ZIPVFS mdevtest
```
## Investigating Source Code Test Failures
Investigating a test failure that occurs during source code testing is a
two step process:
1. Recreating the build configuration in which the test failed, and
2. Re-running the actual test.
To recreate a build configuration, use the testrunner.tcl **script** command
to create a build script. A build script is a bash script on Linux or OSX, or
a dos \*.bat file on windows. For example:
```
# Create a script that recreates build configuration "Device-One" on
# Linux or OSX:
tclsh $TESTDIR/testrunner.tcl script Device-One > make.sh
# Create a script that recreates build configuration "Have-Not" on Windows:
tclsh $TESTDIR/testrunner.tcl script Have-Not > make.bat
```
The generated bash or \*.bat file script accepts a single argument - a makefile
target to build. This may be used either to run a [make] command test directly,
or else to build a testfixture (or testfixture.exe) binary with which to
run a Tcl test script, as <a href=#binary_test_failures>described above</a>.
# 4. Controlling CPU Core Utilization
When running either binary or source code tests, testrunner.tcl reports the
number of jobs it intends to use to stdout. e.g.
```
$ ./testfixture $TESTDIR/testrunner.tcl
splitting work across 16 jobs
... more output ...
```
By default, testfixture.tcl attempts to set the number of jobs to the number
of real cores on the machine. This can be overridden using the "--jobs" (or -j)
switch:
```
$ ./testfixture $TESTDIR/testrunner.tcl --jobs 8
splitting work across 8 jobs
... more output ...
```
The number of jobs may also be changed while an instance of testrunner.tcl is
running by exucuting the following command from the directory containing the
testrunner.log and testrunner.db files:
```
$ ./testfixture $TESTDIR/testrunner.tcl njob $NEW_NUMBER_OF_JOBS
```
+19
View File
@@ -464,4 +464,23 @@ do_execsql_test 5.3 {
t2 t2_idx_0001295b {100 20 5}
}
if 0 {
do_test expert1-6.0 {
catchcmd :memory: {
.expert
select base64('');
.expert
select name from pragma_collation_list order by name collate uint;
}
} {0 {(no new indexes)
SCAN CONSTANT ROW
(no new indexes)
SCAN pragma_collation_list VIRTUAL TABLE INDEX 0:
USE TEMP B-TREE FOR ORDER BY
}}
}
finish_test
+103 -2
View File
@@ -32,7 +32,7 @@
#endif /* !defined(SQLITE_AMALGAMATION) */
#ifndef SQLITE_OMIT_VIRTUALTABLE
#ifndef SQLITE_OMIT_VIRTUALTABLE
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
@@ -662,6 +662,7 @@ static int idxRegisterVtab(sqlite3expert *p){
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0, /* xIntegrity */
};
return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
@@ -1818,6 +1819,88 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
return rc;
}
/*
** Define and possibly pretend to use a useless collation sequence.
** This pretense allows expert to accept SQL using custom collations.
*/
int dummyCompare(void *up1, int up2, const void *up3, int up4, const void *up5){
(void)up1;
(void)up2;
(void)up3;
(void)up4;
(void)up5;
assert(0); /* VDBE should never be run. */
return 0;
}
/* And a callback to register above upon actual need */
void useDummyCS(void *up1, sqlite3 *db, int etr, const char *zName){
(void)up1;
sqlite3_create_collation_v2(db, zName, etr, 0, dummyCompare, 0);
}
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) \
&& !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
/*
** dummy functions for no-op implementation of UDFs during expert's work
*/
void dummyUDF(sqlite3_context *up1, int up2, sqlite3_value **up3){
(void)up1;
(void)up2;
(void)up3;
assert(0); /* VDBE should never be run. */
}
void dummyUDFvalue(sqlite3_context *up1){
(void)up1;
assert(0); /* VDBE should never be run. */
}
/*
** Register UDFs from user database with another.
*/
int registerUDFs(sqlite3 *dbSrc, sqlite3 *dbDst){
sqlite3_stmt *pStmt;
int rc = sqlite3_prepare_v2(dbSrc,
"SELECT name,type,enc,narg,flags "
"FROM pragma_function_list() "
"WHERE builtin==0", -1, &pStmt, 0);
if( rc==SQLITE_OK ){
while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
int nargs = sqlite3_column_int(pStmt,3);
int flags = sqlite3_column_int(pStmt,4);
const char *name = (char*)sqlite3_column_text(pStmt,0);
const char *type = (char*)sqlite3_column_text(pStmt,1);
const char *enc = (char*)sqlite3_column_text(pStmt,2);
if( name==0 || type==0 || enc==0 ){
/* no-op. Only happens on OOM */
}else{
int ienc = SQLITE_UTF8;
int rcf = SQLITE_ERROR;
if( strcmp(enc,"utf16le")==0 ) ienc = SQLITE_UTF16LE;
else if( strcmp(enc,"utf16be")==0 ) ienc = SQLITE_UTF16BE;
ienc |= (flags & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY));
if( strcmp(type,"w")==0 ){
rcf = sqlite3_create_window_function(dbDst,name,nargs,ienc,0,
dummyUDF,dummyUDFvalue,0,0,0);
}else if( strcmp(type,"a")==0 ){
rcf = sqlite3_create_function(dbDst,name,nargs,ienc,0,
0,dummyUDF,dummyUDFvalue);
}else if( strcmp(type,"s")==0 ){
rcf = sqlite3_create_function(dbDst,name,nargs,ienc,0,
dummyUDF,0,0);
}
if( rcf!=SQLITE_OK ){
rc = rcf;
break;
}
}
}
sqlite3_finalize(pStmt);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
return rc;
}
#endif
/*
** Allocate a new sqlite3expert object.
*/
@@ -1844,7 +1927,21 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
}
}
/* Allow custom collations to be dealt with through prepare. */
if( rc==SQLITE_OK ) rc = sqlite3_collation_needed(pNew->dbm,0,useDummyCS);
if( rc==SQLITE_OK ) rc = sqlite3_collation_needed(pNew->dbv,0,useDummyCS);
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) \
&& !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
/* Register UDFs from database [db] with [dbm] and [dbv]. */
if( rc==SQLITE_OK ){
rc = registerUDFs(pNew->db, pNew->dbm);
}
if( rc==SQLITE_OK ){
rc = registerUDFs(pNew->db, pNew->dbv);
}
#endif
/* Copy the entire schema of database [db] into [dbm]. */
if( rc==SQLITE_OK ){
@@ -1920,6 +2017,10 @@ int sqlite3_expert_sql(
while( rc==SQLITE_OK && zStmt && zStmt[0] ){
sqlite3_stmt *pStmt = 0;
/* Ensure that the provided statement compiles against user's DB. */
rc = idxPrepareStmt(p->db, &pStmt, pzErr, zStmt);
if( rc!=SQLITE_OK ) break;
sqlite3_finalize(pStmt);
rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
if( rc==SQLITE_OK ){
if( pStmt ){
+81 -17
View File
@@ -640,6 +640,7 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){
zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid");
sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
sqlite3_vtab_config(p->db, SQLITE_VTAB_INNOCUOUS);
/* Create a list of user columns for the virtual table */
zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
@@ -3889,6 +3890,8 @@ static int fts3RenameMethod(
rc = sqlite3Fts3PendingTermsFlush(p);
}
p->bIgnoreSavepoint = 1;
if( p->zContentTbl==0 ){
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
@@ -3916,6 +3919,8 @@ static int fts3RenameMethod(
"ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
p->zDb, p->zName, zName
);
p->bIgnoreSavepoint = 0;
return rc;
}
@@ -3926,12 +3931,28 @@ static int fts3RenameMethod(
*/
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
int rc = SQLITE_OK;
UNUSED_PARAMETER(iSavepoint);
assert( ((Fts3Table *)pVtab)->inTransaction );
assert( ((Fts3Table *)pVtab)->mxSavepoint <= iSavepoint );
TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){
rc = fts3SyncMethod(pVtab);
Fts3Table *pTab = (Fts3Table*)pVtab;
assert( pTab->inTransaction );
assert( pTab->mxSavepoint<=iSavepoint );
TESTONLY( pTab->mxSavepoint = iSavepoint );
if( pTab->bIgnoreSavepoint==0 ){
if( fts3HashCount(&pTab->aIndex[0].hPending)>0 ){
char *zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')",
pTab->zDb, pTab->zName, pTab->zName
);
if( zSql ){
pTab->bIgnoreSavepoint = 1;
rc = sqlite3_exec(pTab->db, zSql, 0, 0, 0);
pTab->bIgnoreSavepoint = 0;
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
pTab->iSavepoint = iSavepoint+1;
}
}
return rc;
}
@@ -3942,12 +3963,11 @@ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
** This is a no-op.
*/
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
UNUSED_PARAMETER(iSavepoint);
UNUSED_PARAMETER(pVtab);
assert( p->inTransaction );
assert( p->mxSavepoint >= iSavepoint );
TESTONLY( p->mxSavepoint = iSavepoint-1 );
Fts3Table *pTab = (Fts3Table*)pVtab;
assert( pTab->inTransaction );
assert( pTab->mxSavepoint >= iSavepoint );
TESTONLY( pTab->mxSavepoint = iSavepoint-1 );
pTab->iSavepoint = iSavepoint;
return SQLITE_OK;
}
@@ -3957,11 +3977,13 @@ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
** Discard the contents of the pending terms table.
*/
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts3Table *p = (Fts3Table*)pVtab;
Fts3Table *pTab = (Fts3Table*)pVtab;
UNUSED_PARAMETER(iSavepoint);
assert( p->inTransaction );
TESTONLY( p->mxSavepoint = iSavepoint );
sqlite3Fts3PendingTermsClear(p);
assert( pTab->inTransaction );
TESTONLY( pTab->mxSavepoint = iSavepoint );
if( (iSavepoint+1)<=pTab->iSavepoint ){
sqlite3Fts3PendingTermsClear(pTab);
}
return SQLITE_OK;
}
@@ -3980,8 +4002,49 @@ static int fts3ShadowName(const char *zName){
return 0;
}
/*
** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual
** table.
*/
static int fts3Integrity(
sqlite3_vtab *pVtab, /* The virtual table to be checked */
const char *zSchema, /* Name of schema in which pVtab lives */
const char *zTabname, /* Name of the pVTab table */
int isQuick, /* True if this is a quick_check */
char **pzErr /* Write error message here */
){
Fts3Table *p = (Fts3Table*)pVtab;
char *zSql;
int rc;
char *zErr = 0;
assert( pzErr!=0 );
assert( *pzErr==0 );
UNUSED_PARAMETER(isQuick);
zSql = sqlite3_mprintf(
"INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
zSchema, zTabname, zTabname);
if( zSql==0 ){
return SQLITE_NOMEM;
}
rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr);
sqlite3_free(zSql);
if( (rc&0xff)==SQLITE_CORRUPT ){
*pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
p->bFts4 ? 4 : 3, zSchema, zTabname);
}else if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
" FTS%d table %s.%s: %s",
p->bFts4 ? 4 : 3, zSchema, zTabname, zErr);
}
sqlite3_free(zErr);
return SQLITE_OK;
}
static const sqlite3_module fts3Module = {
/* iVersion */ 3,
/* iVersion */ 4,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
/* xBestIndex */ fts3BestIndexMethod,
@@ -4005,6 +4068,7 @@ static const sqlite3_module fts3Module = {
/* xRelease */ fts3ReleaseMethod,
/* xRollbackTo */ fts3RollbackToMethod,
/* xShadowName */ fts3ShadowName,
/* xIntegrity */ fts3Integrity,
};
/*
+1
View File
@@ -265,6 +265,7 @@ struct Fts3Table {
int nPgsz; /* Page size for host database */
char *zSegmentsTbl; /* Name of %_segments table */
sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
int iSavepoint;
/*
** The following array of hash tables is used to buffer pending index
+2 -1
View File
@@ -545,7 +545,8 @@ int sqlite3Fts3InitAux(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xIntegrity */
};
int rc; /* Return code */
+2 -1
View File
@@ -362,7 +362,8 @@ int sqlite3Fts3InitTerm(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xIntegrity */
};
int rc; /* Return code */
+2 -1
View File
@@ -445,7 +445,8 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xIntegrity */
};
int rc; /* Return code */
+20 -8
View File
@@ -3325,7 +3325,6 @@ int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
sqlite3Fts3PendingTermsClear(p);
/* Determine the auto-incr-merge setting if unknown. If enabled,
** estimate the number of leaf blocks of content to be written
@@ -3347,6 +3346,10 @@ int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
rc = sqlite3_reset(pStmt);
}
}
if( rc==SQLITE_OK ){
sqlite3Fts3PendingTermsClear(p);
}
return rc;
}
@@ -3978,6 +3981,8 @@ static int fts3AppendToNode(
blobGrowBuffer(pPrev, nTerm, &rc);
if( rc!=SQLITE_OK ) return rc;
assert( pPrev!=0 );
assert( pPrev->a!=0 );
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
@@ -4034,9 +4039,13 @@ static int fts3IncrmergeAppend(
nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
/* If the current block is not empty, and if adding this term/doclist
** to the current block would make it larger than Fts3Table.nNodeSize
** bytes, write this block out to the database. */
if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){
** to the current block would make it larger than Fts3Table.nNodeSize bytes,
** and if there is still room for another leaf page, write this block out to
** the database. */
if( pLeaf->block.n>0
&& (pLeaf->block.n + nSpace)>p->nNodeSize
&& pLeaf->iBlock < (pWriter->iStart + pWriter->nLeafEst)
){
rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
pWriter->nWork++;
@@ -4368,7 +4377,7 @@ static int fts3IncrmergeLoad(
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
blobGrowBuffer(&pNode->block,
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
);
);
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aBlock, nBlock);
pNode->block.n = nBlock;
@@ -5218,7 +5227,7 @@ static u64 fts3ChecksumIndex(
int rc;
u64 cksum = 0;
assert( *pRc==SQLITE_OK );
if( *pRc ) return 0;
memset(&filter, 0, sizeof(filter));
memset(&csr, 0, sizeof(csr));
@@ -5433,8 +5442,11 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
rc = fts3DoIncrmerge(p, &zVal[6]);
}else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
rc = fts3DoAutoincrmerge(p, &zVal[10]);
}else if( nVal==5 && 0==sqlite3_strnicmp(zVal, "flush", 5) ){
rc = sqlite3Fts3PendingTermsFlush(p);
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
}else{
else{
int v;
if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
v = atoi(&zVal[9]);
@@ -5452,8 +5464,8 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
rc = SQLITE_OK;
}
#endif
}
#endif
return rc;
}
+39 -12
View File
@@ -110,15 +110,19 @@ static int fts5CInstIterInit(
*/
typedef struct HighlightContext HighlightContext;
struct HighlightContext {
CInstIter iter; /* Coalesced Instance Iterator */
int iPos; /* Current token offset in zIn[] */
/* Constant parameters to fts5HighlightCb() */
int iRangeStart; /* First token to include */
int iRangeEnd; /* If non-zero, last token to include */
const char *zOpen; /* Opening highlight */
const char *zClose; /* Closing highlight */
const char *zIn; /* Input text */
int nIn; /* Size of input text in bytes */
int iOff; /* Current offset within zIn[] */
/* Variables modified by fts5HighlightCb() */
CInstIter iter; /* Coalesced Instance Iterator */
int iPos; /* Current token offset in zIn[] */
int iOff; /* Have copied up to this offset in zIn[] */
int bOpen; /* True if highlight is open */
char *zOut; /* Output value */
};
@@ -151,8 +155,8 @@ static int fts5HighlightCb(
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Buffer containing token */
int nToken, /* Size of token in bytes */
int iStartOff, /* Start offset of token */
int iEndOff /* End offset of token */
int iStartOff, /* Start byte offset of token */
int iEndOff /* End byte offset of token */
){
HighlightContext *p = (HighlightContext*)pContext;
int rc = SQLITE_OK;
@@ -168,30 +172,47 @@ static int fts5HighlightCb(
if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff;
}
if( iPos==p->iter.iStart ){
/* If the parenthesis is open, and this token is not part of the current
** phrase, and the starting byte offset of this token is past the point
** that has currently been copied into the output buffer, close the
** parenthesis. */
if( p->bOpen
&& (iPos<=p->iter.iStart || p->iter.iStart<0)
&& iStartOff>p->iOff
){
fts5HighlightAppend(&rc, p, p->zClose, -1);
p->bOpen = 0;
}
/* If this is the start of a new phrase, and the highlight is not open:
**
** * copy text from the input up to the start of the phrase, and
** * open the highlight.
*/
if( iPos==p->iter.iStart && p->bOpen==0 ){
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff);
fts5HighlightAppend(&rc, p, p->zOpen, -1);
p->iOff = iStartOff;
p->bOpen = 1;
}
if( iPos==p->iter.iEnd ){
if( p->iRangeEnd>=0 && p->iter.iStart<p->iRangeStart ){
if( p->bOpen==0 ){
assert( p->iRangeEnd>=0 );
fts5HighlightAppend(&rc, p, p->zOpen, -1);
p->bOpen = 1;
}
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
fts5HighlightAppend(&rc, p, p->zClose, -1);
p->iOff = iEndOff;
if( rc==SQLITE_OK ){
rc = fts5CInstIterNext(&p->iter);
}
}
if( p->iRangeEnd>=0 && iPos==p->iRangeEnd ){
if( iPos==p->iRangeEnd ){
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
p->iOff = iEndOff;
if( iPos>=p->iter.iStart && iPos<p->iter.iEnd ){
fts5HighlightAppend(&rc, p, p->zClose, -1);
}
}
return rc;
@@ -232,6 +253,9 @@ static void fts5HighlightFunction(
if( rc==SQLITE_OK ){
rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
}
if( ctx.bOpen ){
fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
}
fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
if( rc==SQLITE_OK ){
@@ -510,6 +534,9 @@ static void fts5SnippetFunction(
if( rc==SQLITE_OK ){
rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
}
if( ctx.bOpen ){
fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
}
if( ctx.iRangeEnd>=(nColSize-1) ){
fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
}else{
+153 -101
View File
@@ -2904,7 +2904,6 @@ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){
assert_nc( i2!=0 );
pRes->bTermEq = 1;
if( p1->iRowid==p2->iRowid ){
p1->bDel = p2->bDel;
return i2;
}
res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1;
@@ -3272,7 +3271,7 @@ static Fts5Iter *fts5MultiIterAlloc(
int nSeg
){
Fts5Iter *pNew;
int nSlot; /* Power of two >= nSeg */
i64 nSlot; /* Power of two >= nSeg */
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
pNew = fts5IdxMalloc(p,
@@ -5048,7 +5047,6 @@ static void fts5DoSecureDelete(
int iPgIdx = pSeg->pLeaf->szLeaf;
u64 iDelta = 0;
u64 iNextDelta = 0;
int iNextOff = 0;
int iOff = 0;
int nIdx = 0;
@@ -5056,8 +5054,6 @@ static void fts5DoSecureDelete(
int bLastInDoclist = 0;
int iIdx = 0;
int iStart = 0;
int iKeyOff = 0;
int iPrevKeyOff = 0;
int iDelKeyOff = 0; /* Offset of deleted key, if any */
nIdx = nPg-iPgIdx;
@@ -5082,10 +5078,21 @@ static void fts5DoSecureDelete(
** This block sets the following variables:
**
** iStart:
** The offset of the first byte of the rowid or delta-rowid
** value for the doclist entry being removed.
**
** iDelta:
** The value of the rowid or delta-rowid value for the doclist
** entry being removed.
**
** iNextOff:
** The offset of the next entry following the position list
** for the one being removed. If the position list for this
** entry overflows onto the next leaf page, this value will be
** greater than pLeaf->szLeaf.
*/
{
int iSOP;
int iSOP; /* Start-Of-Position-list */
if( pSeg->iLeafPgno==pSeg->iTermLeafPgno ){
iStart = pSeg->iTermLeafOffset;
}else{
@@ -5121,47 +5128,75 @@ static void fts5DoSecureDelete(
}
iOff = iStart;
if( iNextOff>=iPgIdx ){
int pgno = pSeg->iLeafPgno+1;
fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
iNextOff = iPgIdx;
}else{
/* Set bLastInDoclist to true if the entry being removed is the last
** in its doclist. */
for(iIdx=0, iKeyOff=0; iIdx<nIdx; /* no-op */){
u32 iVal = 0;
iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
iKeyOff += iVal;
if( iKeyOff==iNextOff ){
bLastInDoclist = 1;
/* Set variable bLastInDoclist to true if this entry happens to be
** the last rowid in the doclist for its term. */
if( pSeg->bDel==0 ){
if( iNextOff>=iPgIdx ){
int pgno = pSeg->iLeafPgno+1;
fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
iNextOff = iPgIdx;
}else{
/* Loop through the page-footer. If iNextOff (offset of the
** entry following the one we are removing) is equal to the
** offset of a key on this page, then the entry is the last
** in its doclist. */
int iKeyOff = 0;
for(iIdx=0; iIdx<nIdx; /* no-op */){
u32 iVal = 0;
iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
iKeyOff += iVal;
if( iKeyOff==iNextOff ){
bLastInDoclist = 1;
}
}
}
/* If this is (a) the first rowid on a page and (b) is not followed by
** another position list on the same page, set the "first-rowid" field
** of the header to 0. */
if( fts5GetU16(&aPg[0])==iStart && (bLastInDoclist || iNextOff==iPgIdx) ){
fts5PutU16(&aPg[0], 0);
}
}
if( fts5GetU16(&aPg[0])==iStart && (bLastInDoclist||iNextOff==iPgIdx) ){
fts5PutU16(&aPg[0], 0);
}
if( bLastInDoclist==0 ){
if( pSeg->bDel ){
iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta);
aPg[iOff++] = 0x01;
}else if( bLastInDoclist==0 ){
if( iNextOff!=iPgIdx ){
u64 iNextDelta = 0;
iNextOff += fts5GetVarint(&aPg[iNextOff], &iNextDelta);
iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta + iNextDelta);
}
}else if(
iStart==pSeg->iTermLeafOffset && pSeg->iLeafPgno==pSeg->iTermLeafPgno
pSeg->iLeafPgno==pSeg->iTermLeafPgno
&& iStart==pSeg->iTermLeafOffset
){
/* The entry being removed was the only position list in its
** doclist. Therefore the term needs to be removed as well. */
int iKey = 0;
for(iIdx=0, iKeyOff=0; iIdx<nIdx; iKey++){
int iKeyOff = 0;
/* Set iKeyOff to the offset of the term that will be removed - the
** last offset in the footer that is not greater than iStart. */
for(iIdx=0; iIdx<nIdx; iKey++){
u32 iVal = 0;
iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
if( (iKeyOff+iVal)>(u32)iStart ) break;
iKeyOff += iVal;
}
assert_nc( iKey>=1 );
/* Set iDelKeyOff to the value of the footer entry to remove from
** the page. */
iDelKeyOff = iOff = iKeyOff;
if( iNextOff!=iPgIdx ){
/* This is the only position-list associated with the term, and there
** is another term following it on this page. So the subsequent term
** needs to be moved to replace the term associated with the entry
** being removed. */
int nPrefix = 0;
int nSuffix = 0;
int nPrefix2 = 0;
@@ -5198,80 +5233,88 @@ static void fts5DoSecureDelete(
}
}
}else if( iStart==4 ){
int iPgno;
int iPgno;
assert_nc( pSeg->iLeafPgno>pSeg->iTermLeafPgno );
/* The entry being removed may be the only position list in
** its doclist. */
for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){
Fts5Data *pPg = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
int bEmpty = (pPg && pPg->nn==4);
fts5DataRelease(pPg);
if( bEmpty==0 ) break;
}
assert_nc( pSeg->iLeafPgno>pSeg->iTermLeafPgno );
/* The entry being removed may be the only position list in
** its doclist. */
for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){
Fts5Data *pPg = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
int bEmpty = (pPg && pPg->nn==4);
fts5DataRelease(pPg);
if( bEmpty==0 ) break;
}
if( iPgno==pSeg->iTermLeafPgno ){
i64 iId = FTS5_SEGMENT_ROWID(iSegid, pSeg->iTermLeafPgno);
Fts5Data *pTerm = fts5DataRead(p, iId);
if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
int nTermIdx = pTerm->nn - pTerm->szLeaf;
int iTermIdx = 0;
int iTermOff = 0;
if( iPgno==pSeg->iTermLeafPgno ){
i64 iId = FTS5_SEGMENT_ROWID(iSegid, pSeg->iTermLeafPgno);
Fts5Data *pTerm = fts5DataRead(p, iId);
if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
int nTermIdx = pTerm->nn - pTerm->szLeaf;
int iTermIdx = 0;
int iTermOff = 0;
while( 1 ){
u32 iVal = 0;
int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal);
iTermOff += iVal;
if( (iTermIdx+nByte)>=nTermIdx ) break;
iTermIdx += nByte;
}
nTermIdx = iTermIdx;
memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
fts5PutU16(&pTerm->p[2], iTermOff);
fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
if( nTermIdx==0 ){
fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
}
while( 1 ){
u32 iVal = 0;
int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal);
iTermOff += iVal;
if( (iTermIdx+nByte)>=nTermIdx ) break;
iTermIdx += nByte;
}
fts5DataRelease(pTerm);
nTermIdx = iTermIdx;
memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
fts5PutU16(&pTerm->p[2], iTermOff);
fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
if( nTermIdx==0 ){
fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
}
}
fts5DataRelease(pTerm);
}
}
/* Assuming no error has occurred, this block does final edits to the
** leaf page before writing it back to disk. Input variables are:
**
** nPg: Total initial size of leaf page.
** iPgIdx: Initial offset of page footer.
**
** iOff: Offset to move data to
** iNextOff: Offset to move data from
*/
if( p->rc==SQLITE_OK ){
const int nMove = nPg - iNextOff; /* Number of bytes to move */
int nShift = iNextOff - iOff; /* Distance to move them */
int iPrevKeyOut = 0;
int iKeyIn = 0;
memmove(&aPg[iOff], &aPg[iNextOff], nMove);
iPgIdx -= nShift;
nPg = iPgIdx;
fts5PutU16(&aPg[2], iPgIdx);
for(iIdx=0; iIdx<nIdx; /* no-op */){
u32 iVal = 0;
iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
iKeyIn += iVal;
if( iKeyIn!=iDelKeyOff ){
int iKeyOut = (iKeyIn - (iKeyIn>iOff ? nShift : 0));
nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOut - iPrevKeyOut);
iPrevKeyOut = iKeyOut;
}
}
if( p->rc==SQLITE_OK ){
const int nMove = nPg - iNextOff;
int nShift = 0;
memmove(&aPg[iOff], &aPg[iNextOff], nMove);
iPgIdx -= (iNextOff - iOff);
nPg = iPgIdx;
fts5PutU16(&aPg[2], iPgIdx);
nShift = iNextOff - iOff;
for(iIdx=0, iKeyOff=0, iPrevKeyOff=0; iIdx<nIdx; /* no-op */){
u32 iVal = 0;
iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
iKeyOff += iVal;
if( iKeyOff!=iDelKeyOff ){
if( iKeyOff>iOff ){
iKeyOff -= nShift;
nShift = 0;
}
nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOff - iPrevKeyOff);
iPrevKeyOff = iKeyOff;
}
}
if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno);
}
assert_nc( nPg>4 || fts5GetU16(aPg)==0 );
fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg,nPg);
if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno);
}
sqlite3_free(aIdx);
assert_nc( nPg>4 || fts5GetU16(aPg)==0 );
fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg, nPg);
}
sqlite3_free(aIdx);
}
/*
@@ -5441,10 +5484,16 @@ static void fts5FlushOneHash(Fts5Index *p){
fts5WriteFlushLeaf(p, &writer);
}
}else{
int bDummy;
int nPos;
int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
nCopy += nPos;
int bDel = 0;
int nPos = 0;
int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDel);
if( bDel && bSecureDelete ){
fts5BufferAppendVarint(&p->rc, pBuf, nPos*2);
iOff += nCopy;
nCopy = nPos;
}else{
nCopy += nPos;
}
if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
/* The entire poslist will fit on the current leaf. So copy
** it in one go. */
@@ -5482,7 +5531,6 @@ static void fts5FlushOneHash(Fts5Index *p){
assert( pBuf->n<=pBuf->nSpace );
if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
}
sqlite3Fts5HashClear(pHash);
fts5WriteFinish(p, &writer, &pgnoLast);
assert( p->rc!=SQLITE_OK || bSecureDelete || pgnoLast>0 );
@@ -5515,7 +5563,6 @@ static void fts5FlushOneHash(Fts5Index *p){
fts5IndexCrisismerge(p, &pStruct);
fts5StructureWrite(p, pStruct);
fts5StructureRelease(pStruct);
p->nContentlessDelete = 0;
}
/*
@@ -5526,8 +5573,12 @@ static void fts5IndexFlush(Fts5Index *p){
if( p->nPendingData || p->nContentlessDelete ){
assert( p->pHash );
fts5FlushOneHash(p);
p->nPendingData = 0;
p->nPendingRow = 0;
if( p->rc==SQLITE_OK ){
sqlite3Fts5HashClear(p->pHash);
p->nPendingData = 0;
p->nPendingRow = 0;
p->nContentlessDelete = 0;
}
}
}
@@ -8269,7 +8320,8 @@ int sqlite3Fts5IndexInit(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xIntegrity */
};
rc = sqlite3_create_module(db, "fts5_structure", &fts5structure_module, 0);
}
+110 -13
View File
@@ -117,6 +117,8 @@ struct Fts5FullTable {
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
int iSavepoint; /* Successful xSavepoint()+1 */
int bInSavepoint;
#ifdef SQLITE_DEBUG
struct Fts5TransactionState ts;
#endif
@@ -405,6 +407,13 @@ static int fts5InitVtab(
pConfig->pzErrmsg = 0;
}
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1);
}
if( rc==SQLITE_OK ){
rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
}
if( rc!=SQLITE_OK ){
fts5FreeVtab(pTab);
pTab = 0;
@@ -1329,6 +1338,9 @@ static int fts5FilterMethod(
pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
}
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
if( rc!=SQLITE_OK ) goto filter_out;
if( pTab->pSortCsr ){
/* If pSortCsr is non-NULL, then this call is being made as part of
** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
@@ -1351,6 +1363,7 @@ static int fts5FilterMethod(
pCsr->pExpr = pTab->pSortCsr->pExpr;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}else if( pCsr->pExpr ){
assert( rc==SQLITE_OK );
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
@@ -1522,6 +1535,7 @@ static int fts5SpecialInsert(
Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
int bError = 0;
int bLoadConfig = 0;
if( 0==sqlite3_stricmp("delete-all", zCmd) ){
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
@@ -1533,6 +1547,7 @@ static int fts5SpecialInsert(
}else{
rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage);
}
bLoadConfig = 1;
}else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
if( pConfig->eContent==FTS5_CONTENT_NONE ){
fts5SetVtabError(pTab,
@@ -1542,6 +1557,7 @@ static int fts5SpecialInsert(
}else{
rc = sqlite3Fts5StorageRebuild(pTab->pStorage);
}
bLoadConfig = 1;
}else if( 0==sqlite3_stricmp("optimize", zCmd) ){
rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
}else if( 0==sqlite3_stricmp("merge", zCmd) ){
@@ -1554,6 +1570,8 @@ static int fts5SpecialInsert(
}else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
#endif
}else if( 0==sqlite3_stricmp("flush", zCmd) ){
rc = sqlite3Fts5FlushToDisk(&pTab->p);
}else{
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
if( rc==SQLITE_OK ){
@@ -1567,6 +1585,12 @@ static int fts5SpecialInsert(
}
}
}
if( rc==SQLITE_OK && bLoadConfig ){
pTab->p.pConfig->iCookie--;
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
}
return rc;
}
@@ -1685,7 +1709,7 @@ static int fts5UpdateMethod(
assert( nArg!=1 || eType0==SQLITE_INTEGER );
/* Filter out attempts to run UPDATE or DELETE on contentless tables.
** This is not suported. Except - DELETE is supported if the CREATE
** This is not suported. Except - they are both supported if the CREATE
** VIRTUAL TABLE statement contained "contentless_delete=1". */
if( eType0==SQLITE_INTEGER
&& pConfig->eContent==FTS5_CONTENT_NONE
@@ -1714,7 +1738,8 @@ static int fts5UpdateMethod(
}
else if( eType0!=SQLITE_INTEGER ){
/* If this is a REPLACE, first remove the current entry (if any) */
/* An INSERT statement. If the conflict-mode is REPLACE, first remove
** the current entry (if any). */
if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
@@ -2588,8 +2613,12 @@ static int fts5RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
int rc;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
return sqlite3Fts5StorageRename(pTab->pStorage, zName);
pTab->bInSavepoint = 1;
rc = sqlite3Fts5StorageRename(pTab->pStorage, zName);
pTab->bInSavepoint = 0;
return rc;
}
int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
@@ -2603,9 +2632,29 @@ int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint);
return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
int rc = SQLITE_OK;
char *zSql = 0;
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
if( pTab->bInSavepoint==0 ){
zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')",
pTab->p.pConfig->zDb, pTab->p.pConfig->zName, pTab->p.pConfig->zName
);
if( zSql ){
pTab->bInSavepoint = 1;
rc = sqlite3_exec(pTab->p.pConfig->db, zSql, 0, 0, 0);
pTab->bInSavepoint = 0;
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
pTab->iSavepoint = iSavepoint+1;
}
}
return rc;
}
/*
@@ -2614,9 +2663,16 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
** This is a no-op.
*/
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint);
return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
int rc = SQLITE_OK;
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
if( (iSavepoint+1)<pTab->iSavepoint ){
rc = sqlite3Fts5FlushToDisk(&pTab->p);
if( rc==SQLITE_OK ){
pTab->iSavepoint = iSavepoint;
}
}
return rc;
}
/*
@@ -2626,11 +2682,14 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
*/
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
int rc = SQLITE_OK;
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
fts5TripCursors(pTab);
pTab->p.pConfig->pgsz = 0;
return sqlite3Fts5StorageRollback(pTab->pStorage);
if( (iSavepoint+1)<=pTab->iSavepoint ){
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
}
return rc;
}
/*
@@ -2850,9 +2909,46 @@ static int fts5ShadowName(const char *zName){
return 0;
}
/*
** Run an integrity check on the FTS5 data structures. Return a string
** if anything is found amiss. Return a NULL pointer if everything is
** OK.
*/
static int fts5Integrity(
sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */
const char *zSchema, /* Name of schema in which this table lives */
const char *zTabname, /* Name of the table itself */
int isQuick, /* True if this is a quick-check */
char **pzErr /* Write error message here */
){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Config *pConfig = pTab->p.pConfig;
char *zSql;
char *zErr = 0;
int rc;
assert( pzErr!=0 && *pzErr==0 );
UNUSED_PARAM(isQuick);
zSql = sqlite3_mprintf(
"INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
zSchema, zTabname, pConfig->zName);
if( zSql==0 ) return SQLITE_NOMEM;
rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr);
sqlite3_free(zSql);
if( (rc&0xff)==SQLITE_CORRUPT ){
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
zSchema, zTabname);
}else if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
" FTS5 table %s.%s: %s",
zSchema, zTabname, zErr);
}
sqlite3_free(zErr);
return SQLITE_OK;
}
static int fts5Init(sqlite3 *db){
static const sqlite3_module fts5Mod = {
/* iVersion */ 3,
/* iVersion */ 4,
/* xCreate */ fts5CreateMethod,
/* xConnect */ fts5ConnectMethod,
/* xBestIndex */ fts5BestIndexMethod,
@@ -2875,7 +2971,8 @@ static int fts5Init(sqlite3 *db){
/* xSavepoint */ fts5SavepointMethod,
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
/* xShadowName */ fts5ShadowName
/* xShadowName */ fts5ShadowName,
/* xIntegrity */ fts5Integrity
};
int rc;
+3 -1
View File
@@ -1184,7 +1184,9 @@ int sqlite3Fts5StorageSync(Fts5Storage *p){
i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
if( p->bTotalsValid ){
rc = fts5StorageSaveTotals(p);
p->bTotalsValid = 0;
if( rc==SQLITE_OK ){
p->bTotalsValid = 0;
}
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexSync(p->pIndex);
+2 -1
View File
@@ -472,7 +472,8 @@ int sqlite3Fts5TestRegisterTok(sqlite3 *db, fts5_api *pApi){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xIntegrity */
};
int rc; /* Return code */
+2 -1
View File
@@ -783,7 +783,8 @@ int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
/* xShadowName */ 0,
/* xIntegrity */ 0
};
void *p = (void*)pGlobal;
+5 -2
View File
@@ -65,7 +65,9 @@ foreach w {a b c d e f} {
do_execsql_test 2.4 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
PRAGMA integrity_check;
PRAGMA integrity_check(t1);
} {ok ok}
#-------------------------------------------------------------------------
@@ -88,6 +90,7 @@ foreach {i x y} {
} {
do_execsql_test 3.$i.1 { INSERT INTO t1 VALUES($x, $y) }
do_execsql_test 3.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
do_execsql_test 3.$i.3 { PRAGMA integrity_check(t1) } ok
if {[set_test_counter errors]} break
}
@@ -135,7 +138,7 @@ foreach {i x y} {
10 {ddd abcde dddd dd c} {dddd c c d abcde}
} {
do_execsql_test 5.$i.1 { INSERT INTO t1 VALUES($x, $y) }
do_execsql_test 5.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
do_execsql_test 5.$i.2 { PRAGMA integrity_check(t1) } ok
if {[set_test_counter errors]} break
}
+27 -1
View File
@@ -307,5 +307,31 @@ do_catchsql_test 10.1.4 {
SELECT group_concat(firstcol(t1), '.') FROM t1 GROUP BY rowid
} {1 {unable to use function firstcol in the requested context}}
finish_test
#-------------------------------------------------------------------------
# Test that xInstCount() works from within an xPhraseQuery() callback.
#
reset_db
proc xCallback {cmd} {
incr ::hitcount [$cmd xInstCount]
return SQLITE_OK
}
proc fts5_hitcount {cmd} {
set ::hitcount 0
$cmd xQueryPhrase 0 xCallback
return $::hitcount
}
sqlite3_fts5_create_function db fts5_hitcount fts5_hitcount
do_execsql_test 11.1 {
CREATE VIRTUAL TABLE x1 USING fts5(z);
INSERT INTO x1 VALUES('one two three');
INSERT INTO x1 VALUES('one two one three one');
INSERT INTO x1 VALUES('one two three');
}
do_execsql_test 11.2 {
SELECT fts5_hitcount(x1) FROM x1('one') LIMIT 1;
} {5}
finish_test
+40
View File
@@ -65,4 +65,44 @@ do_execsql_test 2.1 {
INSERT INTO fts_idx(fts_idx) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
# Tests for OR IGNORE conflict handling.
#
reset_db
foreach_detail_mode $::testprefix {
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE t1 USING fts5(xyz, detail=%DETAIL%);
BEGIN;
INSERT INTO t1(rowid, xyz) VALUES(13, 'thirteen documents');
INSERT INTO t1(rowid, xyz) VALUES(14, 'fourteen documents');
INSERT INTO t1(rowid, xyz) VALUES(15, 'fifteen documents');
COMMIT;
}
set db_cksum [cksum]
foreach {tn sql} {
1 {
INSERT OR IGNORE INTO t1(rowid, xyz) VALUES(14, 'new text');
}
2 {
UPDATE OR IGNORE t1 SET rowid=13 WHERE rowid=15;
}
3 {
INSERT OR IGNORE INTO t1(rowid, xyz)
SELECT 13, 'some text'
UNION ALL
SELECT 14, 'some text'
UNION ALL
SELECT 15, 'some text'
}
} {
do_execsql_test 3.1.$tn.1 $sql
do_test 3.1.$tn.2 { cksum } $db_cksum
}
}
finish_test
-1
View File
@@ -294,4 +294,3 @@ do_catchsql_test 7.2.5 {
} {1 {recursively defined fts5 content table}}
finish_test
-1
View File
@@ -268,4 +268,3 @@ do_execsql_test 8.2 {
} {}
finish_test
-1
View File
@@ -205,4 +205,3 @@ foreach {tn step} {
finish_test
-1
View File
@@ -193,4 +193,3 @@ do_execsql_test 3.7 {
finish_test
-1
View File
@@ -245,4 +245,3 @@ do_execsql_test 4.3 {
}
finish_test
-1
View File
@@ -56,4 +56,3 @@ foreach {tn up err} {
}
finish_test
+4
View File
@@ -48,6 +48,10 @@ do_test 1.3 {
}
catchsql { INSERT INTO t1(t1) VALUES('integrity-check') }
} {1 {database disk image is malformed}}
do_execsql_test 1.3b {
PRAGMA integrity_check(t1);
} {{malformed inverted index for FTS5 table main.t1}}
do_test 1.4 {
db_restore_and_reopen
+3
View File
@@ -167,6 +167,9 @@ foreach {tn hdr} {
do_test 3.$tn.$tn2.2 {
catchsql { INSERT INTO x3(x3) VALUES('integrity-check') }
} {1 {database disk image is malformed}}
do_execsql_test 3.$tn.$tn2.3 {
PRAGMA integrity_check(x3);
} {{malformed inverted index for FTS5 table main.x3}}
}
execsql ROLLBACK
+50
View File
@@ -0,0 +1,50 @@
# 2010 June 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5faultG
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
set ::testprefix fts5faultG
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
INSERT INTO t1 VALUES('test renaming the table');
INSERT INTO t1 VALUES(' after it has been written');
INSERT INTO t1 VALUES(' actually other stuff instead');
}
faultsim_save_and_close
do_faultsim_test 1 -faults oom* -prep {
faultsim_restore_and_reopen
execsql {
BEGIN;
DELETE FROM t1 WHERE rowid=2;
}
} -body {
execsql {
DELETE FROM t1;
}
} -test {
catchsql { COMMIT }
faultsim_integrity_check
faultsim_test_result {0 {}}
}
finish_test
+38
View File
@@ -77,6 +77,9 @@ do_catchsql_test 4.2 {
UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3;
INSERT INTO aa(aa) VALUES('integrity-check');
} {1 {database disk image is malformed}}
do_execsql_test 4.2.1 {
PRAGMA integrity_check(aa);
} {{malformed inverted index for FTS5 table main.aa}}
do_catchsql_test 4.3 {
ROLLBACK;
@@ -317,4 +320,39 @@ do_catchsql_test 10.5.3 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
} {0 {}}
reset_db
proc slang {in} {return [string map {th d e eh} $in]}
db function slang -deterministic -innocuous slang
do_execsql_test 11.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT AS (slang(b)));
INSERT INTO t1(b) VALUES('the quick fox jumps over the lazy brown dog');
SELECT c FROM t1;
} {{deh quick fox jumps ovehr deh lazy brown dog}}
do_execsql_test 11.1 {
CREATE VIRTUAL TABLE t2 USING fts5(content="t1", c);
INSERT INTO t2(t2) VALUES('rebuild');
SELECT rowid FROM t2 WHERE t2 MATCH 'deh';
} {1}
do_execsql_test 11.2 {
PRAGMA integrity_check(t2);
} {ok}
db close
sqlite3 db test.db
# FIX ME?
#
# FTS5 integrity-check does not care if the content table is unreadable or
# does not exist. It only looks for internal inconsistencies in the
# inverted index.
#
do_execsql_test 11.3 {
PRAGMA integrity_check(t2);
} {ok}
do_execsql_test 11.4 {
DROP TABLE t1;
PRAGMA integrity_check(t2);
} {ok}
finish_test
+2 -2
View File
@@ -44,12 +44,12 @@ do_catchsql_test 1.2.2 {
do_catchsql_test 1.3.1 {
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
} {1 {no such cursor: 1}}
} {1 {no such cursor: 2}}
do_catchsql_test 1.3.2 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}
} {1 {no such cursor: 2}}
db close
sqlite3 db test.db
+1 -20
View File
@@ -9,7 +9,7 @@
#
#***********************************************************************
#
# TESTRUNNER: slow
# TESTRUNNER: superslow
#
source [file join [file dirname [info script]] fts5_common.tcl]
@@ -42,23 +42,4 @@ do_execsql_test 1.2 {
SELECT count(*) FROM t1('mno')
} $nLoop
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t2 USING fts5(x);
INSERT INTO t2(t2, rank) VALUES('pgsz', 32);
}
do_test 2.1 {
for {set ii 0} {$ii < $nLoop} {incr ii} {
execsql {
INSERT INTO t2 VALUES('abc def ghi');
INSERT INTO t2 VALUES('jkl mno pqr');
INSERT INTO t2(t2, rank) VALUES('merge', -1);
}
}
} {}
do_execsql_test 2.2 {
SELECT count(*) FROM t2('mno')
} $nLoop
finish_test
+45
View File
@@ -0,0 +1,45 @@
# 2023 Aug 27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# TESTRUNNER: superslow
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5optimize2
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
set nLoop 2500
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t2 USING fts5(x);
INSERT INTO t2(t2, rank) VALUES('pgsz', 32);
}
do_test 1.1 {
for {set ii 0} {$ii < $nLoop} {incr ii} {
execsql {
INSERT INTO t2 VALUES('abc def ghi');
INSERT INTO t2 VALUES('jkl mno pqr');
INSERT INTO t2(t2, rank) VALUES('merge', -1);
}
}
} {}
do_execsql_test 1.2 {
SELECT count(*) FROM t2('mno')
} $nLoop
finish_test
+24
View File
@@ -180,4 +180,28 @@ do_execsql_test 6.1 {
{table table table} {the table names.} {rank on an fts5 table}
}
#-------------------------------------------------------------------------
# forum post: https://sqlite.org/forum/forumpost/a2dd636330
#
reset_db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t USING fts5 (a, b);
INSERT INTO t (a, b) VALUES ('data1', 'sentence1'), ('data2', 'sentence2');
INSERT INTO t(t, rank) VALUES ('rank', 'bm25(10.0,1.0)');
}
sqlite3 db2 test.db
do_execsql_test -db db2 1.1 {
SELECT *, rank<0.0 FROM t('data*') ORDER BY RANK;
} {data1 sentence1 1 data2 sentence2 1}
do_execsql_test 1.2 {
INSERT INTO t(t, rank) VALUES ('rank', 'bm25(10.0,1.0)');
}
do_execsql_test -db db2 1.3 {
SELECT *, rank<0.0 FROM t('data*') ORDER BY RANK;
} {data1 sentence1 1 data2 sentence2 1}
db2 close
finish_test
+1 -1
View File
@@ -71,7 +71,7 @@ ifcapable fts3 {
do_catchsql_test 3.2 {
DROP TABLE vt1;
} {1 {SQL logic error}}
} {0 {}}
do_execsql_test 3.3 {
SAVEPOINT x;
+70
View File
@@ -273,6 +273,76 @@ do_execsql_test 5.3 {
do_execsql_test 5.4 { SELECT rowid FROM t1('abc'); } 2
do_execsql_test 5.5 { SELECT rowid FROM t1('aa'); } 2
#-------------------------------------------------------------------------
# Tests for the bug fixed by https://sqlite.org/src/info/4b60a1c3
#
reset_db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE fts USING fts5(content);
INSERT INTO fts(fts, rank) VALUES ('secure-delete', 1);
INSERT INTO fts(rowid, content) VALUES
(3407, 'profile profile profile profile profile profile profile profile pull pulling pulling really');
DELETE FROM fts WHERE rowid IS 3407;
INSERT INTO fts(fts) VALUES ('integrity-check');
}
foreach {tn detail} {
1 full
2 column
3 none
} {
do_execsql_test 6.1.$detail "
DROP TABLE IF EXISTS t1;
CREATE VIRTUAL TABLE t1 USING fts5(x, detail=$detail);
"
do_execsql_test 6.2.$detail {
INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
}
for {set ii 1} {$ii < 100} {incr ii} {
do_execsql_test 6.3.$detail.$ii.1 {
BEGIN;
INSERT INTO t1(rowid, x) VALUES(10, 'word1');
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<CAST($ii AS integer)
)
INSERT INTO t1(x) SELECT 'word3' FROM s;
COMMIT;
INSERT INTO t1(t1) VALUES('optimize');
}
do_execsql_test 6.3.$detail.$ii.2 {
DELETE FROM t1 WHERE rowid=10;
INSERT INTO t1(t1) VALUES ('integrity-check');
}
do_execsql_test 6.3.$detail.$ii.3 {
DELETE FROM t1;
}
do_execsql_test 6.3.$detail.$ii.4 {
BEGIN;
INSERT INTO t1(rowid, x) VALUES(10, 'tokenA');
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<CAST($ii AS integer)
)
INSERT INTO t1(x) SELECT group_concat('tokenB ') FROM s;
COMMIT;
INSERT INTO t1(t1) VALUES('optimize');
}
do_execsql_test 6.3.$detail.$ii.5 {
DELETE FROM t1 WHERE rowid=10;
INSERT INTO t1(t1) VALUES ('integrity-check');
}
do_execsql_test 6.3.$detail.$ii.6 {
DELETE FROM t1;
}
}
}
finish_test
+68 -1
View File
@@ -18,7 +18,7 @@ db progress 1 progress_handler
set ::PHC 0
proc progress_handler {args} {
incr ::PHC
if {($::PHC % 100000)==0} breakpoint
# if {($::PHC % 100000)==0} breakpoint
return 0
}
@@ -70,5 +70,72 @@ do_execsql_test 2.2 {
SELECT rowid FROM t1('def')
} {-100000 -99999 9223372036854775800}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(t1, rank) VALUES('secure-delete', $sd)
}
do_execsql_test 3.1 {
BEGIN;
INSERT INTO t1(rowid, x)
VALUES(51869, 'when whenever where weress what turn'),
(51871, 'to were');
COMMIT;
}
do_execsql_test 3.2 {
DELETE FROM t1 WHERE rowid=51871;
INSERT INTO t1(t1) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(rowid, x) VALUES(10, 'one two');
}
do_execsql_test 4.1 {
UPDATE t1 SET x = 'one three' WHERE rowid=10;
INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
}
do_execsql_test 4.2 {
DELETE FROM t1 WHERE rowid=10;
}
do_execsql_test 4.3 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE t1 USING fts5(content);
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
INSERT INTO t1 VALUES('active'),('boomer'),('atom'),('atomic'),
('alpha channel backup abandon test aback boomer atom alpha active');
DELETE FROM t1 WHERE t1 MATCH 'abandon';
}
do_execsql_test 5.1 {
INSERT INTO t1(t1) VALUES('rebuild');
}
do_execsql_test 5.2 {
DELETE FROM t1 WHERE rowid NOTNULL<5;
}
db close
sqlite3 db test.db
do_execsql_test 5.3 {
PRAGMA integrity_check;
} {ok}
finish_test
+116
View File
@@ -0,0 +1,116 @@
# 2023 Feb 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
# TESTRUNNER: slow
#
source [file join [file dirname [info script]] fts5_common.tcl]
ifcapable !fts5 { finish_test ; return }
set ::testprefix fts5secure7
set NVOCAB 500
set NDOC [expr 1000]
set NREP 100
set nDeletePerRep [expr 5]
set VOCAB [list]
proc select_one {list} {
set n [llength $list]
lindex $list [expr {abs(int(rand()*$n))}]
}
proc init_vocab {} {
set L [split "abcdefghijklmnopqrstuvwxyz" {}]
set nL [llength $L]
for {set i 0} {$i < $::NVOCAB} {incr i} {
set n [expr {6 + int(rand()*8)}]
set word ""
for {set j 0} {$j < $n} {incr j} {
append word [select_one $L]
}
lappend ::VOCAB $word
}
}
proc get_word {} {
select_one $::VOCAB
}
proc get_document {nWord} {
set ret [list]
for {set i 0} {$i < $nWord} {incr i} {
lappend ret [get_word]
}
return $ret
}
init_vocab
db func document [list get_document 12]
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(body);
INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
}
do_execsql_test 1.1 {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$NDOC
)
INSERT INTO t1 SELECT document() FROM s;
}
for {set iRep 0} {$iRep < $NREP} {incr iRep} {
set lRowid [db eval {SELECT rowid FROM t1}]
for {set iDel 0} {$iDel < $nDeletePerRep} {incr iDel} {
set idx [select_one $lRowid]
db eval {
DELETE FROM t1 WHERE rowid=$idx
}
}
db eval {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$nDeletePerRep
)
INSERT INTO t1 SELECT document() FROM s;
}
do_execsql_test 1.2.$iRep {
INSERT INTO t1(t1) VALUES('integrity-check');
}
}
reset_db
db func document [list get_document 12]
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(body);
INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
INSERT INTO t1(t1, rank) VALUES('pgsz', 128);
}
do_execsql_test 2.1 {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$NDOC
)
INSERT INTO t1 SELECT document() FROM s;
}
for {set ii 0} {$ii < $NDOC} {incr ii} {
set lRowid [db eval {SELECT rowid FROM t1}]
set idx [select_one $lRowid]
db eval { DELETE FROM t1 WHERE rowid=$idx }
do_execsql_test 2.2.$ii {
INSERT INTO t1(t1) VALUES('integrity-check');
}
}
finish_test
+38
View File
@@ -215,4 +215,42 @@ do_execsql_test 7.2 {
SELECT rowid FROM f WHERE filename GLOB '*ир*';
} {20}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
CREATE VIRTUAL TABLE t1 USING fts5(y, tokenize=trigram);
INSERT INTO t1 VALUES('abcdefghijklm');
}
foreach {tn match res} {
1 "abc ghi" "(abc)def(ghi)jklm"
2 "def ghi" "abc(defghi)jklm"
3 "efg ghi" "abcd(efghi)jklm"
4 "efghi" "abcd(efghi)jklm"
5 "abcd jklm" "(abcd)efghi(jklm)"
6 "ijkl jklm" "abcdefgh(ijklm)"
7 "ijk ijkl hijk" "abcdefg(hijkl)m"
} {
do_execsql_test 8.1.$tn {
SELECT highlight(t1, 0, '(', ')') FROM t1($match)
} $res
}
do_execsql_test 8.2 {
CREATE VIRTUAL TABLE ft2 USING fts5(a, tokenize="trigram");
INSERT INTO ft2 VALUES('abc x cde');
INSERT INTO ft2 VALUES('abc cde');
INSERT INTO ft2 VALUES('abcde');
}
do_execsql_test 8.3 {
SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'abc AND cde';
} {
{[abc] x [cde]}
{[abc] [cde]}
{[abcde]}
}
finish_test
+257 -105
View File
@@ -6,9 +6,10 @@ JAVA_HOME ?= $(HOME)/jdk/current
# e.g. /usr/lib/jvm/default-javajava-19-openjdk-amd64
JDK_HOME ?= $(JAVA_HOME)
# ^^^ JDK_HOME is not as widely used as JAVA_HOME
bin.javac := $(JDK_HOME)/bin/javac
bin.java := $(JDK_HOME)/bin/java
bin.jar := $(JDK_HOME)/bin/jar
bin.jar := $(JDK_HOME)/bin/jar
bin.java := $(JDK_HOME)/bin/java
bin.javac := $(JDK_HOME)/bin/javac
bin.javadoc := $(JDK_HOME)/bin/javadoc
ifeq (,$(wildcard $(JDK_HOME)))
$(error set JDK_HOME to the top-most dir of your JDK installation.)
endif
@@ -17,18 +18,27 @@ $(MAKEFILE):
package.jar := sqlite3-jni.jar
dir.top := ../..
dir.tool := ../../tool
dir.jni := $(patsubst %/,%,$(dir $(MAKEFILE)))
dir.top := ../..
dir.tool := ../../tool
dir.jni := $(patsubst %/,%,$(dir $(MAKEFILE)))
dir.src := $(dir.jni)/src
dir.src.c := $(dir.src)/c
dir.bld := $(dir.jni)/bld
dir.bld.c := $(dir.bld)
dir.src.jni := $(dir.src)/org/sqlite/jni
dir.src.jni.tester := $(dir.src.jni)/tester
dir.src.capi := $(dir.src.jni)/capi
dir.src.fts5 := $(dir.src.jni)/fts5
dir.tests := $(dir.src)/tests
mkdir ?= mkdir -p
$(dir.bld.c):
mkdir -p $@
$(mkdir) $@
javac.flags ?= -Xlint:unchecked -Xlint:deprecation
java.flags ?=
jnicheck ?= 1
ifeq (1,$(jnicheck))
java.flags += -Xcheck:jni
endif
classpath := $(dir.src)
CLEAN_FILES := $(package.jar)
@@ -36,17 +46,28 @@ DISTCLEAN_FILES := $(dir.jni)/*~ $(dir.src.c)/*~ $(dir.src.jni)/*~
sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
.NOTPARALLEL: $(sqlite3-jni.h)
SQLite3Jni.java := src/org/sqlite/jni/SQLite3Jni.java
SQLTester.java := src/org/sqlite/jni/tester/SQLTester.java
SQLite3Jni.class := $(SQLite3Jni.java:.java=.class)
CApi.java := $(dir.src.capi)/CApi.java
SQLTester.java := $(dir.src.capi)/SQLTester.java
CApi.class := $(CApi.java:.java=.class)
SQLTester.class := $(SQLTester.java:.java=.class)
########################################################################
# The future of FTS5 customization in this API is as yet unclear.
# It would be a real doozy to bind to JNI.
# The pieces are all in place, and are all thin proxies so not much
# complexity, but some semantic changes were required in porting
# which are largely untested.
#
# Reminder: this flag influences the contents of $(sqlite3-jni.h),
# which is checked in. Please do not check in changes to that file in
# which the fts5 APIs have been stripped unless that feature is
# intended to be stripped for good.
enable.fts5 ?= 1
# If enable.tester is 0, the org/sqlite/jni/tester/* bits are elided.
enable.tester ?= 1
ifeq (,$(wildcard $(dir.tests)/*))
enable.tester := 0
else
enable.tester := 1
endif
# bin.version-info = binary to output various sqlite3 version info
# building the distribution zip file.
@@ -57,68 +78,95 @@ $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
# Be explicit about which Java files to compile so that we can work on
# in-progress files without requiring them to be in a compilable statae.
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/%,\
BusyHandler.java \
Collation.java \
CollationNeeded.java \
CommitHook.java \
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
NotNull.java \
Nullable.java \
) $(patsubst %,$(dir.src.capi)/%,\
AbstractCollationCallback.java \
AggregateFunction.java \
AuthorizerCallback.java \
AutoExtensionCallback.java \
BusyHandlerCallback.java \
CollationCallback.java \
CollationNeededCallback.java \
CommitHookCallback.java \
ConfigLogCallback.java \
ConfigSqllogCallback.java \
NativePointerHolder.java \
OutputPointer.java \
ProgressHandler.java \
PrepareMultiCallback.java \
PreupdateHookCallback.java \
ProgressHandlerCallback.java \
ResultCode.java \
RollbackHook.java \
RollbackHookCallback.java \
ScalarFunction.java \
SQLFunction.java \
sqlite3_context.java \
CallbackProxy.java \
CApi.java \
TableColumnMetadata.java \
TraceV2Callback.java \
UpdateHookCallback.java \
ValueHolder.java \
WindowFunction.java \
XDestroyCallback.java \
sqlite3.java \
SQLite3Jni.java \
sqlite3_context.java \
sqlite3_stmt.java \
sqlite3_value.java \
Tester1.java \
Tracer.java \
UpdateHook.java \
) $(patsubst %,$(dir.src.jni)/wrapper1/%,\
AggregateFunction.java \
ScalarFunction.java \
SqlFunction.java \
Sqlite.java \
SqliteException.java \
ValueHolder.java \
)
JAVA_FILES.unittest := $(patsubst %,$(dir.src.jni)/%,\
capi/Tester1.java \
wrapper1/Tester2.java \
)
ifeq (1,$(enable.fts5))
JAVA_FILES.main += $(patsubst %,$(dir.src.jni)/%,\
JAVA_FILES.unittest += $(patsubst %,$(dir.src.fts5)/%,\
TesterFts5.java \
)
JAVA_FILES.main += $(patsubst %,$(dir.src.fts5)/%,\
fts5_api.java \
fts5_extension_function.java \
fts5_tokenizer.java \
Fts5.java \
Fts5Context.java \
Fts5ExtensionApi.java \
Fts5Function.java \
Fts5PhraseIter.java \
Fts5Tokenizer.java \
TesterFts5.java \
XTokenizeCallback.java \
)
endif
JAVA_FILES.tester := $(dir.src.jni.tester)/SQLTester.java
JAVA_FILES.tester := $(SQLTester.java)
JAVA_FILES.package.info := \
$(dir.src.jni)/package-info.java \
$(dir.src.jni)/annotation/package-info.java
CLASS_FILES.main := $(JAVA_FILES.main:.java=.class)
CLASS_FILES.unittest := $(JAVA_FILES.unittest:.java=.class)
CLASS_FILES.tester := $(JAVA_FILES.tester:.java=.class)
JAVA_FILES += $(JAVA_FILES.main)
JAVA_FILES += $(JAVA_FILES.main) $(JAVA_FILES.unittest)
ifeq (1,$(enable.tester))
JAVA_FILES += $(JAVA_FILES.tester)
endif
CLASS_FILES :=
define DOTCLASS_DEPS
$(1).class: $(1).java $(MAKEFILE)
define CLASSFILE_DEPS
all: $(1).class
CLASS_FILES += $(1).class
endef
$(foreach B,$(basename $(JAVA_FILES)),$(eval $(call DOTCLASS_DEPS,$(B))))
$(CLASS_FILES.tester): $(CLASS_FILES.main)
javac.flags ?= -Xlint:unchecked -Xlint:deprecation
java.flags ?=
jnicheck ?= 1
ifeq (1,$(jnicheck))
java.flags += -Xcheck:jni
endif
$(SQLite3Jni.class): $(JAVA_FILES)
$(foreach B,$(basename \
$(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.tester)),\
$(eval $(call CLASSFILE_DEPS,$(B))))
$(CLASS_FILES): $(JAVA_FILES) $(MAKEFILE)
$(bin.javac) $(javac.flags) -h $(dir.bld.c) -cp $(classpath) $(JAVA_FILES)
all: $(SQLite3Jni.class)
#.PHONY: classfiles
########################################################################
@@ -152,27 +200,40 @@ $(sqlite3.h):
$(MAKE) -C $(dir.top) sqlite3.c
$(sqlite3.c): $(sqlite3.h)
opt.threadsafe ?= 1
opt.fatal-oom ?= 1
opt.debug ?= 1
opt.metrics ?= 1
SQLITE_OPT = \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_THREADSAFE=$(opt.threadsafe) \
-DSQLITE_TEMP_STORE=2 \
-DSQLITE_USE_URI=1 \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_C=$(sqlite3.c) \
-DSQLITE_JNI_FATAL_OOM=$(opt.fatal-oom) \
-DSQLITE_JNI_ENABLE_METRICS=$(opt.metrics)
opt.extras ?= 1
ifeq (1,$(opt.extras))
SQLITE_OPT += -DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
-DSQLITE_ENABLE_OFFSET_SQL_FUNC \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_TEMP_STORE=2 \
-DSQLITE_USE_URI=1 \
-DSQLITE_C=$(sqlite3.c)
# -DSQLITE_DEBUG
# -DSQLITE_DEBUG is just to work around a -Wall warning
# for a var which gets set in all builds but only read
# via assert().
-DSQLITE_ENABLE_PREUPDATE_HOOK \
-DSQLITE_ENABLE_NORMALIZE \
-DSQLITE_ENABLE_SQLLOG
endif
SQLITE_OPT += -g -DDEBUG -UNDEBUG
ifeq (1,$(opt.debug))
SQLITE_OPT += -DSQLITE_DEBUG -g -DDEBUG -UNDEBUG
else
SQLITE_OPT += -Os
endif
ifeq (1,$(enable.fts5))
SQLITE_OPT += -DSQLITE_ENABLE_FTS5
@@ -181,25 +242,30 @@ endif
sqlite3-jni.c := $(dir.src.c)/sqlite3-jni.c
sqlite3-jni.o := $(dir.bld.c)/sqlite3-jni.o
sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
sqlite3-jni.dll := $(dir.bld.c)/libsqlite3-jni.so
package.dll := $(dir.bld.c)/libsqlite3-jni.so
# All javac-generated .h files must be listed in $(sqlite3-jni.h.in):
sqlite3-jni.h.in :=
# $(java.with.jni) lists all Java files which contain JNI decls:
java.with.jni :=
define ADD_JNI_H
sqlite3-jni.h.in += $$(dir.bld.c)/org_sqlite_jni_$(1).h
$$(dir.bld.c)/org_sqlite_jni_$(1).h: $$(dir.src.jni)/$(1).java
sqlite3-jni.h.in += $$(dir.bld.c)/org_sqlite_jni$(3)_$(2).h
java.with.jni += $(1)/$(2).java
$$(dir.bld.c)/org_sqlite_jni$(3)_$(2).h: $(1)/$(2).java
endef
$(eval $(call ADD_JNI_H,SQLite3Jni))
# Invoke ADD_JNI_H once for each Java file which includes JNI
# declarations:
$(eval $(call ADD_JNI_H,$(dir.src.capi),CApi,_capi))
$(eval $(call ADD_JNI_H,$(dir.src.capi),SQLTester,_capi))
ifeq (1,$(enable.fts5))
$(eval $(call ADD_JNI_H,Fts5ExtensionApi))
$(eval $(call ADD_JNI_H,fts5_api))
$(eval $(call ADD_JNI_H,fts5_tokenizer))
$(eval $(call ADD_JNI_H,$(dir.src.fts5),Fts5ExtensionApi,_fts5))
$(eval $(call ADD_JNI_H,$(dir.src.fts5),fts5_api,_fts5))
$(eval $(call ADD_JNI_H,$(dir.src.fts5),fts5_tokenizer,_fts5))
endif
ifeq (1,$(enable.tester))
sqlite3-jni.h.in += $(dir.bld.c)/org_sqlite_jni_tester_SQLTester.h
$(dir.bld.c)/org_sqlite_jni_tester_SQLTester.h: $(dir.src.jni.tester)/SQLTester.java
endif
#sqlite3-jni.dll.cfiles := $(dir.src.c)
sqlite3-jni.dll.cflags = \
$(sqlite3-jni.h.in): $(dir.bld.c)
#package.dll.cfiles :=
package.dll.cflags = \
-std=c99 \
-fPIC \
-I. \
-I$(dir $(sqlite3.h)) \
@@ -207,54 +273,82 @@ sqlite3-jni.dll.cflags = \
-I$(JDK_HOME)/include \
$(patsubst %,-I%,$(patsubst %.h,,$(wildcard $(JDK_HOME)/include/*))) \
-Wall
# Using (-Wall -Wextra) triggers an untennable number of
# gcc warnings from sqlite3.c for mundane things like
# unused parameters.
#
# The gross $(patsubst...) above is to include the platform-specific
# subdir which lives under $(JDK_HOME)/include and is a required
# include path for client-level code.
#
# Using (-Wall -Wextra) triggers an untennable number of
# gcc warnings from sqlite3.c for mundane things like
# unused parameters.
########################################################################
ifeq (1,$(enable.tester))
sqlite3-jni.dll.cflags += -DS3JNI_ENABLE_SQLTester
package.dll.cflags += -DSQLITE_JNI_ENABLE_SQLTester
endif
$(sqlite3-jni.h): $(sqlite3-jni.h.in) $(MAKEFILE)
cat $(sqlite3-jni.h.in) > $@
$(sqlite3-jni.dll): $(sqlite3-jni.h) $(sqlite3.c) $(sqlite3.h)
$(sqlite3-jni.dll): $(dir.bld.c) $(sqlite3-jni.c) $(SQLite3Jni.java) $(MAKEFILE)
$(CC) $(sqlite3-jni.dll.cflags) $(SQLITE_OPT) \
$(sqlite3-jni.c) -shared -o $@
all: $(sqlite3-jni.dll)
.PHONY: test
test.flags ?= -v
test: $(SQLite3Jni.class) $(sqlite3-jni.dll)
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
$(java.flags) -cp $(classpath) \
org.sqlite.jni.Tester1 $(if $(test.flags),-- $(test.flags),)
$(sqlite3-jni.h): $(sqlite3-jni.h.in) $(MAKEFILE)
@cat $(sqlite3-jni.h.in) > $@.tmp
@if cmp $@ $@.tmp >/dev/null; then \
rm -f $@.tmp; \
echo "$@ not modified"; \
else \
mv $@.tmp $@; \
echo "Updated $@"; \
fi
@if [ x1 != x$(enable.fts5) ]; then \
echo "*** REMINDER:"; \
echo "*** enable.fts5=0, so please do not check in changes to $@."; \
fi
$(package.dll): $(sqlite3-jni.h) $(sqlite3.c) $(sqlite3.h)
$(package.dll): $(sqlite3-jni.c) $(MAKEFILE)
$(CC) $(package.dll.cflags) $(SQLITE_OPT) \
$(sqlite3-jni.c) -shared -o $@
all: $(package.dll)
.PHONY: test test-one
Tester1.flags ?=
Tester2.flags ?=
test.flags.jvm = -ea -Djava.library.path=$(dir.bld.c) \
$(java.flags) -cp $(classpath)
test.deps := $(CLASS_FILES) $(package.dll)
test-one: $(test.deps)
$(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 $(Tester1.flags)
$(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 $(Tester2.flags)
test-sqllog: $(test.deps)
@echo "Testing with -sqllog..."
$(bin.java) $(test.flags.jvm) -sqllog
test-mt: $(test.deps)
@echo "Testing in multi-threaded mode:";
$(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 \
-t 7 -r 50 -shuffle $(Tester1.flags)
$(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 \
-t 7 -r 50 -shuffle $(Tester2.flags)
test: test-one test-mt
tests: test test-sqllog
tester.scripts := $(sort $(wildcard $(dir.src)/tests/*.test))
tester.flags ?= # --verbose
.PHONY: tester tester-local tester-ext
ifeq (1,$(enable.tester))
tester-local: $(CLASS_FILES.tester) $(sqlite3-jni.dll)
tester-local: $(CLASS_FILES.tester) $(package.dll)
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
$(java.flags) -cp $(classpath) \
org.sqlite.jni.tester.SQLTester $(tester.flags) $(tester.scripts)
org.sqlite.jni.capi.SQLTester $(tester.flags) $(tester.scripts)
tester: tester-local
else
tester:
@echo "SQLTester support is disabled. Build with enable.tester=1 to enable it."
@echo "SQLTester support is disabled."
endif
tester.extdir.default := src/tests/ext
tester.extdir.default := $(dir.tests)/ext
tester.extdir ?= $(tester.extdir.default)
tester.extern-scripts := $(wildcard $(tester.extdir)/*.test)
ifneq (,$(tester.extern-scripts))
tester-ext:
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
$(java.flags) -cp $(classpath) \
org.sqlite.jni.tester.SQLTester $(tester.flags) $(tester.extern-scripts)
org.sqlite.jni.capi.SQLTester $(tester.flags) $(tester.extern-scripts)
else
tester-ext:
@echo "******************************************************"; \
@@ -267,25 +361,79 @@ endif
tester-ext: tester-local
tester: tester-ext
tests: test tester
tests: tester
########################################################################
# Build each SQLITE_THREADMODE variant and run all tests against them.
multitest: clean
define MULTIOPT
multitest: multitest-$(1)
multitest-$(1):
$$(MAKE) opt.debug=$$(opt.debug) $(patsubst %,opt.%,$(2)) \
tests clean enable.fts5=1
endef
$(eval $(call MULTIOPT,01,threadsafe=0 oom=1))
$(eval $(call MULTIOPT,00,threadsafe=0 oom=0))
$(eval $(call MULTIOPT,11,threadsafe=1 oom=1))
$(eval $(call MULTIOPT,10,threadsafe=1 oom=0))
$(eval $(call MULTIOPT,21,threadsafe=2 oom=1))
$(eval $(call MULTIOPT,20,threadsafe=2 oom=0))
########################################################################
# jar bundle...
package.jar.in := $(abspath $(dir.src)/jar.in)
CLEAN_FILES += $(package.jar.in)
$(package.jar.in): $(MAKEFILE) $(CLASS_FILES.main)
cd $(dir.src); ls -1 org/sqlite/jni/*.java org/sqlite/jni/*.class > $@
@ls -la $@
@echo "To use this jar you will need the -Djava.library.path=DIR/WITH/libsqlite3-jni.so flag."
@echo "e.g. java -jar $@ -Djava.library.path=bld"
JAVA_FILES.jar := $(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.package.info)
CLASS_FILES.jar := $(filter-out %/package-info.class,$(JAVA_FILES.jar:.java=.class))
$(package.jar.in): $(package.dll) $(MAKEFILE)
ls -1 \
$(dir.src.jni)/*/*.java $(dir.src.jni)/*/*.class \
| sed -e 's,^$(dir.src)/,,' | sort > $@
$(package.jar): $(CLASS_FILES) $(MAKEFILE) $(package.jar.in)
rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~
cd $(dir.src); $(bin.jar) -cfe ../$@ org.sqlite.jni.Tester1 @$(package.jar.in)
$(package.jar): $(CLASS_FILES.jar) $(MAKEFILE) $(package.jar.in)
@rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~
cd $(dir.src); $(bin.jar) -cfe ../$@ org.sqlite.jni.capi.Tester1 @$(package.jar.in)
@ls -la $@
@echo "To use this jar you will need the -Djava.library.path=DIR/CONTAINING/libsqlite3-jni.so flag."
@echo "e.g. java -Djava.library.path=bld -jar $@"
jar: $(package.jar)
run-jar: $(package.jar) $(package.dll)
$(bin.java) -Djava.library.path=$(dir.bld) -jar $(package.jar) $(run-jar.flags)
########################################################################
# javadoc...
dir.doc := $(dir.jni)/javadoc
doc.index := $(dir.doc)/index.html
javadoc.exclude := -exclude org.sqlite.jni.fts5
# ^^^^ 2023-09-13: elide the fts5 parts from the public docs for
# the time being, as it's not clear where the Java bindings for
# those bits are going.
# javadoc.exclude += -exclude org.sqlite.jni.capi
# ^^^^ exclude the capi API only for certain builds (TBD)
$(doc.index): $(JAVA_FILES.main) $(MAKEFILE)
@if [ -d $(dir.doc) ]; then rm -fr $(dir.doc)/*; fi
$(bin.javadoc) -cp $(classpath) -d $(dir.doc) -quiet \
-subpackages org.sqlite.jni $(javadoc.exclude)
@echo "javadoc output is in $@"
.PHONY: doc javadoc docserve
.FORCE: doc
doc: $(doc.index)
javadoc: $(doc.index)
# Force rebild of docs
redoc:
@rm -f $(doc.index)
@$(MAKE) doc
docserve: $(doc.index)
cd $(dir.doc) && althttpd -max-age 1 -page index.html
########################################################################
# Clean up...
CLEAN_FILES += $(dir.bld.c)/* \
$(dir.src.jni)/*.class \
$(dir.src.jni.tester)/*.class \
$(sqlite3-jni.dll) \
$(dir.src.jni)/*/*.class \
$(package.dll) \
hs_err_pid*.log
.PHONY: clean distclean
@@ -293,7 +441,7 @@ clean:
-rm -f $(CLEAN_FILES)
distclean: clean
-rm -f $(DISTCLEAN_FILES)
-rm -fr $(dir.bld.c)
-rm -fr $(dir.bld.c) $(dir.doc)
########################################################################
# disttribution bundle rules...
@@ -317,6 +465,10 @@ dist: \
$(bin.version-info) $(sqlite3.canonical.c) \
$(package.jar) $(MAKEFILE)
@echo "Making end-user deliverables..."
@echo "****************************************************************************"; \
echo "*** WARNING: be sure to build this with JDK8 (javac 1.8) for compatibility."; \
echo "*** reasons!"; $$($(bin.javac) -version); \
echo "****************************************************************************"
@rm -fr $(dist-dir.top)
@mkdir -p $(dist-dir.src)
@cp -p $(dist.top.extras) $(dist-dir.top)/.
+127 -48
View File
@@ -15,7 +15,10 @@ Technical support is available in the 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.
information about its API until this disclaimer is removed. The JNI
bindings released with version 3.43 are a "tech preview" and 3.44
will be "final," at which point strong backward compatibility
guarantees will apply.
Project goals/requirements:
@@ -40,13 +43,41 @@ Non-goals:
- Creation of high-level OO wrapper APIs. Clients are free to create
them off of the C-style API.
- Support for mixed-mode operation, where client code accesses SQLite
both via the Java-side API and the C API via their own native
code. In such cases, proxy functionalities (primarily callback
handler wrappers of all sorts) may fail because the C-side use of
the SQLite APIs will bypass those proxies.
Significant TODOs
========================================================================
- The initial beta release with version 3.43 has severe threading
limitations. Namely, two threads cannot call into the JNI-bound API
at once. This limitation will be remove in a subsequent release.
Hello World
-----------------------------------------------------------------------
```java
import org.sqlite.jni.*;
import static org.sqlite.jni.CApi.*;
...
final sqlite3 db = sqlite3_open(":memory:");
try {
final int rc = sqlite3_errcode(db);
if( 0 != rc ){
if( null != db ){
System.out.print("Error opening db: "+sqlite3_errmsg(db));
}else{
System.out.print("Error opening db: rc="+rc);
}
... handle error ...
}
// ... else use the db ...
}finally{
// ALWAYS close databases using sqlite3_close() or sqlite3_close_v2()
// when done with them. All of their active statement handles must
// first have been passed to sqlite3_finalize().
sqlite3_close_v2(db);
}
```
Building
@@ -60,55 +91,97 @@ The canonical builds assumes a Linux-like environment and requires:
Put simply:
```
```console
$ export JAVA_HOME=/path/to/jdk/root
$ make
$ make test
$ make clean
```
The jar distribution can be created with `make jar`, but note that it
does not contain the binary DLL file. A different DLL is needed for
each target platform.
<a id='1to1ish'></a>
One-to-One(-ish) Mapping to C
========================================================================
This JNI binding aims to provide as close to a 1-to-1 experience with
the C API as cross-language semantics allow. Exceptions are
the C API as cross-language semantics allow. Interface changes are
necessarily made where cross-language semantics do not allow a 1-to-1,
and judiciously made where a 1-to-1 mapping would be unduly cumbersome
to use in Java.
to use in Java. In all cases, this binding makes every effort to
provide semantics compatible with the C API documentation even if the
interface to those semantics is slightly different. Any cases which
deviate from those semantics (either removing or adding semantics) are
clearly documented.
Golden Rule: _Never_ Throw from Callbacks
Where it makes sense to do so for usability, Java-side overloads are
provided which accept or return data in alternative forms or provide
sensible default argument values. In all such cases they are thin
proxies around the corresponding C APIs and do not introduce new
semantics.
In some very few cases, Java-specific capabilities have been added in
new APIs, all of which have "_java" somewhere in their names.
Examples include:
- `sqlite3_result_java_object()`
- `sqlite3_column_java_object()`
- `sqlite3_column_java_casted()`
- `sqlite3_value_java_object()`
- `sqlite3_value_java_casted()`
which, as one might surmise, collectively enable the passing of
arbitrary Java objects from user-defined SQL functions through to the
caller.
Golden Rule: Garbage Collection Cannot Free SQLite Resources
------------------------------------------------------------------------
JNI bindings which accept client-defined functions _must never throw
exceptions_ unless _very explicitly documented_ as being
throw-safe. Exceptions are generally reserved for higher-level
bindings which are constructed to specifically deal with them and
ensure that they do not leak C-level resources. Some of the JNI
bindings are provided as Java functions which expect this rule to
always hold.
It is important that all databases and prepared statement handles get
cleaned up by client code. A database cannot be closed if it has open
statement handles. `sqlite3_close()` fails if the db cannot be closed
whereas `sqlite3_close_v2()` recognizes that case and marks the db as
a "zombie," pending finalization when the library detects that all
pending statements have been closed. Be aware that Java garbage
collection _cannot_ close a database or finalize a prepared statement.
Those things require explicit API calls.
UTF-8(-ish)
Golden Rule #2: _Never_ Throw from Callbacks (Unless...)
------------------------------------------------------------------------
SQLite internally uses UTF-8 encoding, whereas Java natively uses
UTF-16. Java JNI has routines for converting to and from UTF-8, _but_
Java uses what its docs call "[modified UTF-8][modutf8]." Care must be
taken when converting Java strings to UTF-8 to ensure that the proper
conversion is performed. In short,
`String.getBytes(StandardCharsets.UTF_8)` performs the proper
conversion in Java, and there is no JNI C API for that conversion
(JNI's `NewStringUTF()` returns MUTF-8).
All routines in this API, barring explicitly documented exceptions,
retain C-like semantics. For example, they are not permitted to throw
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
shouldn't be used. The APIs clearly mark function parameters which
should not be null, but does not 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`.
Known consequences and limitations of this discrepancy include:
Client-defined callbacks _must never throw exceptions_ unless _very
explicitly documented_ as being throw-safe. Exceptions are generally
reserved for higher-level bindings which are constructed to
specifically deal with them and ensure that they do not leak C-level
resources. In some cases, callback handlers are permitted to throw, in
which cases they get translated to C-level result codes and/or
messages. If a callback which is not permitted to throw throws, its
exception may trigger debug output but will otherwise be suppressed.
- Names of databases, tables, and collations must not contain
characters which differ in MUTF-8 and UTF-8, or certain APIs will
mis-translate them on their way between languages. APIs which
transfer other client-side data to Java take extra care to
convert the data at the cost of performance.
[modutf8]: https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#modified-utf-8
The reason some callbacks are permitted to throw and others not is
because all such callbacks act as proxies for C function callback
interfaces and some of those interfaces have no error-reporting
mechanism. Those which are capable of propagating errors back through
the library convert exceptions from callbacks into corresponding
C-level error information. Those which cannot propagate errors
necessarily suppress any exceptions in order to maintain the C-style
semantics of the APIs.
Unwieldy Constructs are Re-mapped
@@ -126,7 +199,7 @@ A prime example of where interface changes for Java are necessary for
usability is [registration of a custom
collation](https://sqlite.org/c3ref/create_collation.html):
```
```c
// C:
int sqlite3_create_collation(sqlite3 * db, const char * name, int eTextRep,
void *pUserData,
@@ -145,7 +218,7 @@ passed that object as their first argument. That data is passed around
bind that part as-is to Java, the result would be awkward to use (^Yes,
we tried this.):
```
```java
// Java:
int sqlite3_create_collation(sqlite3 db, String name, int eTextRep,
Object pUserData, xCompareType xCompare);
@@ -160,20 +233,20 @@ for callbacks and (B) having their internal state provided separately,
which is ill-fitting in Java. For the sake of usability, C APIs which
follow that pattern use a slightly different Java interface:
```
```java
int sqlite3_create_collation(sqlite3 db, String name, int eTextRep,
Collation collation);
SomeCallbackType collation);
```
Where the `Collation` class has an abstract `xCompare()` method and
Where the `Collation` class has an abstract `call()` method and
no-op `xDestroy()` method which can be overridden if needed, leading to
a much more Java-esque usage:
```
int rc = sqlite3_create_collation(db, "mycollation", SQLITE_UTF8, new Collation(){
```java
int rc = sqlite3_create_collation(db, "mycollation", SQLITE_UTF8, new SomeCallbackType(){
// Required comparison function:
@Override public int xCompare(byte[] lhs, byte[] rhs){ ... }
@Override public int call(byte[] lhs, byte[] rhs){ ... }
// Optional finalizer function:
@Override public void xDestroy(){ ... }
@@ -188,8 +261,8 @@ int rc = sqlite3_create_collation(db, "mycollation", SQLITE_UTF8, new Collation(
Noting that:
- It is still possible to bind in call-scope-local state via closures,
if desired.
- It is possible to bind in call-scope-local state via closures, if
desired, as opposed to packing it into the Collation object.
- No capabilities of the C API are lost or unduly obscured via the
above API reshaping, so power users need not make any compromises.
@@ -200,6 +273,7 @@ Noting that:
overriding the `xDestroy()` method effectively gives it v2
semantics.
### User-defined SQL Functions (a.k.a. UDFs)
The [`sqlite3_create_function()`](https://sqlite.org/c3ref/create_function.html)
@@ -207,12 +281,13 @@ family of APIs make heavy use of function pointers to provide
client-defined callbacks, necessitating interface changes in the JNI
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);
```
> Design question: does the encoding argument serve any purpose in JS?
> 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:
@@ -230,5 +305,9 @@ Search [`Tester1.java`](/file/ext/jni/src/org/sqlite/jni/Tester1.java) for
Reminder: see the disclaimer at the top of this document regarding the
in-flux nature of this API.
[jsrc]: /file/
[www]: https://sqlite.org
### And so on...
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.
+9 -4
View File
@@ -6,7 +6,9 @@
# proper top-level JDK directory and, depending on the platform, add a
# platform-specific -I directory. It should build as-is with any
# 2020s-era version of gcc or clang. It requires JDK version 8 or
# higher.
# higher and that JAVA_HOME points to the top-most installation
# directory of that JDK. On Ubuntu-style systems the JDK is typically
# installed under /usr/lib/jvm/java-VERSION-PLATFORM.
default: all
@@ -31,10 +33,11 @@ SQLITE_OPT = \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_THREADSAFE=1 \
-DSQLITE_TEMP_STORE=2 \
-DSQLITE_USE_URI=1 \
-DSQLITE_ENABLE_FTS5
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_DEBUG
sqlite3-jni.dll = libsqlite3-jni.so
$(sqlite3-jni.dll):
@@ -46,8 +49,10 @@ $(sqlite3-jni.dll):
src/sqlite3-jni.c -shared -o $@
@echo "Now try running it with: make test"
test.flags = -Djava.library.path=. sqlite3-jni-*.jar
test: $(sqlite3-jni.dll)
java -jar -Djava.library.path=. sqlite3-jni-*.jar
java -jar $(test.flags)
java -jar $(test.flags) -t 7 -r 10 -shuffle
clean:
-rm -f $(sqlite3-jni.dll)
+4189 -2710
View File
File diff suppressed because it is too large Load Diff
+2220 -1830
View File
File diff suppressed because it is too large Load Diff
@@ -1,32 +0,0 @@
/*
** 2023-08-05
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
A callback for use with sqlite3_set_authorizer().
*/
public interface Authorizer {
/**
Must functions as described for the sqlite3_set_authorizer()
callback, with one caveat: the string values passed here were
initially (at the C level) encoded in standard UTF-8. If they
contained any constructs which are not compatible with MUTF-8,
these strings will not have the expected values. For further
details, see the documentation for the SQLite3Jni class.
Must not throw.
*/
int xAuth(int opId, @Nullable String s1, @Nullable String s2,
@Nullable String s3, @Nullable String s4);
}
@@ -1,31 +0,0 @@
/*
** 2023-08-05
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
A callback for use with sqlite3_auto_extension().
*/
public interface AutoExtension {
/**
Must function as described for the sqlite3_auto_extension(),
with the caveat that the signature is more limited.
As an exception (as it were) to the callbacks-must-not-throw
rule, AutoExtensions may do so and the exception's error message
will be set as the db's error string.
Results are undefined if db is closed by an auto-extension.
*/
int xEntryPoint(sqlite3 db);
}
@@ -1,45 +0,0 @@
/*
** 2023-07-22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
Callback proxy for use with sqlite3_busy_handler().
*/
public abstract class BusyHandler {
/**
Must function as documented for the sqlite3_busy_handler()
callback argument, minus the (void*) argument the C-level
function requires.
Any exceptions thrown by this callback are suppressed in order to
retain the C-style API semantics of the JNI bindings.
*/
public abstract int xCallback(int n);
/**
Optionally override to perform any cleanup when this busy
handler is destroyed. It is destroyed when:
- The associated db is passed to sqlite3_close() or
sqlite3_close_v2().
- sqlite3_busy_handler() is called to replace the handler,
whether it's passed a null handler or any other instance of
this class.
- sqlite3_busy_timeout() is called, which implicitly installs
a busy handler.
*/
public void xDestroy(){}
}
@@ -1,27 +0,0 @@
/*
** 2023-08-04
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
Fts5Function is used in conjunction with the
sqlite3_create_fts_function() JNI-bound API to give that native code
access to the callback functions needed in order to implement
FTS5 auxiliary functions in Java.
*/
public abstract class Fts5Function {
public abstract void xFunction(Fts5ExtensionApi pApi, Fts5Context pFts,
sqlite3_context pCtx, sqlite3_value argv[]);
public void xDestroy() {}
}
@@ -1,165 +0,0 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
Helper classes for handling JNI output pointers.
We do not use a generic OutputPointer<T> because working with those
from the native JNI code is unduly quirky due to a lack of
autoboxing at that level.
The usage is similar for all of thes types:
```
OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
assert( null==out.get() );
int rc = sqlite3_open(":memory:", out);
if( 0!=rc ) ... error;
assert( null!=out.get() );
sqlite3 db = out.take();
assert( null==out.get() );
```
With the minor exception that the primitive types permit direct
access to the object's value via the `value` property, whereas the
JNI-level opaque types do not permit client-level code to set that
property.
*/
public final class OutputPointer {
/**
Output pointer for use with routines, such as sqlite3_open(),
which return a database handle via an output pointer. These
pointers can only be set by the JNI layer, not by client-level
code.
*/
public static final class sqlite3 {
private org.sqlite.jni.sqlite3 value;
//! Initializes with a null value.
public sqlite3(){value = null;}
//! Sets the current value to null.
public void clear(){value = null;}
//! Returns the current value.
public final org.sqlite.jni.sqlite3 get(){return value;}
//! Equivalent to calling get() then clear().
public final org.sqlite.jni.sqlite3 take(){
final org.sqlite.jni.sqlite3 v = value;
value = null;
return v;
}
}
/**
Output pointer for use with routines, such as sqlite3_prepare(),
which return a statement handle via an output pointer. These
pointers can only be set by the JNI layer, not by client-level
code.
*/
public static final class sqlite3_stmt {
private org.sqlite.jni.sqlite3_stmt value;
//! Initializes with a null value.
public sqlite3_stmt(){value = null;}
//! Sets the current value to null.
public void clear(){value = null;}
//! Returns the current value.
public final org.sqlite.jni.sqlite3_stmt get(){return value;}
//! Equivalent to calling get() then clear().
public final org.sqlite.jni.sqlite3_stmt take(){
final org.sqlite.jni.sqlite3_stmt v = value;
value = null;
return v;
}
}
/**
Output pointer for use with native routines which return integers via
output pointers.
*/
public static final class Int32 {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public int value;
//! Initializes with the value 0.
public Int32(){this(0);}
//! Initializes with the value v.
public Int32(int v){value = v;}
//! Returns the current value.
public final int get(){return value;}
//! Sets the current value to v.
public final void set(int v){value = v;}
}
/**
Output pointer for use with native routines which return 64-bit integers
via output pointers.
*/
public static final class Int64 {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public long value;
//! Initializes with the value 0.
public Int64(){this(0);}
//! Initializes with the value v.
public Int64(long v){value = v;}
//! Returns the current value.
public final long get(){return value;}
//! Sets the current value.
public final void set(long v){value = v;}
}
/**
Output pointer for use with native routines which return strings via
output pointers.
*/
public static final class String {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public java.lang.String value;
//! Initializes with a null value.
public String(){this(null);}
//! Initializes with the value v.
public String(java.lang.String v){value = v;}
//! Returns the current value.
public final java.lang.String get(){return value;}
//! Sets the current value.
public final void set(java.lang.String v){value = v;}
}
/**
Output pointer for use with native routines which return byte
arrays via output pointers.
*/
public static final class ByteArray {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public byte[] value;
//! Initializes with the value null.
public ByteArray(){this(null);}
//! Initializes with the value v.
public ByteArray(byte[] v){value = v;}
//! Returns the current value.
public final byte[] get(){return value;}
//! Sets the current value.
public final void set(byte[] v){value = v;}
}
}
-155
View File
@@ -1,155 +0,0 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
This enum contains all of the core and "extended" result codes used
by the sqlite3 library. It is provided not for use with the C-style
API (with which it won't work) but for higher-level code which may
find it useful to map SQLite result codes to human-readable names.
*/
public enum ResultCode {
SQLITE_OK(SQLite3Jni.SQLITE_OK),
SQLITE_ERROR(SQLite3Jni.SQLITE_ERROR),
SQLITE_INTERNAL(SQLite3Jni.SQLITE_INTERNAL),
SQLITE_PERM(SQLite3Jni.SQLITE_PERM),
SQLITE_ABORT(SQLite3Jni.SQLITE_ABORT),
SQLITE_BUSY(SQLite3Jni.SQLITE_BUSY),
SQLITE_LOCKED(SQLite3Jni.SQLITE_LOCKED),
SQLITE_NOMEM(SQLite3Jni.SQLITE_NOMEM),
SQLITE_READONLY(SQLite3Jni.SQLITE_READONLY),
SQLITE_INTERRUPT(SQLite3Jni.SQLITE_INTERRUPT),
SQLITE_IOERR(SQLite3Jni.SQLITE_IOERR),
SQLITE_CORRUPT(SQLite3Jni.SQLITE_CORRUPT),
SQLITE_NOTFOUND(SQLite3Jni.SQLITE_NOTFOUND),
SQLITE_FULL(SQLite3Jni.SQLITE_FULL),
SQLITE_CANTOPEN(SQLite3Jni.SQLITE_CANTOPEN),
SQLITE_PROTOCOL(SQLite3Jni.SQLITE_PROTOCOL),
SQLITE_EMPTY(SQLite3Jni.SQLITE_EMPTY),
SQLITE_SCHEMA(SQLite3Jni.SQLITE_SCHEMA),
SQLITE_TOOBIG(SQLite3Jni.SQLITE_TOOBIG),
SQLITE_CONSTRAINT(SQLite3Jni.SQLITE_CONSTRAINT),
SQLITE_MISMATCH(SQLite3Jni.SQLITE_MISMATCH),
SQLITE_MISUSE(SQLite3Jni.SQLITE_MISUSE),
SQLITE_NOLFS(SQLite3Jni.SQLITE_NOLFS),
SQLITE_AUTH(SQLite3Jni.SQLITE_AUTH),
SQLITE_FORMAT(SQLite3Jni.SQLITE_FORMAT),
SQLITE_RANGE(SQLite3Jni.SQLITE_RANGE),
SQLITE_NOTADB(SQLite3Jni.SQLITE_NOTADB),
SQLITE_NOTICE(SQLite3Jni.SQLITE_NOTICE),
SQLITE_WARNING(SQLite3Jni.SQLITE_WARNING),
SQLITE_ROW(SQLite3Jni.SQLITE_ROW),
SQLITE_DONE(SQLite3Jni.SQLITE_DONE),
SQLITE_ERROR_MISSING_COLLSEQ(SQLite3Jni.SQLITE_ERROR_MISSING_COLLSEQ),
SQLITE_ERROR_RETRY(SQLite3Jni.SQLITE_ERROR_RETRY),
SQLITE_ERROR_SNAPSHOT(SQLite3Jni.SQLITE_ERROR_SNAPSHOT),
SQLITE_IOERR_READ(SQLite3Jni.SQLITE_IOERR_READ),
SQLITE_IOERR_SHORT_READ(SQLite3Jni.SQLITE_IOERR_SHORT_READ),
SQLITE_IOERR_WRITE(SQLite3Jni.SQLITE_IOERR_WRITE),
SQLITE_IOERR_FSYNC(SQLite3Jni.SQLITE_IOERR_FSYNC),
SQLITE_IOERR_DIR_FSYNC(SQLite3Jni.SQLITE_IOERR_DIR_FSYNC),
SQLITE_IOERR_TRUNCATE(SQLite3Jni.SQLITE_IOERR_TRUNCATE),
SQLITE_IOERR_FSTAT(SQLite3Jni.SQLITE_IOERR_FSTAT),
SQLITE_IOERR_UNLOCK(SQLite3Jni.SQLITE_IOERR_UNLOCK),
SQLITE_IOERR_RDLOCK(SQLite3Jni.SQLITE_IOERR_RDLOCK),
SQLITE_IOERR_DELETE(SQLite3Jni.SQLITE_IOERR_DELETE),
SQLITE_IOERR_BLOCKED(SQLite3Jni.SQLITE_IOERR_BLOCKED),
SQLITE_IOERR_NOMEM(SQLite3Jni.SQLITE_IOERR_NOMEM),
SQLITE_IOERR_ACCESS(SQLite3Jni.SQLITE_IOERR_ACCESS),
SQLITE_IOERR_CHECKRESERVEDLOCK(SQLite3Jni.SQLITE_IOERR_CHECKRESERVEDLOCK),
SQLITE_IOERR_LOCK(SQLite3Jni.SQLITE_IOERR_LOCK),
SQLITE_IOERR_CLOSE(SQLite3Jni.SQLITE_IOERR_CLOSE),
SQLITE_IOERR_DIR_CLOSE(SQLite3Jni.SQLITE_IOERR_DIR_CLOSE),
SQLITE_IOERR_SHMOPEN(SQLite3Jni.SQLITE_IOERR_SHMOPEN),
SQLITE_IOERR_SHMSIZE(SQLite3Jni.SQLITE_IOERR_SHMSIZE),
SQLITE_IOERR_SHMLOCK(SQLite3Jni.SQLITE_IOERR_SHMLOCK),
SQLITE_IOERR_SHMMAP(SQLite3Jni.SQLITE_IOERR_SHMMAP),
SQLITE_IOERR_SEEK(SQLite3Jni.SQLITE_IOERR_SEEK),
SQLITE_IOERR_DELETE_NOENT(SQLite3Jni.SQLITE_IOERR_DELETE_NOENT),
SQLITE_IOERR_MMAP(SQLite3Jni.SQLITE_IOERR_MMAP),
SQLITE_IOERR_GETTEMPPATH(SQLite3Jni.SQLITE_IOERR_GETTEMPPATH),
SQLITE_IOERR_CONVPATH(SQLite3Jni.SQLITE_IOERR_CONVPATH),
SQLITE_IOERR_VNODE(SQLite3Jni.SQLITE_IOERR_VNODE),
SQLITE_IOERR_AUTH(SQLite3Jni.SQLITE_IOERR_AUTH),
SQLITE_IOERR_BEGIN_ATOMIC(SQLite3Jni.SQLITE_IOERR_BEGIN_ATOMIC),
SQLITE_IOERR_COMMIT_ATOMIC(SQLite3Jni.SQLITE_IOERR_COMMIT_ATOMIC),
SQLITE_IOERR_ROLLBACK_ATOMIC(SQLite3Jni.SQLITE_IOERR_ROLLBACK_ATOMIC),
SQLITE_IOERR_DATA(SQLite3Jni.SQLITE_IOERR_DATA),
SQLITE_IOERR_CORRUPTFS(SQLite3Jni.SQLITE_IOERR_CORRUPTFS),
SQLITE_LOCKED_SHAREDCACHE(SQLite3Jni.SQLITE_LOCKED_SHAREDCACHE),
SQLITE_LOCKED_VTAB(SQLite3Jni.SQLITE_LOCKED_VTAB),
SQLITE_BUSY_RECOVERY(SQLite3Jni.SQLITE_BUSY_RECOVERY),
SQLITE_BUSY_SNAPSHOT(SQLite3Jni.SQLITE_BUSY_SNAPSHOT),
SQLITE_BUSY_TIMEOUT(SQLite3Jni.SQLITE_BUSY_TIMEOUT),
SQLITE_CANTOPEN_NOTEMPDIR(SQLite3Jni.SQLITE_CANTOPEN_NOTEMPDIR),
SQLITE_CANTOPEN_ISDIR(SQLite3Jni.SQLITE_CANTOPEN_ISDIR),
SQLITE_CANTOPEN_FULLPATH(SQLite3Jni.SQLITE_CANTOPEN_FULLPATH),
SQLITE_CANTOPEN_CONVPATH(SQLite3Jni.SQLITE_CANTOPEN_CONVPATH),
SQLITE_CANTOPEN_SYMLINK(SQLite3Jni.SQLITE_CANTOPEN_SYMLINK),
SQLITE_CORRUPT_VTAB(SQLite3Jni.SQLITE_CORRUPT_VTAB),
SQLITE_CORRUPT_SEQUENCE(SQLite3Jni.SQLITE_CORRUPT_SEQUENCE),
SQLITE_CORRUPT_INDEX(SQLite3Jni.SQLITE_CORRUPT_INDEX),
SQLITE_READONLY_RECOVERY(SQLite3Jni.SQLITE_READONLY_RECOVERY),
SQLITE_READONLY_CANTLOCK(SQLite3Jni.SQLITE_READONLY_CANTLOCK),
SQLITE_READONLY_ROLLBACK(SQLite3Jni.SQLITE_READONLY_ROLLBACK),
SQLITE_READONLY_DBMOVED(SQLite3Jni.SQLITE_READONLY_DBMOVED),
SQLITE_READONLY_CANTINIT(SQLite3Jni.SQLITE_READONLY_CANTINIT),
SQLITE_READONLY_DIRECTORY(SQLite3Jni.SQLITE_READONLY_DIRECTORY),
SQLITE_ABORT_ROLLBACK(SQLite3Jni.SQLITE_ABORT_ROLLBACK),
SQLITE_CONSTRAINT_CHECK(SQLite3Jni.SQLITE_CONSTRAINT_CHECK),
SQLITE_CONSTRAINT_COMMITHOOK(SQLite3Jni.SQLITE_CONSTRAINT_COMMITHOOK),
SQLITE_CONSTRAINT_FOREIGNKEY(SQLite3Jni.SQLITE_CONSTRAINT_FOREIGNKEY),
SQLITE_CONSTRAINT_FUNCTION(SQLite3Jni.SQLITE_CONSTRAINT_FUNCTION),
SQLITE_CONSTRAINT_NOTNULL(SQLite3Jni.SQLITE_CONSTRAINT_NOTNULL),
SQLITE_CONSTRAINT_PRIMARYKEY(SQLite3Jni.SQLITE_CONSTRAINT_PRIMARYKEY),
SQLITE_CONSTRAINT_TRIGGER(SQLite3Jni.SQLITE_CONSTRAINT_TRIGGER),
SQLITE_CONSTRAINT_UNIQUE(SQLite3Jni.SQLITE_CONSTRAINT_UNIQUE),
SQLITE_CONSTRAINT_VTAB(SQLite3Jni.SQLITE_CONSTRAINT_VTAB),
SQLITE_CONSTRAINT_ROWID(SQLite3Jni.SQLITE_CONSTRAINT_ROWID),
SQLITE_CONSTRAINT_PINNED(SQLite3Jni.SQLITE_CONSTRAINT_PINNED),
SQLITE_CONSTRAINT_DATATYPE(SQLite3Jni.SQLITE_CONSTRAINT_DATATYPE),
SQLITE_NOTICE_RECOVER_WAL(SQLite3Jni.SQLITE_NOTICE_RECOVER_WAL),
SQLITE_NOTICE_RECOVER_ROLLBACK(SQLite3Jni.SQLITE_NOTICE_RECOVER_ROLLBACK),
SQLITE_WARNING_AUTOINDEX(SQLite3Jni.SQLITE_WARNING_AUTOINDEX),
SQLITE_AUTH_USER(SQLite3Jni.SQLITE_AUTH_USER),
SQLITE_OK_LOAD_PERMANENTLY(SQLite3Jni.SQLITE_OK_LOAD_PERMANENTLY);
public final int value;
ResultCode(int rc){
value = rc;
ResultCodeMap.set(rc, this);
}
/**
Returns the entry from this enum for the given result code, or
null if no match is found.
*/
public static ResultCode getEntryForInt(int rc){
return ResultCodeMap.get(rc);
}
/**
Internal level of indirection required because we cannot initialize
static enum members in an enum before the enum constructor is
invoked.
*/
private static final class ResultCodeMap {
private static final java.util.Map<Integer,ResultCode> i2e
= new java.util.HashMap<>();
private static void set(int rc, ResultCode e){ i2e.put(rc, e); }
private static ResultCode get(int rc){ return i2e.get(rc); }
}
}
-172
View File
@@ -1,172 +0,0 @@
/*
** 2023-07-22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
SQLFunction is used in conjunction with the
sqlite3_create_function() JNI-bound API to give that native code
access to the callback functions needed in order to implement SQL
functions in Java.
This class is not used by itself, but is a marker base class. The
three UDF types are modelled by the inner classes Scalar,
Aggregate<T>, and Window<T>. Most simply, clients may create
anonymous classes from those to implement UDFs. Clients are free to
create their own classes for use with UDFs, so long as they conform
to the public interfaces defined by those three classes. The JNI
layer only actively relies on the SQLFunction base class.
*/
public abstract class SQLFunction {
/**
PerContextState assists aggregate and window functions in
managinga their accumulator state across calls to the UDF's
callbacks.
If a given aggregate or window function is called multiple times
in a single SQL statement, e.g. SELECT MYFUNC(A), MYFUNC(B)...,
then the clients need some way of knowing which call is which so
that they can map their state between their various UDF callbacks
and reset it via xFinal(). This class takes care of such
mappings.
This class works by mapping
sqlite3_context.getAggregateContext() to a single piece of
state, of a client-defined type (the T part of this class), which
persists across a "matching set" of the UDF's callbacks.
This class is a helper providing commonly-needed functionality -
it is not required for use with aggregate or window functions.
Client UDFs are free to perform such mappings using custom
approaches. The provided Aggregate<T> and Window<T> classes
use this.
*/
public static final class PerContextState<T> {
private final java.util.Map<Long,ValueHolder<T>> map
= new java.util.HashMap<>();
/**
Should be called from a UDF's xStep(), xValue(), and xInverse()
methods, passing it that method's first argument and an initial
value for the persistent state. If there is currently no
mapping for cx.getAggregateContext() within the map, one is
created using the given initial value, else the existing one is
used and the 2nd argument is ignored. It returns a
ValueHolder<T> which can be used to modify that state directly
without requiring that the client update the underlying map's
entry.
T must be of a type which can be legally stored as a value in
java.util.HashMap<KeyType,T>.
*/
public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
ValueHolder<T> rc = map.get(cx.getAggregateContext());
if(null == rc){
map.put(cx.getAggregateContext(), rc = new ValueHolder<>(initialValue));
}
return rc;
}
/**
Should be called from a UDF's xFinal() method and passed that
method's first argument. This function removes the value
associated with cx.getAggregateContext() from the map and
returns it, returning null if no other UDF method has been
called to set up such a mapping. The latter condition will be
the case if a UDF is used in a statement which has no result
rows.
*/
public T takeAggregateState(sqlite3_context cx){
final ValueHolder<T> h = map.remove(cx.getAggregateContext());
return null==h ? null : h.value;
}
}
//! Subclass for creating scalar functions.
public static abstract class Scalar extends SQLFunction {
//! As for the xFunc() argument of the C API's sqlite3_create_function()
public abstract void xFunc(sqlite3_context cx, sqlite3_value[] args);
/**
Optionally override to be notified when the UDF is finalized by
SQLite.
*/
public void xDestroy() {}
}
/**
SQLFunction Subclass for creating aggregate functions. Its T is
the data type of its "accumulator" state, an instance of which is
intended to be be managed using the getAggregateState() and
takeAggregateState() methods.
*/
public static abstract class Aggregate<T> extends SQLFunction {
//! As for the xStep() argument of the C API's sqlite3_create_function()
public abstract void xStep(sqlite3_context cx, sqlite3_value[] args);
//! As for the xFinal() argument of the C API's sqlite3_create_function()
public abstract void xFinal(sqlite3_context cx);
/**
Optionally override to be notified when the UDF is finalized by
SQLite.
*/
public void xDestroy() {}
//! Per-invocation state for the UDF.
private final PerContextState<T> map = new PerContextState<>();
/**
To be called from the implementation's xStep() method, as well
as the xValue() and xInverse() methods of the Window<T>
subclass, to fetch the current per-call UDF state. On the
first call to this method for any given sqlite3_context
argument, the context is set to the given initial value. On all other
calls, the 2nd argument is ignored.
@see PerContextState<T>#takeAggregateState()
*/
protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
return map.getAggregateState(cx, initialValue);
}
/**
To be called from the implementation's xFinal() method to fetch
the final state of the UDF and remove its mapping.
@see PerContextState<T>#takeAggregateState()
*/
protected final T takeAggregateState(sqlite3_context cx){
return map.takeAggregateState(cx);
}
}
/**
An SQLFunction subclass for creating window functions. Note that
Window<T> inherits from Aggregate<T> and each instance is
required to implement the inherited abstract methods from that
class. See Aggregate<T> for information on managing the UDF's
invocation-specific state.
*/
public static abstract class Window<T> extends Aggregate<T> {
//! As for the xInverse() argument of the C API's sqlite3_create_window_function()
public abstract void xInverse(sqlite3_context cx, sqlite3_value[] args);
//! As for the xValue() argument of the C API's sqlite3_create_window_function()
public abstract void xValue(sqlite3_context cx);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,87 +0,0 @@
/*
** 2023-08-04
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains a set of tests for the sqlite3 JNI bindings.
*/
package org.sqlite.jni;
import static org.sqlite.jni.SQLite3Jni.*;
import static org.sqlite.jni.Tester1.*;
public class TesterFts5 {
private static void test1(){
Fts5ExtensionApi fea = Fts5ExtensionApi.getInstance();
affirm( null != fea );
affirm( fea.getNativePointer() != 0 );
affirm( fea == Fts5ExtensionApi.getInstance() )/*singleton*/;
sqlite3 db = createNewDb();
fts5_api fApi = fts5_api.getInstanceForDb(db);
affirm( fApi != null );
affirm( fApi == fts5_api.getInstanceForDb(db) /* singleton per db */ );
execSql(db, new String[] {
"CREATE VIRTUAL TABLE ft USING fts5(a, b);",
"INSERT INTO ft(rowid, a, b) VALUES(1, 'X Y', 'Y Z');",
"INSERT INTO ft(rowid, a, b) VALUES(2, 'A Z', 'Y Y');"
});
final String pUserData = "This is pUserData";
ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false);
ValueHolder<Integer> xFuncCount = new ValueHolder<>(0);
final fts5_extension_function func = new fts5_extension_function(){
public void xFunction(Fts5ExtensionApi ext, Fts5Context fCx,
sqlite3_context pCx, sqlite3_value argv[]){
int nCols = ext.xColumnCount(fCx);
affirm( 2 == nCols );
affirm( nCols == argv.length );
affirm( ext.xUserData(fCx) == pUserData );
if(true){
OutputPointer.String op = new OutputPointer.String();
for(int i = 0; i < nCols; ++i ){
int rc = ext.xColumnText(fCx, i, op);
affirm( 0 == rc );
final String val = op.value;
affirm( val.equals(sqlite3_value_text(argv[i])) );
//outln("xFunction col "+i+": "+val);
}
}
++xFuncCount.value;
}
public void xDestroy(){
xDestroyCalled.value = true;
}
};
int rc = fApi.xCreateFunction("myaux", pUserData, func);
affirm( 0==rc );
affirm( 0==xFuncCount.value );
execSql(db, "select myaux(ft,a,b) from ft;");
affirm( 2==xFuncCount.value );
affirm( !xDestroyCalled.value );
sqlite3_close_v2(db);
affirm( xDestroyCalled.value );
}
public TesterFts5(){
int oldAffirmCount = Tester1.affirmCount;
Tester1.affirmCount = 0;
final long timeStart = System.nanoTime();
test1();
final long timeEnd = System.nanoTime();
outln("FTS5 Tests done. Metrics:");
outln("\tAssertions checked: "+Tester1.affirmCount);
outln("\tTotal time = "
+((timeEnd - timeStart)/1000000.0)+"ms");
Tester1.affirmCount = oldAffirmCount;
}
}
-62
View File
@@ -1,62 +0,0 @@
/*
** 2023-07-22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
Callback proxy for use with sqlite3_trace_v2().
*/
public interface Tracer {
/**
Achtung: this interface is subject to change because the current
approach to mapping the passed-in natives back to Java is
uncomfortably quirky.
Called by sqlite3 for various tracing operations, as per
sqlite3_trace_v2(). Note that this interface elides the 2nd
argument to the native trace callback, as that role is better
filled by instance-local state.
The 2nd argument to this function, if non-0, will be a native
pointer to either an sqlite3 or sqlite3_stmt object, depending on
the first argument (see below). Client code can pass it to the
sqlite3 resp. sqlite3_stmt constructor to create a wrapping
object, if necessary. This API does not do so by default because
tracing can be called frequently, creating such a wrapper for
each call is comparatively expensive, and the objects are
probably only seldom useful.
The final argument to this function is the "X" argument
documented for sqlite3_trace() and sqlite3_trace_v2(). Its type
depends on value of the first argument:
- SQLITE_TRACE_STMT: pNative is a sqlite3_stmt. pX is a string
containing the prepared SQL, with one caveat: JNI only provides
us with the ability to convert that string to MUTF-8, as
opposed to standard UTF-8, and is cannot be ruled out that that
difference may be significant for certain inputs. The
alternative would be that we first convert it to UTF-16 before
passing it on, but there's no readily-available way to do that
without calling back into the db to peform the conversion
(which would lead to further tracing).
- SQLITE_TRACE_PROFILE: pNative is a sqlite3_stmt. pX is a Long
holding an approximate number of nanoseconds the statement took
to run.
- SQLITE_TRACE_ROW: pNative is a sqlite3_stmt. pX is null.
- SQLITE_TRACE_CLOSE: pNative is a sqlite3. pX is null.
*/
int xCallback(int traceFlag, Object pNative, Object pX);
}
@@ -0,0 +1,59 @@
/*
** 2023-09-27
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file houses the NotNull annotaion for the sqlite3 C API.
*/
package org.sqlite.jni.annotation;
/**
This annotation is for flagging parameters which may not legally be
null or point to closed/finalized C-side resources.
<p>In the case of Java types which map directly to C struct types
(e.g. {@link org.sqlite.jni.sqlite3}, {@link
org.sqlite.jni.sqlite3_stmt}, and {@link
org.sqlite.jni.sqlite3_context}), a closed/finalized resource is
also considered to be null for purposes this annotation because the
C-side effect of passing such a handle is the same as if null is
passed.</p>
<p>When used in the context of Java interfaces which are called
from the C APIs, this annotation communicates that the C API will
never pass a null value to the callback for that parameter.</p>
<p>Passing a null, for this annotation's definition of null, for
any parameter marked with this annoation specifically invokes
undefined behavior.</p>
<p>Passing 0 (i.e. C NULL) or a negative value for any long-type
parameter marked with this annoation specifically invokes undefined
behavior. Such values are treated as C pointers in the JNI
layer.</p>
<p>Note that the C-style API does not throw any exceptions on its
own because it has a no-throw policy in order to retain its C-style
semantics, but it may trigger NullPointerExceptions (or similar) if
passed a null for a parameter flagged with this annotation.</p>
<p>This annotation is informational only. No policy is in place to
programmatically ensure that NotNull is conformed to in client
code.</p>
<p>This annotation is solely for the use by the classes in the
org.sqlite package and subpackages, but is made public so that
javadoc will link to it from the annotated functions. It is not
part of the public API and client-level code must not rely on
it.</p>
*/
@java.lang.annotation.Documented
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
@java.lang.annotation.Target(java.lang.annotation.ElementType.PARAMETER)
public @interface NotNull{}
@@ -0,0 +1,32 @@
/*
** 2023-09-27
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file houses the Nullable annotaion for the sqlite3 C API.
*/
package org.sqlite.jni.annotation;
/**
This annotation is for flagging parameters which may legally be
null, noting that they may behave differently if passed null but
are prepared to expect null as a value. When used in the context of
callback methods which are called into from the C APIs, this
annotation communicates that the C API may pass a null value to the
callback.
<p>This annotation is solely for the use by the classes in this
package but is made public so that javadoc will link to it from the
annotated functions. It is not part of the public API and
client-level code must not rely on it.
*/
@java.lang.annotation.Documented
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
@java.lang.annotation.Target(java.lang.annotation.ElementType.PARAMETER)
public @interface Nullable{}
@@ -0,0 +1,17 @@
/*
** 2023-09-27
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
/**
This package houses annotations specific to the JNI bindings of the
SQLite3 C API.
*/
package org.sqlite.jni.annotation;
@@ -0,0 +1,34 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
import org.sqlite.jni.annotation.NotNull;
/**
An implementation of {@link CollationCallback} which provides a
no-op xDestroy() method.
*/
public abstract class AbstractCollationCallback
implements CollationCallback, XDestroyCallback {
/**
Must compare the given byte arrays and return the result using
{@code memcmp()} semantics.
*/
public abstract int call(@NotNull byte[] lhs, @NotNull byte[] rhs);
/**
Optionally override to be notified when the UDF is finalized by
SQLite. This implementation does nothing.
*/
public void xDestroy(){}
}
@@ -0,0 +1,72 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A SQLFunction implementation for aggregate functions. Its T is the
data type of its "accumulator" state, an instance of which is
intended to be be managed using the getAggregateState() and
takeAggregateState() methods.
*/
public abstract class AggregateFunction<T> implements SQLFunction {
/**
As for the xStep() argument of the C API's
sqlite3_create_function(). If this function throws, the
exception is not propagated and a warning might be emitted to a
debugging channel.
*/
public abstract void xStep(sqlite3_context cx, sqlite3_value[] args);
/**
As for the xFinal() argument of the C API's sqlite3_create_function().
If this function throws, it is translated into an sqlite3_result_error().
*/
public abstract void xFinal(sqlite3_context cx);
/**
Optionally override to be notified when the UDF is finalized by
SQLite.
*/
public void xDestroy() {}
/** Per-invocation state for the UDF. */
private final SQLFunction.PerContextState<T> map =
new SQLFunction.PerContextState<>();
/**
To be called from the implementation's xStep() method, as well
as the xValue() and xInverse() methods of the {@link WindowFunction}
subclass, to fetch the current per-call UDF state. On the
first call to this method for any given sqlite3_context
argument, the context is set to the given initial value. On all other
calls, the 2nd argument is ignored.
@see SQLFunction.PerContextState#getAggregateState
*/
protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
return map.getAggregateState(cx, initialValue);
}
/**
To be called from the implementation's xFinal() method to fetch
the final state of the UDF and remove its mapping.
see SQLFunction.PerContextState#takeAggregateState
*/
protected final T takeAggregateState(sqlite3_context cx){
return map.takeAggregateState(cx);
}
}
@@ -0,0 +1,28 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
import org.sqlite.jni.annotation.*;
/**
Callback for use with {@link CApi#sqlite3_set_authorizer}.
*/
public interface AuthorizerCallback extends CallbackProxy {
/**
Must function as described for the C-level
sqlite3_set_authorizer() callback.
*/
int call(int opId, @Nullable String s1, @Nullable String s2,
@Nullable String s3, @Nullable String s4);
}
@@ -0,0 +1,40 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
Callback for use with the {@link CApi#sqlite3_auto_extension}
family of APIs.
*/
public interface AutoExtensionCallback extends CallbackProxy {
/**
Must function as described for a C-level
sqlite3_auto_extension() callback.
<p>This callback may throw and the exception's error message will
be set as the db's error string.
<p>Tips for implementations:
<p>- Opening a database from an auto-extension handler will lead to
an endless recursion of the auto-handler triggering itself
indirectly for each newly-opened database.
<p>- If this routine is stateful, it may be useful to make the
overridden method synchronized.
<p>- Results are undefined if the given db is closed by an auto-extension.
*/
int call(sqlite3 db);
}
@@ -0,0 +1,26 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
Callback for use with {@link CApi#sqlite3_busy_handler}.
*/
public interface BusyHandlerCallback extends CallbackProxy {
/**
Must function as documented for the C-level
sqlite3_busy_handler() callback argument, minus the (void*)
argument the C-level function requires.
*/
int call(int n);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,44 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
This marker interface exists soley for use as a documentation and
class-grouping tool. It should be applied to interfaces or
classes which have a call() method implementing some specific
callback interface on behalf of the C library.
<p>Unless very explicitely documented otherwise, callbacks must
never throw. Any which do throw but should not might trigger debug
output regarding the error, but the exception will not be
propagated. For callback interfaces which support returning error
info to the core, the JNI binding will convert any exceptions to
C-level error information. For callback interfaces which do not
support, all exceptions will necessarily be suppressed in order to
retain the C-style no-throw semantics.
<p>Callbacks of this style follow a common naming convention:
<p>1) They use the UpperCamelCase form of the C function they're
proxying for, minus the {@code sqlite3_} prefix, plus a {@code
Callback} suffix. e.g. {@code sqlite3_busy_handler()}'s callback is
named {@code BusyHandlerCallback}. Exceptions are made where that
would potentially be ambiguous, e.g. {@link ConfigSqllogCallback}
instead of {@code ConfigCallback} because the {@code
sqlite3_config()} interface may need to support more callback types
in the future.
<p>2) They all have a {@code call()} method but its signature is
callback-specific.
*/
public interface CallbackProxy {}
@@ -0,0 +1,35 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
import org.sqlite.jni.annotation.NotNull;
/**
Callback for use with {@link CApi#sqlite3_create_collation}.
@see AbstractCollationCallback
*/
public interface CollationCallback
extends CallbackProxy, XDestroyCallback {
/**
Must compare the given byte arrays and return the result using
{@code memcmp()} semantics.
*/
int call(@NotNull byte[] lhs, @NotNull byte[] rhs);
/**
Called by SQLite when the collation is destroyed. If a collation
requires custom cleanup, override this method.
*/
void xDestroy();
}
@@ -1,5 +1,5 @@
/*
** 2023-07-30
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -11,18 +11,18 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
Callback proxy for use with sqlite3_collation_needed().
Callback for use with {@link CApi#sqlite3_collation_needed}.
*/
public interface CollationNeeded {
public interface CollationNeededCallback extends CallbackProxy {
/**
Has the same semantics as the C-level sqlite3_create_collation()
callback.
If it throws, the exception message is passed on to the db and
<p>If it throws, the exception message is passed on to the db and
the exception is suppressed.
*/
int xCollationNeeded(sqlite3 db, int eTextRep, String collationName);
int call(sqlite3 db, int eTextRep, String collationName);
}
@@ -1,5 +1,5 @@
/*
** 2023-07-22
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -11,15 +11,15 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
Callback proxy for use with sqlite3_update_hook().
Callback for use with {@link CApi#sqlite3_commit_hook}.
*/
public interface UpdateHook {
public interface CommitHookCallback extends CallbackProxy {
/**
Works as documented for the sqlite3_update_hook() callback.
Must not throw.
Works as documented for the C-level sqlite3_commit_hook()
callback. Must not throw.
*/
void xUpdateHook(int opId, String dbName, String tableName, long rowId);
int call();
}
@@ -0,0 +1,25 @@
/*
** 2023-08-23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A callback for use with sqlite3_config().
*/
public interface ConfigLogCallback {
/**
Must function as described for a C-level callback for
{@link CApi#sqlite3_config(ConfigLogCallback)}, with the slight signature change.
*/
void call(int errCode, String msg);
}
@@ -0,0 +1,25 @@
/*
** 2023-08-23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A callback for use with sqlite3_config().
*/
public interface ConfigSqllogCallback {
/**
Must function as described for a C-level callback for
{@link CApi#sqlite3_config(ConfigSqllogCallback)}, with the slight signature change.
*/
void call(sqlite3 db, String msg, int msgType );
}
@@ -11,7 +11,7 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
A helper for passing pointers between JNI C code and Java, in
@@ -23,11 +23,24 @@ package org.sqlite.jni;
NativePointerHolder is not inadvertently passed to an incompatible
function signature.
These objects do not _own_ the pointer they refer to. They are
These objects do not own the pointer they refer to. They are
intended simply to communicate that pointer between C and Java.
*/
public class NativePointerHolder<ContextType> {
//! Only set from JNI, where access permissions don't matter.
private long nativePointer = 0;
private volatile long nativePointer = 0;
/**
For use ONLY by package-level APIs which act as proxies for
close/finalize operations. Such ops must call this to zero out
the pointer so that this object is not carrying a stale
pointer. This function returns the prior value of the pointer and
sets it to 0.
*/
final long clearNativePointer() {
final long rv = nativePointer;
nativePointer= 0;
return rv;
}
public final long getNativePointer(){ return nativePointer; }
}
@@ -0,0 +1,231 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
Helper classes for handling JNI output pointers.
<p>We do not use a generic OutputPointer<T> because working with those
from the native JNI code is unduly quirky due to a lack of
autoboxing at that level.
<p>The usage is similar for all of thes types:
<pre>{@code
OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
assert( null==out.get() );
int rc = sqlite3_open(":memory:", out);
if( 0!=rc ) ... error;
assert( null!=out.get() );
sqlite3 db = out.take();
assert( null==out.get() );
}</pre>
<p>With the minor exception that the primitive types permit direct
access to the object's value via the `value` property, whereas the
JNI-level opaque types do not permit client-level code to set that
property.
<p>Warning: do not share instances of these classes across
threads. Doing so may lead to corrupting sqlite3-internal state.
*/
public final class OutputPointer {
/**
Output pointer for use with routines, such as sqlite3_open(),
which return a database handle via an output pointer. These
pointers can only be set by the JNI layer, not by client-level
code.
*/
public static final class sqlite3 {
private org.sqlite.jni.capi.sqlite3 value;
/** Initializes with a null value. */
public sqlite3(){value = null;}
/** Sets the current value to null. */
public void clear(){value = null;}
/** Returns the current value. */
public final org.sqlite.jni.capi.sqlite3 get(){return value;}
/** Equivalent to calling get() then clear(). */
public final org.sqlite.jni.capi.sqlite3 take(){
final org.sqlite.jni.capi.sqlite3 v = value;
value = null;
return v;
}
}
/**
Output pointer for sqlite3_blob_open(). These
pointers can only be set by the JNI layer, not by client-level
code.
*/
public static final class sqlite3_blob {
private org.sqlite.jni.capi.sqlite3_blob value;
/** Initializes with a null value. */
public sqlite3_blob(){value = null;}
/** Sets the current value to null. */
public void clear(){value = null;}
/** Returns the current value. */
public final org.sqlite.jni.capi.sqlite3_blob get(){return value;}
/** Equivalent to calling get() then clear(). */
public final org.sqlite.jni.capi.sqlite3_blob take(){
final org.sqlite.jni.capi.sqlite3_blob v = value;
value = null;
return v;
}
}
/**
Output pointer for use with routines, such as sqlite3_prepare(),
which return a statement handle via an output pointer. These
pointers can only be set by the JNI layer, not by client-level
code.
*/
public static final class sqlite3_stmt {
private org.sqlite.jni.capi.sqlite3_stmt value;
/** Initializes with a null value. */
public sqlite3_stmt(){value = null;}
/** Sets the current value to null. */
public void clear(){value = null;}
/** Returns the current value. */
public final org.sqlite.jni.capi.sqlite3_stmt get(){return value;}
/** Equivalent to calling get() then clear(). */
public final org.sqlite.jni.capi.sqlite3_stmt take(){
final org.sqlite.jni.capi.sqlite3_stmt v = value;
value = null;
return v;
}
}
/**
Output pointer for use with routines, such as sqlite3_prepupdate_new(),
which return a sqlite3_value handle via an output pointer. These
pointers can only be set by the JNI layer, not by client-level
code.
*/
public static final class sqlite3_value {
private org.sqlite.jni.capi.sqlite3_value value;
/** Initializes with a null value. */
public sqlite3_value(){value = null;}
/** Sets the current value to null. */
public void clear(){value = null;}
/** Returns the current value. */
public final org.sqlite.jni.capi.sqlite3_value get(){return value;}
/** Equivalent to calling get() then clear(). */
public final org.sqlite.jni.capi.sqlite3_value take(){
final org.sqlite.jni.capi.sqlite3_value v = value;
value = null;
return v;
}
}
/**
Output pointer for use with native routines which return booleans
via integer output pointers.
*/
public static final class Bool {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public boolean value;
/** Initializes with the value 0. */
public Bool(){this(false);}
/** Initializes with the value v. */
public Bool(boolean v){value = v;}
/** Returns the current value. */
public final boolean get(){return value;}
/** Sets the current value to v. */
public final void set(boolean v){value = v;}
}
/**
Output pointer for use with native routines which return integers via
output pointers.
*/
public static final class Int32 {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public int value;
/** Initializes with the value 0. */
public Int32(){this(0);}
/** Initializes with the value v. */
public Int32(int v){value = v;}
/** Returns the current value. */
public final int get(){return value;}
/** Sets the current value to v. */
public final void set(int v){value = v;}
}
/**
Output pointer for use with native routines which return 64-bit integers
via output pointers.
*/
public static final class Int64 {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public long value;
/** Initializes with the value 0. */
public Int64(){this(0);}
/** Initializes with the value v. */
public Int64(long v){value = v;}
/** Returns the current value. */
public final long get(){return value;}
/** Sets the current value. */
public final void set(long v){value = v;}
}
/**
Output pointer for use with native routines which return strings via
output pointers.
*/
public static final class String {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public java.lang.String value;
/** Initializes with a null value. */
public String(){this(null);}
/** Initializes with the value v. */
public String(java.lang.String v){value = v;}
/** Returns the current value. */
public final java.lang.String get(){return value;}
/** Sets the current value. */
public final void set(java.lang.String v){value = v;}
}
/**
Output pointer for use with native routines which return byte
arrays via output pointers.
*/
public static final class ByteArray {
/**
This is public for ease of use. Accessors are provided for
consistency with the higher-level types.
*/
public byte[] value;
/** Initializes with the value null. */
public ByteArray(){this(null);}
/** Initializes with the value v. */
public ByteArray(byte[] v){value = v;}
/** Returns the current value. */
public final byte[] get(){return value;}
/** Sets the current value. */
public final void set(byte[] v){value = v;}
}
}
@@ -0,0 +1,78 @@
/*
** 2023-09-13
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
Callback for use with {@link CApi#sqlite3_prepare_multi}.
*/
public interface PrepareMultiCallback extends CallbackProxy {
/**
Gets passed a sqlite3_stmt which it may handle in arbitrary ways,
transfering ownership of it to this function.
sqlite3_prepare_multi() will _not_ finalize st - it is up
to the call() implementation how st is handled.
Must return 0 on success or an SQLITE_... code on error.
See the {@link Finalize} class for a wrapper which finalizes the
statement after calling a proxy PrepareMultiCallback.
*/
int call(sqlite3_stmt st);
/**
A PrepareMultiCallback impl which wraps a separate impl and finalizes
any sqlite3_stmt passed to its callback.
*/
public static final class Finalize implements PrepareMultiCallback {
private PrepareMultiCallback p;
/**
p is the proxy to call() when this.call() is called.
*/
public Finalize( PrepareMultiCallback p ){
this.p = p;
}
/**
Calls the call() method of the proxied callback and either returns its
result or propagates an exception. Either way, it passes its argument to
sqlite3_finalize() before returning.
*/
@Override public int call(sqlite3_stmt st){
try {
return this.p.call(st);
}finally{
CApi.sqlite3_finalize(st);
}
}
}
/**
A PrepareMultiCallback impl which steps entirely through a result set,
ignoring all non-error results.
*/
public static final class StepAll implements PrepareMultiCallback {
public StepAll(){}
/**
Calls sqlite3_step() on st until it returns something other than
SQLITE_ROW. If the final result is SQLITE_DONE then 0 is returned,
else the result of the final step is returned.
*/
@Override public int call(sqlite3_stmt st){
int rc = CApi.SQLITE_DONE;
while( CApi.SQLITE_ROW == (rc = CApi.sqlite3_step(st)) ){}
return CApi.SQLITE_DONE==rc ? 0 : rc;
}
}
}
@@ -1,5 +1,5 @@
/*
** 2023-07-22
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -11,18 +11,16 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
Callback for use with {@link CApi#sqlite3_preupdate_hook}.
*/
public abstract class Collation {
public interface PreupdateHookCallback extends CallbackProxy {
/**
Must compare the given byte arrays using memcmp() semantics.
Must function as described for the C-level sqlite3_preupdate_hook()
callback.
*/
public abstract int xCompare(byte[] lhs, byte[] rhs);
/**
Called by SQLite when the collation is destroyed. If a Collation
requires custom cleanup, override this method.
*/
public void xDestroy() {}
void call(sqlite3 db, int op, String dbName, String dbTable,
long iKey1, long iKey2 );
}
@@ -1,5 +1,5 @@
/*
** 2023-07-22
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -11,17 +11,17 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
Callback proxy for use with sqlite3_progress_handler().
Callback for use with {@link CApi#sqlite3_progress_handler}.
*/
public interface ProgressHandler {
public interface ProgressHandlerCallback extends CallbackProxy {
/**
Works as documented for the sqlite3_progress_handler() callback.
Works as documented for the C-level sqlite3_progress_handler() callback.
If it throws, the exception message is passed on to the db and
<p>If it throws, the exception message is passed on to the db and
the exception is suppressed.
*/
int xCallback();
int call();
}
@@ -0,0 +1,155 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
This enum contains all of the core and "extended" result codes used
by the sqlite3 library. It is provided not for use with the C-style
API (with which it won't work) but for higher-level code which may
find it useful to map SQLite result codes to human-readable names.
*/
public enum ResultCode {
SQLITE_OK(CApi.SQLITE_OK),
SQLITE_ERROR(CApi.SQLITE_ERROR),
SQLITE_INTERNAL(CApi.SQLITE_INTERNAL),
SQLITE_PERM(CApi.SQLITE_PERM),
SQLITE_ABORT(CApi.SQLITE_ABORT),
SQLITE_BUSY(CApi.SQLITE_BUSY),
SQLITE_LOCKED(CApi.SQLITE_LOCKED),
SQLITE_NOMEM(CApi.SQLITE_NOMEM),
SQLITE_READONLY(CApi.SQLITE_READONLY),
SQLITE_INTERRUPT(CApi.SQLITE_INTERRUPT),
SQLITE_IOERR(CApi.SQLITE_IOERR),
SQLITE_CORRUPT(CApi.SQLITE_CORRUPT),
SQLITE_NOTFOUND(CApi.SQLITE_NOTFOUND),
SQLITE_FULL(CApi.SQLITE_FULL),
SQLITE_CANTOPEN(CApi.SQLITE_CANTOPEN),
SQLITE_PROTOCOL(CApi.SQLITE_PROTOCOL),
SQLITE_EMPTY(CApi.SQLITE_EMPTY),
SQLITE_SCHEMA(CApi.SQLITE_SCHEMA),
SQLITE_TOOBIG(CApi.SQLITE_TOOBIG),
SQLITE_CONSTRAINT(CApi.SQLITE_CONSTRAINT),
SQLITE_MISMATCH(CApi.SQLITE_MISMATCH),
SQLITE_MISUSE(CApi.SQLITE_MISUSE),
SQLITE_NOLFS(CApi.SQLITE_NOLFS),
SQLITE_AUTH(CApi.SQLITE_AUTH),
SQLITE_FORMAT(CApi.SQLITE_FORMAT),
SQLITE_RANGE(CApi.SQLITE_RANGE),
SQLITE_NOTADB(CApi.SQLITE_NOTADB),
SQLITE_NOTICE(CApi.SQLITE_NOTICE),
SQLITE_WARNING(CApi.SQLITE_WARNING),
SQLITE_ROW(CApi.SQLITE_ROW),
SQLITE_DONE(CApi.SQLITE_DONE),
SQLITE_ERROR_MISSING_COLLSEQ(CApi.SQLITE_ERROR_MISSING_COLLSEQ),
SQLITE_ERROR_RETRY(CApi.SQLITE_ERROR_RETRY),
SQLITE_ERROR_SNAPSHOT(CApi.SQLITE_ERROR_SNAPSHOT),
SQLITE_IOERR_READ(CApi.SQLITE_IOERR_READ),
SQLITE_IOERR_SHORT_READ(CApi.SQLITE_IOERR_SHORT_READ),
SQLITE_IOERR_WRITE(CApi.SQLITE_IOERR_WRITE),
SQLITE_IOERR_FSYNC(CApi.SQLITE_IOERR_FSYNC),
SQLITE_IOERR_DIR_FSYNC(CApi.SQLITE_IOERR_DIR_FSYNC),
SQLITE_IOERR_TRUNCATE(CApi.SQLITE_IOERR_TRUNCATE),
SQLITE_IOERR_FSTAT(CApi.SQLITE_IOERR_FSTAT),
SQLITE_IOERR_UNLOCK(CApi.SQLITE_IOERR_UNLOCK),
SQLITE_IOERR_RDLOCK(CApi.SQLITE_IOERR_RDLOCK),
SQLITE_IOERR_DELETE(CApi.SQLITE_IOERR_DELETE),
SQLITE_IOERR_BLOCKED(CApi.SQLITE_IOERR_BLOCKED),
SQLITE_IOERR_NOMEM(CApi.SQLITE_IOERR_NOMEM),
SQLITE_IOERR_ACCESS(CApi.SQLITE_IOERR_ACCESS),
SQLITE_IOERR_CHECKRESERVEDLOCK(CApi.SQLITE_IOERR_CHECKRESERVEDLOCK),
SQLITE_IOERR_LOCK(CApi.SQLITE_IOERR_LOCK),
SQLITE_IOERR_CLOSE(CApi.SQLITE_IOERR_CLOSE),
SQLITE_IOERR_DIR_CLOSE(CApi.SQLITE_IOERR_DIR_CLOSE),
SQLITE_IOERR_SHMOPEN(CApi.SQLITE_IOERR_SHMOPEN),
SQLITE_IOERR_SHMSIZE(CApi.SQLITE_IOERR_SHMSIZE),
SQLITE_IOERR_SHMLOCK(CApi.SQLITE_IOERR_SHMLOCK),
SQLITE_IOERR_SHMMAP(CApi.SQLITE_IOERR_SHMMAP),
SQLITE_IOERR_SEEK(CApi.SQLITE_IOERR_SEEK),
SQLITE_IOERR_DELETE_NOENT(CApi.SQLITE_IOERR_DELETE_NOENT),
SQLITE_IOERR_MMAP(CApi.SQLITE_IOERR_MMAP),
SQLITE_IOERR_GETTEMPPATH(CApi.SQLITE_IOERR_GETTEMPPATH),
SQLITE_IOERR_CONVPATH(CApi.SQLITE_IOERR_CONVPATH),
SQLITE_IOERR_VNODE(CApi.SQLITE_IOERR_VNODE),
SQLITE_IOERR_AUTH(CApi.SQLITE_IOERR_AUTH),
SQLITE_IOERR_BEGIN_ATOMIC(CApi.SQLITE_IOERR_BEGIN_ATOMIC),
SQLITE_IOERR_COMMIT_ATOMIC(CApi.SQLITE_IOERR_COMMIT_ATOMIC),
SQLITE_IOERR_ROLLBACK_ATOMIC(CApi.SQLITE_IOERR_ROLLBACK_ATOMIC),
SQLITE_IOERR_DATA(CApi.SQLITE_IOERR_DATA),
SQLITE_IOERR_CORRUPTFS(CApi.SQLITE_IOERR_CORRUPTFS),
SQLITE_LOCKED_SHAREDCACHE(CApi.SQLITE_LOCKED_SHAREDCACHE),
SQLITE_LOCKED_VTAB(CApi.SQLITE_LOCKED_VTAB),
SQLITE_BUSY_RECOVERY(CApi.SQLITE_BUSY_RECOVERY),
SQLITE_BUSY_SNAPSHOT(CApi.SQLITE_BUSY_SNAPSHOT),
SQLITE_BUSY_TIMEOUT(CApi.SQLITE_BUSY_TIMEOUT),
SQLITE_CANTOPEN_NOTEMPDIR(CApi.SQLITE_CANTOPEN_NOTEMPDIR),
SQLITE_CANTOPEN_ISDIR(CApi.SQLITE_CANTOPEN_ISDIR),
SQLITE_CANTOPEN_FULLPATH(CApi.SQLITE_CANTOPEN_FULLPATH),
SQLITE_CANTOPEN_CONVPATH(CApi.SQLITE_CANTOPEN_CONVPATH),
SQLITE_CANTOPEN_SYMLINK(CApi.SQLITE_CANTOPEN_SYMLINK),
SQLITE_CORRUPT_VTAB(CApi.SQLITE_CORRUPT_VTAB),
SQLITE_CORRUPT_SEQUENCE(CApi.SQLITE_CORRUPT_SEQUENCE),
SQLITE_CORRUPT_INDEX(CApi.SQLITE_CORRUPT_INDEX),
SQLITE_READONLY_RECOVERY(CApi.SQLITE_READONLY_RECOVERY),
SQLITE_READONLY_CANTLOCK(CApi.SQLITE_READONLY_CANTLOCK),
SQLITE_READONLY_ROLLBACK(CApi.SQLITE_READONLY_ROLLBACK),
SQLITE_READONLY_DBMOVED(CApi.SQLITE_READONLY_DBMOVED),
SQLITE_READONLY_CANTINIT(CApi.SQLITE_READONLY_CANTINIT),
SQLITE_READONLY_DIRECTORY(CApi.SQLITE_READONLY_DIRECTORY),
SQLITE_ABORT_ROLLBACK(CApi.SQLITE_ABORT_ROLLBACK),
SQLITE_CONSTRAINT_CHECK(CApi.SQLITE_CONSTRAINT_CHECK),
SQLITE_CONSTRAINT_COMMITHOOK(CApi.SQLITE_CONSTRAINT_COMMITHOOK),
SQLITE_CONSTRAINT_FOREIGNKEY(CApi.SQLITE_CONSTRAINT_FOREIGNKEY),
SQLITE_CONSTRAINT_FUNCTION(CApi.SQLITE_CONSTRAINT_FUNCTION),
SQLITE_CONSTRAINT_NOTNULL(CApi.SQLITE_CONSTRAINT_NOTNULL),
SQLITE_CONSTRAINT_PRIMARYKEY(CApi.SQLITE_CONSTRAINT_PRIMARYKEY),
SQLITE_CONSTRAINT_TRIGGER(CApi.SQLITE_CONSTRAINT_TRIGGER),
SQLITE_CONSTRAINT_UNIQUE(CApi.SQLITE_CONSTRAINT_UNIQUE),
SQLITE_CONSTRAINT_VTAB(CApi.SQLITE_CONSTRAINT_VTAB),
SQLITE_CONSTRAINT_ROWID(CApi.SQLITE_CONSTRAINT_ROWID),
SQLITE_CONSTRAINT_PINNED(CApi.SQLITE_CONSTRAINT_PINNED),
SQLITE_CONSTRAINT_DATATYPE(CApi.SQLITE_CONSTRAINT_DATATYPE),
SQLITE_NOTICE_RECOVER_WAL(CApi.SQLITE_NOTICE_RECOVER_WAL),
SQLITE_NOTICE_RECOVER_ROLLBACK(CApi.SQLITE_NOTICE_RECOVER_ROLLBACK),
SQLITE_WARNING_AUTOINDEX(CApi.SQLITE_WARNING_AUTOINDEX),
SQLITE_AUTH_USER(CApi.SQLITE_AUTH_USER),
SQLITE_OK_LOAD_PERMANENTLY(CApi.SQLITE_OK_LOAD_PERMANENTLY);
public final int value;
ResultCode(int rc){
value = rc;
ResultCodeMap.set(rc, this);
}
/**
Returns the entry from this enum for the given result code, or
null if no match is found.
*/
public static ResultCode getEntryForInt(int rc){
return ResultCodeMap.get(rc);
}
/**
Internal level of indirection required because we cannot initialize
static enum members in an enum before the enum constructor is
invoked.
*/
private static final class ResultCodeMap {
private static final java.util.Map<Integer,ResultCode> i2e
= new java.util.HashMap<>();
private static void set(int rc, ResultCode e){ i2e.put(rc, e); }
private static ResultCode get(int rc){ return i2e.get(rc); }
}
}
@@ -1,5 +1,5 @@
/*
** 2023-07-22
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -11,15 +11,15 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
Callback proxy for use with sqlite3_rollback_hook().
Callback for use with {@link CApi#sqlite3_rollback_hook}.
*/
public interface RollbackHook {
public interface RollbackHookCallback extends CallbackProxy {
/**
Works as documented for the sqlite3_rollback_hook() callback.
Must not throw.
Works as documented for the C-level sqlite3_rollback_hook()
callback.
*/
void xRollbackHook();
void call();
}
@@ -0,0 +1,103 @@
/*
** 2023-07-22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
SQLFunction is used in conjunction with the
sqlite3_create_function() JNI-bound API to give that native code
access to the callback functions needed in order to implement SQL
functions in Java.
<p>
This class is not used by itself, but is a marker base class. The
three UDF types are modelled by the inner classes Scalar,
Aggregate<T>, and Window<T>. Most simply, clients may subclass
those, or create anonymous classes from them, to implement
UDFs. Clients are free to create their own classes for use with
UDFs, so long as they conform to the public interfaces defined by
those three classes. The JNI layer only actively relies on the
SQLFunction base class and the method names and signatures used by
the UDF callback interfaces.
*/
public interface SQLFunction {
/**
PerContextState assists aggregate and window functions in
managing their accumulator state across calls to the UDF's
callbacks.
<p>T must be of a type which can be legally stored as a value in
java.util.HashMap<KeyType,T>.
<p>If a given aggregate or window function is called multiple times
in a single SQL statement, e.g. SELECT MYFUNC(A), MYFUNC(B)...,
then the clients need some way of knowing which call is which so
that they can map their state between their various UDF callbacks
and reset it via xFinal(). This class takes care of such
mappings.
<p>This class works by mapping
sqlite3_context.getAggregateContext() to a single piece of
state, of a client-defined type (the T part of this class), which
persists across a "matching set" of the UDF's callbacks.
<p>This class is a helper providing commonly-needed functionality
- it is not required for use with aggregate or window functions.
Client UDFs are free to perform such mappings using custom
approaches. The provided {@link AggregateFunction} and {@link
WindowFunction} classes use this.
*/
public static final class PerContextState<T> {
private final java.util.Map<Long,ValueHolder<T>> map
= new java.util.HashMap<>();
/**
Should be called from a UDF's xStep(), xValue(), and xInverse()
methods, passing it that method's first argument and an initial
value for the persistent state. If there is currently no
mapping for the given context within the map, one is created
using the given initial value, else the existing one is used
and the 2nd argument is ignored. It returns a ValueHolder<T>
which can be used to modify that state directly without
requiring that the client update the underlying map's entry.
<p>The caller is obligated to eventually call
takeAggregateState() to clear the mapping.
*/
public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
final Long key = cx.getAggregateContext(true);
ValueHolder<T> rc = null==key ? null : map.get(key);
if( null==rc ){
map.put(key, rc = new ValueHolder<>(initialValue));
}
return rc;
}
/**
Should be called from a UDF's xFinal() method and passed that
method's first argument. This function removes the value
associated with cx.getAggregateContext() from the map and
returns it, returning null if no other UDF method has been
called to set up such a mapping. The latter condition will be
the case if a UDF is used in a statement which has no result
rows.
*/
public T takeAggregateState(sqlite3_context cx){
final ValueHolder<T> h = map.remove(cx.getAggregateContext(false));
return null==h ? null : h.value;
}
}
}
@@ -12,16 +12,13 @@
** This file contains the main application entry pointer for the
** SQLTester framework.
*/
package org.sqlite.jni.tester;
package org.sqlite.jni.capi;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.nio.charset.StandardCharsets;
import java.util.regex.*;
import org.sqlite.jni.*;
import static org.sqlite.jni.SQLite3Jni.*;
import org.sqlite.jni.sqlite3;
import static org.sqlite.jni.capi.CApi.*;
/**
Modes for how to escape (or not) column values and names from
@@ -150,14 +147,17 @@ class Outer {
}
/**
This class provides an application which aims to implement the
<p>This class provides an application which aims to implement the
rudimentary SQL-driven test tool described in the accompanying
test-script-interpreter.md.
{@code test-script-interpreter.md}.
This is a work in progress.
<p>This class is an internal testing tool, not part of the public
interface but is (A) in the same package as the library because
access permissions require it to be so and (B) the JDK8 javadoc
offers no way to filter individual classes out of the doc
generation process (it can only exclude packages, but see (A)).
An instance of this application provides a core set of services
<p>An instance of this application provides a core set of services
which TestScript instances use for processing testing logic.
TestScripts, in turn, delegate the concrete test work to Command
objects, which the TestScript parses on their behalf.
@@ -181,7 +181,7 @@ public class SQLTester {
private int nTestFile = 0;
//! Number of scripts which were aborted.
private int nAbortedScript = 0;
//! Per-script test counter.
//! Incremented by test case handlers
private int nTest = 0;
//! True to enable column name output from execSql()
private boolean emitColNames;
@@ -250,14 +250,14 @@ public class SQLTester {
}
public void runTests() throws Exception {
final long tStart = System.nanoTime();
final long tStart = System.currentTimeMillis();
for(String f : listInFiles){
reset();
++nTestFile;
final TestScript ts = new TestScript(f);
outln(nextStartEmoji(), " starting [",f,"]");
boolean threw = false;
final long timeStart = System.nanoTime();
final long timeStart = System.currentTimeMillis();
try{
ts.run(this);
}catch(SQLTesterException e){
@@ -267,14 +267,13 @@ public class SQLTester {
if( keepGoing ) outln("Continuing anyway becaure of the keep-going option.");
else if( e.isFatal() ) throw e;
}finally{
final long timeEnd = System.nanoTime();
final long timeEnd = System.currentTimeMillis();
outln("🏁",(threw ? "" : "")," ",nTest," test(s) in ",
((timeEnd-timeStart)/1000000.0),"ms.");
//ts.getFilename());
(timeEnd-timeStart),"ms.");
}
}
final long tEnd = System.nanoTime();
outln("Total run-time: ",((tEnd-tStart)/1000000.0),"ms");
final long tEnd = System.currentTimeMillis();
outln("Total run-time: ",(tEnd-tStart),"ms");
Util.unlink(initialDbName);
}
@@ -336,7 +335,9 @@ public class SQLTester {
}
sqlite3 setCurrentDb(int n) throws Exception{
return affirmDbId(n).aDb[n];
affirmDbId(n);
iCurrentDb = n;
return this.aDb[n];
}
sqlite3 getCurrentDb(){ return aDb[iCurrentDb]; }
@@ -399,7 +400,7 @@ public class SQLTester {
nullView = "nil";
emitColNames = false;
iCurrentDb = 0;
dbInitSql.append("SELECT 1;");
//dbInitSql.append("SELECT 1;");
}
void setNullValue(String v){nullView = v;}
@@ -456,7 +457,7 @@ public class SQLTester {
}
private void appendDbErr(sqlite3 db, StringBuilder sb, int rc){
sb.append(org.sqlite.jni.ResultCode.getEntryForInt(rc)).append(' ');
sb.append(org.sqlite.jni.capi.ResultCode.getEntryForInt(rc)).append(' ');
final String msg = escapeSqlValue(sqlite3_errmsg(db));
if( '{' == msg.charAt(0) ){
sb.append(msg);
@@ -474,12 +475,12 @@ public class SQLTester {
the db's result code.
appendMode specifies how/whether to append results to the result
buffer. lineMode specifies whether to output all results in a
buffer. rowMode specifies whether to output all results in a
single line or one line per row. If appendMode is
ResultBufferMode.NONE then lineMode is ignored and may be null.
ResultBufferMode.NONE then rowMode is ignored and may be null.
*/
public int execSql(sqlite3 db, boolean throwOnError,
ResultBufferMode appendMode, ResultRowMode lineMode,
ResultBufferMode appendMode, ResultRowMode rowMode,
String sql) throws SQLTesterException {
if( null==db && null==aDb[0] ){
// Delay opening of the initial db to enable tests to change its
@@ -561,7 +562,7 @@ public class SQLTester {
throw new SQLTesterException("Unhandled ResultBufferMode: "+appendMode);
}
}
if( ResultRowMode.NEWLINE == lineMode ){
if( ResultRowMode.NEWLINE == rowMode ){
spacing = 0;
sb.append('\n');
}
@@ -580,6 +581,10 @@ public class SQLTester {
}
}
}finally{
sqlite3_reset(stmt
/* In order to trigger an exception in the
INSERT...RETURNING locking scenario:
https://sqlite.org/forum/forumpost/36f7a2e7494897df */);
sqlite3_finalize(stmt);
}
if( 0!=rc && throwOnError ){
@@ -609,9 +614,9 @@ public class SQLTester {
}
t.addTestScript(a);
}
final AutoExtension ax = new AutoExtension() {
final AutoExtensionCallback ax = new AutoExtensionCallback() {
private final SQLTester tester = t;
public int xEntryPoint(sqlite3 db){
@Override public int call(sqlite3 db){
final String init = tester.getDbInitSql();
if( !init.isEmpty() ){
tester.execSql(db, true, ResultBufferMode.NONE, null, init);
@@ -629,7 +634,7 @@ public class SQLTester {
t.outln("Aborted ",t.nAbortedScript," script(s).");
}
if( dumpInternals ){
sqlite3_do_something_for_developer();
sqlite3_jni_internal_details();
}
}
}
@@ -663,7 +668,7 @@ public class SQLTester {
static {
System.loadLibrary("sqlite3-jni")
/* Interestingly, when SQLTester is the main app, we have to
load that lib from here. The same load from SQLite3Jni does
load that lib from here. The same load from CApi does
not happen early enough. Without this,
installCustomExtensions() is an unresolved symbol. */;
}
@@ -924,8 +929,8 @@ class RunCommand extends Command {
final sqlite3 db = (1==argv.length)
? t.getCurrentDb() : t.getDbById( Integer.parseInt(argv[1]) );
final String sql = t.takeInputBuffer();
int rc = t.execSql(db, false, ResultBufferMode.NONE,
ResultRowMode.ONELINE, sql);
final int rc = t.execSql(db, false, ResultBufferMode.NONE,
ResultRowMode.ONELINE, sql);
if( 0!=rc && t.isVerbose() ){
String msg = sqlite3_errmsg(db);
ts.verbose1(argv[0]," non-fatal command error #",rc,": ",
@@ -948,8 +953,7 @@ class TableResultCommand extends Command {
if( !body.endsWith("\n--end") ){
ts.toss(argv[0], " must be terminated with --end.");
}else{
int n = body.length();
body = body.substring(0, n-6);
body = body.substring(0, body.length()-6);
}
final String[] globs = body.split("\\s*\\n\\s*");
if( globs.length < 1 ){
@@ -1124,8 +1128,9 @@ class TestScript {
}
public String getOutputPrefix(){
String rc = "["+(moduleName==null ? filename : moduleName)+"]";
String rc = "["+(moduleName==null ? "<unnamed>" : moduleName)+"]";
if( null!=testCaseName ) rc += "["+testCaseName+"]";
if( null!=filename ) rc += "["+filename+"]";
return rc + " line "+ cur.lineNo;
}
@@ -1238,14 +1243,15 @@ class TestScript {
final int oldPB = cur.putbackPos;
final int oldPBL = cur.putbackLineNo;
final int oldLine = cur.lineNo;
final String rc = getLine();
cur.peekedPos = cur.pos;
cur.peekedLineNo = cur.lineNo;
cur.pos = oldPos;
cur.lineNo = oldLine;
cur.putbackPos = oldPB;
cur.putbackLineNo = oldPBL;
return rc;
try{ return getLine(); }
finally{
cur.peekedPos = cur.pos;
cur.peekedLineNo = cur.lineNo;
cur.pos = oldPos;
cur.lineNo = oldLine;
cur.putbackPos = oldPB;
cur.putbackLineNo = oldPBL;
}
}
/**
@@ -1268,6 +1274,7 @@ class TestScript {
}
private boolean checkRequiredProperties(SQLTester t, String[] props) throws SQLTesterException{
if( true ) return false;
int nOk = 0;
for(String rp : props){
verbose1("REQUIRED_PROPERTIES: ",rp);
@@ -1288,6 +1295,12 @@ class TestScript {
t.appendDbInitSql("pragma temp_store=0;");
++nOk;
break;
case "AUTOVACUUM":
t.appendDbInitSql("pragma auto_vacuum=full;");
++nOk;
case "INCRVACUUM":
t.appendDbInitSql("pragma auto_vacuum=incremental;");
++nOk;
default:
break;
}
@@ -1326,9 +1339,9 @@ class TestScript {
m = patternRequiredProperties.matcher(line);
if( m.find() ){
final String rp = m.group(1);
//if( ! checkRequiredProperties( tester, rp.split("\\s+") ) ){
throw new IncompatibleDirective(this, "REQUIRED_PROPERTIES: "+rp);
//}
if( ! checkRequiredProperties( tester, rp.split("\\s+") ) ){
throw new IncompatibleDirective(this, "REQUIRED_PROPERTIES: "+rp);
}
}
m = patternMixedModuleName.matcher(line);
if( m.find() ){
@@ -1372,11 +1385,10 @@ class TestScript {
String line;
while( (null != (line = peekLine())) ){
checkForDirective(tester, line);
if( !isCommandLine(line, true) ){
if( isCommandLine(line, true) ) break;
else {
sb.append(line).append("\n");
consumePeeked();
}else{
break;
}
}
line = sb.toString();
@@ -0,0 +1,33 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A SQLFunction implementation for scalar functions.
*/
public abstract class ScalarFunction implements SQLFunction {
/**
As for the xFunc() argument of the C API's
sqlite3_create_function(). If this function throws, it is
translated into an sqlite3_result_error().
*/
public abstract void xFunc(sqlite3_context cx, sqlite3_value[] args);
/**
Optionally override to be notified when the UDF is finalized by
SQLite. This default implementation does nothing.
*/
public void xDestroy() {}
}
@@ -0,0 +1,35 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A wrapper object for use with sqlite3_table_column_metadata().
They are populated only via that interface.
*/
public final class TableColumnMetadata {
OutputPointer.Bool pNotNull = new OutputPointer.Bool();
OutputPointer.Bool pPrimaryKey = new OutputPointer.Bool();
OutputPointer.Bool pAutoinc = new OutputPointer.Bool();
OutputPointer.String pzCollSeq = new OutputPointer.String();
OutputPointer.String pzDataType = new OutputPointer.String();
public TableColumnMetadata(){
}
public String getDataType(){ return pzDataType.value; }
public String getCollation(){ return pzCollSeq.value; }
public boolean isNotNull(){ return pNotNull.value; }
public boolean isPrimaryKey(){ return pPrimaryKey.value; }
public boolean isAutoincrement(){ return pAutoinc.value; }
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,50 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
import org.sqlite.jni.annotation.Nullable;
/**
Callback for use with {@link CApi#sqlite3_trace_v2}.
*/
public interface TraceV2Callback extends CallbackProxy {
/**
Called by sqlite3 for various tracing operations, as per
sqlite3_trace_v2(). Note that this interface elides the 2nd
argument to the native trace callback, as that role is better
filled by instance-local state.
<p>These callbacks may throw, in which case their exceptions are
converted to C-level error information.
<p>The 2nd argument to this function, if non-null, will be a an
sqlite3 or sqlite3_stmt object, depending on the first argument
(see below).
<p>The final argument to this function is the "X" argument
documented for sqlite3_trace() and sqlite3_trace_v2(). Its type
depends on value of the first argument:
<p>- SQLITE_TRACE_STMT: pNative is a sqlite3_stmt. pX is a String
containing the prepared SQL.
<p>- SQLITE_TRACE_PROFILE: pNative is a sqlite3_stmt. pX is a Long
holding an approximate number of nanoseconds the statement took
to run.
<p>- SQLITE_TRACE_ROW: pNative is a sqlite3_stmt. pX is null.
<p>- SQLITE_TRACE_CLOSE: pNative is a sqlite3. pX is null.
*/
int call(int traceFlag, Object pNative, @Nullable Object pX);
}
@@ -0,0 +1,25 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
Callback for use with {@link CApi#sqlite3_update_hook}.
*/
public interface UpdateHookCallback extends CallbackProxy {
/**
Must function as described for the C-level sqlite3_update_hook()
callback.
*/
void call(int opId, String dbName, String tableName, long rowId);
}
@@ -1,5 +1,5 @@
/*
** 2023-07-21
** 2023-10-16
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -9,12 +9,12 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
** This file contains a set of tests for the sqlite3 JNI bindings.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
A helper class which simply holds a single value. Its current use
A helper class which simply holds a single value. Its primary use
is for communicating values out of anonymous classes, as doing so
requires a "final" reference.
*/
@@ -0,0 +1,39 @@
/*
** 2023-08-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A SQLFunction implementation for window functions. Note that
WindowFunction inherits from {@link AggregateFunction} and each
instance is required to implement the inherited abstract methods
from that class. See {@link AggregateFunction} for information on
managing the UDF's invocation-specific state.
*/
public abstract class WindowFunction<T> extends AggregateFunction<T> {
/**
As for the xInverse() argument of the C API's
sqlite3_create_window_function(). If this function throws, the
exception is not propagated and a warning might be emitted
to a debugging channel.
*/
public abstract void xInverse(sqlite3_context cx, sqlite3_value[] args);
/**
As for the xValue() argument of the C API's sqlite3_create_window_function().
See xInverse() for the fate of any exceptions this throws.
*/
public abstract void xValue(sqlite3_context cx);
}
@@ -0,0 +1,37 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file declares JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
Callback for a hook called by SQLite when certain client-provided
state are destroyed. It gets its name from the pervasive use of
the symbol name xDestroy() for this purpose in the C API
documentation.
*/
public interface XDestroyCallback {
/**
Must perform any cleanup required by this object. Must not
throw. Must not call back into the sqlite3 API, else it might
invoke a deadlock.
WARNING: as a rule, it is never safe to register individual
instances with this interface multiple times in the
library. e.g., do not register the same CollationCallback with
multiple arities or names using sqlite3_create_collation(). If
this rule is violated, the library will eventually try to free
each individual reference, leading to memory corruption or a
crash via duplicate free().
*/
public void xDestroy();
}
@@ -0,0 +1,89 @@
/**
This package houses a JNI binding to the SQLite3 C API.
<p>The primary interfaces are in {@link
org.sqlite.jni.capi.CApi}.</p>
<h1>API Goals and Requirements</h1>
<ul>
<li>A 1-to-1(-ish) mapping of the C API to Java via JNI, insofar
as cross-language semantics allow for. A closely-related goal is
that <a href='https://sqlite.org/c3ref/intro.html'>the C
documentation</a> should be usable as-is, insofar as possible,
for most of the JNI binding. As a rule, undocumented symbols in
the Java interface behave as documented for their C API
counterpart. Only semantic differences and Java-specific features
are documented here.</li>
<li>Support Java as far back as version 8 (2014).</li>
<li>Environment-independent. Should work everywhere both Java and
SQLite3 do.</li>
<li>No 3rd-party dependencies beyond the JDK. That includes no
build-level dependencies for specific IDEs and toolchains. We
welcome the addition of build files for arbitrary environments
insofar as they neither interfere with each other nor become a
maintenance burden for the sqlite developers.</li>
</ul>
<h2>Non-Goals</h2>
<ul>
<li>Creation of high-level OO wrapper APIs. Clients are free to
create them off of the C-style API.</li>
<li>Support for mixed-mode operation, where client code accesses
SQLite both via the Java-side API and the C API via their own
native code. In such cases, proxy functionalities (primarily
callback handler wrappers of all sorts) may fail because the
C-side use of the SQLite APIs will bypass those proxies.</li>
</ul>
<h1>State of this API</h1>
<p>As of version 3.43, this software is in "tech preview" form. We
tentatively plan to stamp it as stable with the 3.44 release.</p>
<h1>Threading Considerations</h1>
<p>This API is, if built with SQLITE_THREADSAFE set to 1 or 2,
thread-safe, insofar as the C API guarantees, with some addenda:</p>
<ul>
<li>It is not legal to use Java-facing SQLite3 resource handles
(sqlite3, sqlite3_stmt, etc) from multiple threads concurrently,
nor to use any database-specific resources concurrently in a
thread separate from the one the database is currently in use
in. i.e. do not use a sqlite3_stmt in thread #2 when thread #1 is
using the database which prepared that handle.
<br>Violating this will eventually corrupt the JNI-level bindings
between Java's and C's view of the database. This is a limitation
of the JNI bindings, not the lower-level library.
</li>
<li>It is legal to use a given handle, and database-specific
resources, across threads, so long as no two threads pass
resources owned by the same database into the library
concurrently.
</li>
</ul>
<p>Any number of threads may, of course, create and use any number
of database handles they wish. Care only needs to be taken when
those handles or their associated resources cross threads, or...</p>
<p>When built with SQLITE_THREADSAFE=0 then no threading guarantees
are provided and multi-threaded use of the library will provoke
undefined behavior.</p>
*/
package org.sqlite.jni.capi;
@@ -11,7 +11,7 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
A wrapper for communicating C-level (sqlite3*) instances with
@@ -19,19 +19,25 @@ package org.sqlite.jni;
simply provide a type-safe way to communicate it between Java
and C via JNI.
*/
public final class sqlite3 extends NativePointerHolder<sqlite3> {
public final class sqlite3 extends NativePointerHolder<sqlite3>
implements AutoCloseable {
// Only invoked from JNI
private sqlite3(){}
public String toString(){
long ptr = getNativePointer();
final long ptr = getNativePointer();
if( 0==ptr ){
return sqlite3.class.getSimpleName()+"@null";
}
String fn = SQLite3Jni.sqlite3_db_filename(this, "main");
final String fn = CApi.sqlite3_db_filename(this, "main");
return sqlite3.class.getSimpleName()
+"@"+String.format("0x%08x",ptr)
+"["+((null == fn) ? "<unnamed>" : fn)+"]"
;
}
@Override public void close(){
CApi.sqlite3_close_v2(this.clearNativePointer());
}
}
@@ -0,0 +1,31 @@
/*
** 2023-09-03
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A wrapper for passing C-level (sqlite3_backup*) instances around in
Java. These wrappers do not own their associated pointer, they
simply provide a type-safe way to communicate it between Java and C
via JNI.
*/
public final class sqlite3_backup extends NativePointerHolder<sqlite3_backup>
implements AutoCloseable {
// Only invoked from JNI.
private sqlite3_backup(){}
@Override public void close(){
CApi.sqlite3_backup_finish(this);
}
}
@@ -0,0 +1,31 @@
/*
** 2023-09-03
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
A wrapper for passing C-level (sqlite3_blob*) instances around in
Java. These wrappers do not own their associated pointer, they
simply provide a type-safe way to communicate it between Java and C
via JNI.
*/
public final class sqlite3_blob extends NativePointerHolder<sqlite3_blob>
implements AutoCloseable {
// Only invoked from JNI.
private sqlite3_blob(){}
@Override public void close(){
CApi.sqlite3_blob_close(this.clearNativePointer());
}
}
@@ -0,0 +1,79 @@
/*
** 2023-07-21
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
sqlite3_context instances are used in conjunction with user-defined
SQL functions (a.k.a. UDFs).
*/
public final class sqlite3_context extends NativePointerHolder<sqlite3_context> {
private Long aggregateContext = null;
/**
getAggregateContext() corresponds to C's
sqlite3_aggregate_context(), with a slightly different interface
to account for cross-language differences. It serves the same
purposes in a slightly different way: it provides a key which is
stable across invocations of a UDF's callbacks, such that all
calls into those callbacks can determine which "set" of those
calls they belong to.
<p>Note that use of this method is not a requirement for proper use
of this class. sqlite3_aggregate_context() can also be used.
<p>If the argument is true and the aggregate context has not yet
been set up, it will be initialized and fetched on demand, else it
won't. The intent is that xStep(), xValue(), and xInverse()
methods pass true and xFinal() methods pass false.
<p>This function treats numeric 0 as null, always returning null instead
of 0.
<p>If this object is being used in the context of an aggregate or
window UDF, this function returns a non-0 value which is distinct
for each set of UDF callbacks from a single invocation of the
UDF, otherwise it returns 0. The returned value is only only
valid within the context of execution of a single SQL statement,
and must not be re-used by future invocations of the UDF in
different SQL statements.
<p>Consider this SQL, where MYFUNC is a user-defined aggregate function:
<pre>{@code
SELECT MYFUNC(A), MYFUNC(B) FROM T;
}</pre>
<p>The xStep() and xFinal() methods of the callback need to be able
to differentiate between those two invocations in order to
perform their work properly. The value returned by
getAggregateContext() will be distinct for each of those
invocations of MYFUNC() and is intended to be used as a lookup
key for mapping callback invocations to whatever client-defined
state is needed by the UDF.
<p>There is one case where this will return null in the context
of an aggregate or window function: if the result set has no
rows, the UDF's xFinal() will be called without any other x...()
members having been called. In that one case, no aggregate
context key will have been generated. xFinal() implementations
need to be prepared to accept that condition as legal.
*/
public synchronized Long getAggregateContext(boolean initIfNeeded){
if( aggregateContext==null ){
aggregateContext = CApi.sqlite3_aggregate_context(this, initIfNeeded);
if( !initIfNeeded && null==aggregateContext ) aggregateContext = 0L;
}
return (null==aggregateContext || 0!=aggregateContext) ? aggregateContext : null;
}
}
@@ -11,7 +11,7 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
/**
A wrapper for communicating C-level (sqlite3_stmt*) instances with
@@ -19,7 +19,12 @@ package org.sqlite.jni;
simply provide a type-safe way to communicate it between Java and C
via JNI.
*/
public final class sqlite3_stmt extends NativePointerHolder<sqlite3_stmt> {
public final class sqlite3_stmt extends NativePointerHolder<sqlite3_stmt>
implements AutoCloseable {
// Only invoked from JNI.
private sqlite3_stmt(){}
@Override public void close(){
CApi.sqlite3_finalize(this.clearNativePointer());
}
}
@@ -11,7 +11,7 @@
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
package org.sqlite.jni.capi;
public final class sqlite3_value extends NativePointerHolder<sqlite3_value> {
//! Invoked only from JNI.

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