Compare commits

..

263 Commits

Author SHA1 Message Date
drh becd92a508 Version 3.45.2
FossilOrigin-Name: d8cd6d49b46a395b13955387d05e9e1a2a47e54fb99f3c9b59835bbefad6af77
2024-03-12 11:06:23 +00:00
drh 0f28d44463 Fix the ".import" command in the CLI so that it works correctly with tables
that contain computed columns.

FossilOrigin-Name: b26f24441f84a30deb9a562ab6c6de7543fbc3b3b93c34277964c9c21d734153
2024-03-11 11:26:20 +00:00
drh 1b386f1d86 Reenable the use of SQLITE_OMIT_VIRTUALTABLE by fixing
a misplaced #endif caused by the merge at [c080560c2d0d753c].

FossilOrigin-Name: 71120ea83783ee04c6dd9ef260f6ec528935b5ea3baf2348c6d5ec258093271b
2024-03-09 13:17:12 +00:00
drh bd1ee6ccdb Fix the rtreeJ.test module to align it with [cd017c28d516399e].
FossilOrigin-Name: 111b3d8270db4f61efd9f4c02636f50e44bd9547261d1d922de2708bc7a07151
2024-03-09 13:10:28 +00:00
drh fd56dbf1b8 Handle an OOM case in fts5 code to query tokendata=1 tables.
FossilOrigin-Name: ebf59fa374000169e2ab3f353e2d7c15efd32e3ce2297e893461e6c303de5d4a
2024-03-09 12:30:30 +00:00
drh c70c328bb7 The NOT NULL strength reduction optimization should
be applied to the WHERE clause only.

FossilOrigin-Name: be266c713963d724802f5e9ad9d7d3c3d7f4daf1d95b63df6df1beb3a065bdab
2024-03-09 00:38:57 +00:00
drh 57976a82fa Silently ignore redundant ON CONFLICT clauses in an UPSERT.
FossilOrigin-Name: 46245855a0be1b4ed0efcde30f0919fb6361affc4443a4ed2fdac01ab6864df1
2024-03-08 14:11:49 +00:00
drh 526128055b Fix a memory leak in new memdb1.test test cases that were added by
[e638d5e408ea2e18].  No changes to SQLite itself.

FossilOrigin-Name: f0a49dc8bc22d4889677d03beccda8f71f7374ae56b5c78f7395769f9272dc77
2024-03-06 21:53:55 +00:00
mistachkin b99f165a1b Fix harmless compiler warning seen with MSVC.
FossilOrigin-Name: 5aa809bcfecc321f122a60f43bc674c7f099cf1ccb2ed976dabb29d8fde83adc
2024-03-06 21:22:34 +00:00
mistachkin 178cac8e2e Fix harmless compiler warnings seen with MSVC.
FossilOrigin-Name: c0f61524103d2421aa1e0fe39f028eed04d115bb4eb245b6c8623bd1c6fed481
2024-03-06 21:08:42 +00:00
mistachkin 0bda8bfbfb Fix a minor test file locking issue on Windows.
FossilOrigin-Name: a44752806f854f06e787bb789d7dbf647219f15d3e315853bb4bc8049f47ef09
2024-03-06 21:06:07 +00:00
mistachkin 4350d16805 Work around obscure floating point issue seen with older versions of MSVC.
FossilOrigin-Name: 6055715febf6e61e37125635b7ec29392fbaab367927411617f5e15d9a95cb82
2024-03-06 21:00:13 +00:00
mistachkin 20f11538f4 Fix two -Werror=lto-type-mismatch warnings reported in [forum:ef62b57bd5|forum post ef62b57bd5].
FossilOrigin-Name: d4e423f3a466a39e435efba81ac33fd80164aaaa43827c2f4f965c1e77b3ef6c
2024-03-06 20:59:38 +00:00
mistachkin c87f53a3f3 The quote() SQL function should convert +Inf into 9.0e+999 and -Inf into -9.0e+999. See [forum:/forumpost/6675b25108|forum post 6675b25108].
FossilOrigin-Name: 07a9ef888db05a85c2baf8781e5ac51a9dd27e0ef94ca4ebd750045e9690226b
2024-03-06 20:58:52 +00:00
mistachkin 31d4a3d27f Make sure key comprisons are done correctly if the index key contains NaN values that have not been shifted into NULLs. That can only happen due to database corruption, but we need to deal with it nevertheless.
FossilOrigin-Name: 7ed922d99ca9801dc1926df529b2fa93be374f587885282ab6e307ea6cf2ccee
2024-03-06 20:58:08 +00:00
mistachkin 0691451557 When inserting a 3-byte cell into a btree, ensure that the extra padding byte is 0x00. This is not necessary for security, as far as I can tell, but it seems like a reasonable precaution.
FossilOrigin-Name: f3e841873dffaa8cd2f4f3cf260487ed402febb99b9ccad04e2a1d481e903aca
2024-03-06 20:56:52 +00:00
mistachkin fe271d6717 Rig sqlite3_serialize() so that it will initialize a previously uninitialized database prior to serializing it, so that it does not have a zero-byte size and does not return NULL (except for OOM). [forum:/forumpost/498777780e16880a|Forum thread 498777780e16880a].
FossilOrigin-Name: 22a33f133e3e833c960f46e1b4c74043010181ff7ba9e57f2d009b65d3275d82
2024-03-06 20:55:44 +00:00
mistachkin e7daad213f When doing a text-affinity comparison between two values where one or both have both a text and a numeric type, make sure the numeric type does not confuse the answer. This is a deeper fix to the problem observed by [forum:/forumpost/3776b48e71|forum post 3776b48e71]. The problem bisects to [25f2246be404f38b] on 2014-08-24, prior to version 3.8.7.
FossilOrigin-Name: 6d385ccda8aba16a37c5e8c39f3aeba97c472321e4c8c9efac2de4518b61bdc8
2024-03-06 20:54:38 +00:00
mistachkin 8013e8cffb Ensure that the replace() SQL function always returns a TEXT value even when its first argument is numeric and its second argument is an empty string. Fix for the issue reported by [forum:/forumpost/3776b48e71|forum post 3776b48e71].
FossilOrigin-Name: a7c98c8f19a1ac049b846da584b246706f2159455f4de7b50aacc1385b9f2987
2024-03-06 20:52:38 +00:00
stephan 91b54ccc8f Reformulate [34439fe3aeea7cbb] slightly to resolve a false-positive OOM reported in [forum:2eadfe94e3|forum post 2eadfe94e3].
FossilOrigin-Name: 320ccb5d5f5c3b25b319426b62c8a86fc3209a04480f5ca7f6f40cb16f04c795
2024-03-05 17:39:56 +00:00
drh 73811c3252 The value returned by the json_each.json field needs to survive longer than
the json_each virtual table itself, in the event that the value is used in
an aggregate expression.  dbsqlfuzz 5120bd0b3bb0b73eebbcb79ac37c6b0663fccad6

FossilOrigin-Name: 040946b342fd532692025806c124643842fdfda55e0c492cd058dcb7f054cc79
2024-03-05 16:59:00 +00:00
drh a187643752 Fix rounding in zero-precision %f and %g printf conversions.
FossilOrigin-Name: 1ebea57ff212aaac83f388cdebd13f319a7c57b0cdc7467b26d3f49cb7e39666
2024-02-17 03:36:05 +00:00
drh 73a9088ef8 Fix the subtype on the value column from json_each/json_tree for cases
when the value is an array or object.

FossilOrigin-Name: b278ae3980066e5d0561baa869ef6d22d10cbd0481d1bc0e67f099e93fc3a93b
2024-02-16 21:34:08 +00:00
drh f3c9b779ff Fix a bug in PRAGMA integrity_check introduced by enhancement (8a) in
release 3.42.0.

FossilOrigin-Name: 60dccb23b11f7e4a743e867f393f34f673600c12f1e7199e505f2e2b81c6dacd
2024-02-13 18:44:28 +00:00
drh fd97f350fd Have rtree avoid keeping a blob handle open following an error.
FossilOrigin-Name: 26978f34bd03b052d40fbc84037fb0e0ca04e571cf8055bf834e9da1dc3cec83
2024-02-12 17:01:33 +00:00
drh 8f28852ca0 Cherrypick multiple fixes for trifling faults from trunk, so that all 834
dbsqlfuzz run clean with ASAN on branch-3.45.
dbsqlfuzz.

FossilOrigin-Name: c080560c2d0d753c41c265c154c8185b7b5065ba1f2457476aa39c687675d91f
2024-02-11 23:25:02 +00:00
larrybr bd3d3486d9 Further clarify sqlite3_exec() callback parameter lifetime.
FossilOrigin-Name: 044ce823a45f024fe3dfe8a44bab8f25affb7bc54cfbe01a00719217b93ff6f8
2024-02-10 03:12:46 +00:00
larrybr 37fdb9696f Mention limited lifetime of string arrays passed to sqlite3_exec() callback.
FossilOrigin-Name: d14a9d81a59cb55be68cc057166050cbb9b474be865a6998a9beeed54d6b388d
2024-02-08 01:23:22 +00:00
drh f7853591ba Detect and respond to an OOM on the jsonStringTerminate() call of
jsonReturnStringAsBlob() routine.

FossilOrigin-Name: 77431aca6ec0aaeacdc9173ca19e996498650ad19934fc77681203c0c9f06632
2024-02-07 14:16:47 +00:00
drh ae819b3a50 Return SQLITE_ABORT if the underlying shadow tables change in the middle of an rtree query in such a way as to invalidate an rtree internal priority queue entry. This replaces the SQLITE_ABORT_ROLLBACK mechanism added in [97cffff331b].
FossilOrigin-Name: 061af0d74a436efa24b348e9a0f9fe6d6d52c02e5c03929e6f9c7f0e2ef3e2a0
2024-02-06 13:36:29 +00:00
drh 8b5f0f37fa Following a ROLLBACK that reverts changes to an RTREE, any pending queries
against that same RTREE abort with code SQLITE_ABORT_ROLLBACK.

FossilOrigin-Name: 97cffff331b5f95abed5451f9d0cef085c3fc8911efbcd2422c1c78eac17b669
2024-02-03 19:41:34 +00:00
drh 189e44dfec Version 3.45.1
FossilOrigin-Name: e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a
2024-01-30 16:01:20 +00:00
drh 651dcec4a7 Detect malformed nested JSONB earlier and stop rendering to avoid long
delays.

FossilOrigin-Name: ab40e282465c989bf249453d7c6f60072a38b691f579411cdf9aad234b20f0f7
2024-01-29 21:29:22 +00:00
drh 3ff77c5053 Avoid a potential buffer overread when handling corrupt json blobs.
FossilOrigin-Name: ac402cc551b2cbe3f8fbbc9c711a04942eab5eeb9d2f4a394e9370d2380427b5
2024-01-29 16:49:28 +00:00
drh f838022342 When rendering JSONB back into text JSON, report an error if a zero-length
integer or floating-point node is encountered.  Otherwise, if the node occurs
at the very end of the JSONB, the rendering logic might read one byte past
the end of the initialized part of the BLOB byte array.  OSSFuzz 66284.

FossilOrigin-Name: 3ab08ac75d97ffd9920f5c924362a4819560b40faa8a4f9100068057f5fa420a
2024-01-29 12:58:12 +00:00
drh e6a50562f4 Automatically disable the DISTINCT optimization during query planning if the
ORDER BY clause exceeds 63 terms.

FossilOrigin-Name: 6edbdcc02d18727f68f0236e15dde4ecfc77e6f452b522eb4e1e895929b1fb63
2024-01-28 17:44:47 +00:00
drh f032114147 Apply the same fix found in [99057383acc8f920] to descending scans.
FossilOrigin-Name: 593d6a1c2e9256d797f160e867278414e882a3d04d7fea269bea86965eaa7576
2024-01-28 00:35:24 +00:00
drh 00af690017 Slight adjustment to test results for Windows in mmap1.test due to
the previous check-in.

FossilOrigin-Name: a8043eaed899285b5cf4aab0c23c3dabb8975910c353cb579fd1f1655db390f6
2024-01-23 21:10:28 +00:00
drh a8556eef91 In os_unix.c and os_win.c, do not allow xFetch() to return a pointer to a page buffer that is right at the end of the mapped region - if the database is corrupted in a specific way such a page buffer might be overread by several bytes.
FossilOrigin-Name: d131cab652ac11795322af13d0b330e7e44ab91587a1a3e73fe7b9a14b2dd531
2024-01-23 16:17:00 +00:00
drh e8df88eae9 Fix harmless "unused parameter" compiler warning in the new fts3IntegrityMethod
implementation.

FossilOrigin-Name: 9d459f6b50fb6f995e6284a0815c5e211cacac44aad0b96bf01ba68af97f51fc
2024-01-23 15:04:07 +00:00
drh 1e47802761 Bump the version number to 3.45.1
FossilOrigin-Name: 54d34edb89430b266221b7e6eea0afbd2c9dafbe774344469473abc8ad1e13fd
2024-01-23 13:58:41 +00:00
drh 5b9e435d7f When a JSON input is a blob, but it looks like valid JSON when cast to text,
then accept it as valid JSON.  This replicates a long-standing bug in the
behavior of JSON routines, and thus avoids breaking legacy apps.

FossilOrigin-Name: 4c2c1b97dce46a279846380c937ac6de5c367927c6843516641eead7ea6db472
2024-01-23 13:53:45 +00:00
dan f05bd8b21a Ensure that the xIntegrity methods of fts3 and fts5 work on read-only databases.
FossilOrigin-Name: e79b97369fa740f62f695057d4a2cf8dae48a683982ec879f04a19039c9cb418
2024-01-23 10:47:04 +00:00
drh b5c5f36da8 When backing out a character in a constructed string in JSON, first make sure
the string has not been reset by on OOM.

FossilOrigin-Name: 950bf9fe7829864e0abe6d71ca0495f346feb5d7943d76c95e55a6b86ea855da
2024-01-20 12:19:16 +00:00
stephan 0dfdf2db59 wasm build: reformulate an awk invocation to account for awks which do not support the -e flag. Problem reported on the forum via a docker-hosted build.
FossilOrigin-Name: 90dd51153fd0a6197e2ee49b5492ad120f0bfc324b60651f3d4f47c286887b46
2024-01-16 14:28:59 +00:00
drh f352e0a9cf Version 3.45.0
FossilOrigin-Name: 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d
2024-01-15 17:01:13 +00:00
dan 4c6554223e Have the shell tool automatically enable SQLITE_CONFIG_DQS_DDL when executing a ".dump" script against an empty db.
FossilOrigin-Name: f47a5f4e0ce078e6cc1183e6cbb3c4013af379b496efae94863a42e5c39928ed
2024-01-12 11:44:49 +00:00
drh e5b2132df6 Fix a comment in sessions. No functional changes.
[forum:/forumpost/8c20dc935b|Forum post 8c20dc935b].

FossilOrigin-Name: b0eb6d3628c1f70399a22d9fd3b79a796bc343adfeba50515440db609565961a
2024-01-11 14:13:17 +00:00
dan c08a8a33d3 In fts5, flush the contents of the in-memory hash table whenever the secure-delete option is toggled. This prevents spurious corruption reports under some circumstances.
FossilOrigin-Name: ccf552319a62bfb329820a3bc1f490bacbaa6e90694a257fc65a568a605542c3
2024-01-11 14:03:08 +00:00
drh 5fdabcf9ff Put an SQLITE_ENABLE_SETLK_TIMEOUT branch inside the appropriate ifdef with
an assert on the else since the condition is always false if SETLK_TIMEOUT
is not available.

FossilOrigin-Name: d81e7a036ac5d70b6a6ee6ab7d81e041c1f5fc04b70bcee47e203d521caf7e93
2024-01-09 23:15:46 +00:00
drh ff6905a1a5 Improved resolution of unqualified names in the REINDEX command.
[forum:/info/74cd0ceabd|Forum thread 74cd0ceabd].

FossilOrigin-Name: 97709ce2a1f5ae05495e412ca27108048e5b8a63a1e3bca4be13933f7527da7b
2024-01-09 12:28:51 +00:00
dan e452bf40a1 Automatically turn off DEFENSIVE mode in the shell tool when executing scripts generated by the ".dump" command against an empty database. Add a warning to the top of generated ".dump" scripts that populate virtual tables.
FossilOrigin-Name: cd016f26bb61549a304f2148035e050f76a8f4a35cdb7131bba2f5fc5d09f49e
2024-01-08 19:55:40 +00:00
dan 62f0c4d139 Fix date on new file shell9.test.
FossilOrigin-Name: c82da712113d5dcd63b764dbc68842026989627abc840acb4a33f3a4972b832a
2024-01-08 18:53:27 +00:00
dan 7cda91c33e Automatically turn off DEFENSIVE mode in the shell tool when executing scripts generated by the ".dump" command against an empty database. Add a warning to the top of generated ".dump" scripts that populate virtual tables.
FossilOrigin-Name: 6e9e96b7e7afb9420110f4b93d10b945c9eadfde5e9c81e59ae9ee8167e75707
2024-01-08 18:46:34 +00:00
drh 3e2ffbd476 Minor change to os_unix.c to facilitate 100% MC/DC testing.
FossilOrigin-Name: 0dfa7b4da134db281c3c4eddb4569c53a450f955f0af2f410e13db801aff4ea2
2024-01-08 15:23:45 +00:00
dan f640f79d6f Ensure that SQLITE_PROTOCOL is not returned too early when a SQLITE_ENABLE_SETLK_TIMEOUT build fails to open a transaction on a wal mode database in cases where blocking locks are not being used.
FossilOrigin-Name: a8e9af1356f5fb2ec460f932dfbe89283bb4e3cf9fa677d1acdbe77ffa11dd04
2024-01-08 13:38:15 +00:00
drh bf64cbd463 Remove an ALWAYS() from RTREE. Dbsqlfuzz found a way to make it false.
FossilOrigin-Name: 40f0a29e6dd90fcb969d7c0e49728ba0ee8f31d9e8f502b9a21469620a8ad283
2024-01-07 20:27:54 +00:00
drh cd6ea30b82 Updates to RTREE to facility testing.
FossilOrigin-Name: 7a5b42ff74882c58493dc8b710fde73d4ff251f5d42271d84be73ceaabc01698
2024-01-07 00:45:53 +00:00
dan 4e50f7763b Ensure that SQLITE_PROTOCOL is not returned too early when a SQLITE_ENABLE_SETLK_TIMEOUT build fails to open a transaction on a wal mode database in cases where blocking locks are not being used.
FossilOrigin-Name: b934a33671d8a0190082ad7e5e68c78fe0c558d102404eafc1de26e4e7d65b92
2024-01-06 19:16:54 +00:00
drh 1ba138401e Update JSON performance testing procedures for clarity and to describe how to
do performance testing of JSONB.

FossilOrigin-Name: b115b4f75bc7c4e6d9bab5edf13297f27a36f30083c80d2c502b01208da5dfc0
2024-01-06 15:22:16 +00:00
dan f537bba1a1 Update extension ext/misc/totext.c to avoid both ubsan warnings and dubious real->integer conversions.
FossilOrigin-Name: 541436004df6458dc2f38bdfa421099f78cab397f5f4795ca5f227531aaa6a3e
2024-01-06 13:58:54 +00:00
dan 1cfc040bba Update extension ext/misc/totext.c to avoid both ubsan warnings and dubious real->integer conversions.
FossilOrigin-Name: c626aa108a7a30cef54af8d93ac9e45749568ed38e4e06623a6bad6b4bf6e8ec
2024-01-05 15:53:58 +00:00
drh 76da0dcbc4 Avoid errors with SQLITE_OMIT_VIRTUALTABLE builds in json106.test and unionall.test.
FossilOrigin-Name: 8940e2a1054fbc19fae3f76e743d744840c3a5aad001be8d3d56ca134226c34b
2024-01-04 17:13:39 +00:00
dan de70e8b9c4 Avoid errors with SQLITE_OMIT_VIRTUALTABLE builds in json106.test and unionall.test.
FossilOrigin-Name: 90e8a233549a2d31e6959ce3fec927693b772ab3c0abce65e81d7350d2ca5cc6
2024-01-04 16:15:21 +00:00
drh 267721e72a Restructure some code to fix what appears to be a false-positive UBSAN warning.
FossilOrigin-Name: fe952c12903ea2150880c8bb57cda2efc00ce9fa801568a68c619e0745f30567
2024-01-04 13:01:02 +00:00
drh aa08f885ba Fix a #ifdef in sqlite3_test_control() that was preventing builds with
SQLITE_OMIT_WSD.

FossilOrigin-Name: d546a9c94caf7408cc6e4530ec190d3a13fae09dc15b71b03d6369e02ee62abd
2024-01-03 20:40:17 +00:00
drh 4093b29610 Convert the JSON functions to use lookaside memory allocation whenever
feasible, to avoid hitting the global memory allocator mutex.

FossilOrigin-Name: a79a244954f728596da3c0e28fa3b887258d1bd831f53881970f418f3fba84c7
2024-01-03 16:41:50 +00:00
drh 433e904d99 Change a constant from decimal to hex to avoid a compiler warning on Mac.
FossilOrigin-Name: e3acb8a43ad544fd5b5341058276bd3b61b6bdb6b719790476a90e0de4320f90
2024-01-03 15:49:04 +00:00
drh 6db9206c18 Enhance sqlite3_analyzer.exe so that it uses the ext/consio extension.
FossilOrigin-Name: 769de0b98e136e4a0945b80216d0c9583c1ccd9de69cb0494875c2300e172646
2024-01-03 14:13:27 +00:00
drh 4167033eaf Update the sqldiff.exe utility program so that it uses the sqlite3_str
string interface, and so that it does console output using the
ext/consio extension.

FossilOrigin-Name: 4443b7e592da97d1cb1b3b79ed0559452d8057a33aba4d184c2fffbf200e05f5
2024-01-03 12:26:02 +00:00
drh d059153deb Back out [b517a52fa36df0a0] which is no longer reachable due to early
error detection enhancements in [166e82dd20efbfd3].

FossilOrigin-Name: 704943e96f2620b99260667ac9922c2f72bc3e92e2dfe1d9c2a91c7b704564d9
2024-01-02 22:49:14 +00:00
drh f5740f72ec Adjust the sqlite3PagerDirectReadOk() routine (part of the
SQLITE_DIRECT_OVERFLOW_READ optimization) to use less code and to be
more easily testable.

FossilOrigin-Name: eed670ea2a9424f7df4eeb01c152fc38f7190a5e39aa891651b28dc91fcdc019
2024-01-02 21:37:51 +00:00
dan 4eb626350a Fix a problem in fts5 caused by a COMMIT involving fts5 data that immediately follows a ROLLBACK TO that does not.
FossilOrigin-Name: 55c61f6a8d6a1bc79497b05669beac5c5397b06382bf24b6bec54845962d219b
2024-01-02 21:08:25 +00:00
drh 533622fb8b Increase the default "max_page_count" to its theoretical maximum of
4294967294.

FossilOrigin-Name: ffb35f1784a4305b979a850485f57f56938104a3a03f4a7aececde92864c4879
2024-01-02 20:34:27 +00:00
stephan aff7664939 Elaborate on the various build flavors used by ext/wasm/. Doc changes only.
FossilOrigin-Name: d489232aa492618d4c8e5817addb2323d0ca067742d7140216914239a66fb221
2024-01-02 09:20:53 +00:00
stephan 3d4d3fb59d Update and clean up the in-makefile docs for ext/wasm.
FossilOrigin-Name: 7a7b295e6d7e95ee4a46cc42761895d11700ab295870c5a4380072bb4a5b7099
2024-01-02 09:03:42 +00:00
stephan fe1d8210c7 Back out [99d11e6d0ae6] (enabling of STAT4 in WASM/JNI), per /chat discussion.
FossilOrigin-Name: cd7929ee2e2c305475fa5a4dff2edaccf90067126ef04a1c2714cf464925453f
2024-01-01 23:28:02 +00:00
drh 92e970ae98 New logic to avoid using indexes that ANALYZE has identified as of little
practical use.  Also a performance optimization in ANALYZE.

FossilOrigin-Name: bcac937526d9a6ef914a74b4d6757fa91cd74edab871bcd934fde4a2f9b6debd
2024-01-01 19:20:00 +00:00
drh 4cfc19f34c Remove some unnecessary computations from ANALYZE so that ANALYZE runs with
fewer CPU cycles.  These changes were spotted while working on the nearby
enhanced-stat1 branch.  So even if enhanced-stat1 is abandoned, that effort
put into it will not have been in vain.

FossilOrigin-Name: 5527e8c4abb904b1a438ec1c353d4a960bf82faaf3a2c742af1df7c613850441
2024-01-01 17:58:57 +00:00
drh 4ccf707c6e Extra steps taken to avoid using low-quality indexes in a query plan.
This branch accomplishes the same end as the nearby enhanced-stat1 branch,
but with much less change and hence less risk.

FossilOrigin-Name: c030e646262fee43a59b45fdc1630d972f8bf88ac3c142b6bdaf4cbb36695a4f
2024-01-01 17:48:02 +00:00
stephan 307f326ba3 JNI: move the ByteBuffer-using APIs from public to package visibility for the time being because they have UB-inducing possibilities which need to be worked out. Update test code to account for a change in custom FTS5 columntext() impls.
FossilOrigin-Name: dc501275fcfab3ad9b6ebbadf7588b225a9dd07a0abac5be83d96f15bfba99e9
2024-01-01 06:58:32 +00:00
stephan 805cd395a9 WASM: various build cleanups and add initial infrastructure for a build which elides the oo1 API and its dependents (worker1 and promiser). Sidebar: an attempt was made to move generation of the build rules to an external script, but the mixed-mode make/script was even less legible than the $(eval) indirection going on in the makefile.
FossilOrigin-Name: 563d313163c02b398ae85b7c2ed231019a14e006726f09a7c1f294a58bf4363f
2024-01-01 05:58:47 +00:00
stephan 7a482b3bcd Use SQLITE_ENABLE_STAT4 in both the WASM and JNI builds.
FossilOrigin-Name: 99d11e6d0ae687ff6bac5119027f7b04d5e7185214e79cf8c56289cfa809b0f9
2023-12-31 04:01:36 +00:00
stephan e24cd27c39 Minor doc touchup in the JS bits.
FossilOrigin-Name: 8d2120c35425081e2158d6a8a6b083c4adf8d694046b2d98f5fd235520920432
2023-12-29 04:29:07 +00:00
drh 2aae3a95a9 Enable SQLITE_DIRECT_OVERFLOW_READ unless it is specifically disabled using
the -DSQLITE_DIRECT_OVERFLOW_READ=0 compile-time option.

FossilOrigin-Name: 630604a4e604bfb36c31602917bfa8d42c10c82966d0819932bf8f827b9158b8
2023-12-28 21:02:08 +00:00
dan 751c4e2152 Update fts5origintext4.test to work with SQLITE_DIRECT_OVERFLOW_READ.
FossilOrigin-Name: 15ed002aed12556aeb9bbe537c4ba839f0c95bac65a69d03401b37cc3fd11b92
2023-12-28 20:54:12 +00:00
drh 4c13d3ca92 Performance improvement by unwinding a loop in jsonAppendString().
FossilOrigin-Name: 190ab3c08431a0ba24d76392eab251f5c1792add05e4ec780998b299208eca95
2023-12-28 19:18:08 +00:00
drh 42203e1b75 Fix harmless compiler warnings in FTS5.
FossilOrigin-Name: 3cd5ef44e40570c357f913a9483fa1cd72e7f2827a5ed5826bff99febae213b1
2023-12-28 16:25:48 +00:00
drh 0546a284fa Enhance the (undocumented, debug-only) json_parse() SQL function so that it
returns the text rendering of the JSONB parse of the input, rather than printing
the rendering on stdout.

FossilOrigin-Name: 056de8d551dcbdf1d162e2db15ed418fa9c786f900cd3972ef8a1dea3f4f3aa1
2023-12-28 16:21:22 +00:00
dan d9ac37fc44 Fix a problem in the shell tool (not library) causing an out-of-bounds write if an ".open" command failed, then the user pressed ctrl-c to interrupt a query running on the substitute in-memory database.
FossilOrigin-Name: 026618b9e321576f616a32e41329066ba629814170c6cfeef35430343f5003f3
2023-12-27 16:24:53 +00:00
dan d82320ac9a Ensure that the xColumnText(), xQueryPhrase() and xPhraseFirstColumn() APIs all return SQLITE_RANGE if they are passed a bad column or phrase number.
FossilOrigin-Name: 1a8a9b1c89519d265869251e8b6d3c5db733f0d3a7dea6c7962811a8f1157dff
2023-12-26 15:52:40 +00:00
drh b2b7490862 Improved handling of malformed unicode within JSON strings.
FossilOrigin-Name: e252bdf5f5de26ba8e2bcc6b0ad94121ed6fc4d86c02fe4a2a058ada93747beb
2023-12-26 13:20:57 +00:00
drh 71a32aede3 Remove an ALWAYS() added in [c50e6c2ace49d092] because it is sometimes false.
dbsqlfuzz c393a4f783d42efd9552772110aff7e5d937f15e.

FossilOrigin-Name: b9daf37e57cde12c4de271a2b1995e8e91b6411f8c2e8882e536241929609b3a
2023-12-24 12:02:36 +00:00
drh 5a85cf5879 Fix harmless compiler warnings associated with [5db30bcc338aac1c]
FossilOrigin-Name: e55d1c2333f35fc20615aa83a7843d08cae7945710a2156d44eee0cc37d90ade
2023-12-24 11:43:49 +00:00
drh c1805ab222 Avoid signed integer overflow during integrity_check of FTS5.
FossilOrigin-Name: 5937df3b25799eceaadfb04d7226c9995d44c8d8edb5ac3ad02af9d7e3570726
2023-12-24 11:31:20 +00:00
drh 57c98747cb Improvements to the query planner to address the inefficiency described
by [forum/forumpost/2568d1f6e6|forum post 2568d1f6e6].

FossilOrigin-Name: 72fcc12cda910a0e3f7875eb3d117b2a5608705c97703985427a02960f1ab5c5
2023-12-23 19:03:50 +00:00
drh 4ed0b117f3 Add debugging output routines sqlite3ShowWhereLoop(X) and
sqlite3ShowWhereLoopList(X) that can be invoked from a debugger to show
a summary of the content of a single WhereLoop object or a list of WhereLoop
objects.  No change in release builds.

FossilOrigin-Name: 5db30bcc338aac1cf081de2deec7e60749ae012e2b6f95ccf745623adb4a31dc
2023-12-23 11:31:47 +00:00
drh 8a630c2aa3 Change parameters on a debugging function to include "const".
FossilOrigin-Name: 94c3e1110c6590261bd30ba317fba4dd94023d69b81a94f4b216cce748fe7489
2023-12-22 21:22:55 +00:00
dan ba5043f818 Add the -fno-sanitize-recover=undefined to the sanitizer builds used for sdevtest and release testing. To ensure that any test that provokes undefined behaviour fails.
FossilOrigin-Name: 89563311adb0ab7c7a3eadb11c2e27fbca50c56fce8ca616628facbc00d72b88
2023-12-22 16:03:45 +00:00
stephan 09e6c82d56 Update #ifdef checks in pager.c and util.c to account for [0462a2612d1fc1d0] to resolve the build problem reported in [forum:9819032aac|forum post 9819032aac].
FossilOrigin-Name: 0f22d809a1c6c80e381f6bcd931fe4ec36dca0e28d07ab4f4f7f83c813424f60
2023-12-22 15:41:13 +00:00
dan 0810150532 Fix a usan complaint about signed integer overflow.
FossilOrigin-Name: e65907e0279f4814ec957f0790777d8b94a86926cd27c52442b311b27efc0185
2023-12-22 14:47:30 +00:00
drh 15bff25111 Add a new comment to debugging output routine sqlite3WhereLoopPrint() to
remind us of what the various fields of the debug output mean.  No changes
to code.

FossilOrigin-Name: da5f34fd4052432b1ae27bb12e56b358cdc5c1282653d60ed0f0fe62f727e4ee
2023-12-22 12:57:49 +00:00
drh c2eff91bd3 Add internal core-developer-only documentation of the JSONB format.
FossilOrigin-Name: 4d30478863b2a60512010de9ec6e3099bfaf75d4afee20acec536713fe94334d
2023-12-21 18:08:05 +00:00
dan 0d7f0e49a4 Fix SQLITE_ENABLE_SETLK_TIMEOUT assert() statements in os_unix.c to avoid reading past the end of the unixShmNode.aMutex[] array.
FossilOrigin-Name: 029a05cd2928d43d81e4549cce5388c432e2c9e75e3fa0b2fe6e91021b2fb9ac
2023-12-20 19:33:41 +00:00
drh 95cf95841c Avoid harmless integer overflow in pager status statistics gathering.
Response to [forum:/forumpost/7f4cdf23f9|forum post 7f4cdf23f9].

FossilOrigin-Name: 206d8c650d937bc700946c40a82a62ea6bc4a80e5f3fb42d0ae2968de25f0644
2023-12-20 11:34:17 +00:00
drh 3262ca83a7 In JSON - minor code cleanup and refactoring with a small size reduction
and performance increase.

FossilOrigin-Name: 215fabda38daecdbd38b1eca5a6aafbc61b6a36a8303f1d7164d5a1138e63134
2023-12-19 21:39:58 +00:00
drh c52aebb443 Remove redundant conditional from sqlite3ExprCanBeNull().
FossilOrigin-Name: 257f96a2d22c605885fa66220c28cf7dc5941c330bccee3f132b9e7b70d89d30
2023-12-19 15:51:14 +00:00
drh 7c1033b010 On second thought, we don't really need sqlite_dbdata accessible to the CLI.
FossilOrigin-Name: 36fe6a61ef8fb393281a5e15119d716521219c7b971fbfd63bdea07d27a78ac9
2023-12-19 15:10:25 +00:00
drh 4449a1b66d Fix harmless compiler warning in the randomjson.c extension.
FossilOrigin-Name: debe7060b16669ada7304ffb9bf7616c8fa30bd286d8be871ed17fd6d64a3d4c
2023-12-19 15:06:40 +00:00
drh 611b9d3efd More precise computation of the size of data structures in the query planner.
Response to [forum:/forumpost/7d8685d49d|Forum post 7d8685d49d].

FossilOrigin-Name: 0c8d88e41167ea92341dd1129be01b596a73f46bdcd5b0dd931441a979c013d0
2023-12-19 14:54:52 +00:00
drh 09259aff6c Add ALWAYS() and NEVER() on branches made unreachable by recent changes.
FossilOrigin-Name: c50e6c2ace49d0928b05cbfd877c621e9a0f77dc4e056ccb1dbe5cf118a00d00
2023-12-19 14:53:39 +00:00
drh 3e2ec83e0b Ignore COLLATE operators when determining whether the result of a subexpression
should be shallow-copied or deep-copied.

FossilOrigin-Name: 34ae36a45e814bed7c8340412c7ef3fc849b82357656d0eb5f0f805e59d846d0
2023-12-19 13:45:05 +00:00
drh 9c36095367 Test case for the previous check-in.
FossilOrigin-Name: df5a07e1a5122e08c2fa6076ac08adb2820f997ee11dd88b84863666899dfb57
2023-12-19 13:00:35 +00:00
drh 60c435dc4b When unable to resolve an identifier, change the Expr node into TK_NULL
rather than TK_COLUMN, to prevent any downstream misuse of the non-existent
column.  dbsqlfuzz 71869261db80a95e4733afa10ff5724bf3c78592.

FossilOrigin-Name: d2e6117e4f97ab98b01deb5fcad5520f8181d00bed8d904d34963c01d73df857
2023-12-19 12:49:35 +00:00
drh 3a0e82611a Always make the sqlite_dbdata virtual table available in the CLI.
FossilOrigin-Name: e5fd3b32ad87586a7413570e568c9c1859a37a4f836cca074126471b125fb682
2023-12-19 12:23:11 +00:00
drh a3569fb2ca Extra ALWAYS() macros to verify state in the sqlite3ExprCanBeNull() routine.
FossilOrigin-Name: be19b84c9f3fe127165809908add148dbe9a827a55608b0490de7e69b7f7f191
2023-12-19 11:57:29 +00:00
drh 459f7b1090 Remove a stray comment in the JSON code.
FossilOrigin-Name: 6618bdf0679405b43911ea8cd94050b12a5dc469f3dfe4759ee3ff850a55229e
2023-12-19 00:07:38 +00:00
drh d9252d09c2 New JSON invariant test cases.
FossilOrigin-Name: a6a1367b0bf364b1a2e20e153c5f4a578624b8846f9ec0b7c9c3cba0ea2ec346
2023-12-18 19:18:46 +00:00
drh c4dd6b42ec Add NEVER() to an unfalsifiable branch.
FossilOrigin-Name: 9a0c67db366d38a0b0741f6a1ae333cf27cfe6f6b7c6eed94bdec9686f9f9f8a
2023-12-18 18:50:47 +00:00
drh fc76750f61 Fix JSON to JSONB translation so that it deals correctly with Infinity
and NaN.

FossilOrigin-Name: 178cb84f36bdb45ba17511900d6d8ea8dfa14912fc5bf7094a20348174a36c95
2023-12-18 18:31:27 +00:00
drh 095f2c5082 Ensure that the insert/delete size delta on JSONB objects in the JSON cache
are always set to zero.

FossilOrigin-Name: 4b4581668a908473dbf1322a3e98bc7cca122998c44518ea183af7f0d1ba9f95
2023-12-18 15:53:48 +00:00
drh cf6fe5abe3 Add randomjson.c to testfixture. Use it for a new set of invariant tests
against JSON functions.

FossilOrigin-Name: f1c040606bfe784804134d8f3ca130908fad5212b47e3c32792baab977470943
2023-12-18 14:24:13 +00:00
drh 0a46ff995b Ensure that all object labels for individual objects generated by
randomjson.c are unique.

FossilOrigin-Name: 29c46aca231b3f1e997ef306a5a651408185bf3ad09ab9fc1fe21ed18caa4d02
2023-12-18 14:16:58 +00:00
drh 52a4691fff Bug fix in the randomjson.c extension.
FossilOrigin-Name: 1f3a33df530dbe330ea8b14a69369b807b413b25a167d1a3938f8f0faf97cc91
2023-12-18 13:51:54 +00:00
drh 2ae95649de Enhancements to ext/misc/randomjson.c.
FossilOrigin-Name: a4e6d1f86f3a502e4170f5a90031e269e48363e95114a66b84d373e3ce0b2704
2023-12-18 12:18:47 +00:00
drh 0d201598a5 Enhancements to the "randomjson.c" extension. Automatically load that extension
into fuzzcheck.

FossilOrigin-Name: 70620405ab01d6a5d38bafa9ae175fd6e4eabaf2efb7854734278dafd7b05c99
2023-12-17 20:41:48 +00:00
drh 13264418ba Enable SQLITE_STRICT_SUBTYPE for default builds of the shell, fuzzcheck,
and testfixture.

FossilOrigin-Name: 5a0c517ed7e46c0f8a3db752cf5b9f8010c60f35084606abe9e7c1c4f993b4a7
2023-12-16 15:48:42 +00:00
drh 5f3dd8668c New test case based on Chromium bug report 1511689.
FossilOrigin-Name: 2c7ef4b4d215f99f8d6787adb64e2037ae96e5dd6cb49c8b81634249f5e1b328
2023-12-16 10:50:06 +00:00
drh 40e614e393 In the count-of-view optimization, deferring freeing obsolete parts of the
parse tree, on the off-chance that some other part of the code might be
holding a pointer to those parts.

FossilOrigin-Name: da442578856c87137eb1677d9b13b7c1cf15828cc41d4756572b278060f69bae
2023-12-15 20:13:09 +00:00
dan 97f7ead3f3 Avoid expiring prepared statements in the middle of an integrity-check.
FossilOrigin-Name: 88beb48472da4667c0727c8ebabe046ea526450ff837fe789d041ed3f1ff105e
2023-12-15 19:26:16 +00:00
drh b7fad0dca3 Add mention of --buildonly and --dryrun to the testrunner.tcl usage screen.
FossilOrigin-Name: 23b92d915c12ee768857e2c3c961832f390cad9b53b8bcfc2b97664baab25bb7
2023-12-15 16:28:02 +00:00
drh baa1aba8d7 Fix a new JSON test case so that it works even if SQLITE_OMIT_VIRTUALTABLE
is defined.

FossilOrigin-Name: b995aae510888a9746b46545d176a0885d4738e1f1bc0b7ad7937ed023efd7d6
2023-12-15 15:22:03 +00:00
dan f2194605f8 Do not run test script fts5origintest4.test with either "memsubsys1" or "mmap" permutations.
FossilOrigin-Name: 05a63d9603ef42cbee6dadff72d97583a9c78e549f70e9a808534d5c1ae7c28a
2023-12-15 15:17:39 +00:00
dan 76dbb58700 Avoid running the "no_mutex_try" tests with SQLITE_ENABLE_SETLK_TIMEOUT builds as part of the release test.
FossilOrigin-Name: 6b4e1344a28c213cbe8fb97f7f3f6688de93fb73ed96bf460ff74c959da1a712
2023-12-15 14:33:50 +00:00
stephan f062506002 Correct --enable-sab flag in ext/wasm/GNUmakefile to fix a silent alhttpd args-parsing error.
FossilOrigin-Name: 7b9b757d872a31395b0f6454e2309a6a4664b8bdd8749f6a15371cbe72c05b60
2023-12-15 13:38:47 +00:00
stephan e982385619 Use SQLITE_STRICT_SUBTYPE=1 by default for the JNI and WASM builds unless they're explicitly built with SQLITE_STRICT_SUBTYPE=0.
FossilOrigin-Name: 990211357badf0ab08bd34cf6d25b58849d0fd8503e289c1839fc837a74e1909
2023-12-14 22:01:55 +00:00
drh eb78d56ec5 Add assert()s to FTS5 to fix static analyzer warnings.
FossilOrigin-Name: 27d4a89a5ff96b7b7fc5dc9650e1269f7c7edf91de9b9aafce40be9ecc8b95e9
2023-12-14 16:34:47 +00:00
drh 4a5c96ace3 Fix harmless compiler warnings in JSON and FTS5.
FossilOrigin-Name: 90135efccfeb1046f002bfcbd8dfec9a1a3b40cbe1b5c714ae065b06368e354f
2023-12-14 15:38:57 +00:00
dan e6289d6dd0 Improve the error message returned by an fts5 'rebuild' command on an external content table if there is a problem with the content table or view.
FossilOrigin-Name: 0fbf4b8a58fde1c187908934da6f59999b146f32e07ac255cc531c5c4d7007fd
2023-12-14 15:31:35 +00:00
drh 8a861a81e8 Enhance aggregate order-by so that it transmits subtype information through the
sorter.  Fix for the deficiency reported by
[forum:/forumpost/87347ad2fb5a8f76|forum post 87347ad2fb5a8f76].

FossilOrigin-Name: d302a389460d0c15775a8b5f5afbac2c1d8a91bc282bc9b04c583ca04a8c09c6
2023-12-14 15:11:39 +00:00
drh 07117f8118 Pass subtype information through the aggregate ORDER BY sorter for
aggregate functions that use subtype information.

FossilOrigin-Name: 3536f4030eab6d650b7ed729d2f71eb6cc3b5fbe16b4e96b99008d66522aaccb
2023-12-14 13:58:50 +00:00
larrybr 9e488a5a40 In CLI, fix .read inability to open 2GB+ files on WIN32.
FossilOrigin-Name: 56c80a62d2e033d64ba5d545ae9cbe3ed7c9d046c0a3fafb6cfa2f0b562d1ef0
2023-12-13 20:37:20 +00:00
drh 3e4195c60d Avoid invoking sqlite3ExprColUsage() on an unresolve column reference.
dbsqlfuzz fc34aa62df4de103705d11b807074687ffafbda5.

FossilOrigin-Name: ac9314c0e335694b48c613145f5397247bb88c51806cd0dc3ed4ec306db4bbad
2023-12-13 16:45:18 +00:00
drh f7c78a2408 Bug fix in the JSONB validator.
dbsqlfuzz ac6fa521a08609a642198e7decf64180e750b3c4

FossilOrigin-Name: 3e940a6a08b0a0434650cd3d8dd286e09ad8ab805b0a4d515e57bba5d3608577
2023-12-13 15:27:03 +00:00
drh 001d1e795c Improvements to UTF8 handling, and especially the handling of invalid UTF8,
in the JSON routines.

FossilOrigin-Name: 1b229c1101d6c384a30f343c5e47b471ab084b2d8e81170eb8f642afc1c67e3b
2023-12-13 14:31:15 +00:00
drh 891f1dc054 Fix the JSON object label comparison object so that it works correctly even
if the label ends with escaped whitespace.

FossilOrigin-Name: 4d5353cadd7b7c5f105bc197f3ec739e2d041472d6b3e939654c9f9cfc2749ae
2023-12-12 18:38:53 +00:00
stephan 9710fa119e Worker1 Promiser API: when multiple db connections are active then use the requested connection instead of always the first-opened connection. Bug reported in [forum:894c330e7f23b177|forum post 894c330e7f23b177].
FossilOrigin-Name: 194276e18e0268829061c09317e7f9f527a703eb45f1755ff1dd30bd99dc1b68
2023-12-12 17:52:27 +00:00
drh df25a8fd4b The json_valid(*,8) function does a much better check of the validity of
the JSONB input.  The json_error_position() function returns an approximate
byte offset to the point of the first detected error in the JSONB.

FossilOrigin-Name: 840efb33a3934a9bdccad65ea15c70d5c335a517502c9844aaad8405d16d1604
2023-12-12 17:31:17 +00:00
drh 78e636bba6 Add NEVER to two unreachable branches in JSON.
FossilOrigin-Name: c96ebb086feb89341565cc52b970ae7799ce1327fe1ad4fc790f1b0dcaa6e229
2023-12-12 17:13:10 +00:00
drh 87399a56db Improvements to JSONB validation - catch more cases where the input does
not conform to spec.

FossilOrigin-Name: be1864eac4eb75cc30bf98f73092c8608467f4bd956240df6a0cbea9f1e09e85
2023-12-12 14:33:52 +00:00
drh cc1a39fd24 Validity checking of text nodes in JSONB.
FossilOrigin-Name: fa5160687c2f970d407e8af73c246f7cd806bb4ce35f29a79ac534a8646a6c8e
2023-12-12 02:31:12 +00:00
drh ad6bc61804 The json_error_position() function now reports an approximate byte offset
to the problem in a JSONB if there is a problem.

FossilOrigin-Name: 80d5d94dff6a2d2557039be3d7d47c1a6003c4b98defe0bd411acfeb963ad5dd
2023-12-11 21:00:55 +00:00
drh 5a890b4ed2 json_error_position() now uses jsonValidityCheck() to find the approximate
position of an error in a JSONB blob.

FossilOrigin-Name: c3d60cf7028a333b825d5b89516945a73e0c158ac81d8bcc117d21bfd98602c8
2023-12-11 20:44:21 +00:00
drh 001caa714f json_valid(*,8) allows minus-signs on hexadecimal literals.
FossilOrigin-Name: c0d7f4520d839a268b3fd2474d0897a9832aa608bd6238b3e287fabecf07a350
2023-12-11 20:19:10 +00:00
drh 7445659559 Activate JSON_SELFCHECK within fuzzcheck.
FossilOrigin-Name: 4d14e733bb521aed65e98533969d2303738232ae87dab70fdf7962e6513195f5
2023-12-11 19:21:06 +00:00
drh ba5505657f Rename the new test-control to SQLITE_TESTCTRL_JSON_SELFCHECK. Make it so
that the current value of the setting can be interrogated.

FossilOrigin-Name: 7aff1d9a4cb17ecd5abab21ab032f35a78741dd641ddd8cbcc85fc4a81a0707d
2023-12-11 19:00:44 +00:00
drh 7d2eaae83e Add SQLITE_TESTCTRL_VALIDATE_JSONB, which if enabled under SQLITE_DEBUG causes
cross-checking of generate JSONB.

FossilOrigin-Name: b410a4db74a650003539ffaaea18519d5159b504daac47db6a4874b730f40ac8
2023-12-11 17:03:12 +00:00
drh ce46e0eb11 Work toward enhanced functionality for json_valid() with deep checking
of the JSONB (second argument has bit 0x08).

FossilOrigin-Name: c370d573198b151767f04e91bf8baa4ae0076751ae468c5709742a0b0ed16770
2023-12-11 14:01:38 +00:00
drh b89e64d822 Fix a potential use of uninitialized value in json_valid() with 2nd
argument of 8.

FossilOrigin-Name: fa102036fe46eeb71b7df3e265be1935ae5c78e0b939b08841bcfb8abadbc77a
2023-12-11 02:39:11 +00:00
drh bfa0de86e6 Fix a harmless UBSAN warning.
FossilOrigin-Name: 1503cba6d17e9bade7a5c103ddd23241ff4741f9a2e3032ffe2987af243dae65
2023-12-08 16:56:50 +00:00
drh 2a27be2107 Fix a potential problem RCStr access on a JsonString object that is not
really and RCStr.  Fuzzer/UBSAN find.

FossilOrigin-Name: d2f2174ce2cc89606034e158149a2d05fc3627ec4d5cdb772add7a2250f29d78
2023-12-08 14:54:22 +00:00
drh 9d2446dc13 Fix a harmless compiler warning about "confusing indentation".
FossilOrigin-Name: 34f9e9a8c4bea13f60f43062e25cd7d9422f2e7f5b371ed0ddadc9abeb3ca256
2023-12-08 12:58:41 +00:00
dan 05980f5931 Avoid dropping an error code in new fts5 tokendata=1 code.
FossilOrigin-Name: a66596e33dc9aa4bab2ec3ff45546e1321d0a11bdc764f8381b315292ca92423
2023-12-08 12:04:32 +00:00
dan 0b427eb796 Ensure an fts5vocab table never uses a special tokendata=1 merge cursor.
FossilOrigin-Name: 1e26510e83b40c9bd2e8bfa2a0e81f2cb915e78fed773204ef537683e48b61dc
2023-12-07 21:09:33 +00:00
dan 7c12666fe9 Avoid an assert() failure when querying an fts5vocab table that accesses a tokendata=1 fts5 table with corrupt %_data records.
FossilOrigin-Name: 386ba9e20423fb2f623d6adc9d3c310fb1b135f54a1dad15ef3b593d97886926
2023-12-07 20:46:40 +00:00
dan 1ddcf7dd95 Fix a null-pointer dereference in fts5 tokendata=1 code.
FossilOrigin-Name: d69fa8f0504887f968d9a190ecb889ddb40bb1b56d0d4479f9819c106aec719b
2023-12-07 19:08:25 +00:00
dan 5f2f8d0028 Fix a problem with handling OOM and other errors in fts5 when querying tokendata=1 tables.
FossilOrigin-Name: bc911ab5953532956510c199be72b1d3c556f2d0ddbd7fc0ae6f5f917b337b48
2023-12-07 18:41:49 +00:00
dan 2f3ccb8886 Different fix for the fts5 COMMIT-following-OOM problem first fixed by [fba3129d]. This one does not cause problems if an fts5 table is renamed and then dropped within the same transaction.
FossilOrigin-Name: d8c6b246944934a7a6e027b3f5b986fd64a19dd5c5c5175f4ea8586da59a6764
2023-12-07 14:41:58 +00:00
drh 5a238ffcae Rework the jsonEachPathLength() routine in json_tree() so that it is
less susceptible to problems due to goofy object labels.

FossilOrigin-Name: 858b76a00e8ff55215f7a2e6a4cd77fc4d4f98dea7224cd90488744f5ce246a4
2023-12-07 14:09:25 +00:00
drh f86a07b0c4 Add ALWAYS() on branches added in [ec0ae4030968c782] that are always true.
FossilOrigin-Name: 451cef8609e96dd9244818adc5c6f240544694bcb4ae620e88f90e403e59d70f
2023-12-07 13:14:34 +00:00
drh 5b6b703461 Improved detection of corrupt JSONB in the jsonReturnFromBlob() function.
FossilOrigin-Name: b014736c1f80ccc46fb4b24ac04310a6ce5cb5b6653665efff366cb3bc742257
2023-12-07 12:55:39 +00:00
dan 00f3ac5544 Fix compiler warning about shadowed variable in fts5_index.c.
FossilOrigin-Name: ee70e4c1c9c41617850228e48d8df44f105cf2fbbe789340ceca6f27ad6ce5eb
2023-12-06 18:34:59 +00:00
drh 82fc1b63f6 Work around LLVM's newfound hatred of function pointer casts.
[forum:/forumpost/1a7d257346636292|Forum post 1a7d257346636292].

FossilOrigin-Name: ec0ae4030968c782af48d1c776351c14b2ada21d40aeb97915f33df30706e18f
2023-12-06 18:25:41 +00:00
dan 83ac79282a Update documentation comments in fts5.h.
FossilOrigin-Name: 38c50e22c98607e6c1fd78d7615cda534773b6d4fd85c712b54749fcd7af0c83
2023-12-06 18:10:50 +00:00
drh a9c8469d03 Do correct comparisons between object labels in JSON even when the two labels
contain different JSON escapes.

FossilOrigin-Name: bda2e30cc22e180b19a7a05824dd345880eb402ae5450b2d2dd954946c3ae135
2023-12-06 17:50:16 +00:00
drh b597fea894 Correctly handle 8-byte sizes in the JSONB format.
[forum:/forumpost/283daf08e91183fc|Forum post 283daf08e91183fc].

FossilOrigin-Name: 73d390f39c0bbbc017e01544e4d43c76761f2599bd57f900131c706270dfd202
2023-12-06 17:39:31 +00:00
drh 9df01b5ccf Fix the routine that determines the json_tree.path value for the first row
so that it correctly takes into account escape sequences in the path
argument.

FossilOrigin-Name: b9243ee8a37c62eb8848e765bd4af83bc1b3d3eb24fb4268a1357ad1f8b2e1fb
2023-12-06 16:57:18 +00:00
larrybr 3207199c98 In CLI, move -interactive flag handling back to arg-loop pass 2.
FossilOrigin-Name: 63cb05a862532d2d56e9e81fe32ced09bf58f03146587a118f11c2a84e195e69
2023-12-06 16:27:29 +00:00
drh 8dfbf4addc Test cases for object label matching with escape sequences.
FossilOrigin-Name: c6f2aa38e95b7888650cfa7bb773b18a28e01d883033ac77be6d504ffe417d18
2023-12-06 15:50:13 +00:00
drh 6a8581d828 The rule for the RHS of the ->> and -> operators when the RHS does not begin
with $ is that it must be (1) all digits, or (2) all alphanumerics, or
(3) contained within [..] or else it will become a quoted label.

FossilOrigin-Name: 0e059a546ec11fa5c6d007bd65c249ee2422f1facbdb2792c53e0bc0ccc97e14
2023-12-06 15:35:38 +00:00
drh 91ec00c25a Increased rigor in comparisons between object labels in JSON.
FossilOrigin-Name: 2bc86d145fccc07107b7753cb1a69122676d4096fe59c454497bd81a6142d45e
2023-12-06 14:50:48 +00:00
dan e751596ee8 Add the tokendata=1 option and related APIs to fts5.
FossilOrigin-Name: a76a636b23c0ebd95d47fdf8358de4729e51a5f68f1a730cd4d89b378e94ac0d
2023-12-06 14:36:34 +00:00
dan 39b08db132 Merge trunk changes into this branch.
FossilOrigin-Name: 8f46eace86e7b2e556913575aa3cd6f7987ac0efcc880f0af649d42c253aeb81
2023-12-06 14:30:34 +00:00
stephan 1f2d7c4312 README.md typo fix reported in the forum and update all links from http: to https:.
FossilOrigin-Name: 5c48acdbb44185b352b54911a57a6986d6c7e624bdeba2af48b985d29f0292bf
2023-12-06 12:30:28 +00:00
drh 88208296c2 Rework the JSON functions so that they use the JSONB format internally.
The original JsonNode parse tree design is removed.  All JSON functions
that accept text JSON also accept JSONB.  New functions generate JSONB.

FossilOrigin-Name: 7f0c79b94e8f55e5013e52ba64ba8b32dad1dc4e2224d2099733cbc561de1810
2023-12-05 19:45:09 +00:00
drh 5afd67b3c3 Use extra assert() statement to silence harmless static analyzer warnings.
FossilOrigin-Name: 174c2b2eef5fecd96a5fc89b81032fe81f7801f12097cea10e7e7f0a02114813
2023-12-05 19:24:07 +00:00
dan fb923fc4cc Further tests for the new code on this branch.
FossilOrigin-Name: 59d008b6c23ab900377bc696ee19381feb7614bac80546eae361e401c3620c4e
2023-12-05 18:36:23 +00:00
drh a0de45459e Miscellaneous comment cleanup and typo fixes.
FossilOrigin-Name: 59446dc0bd0091572122a3c8b4653d7a2dc867d16c4a5919f79b81bc3a673ce3
2023-12-05 18:28:15 +00:00
drh 8eac91fab7 Use strspn() to accelerate whitespace bypass in the JSON parser.
FossilOrigin-Name: 843197df08352bdff4b87be91d160e574572aded0d0c66142fd960000c0b4701
2023-12-05 12:52:13 +00:00
drh 590aaff992 Small performance gain by unwinding the string literal delimiter search
loop in the JSON parser by one more level.

FossilOrigin-Name: 4c587feac153e8ebe526559ec3d254f545f81e8d1ed3126f91a5ff25ec4aa72e
2023-12-05 12:22:05 +00:00
drh 78f7d2f4c1 Clean up the JSONB performance test script.
FossilOrigin-Name: 905301075a7fc1010ee7e754867b1b698c9b8576d50e98125def32a5dfb7ee9d
2023-12-05 12:20:58 +00:00
drh fa43e21711 Use an assert() to fix a harmless static analyzer warning.
FossilOrigin-Name: a249ca657e624028bc6b3d2c2bcedd7162d118addb7d62ce519920cecebf1860
2023-12-05 01:44:15 +00:00
drh ae2e972802 Fix OOM and corrupt JSONB handling in json_patch().
FossilOrigin-Name: 1910feb0b7d5cc2b810c3322f6cca281d8730182d30d162bd7bb56800979ea91
2023-12-05 00:17:17 +00:00
drh 3cdb079476 Rename the internal routine jsonMergePatchBlob() to just jsonMergePatch().
FossilOrigin-Name: ebf667b616235bb64b83832008342ba5e7b10b2c170d7cebc431f040fef7ecfb
2023-12-04 23:12:57 +00:00
dan 49bfbc1ef3 Add further tests for xInstToken().
FossilOrigin-Name: 8582707f16133f003a6687f68cbea03d4eb6c2a0e2e07746b7cace0c44e84fa4
2023-12-04 19:48:08 +00:00
drh f26e26afc5 Fixes to error handling in json_array_length().
FossilOrigin-Name: aa85df2d26b74c171c55bde19ef17c4f11f40b8af7181bbf7162f87cdea7e88b
2023-12-04 19:32:17 +00:00
drh 0b8b1c309d Do not make the input JSONB editable in json_remove() if there are no PATH
argument.

FossilOrigin-Name: 66594544f3ba9977475a3e3f74404eb2b2fb845053b28bd24c2b52c7df94e9d7
2023-12-04 19:14:13 +00:00
drh 3fedb7e59e Fix errors in rendering JSON5 escape sequences embedded in JSONB.
FossilOrigin-Name: f1a51ae3863557526a51c6e98e71fcdf4f1ed14a36212b3c90f7408f926345e4
2023-12-04 18:53:10 +00:00
dan 54318b382a Fixes for xInstToken() with tokendata=0 tables. And with prefix queries.
FossilOrigin-Name: 78fbb71598b1ca756acc078253880a1d0f7983a5a26b9efc683e6488122505a1
2023-12-04 18:45:14 +00:00
dan 910c77b049 Fix memory leak in new code on this branch.
FossilOrigin-Name: ebc160b9a05568df66f86e30804399ee29d34b44a60c57e062f98cb92826353f
2023-12-04 17:58:56 +00:00
dan 3dfc063705 Fix a problem with the xInstCount() API and "ORDER BY rank" queries.
FossilOrigin-Name: 317a50563d9e8586fda136e513727241b414e7267d50a06571c8ebd0eae710bc
2023-12-04 17:45:33 +00:00
drh 9c794b9bff Continuing simplifications and code cleanup.
FossilOrigin-Name: ddf92b5059a9106753fd18b82ba8daa269a62af947561c460790107b83416f0b
2023-12-04 17:40:28 +00:00
dan 9d373ca1c5 Fix bug in xInstToken() causing the wrong token to be returned.
FossilOrigin-Name: da78d07e77cbc783fbc725758911c230fd6a1c1885d9576125de955dcc2bd37f
2023-12-04 17:05:37 +00:00
drh 99c41692f1 Remove reachable ALWAYS and NEVER macros.
FossilOrigin-Name: f601de3eeabd85993c1f5ee96b62de6fdabbeae2fe8950e00d08feb48d42c498
2023-12-04 16:01:39 +00:00
drh 732fb64ad3 Two new NEVER macros.
FossilOrigin-Name: 52632c92cb06faf0e804654b3490fd6c199521107bd30c8fcbc3a2a5a488098f
2023-12-04 15:22:42 +00:00
dan 43b4864a98 Add tests for using tokendata=1 and contentless_delete=1 together.
FossilOrigin-Name: a2506b8c9718054912270055638204753c4156bbc115e55194e6df9d7e76cb10
2023-12-04 15:08:21 +00:00
drh dc138cb186 Repair issues and inefficiencies found during testing.
FossilOrigin-Name: ae973cb1515f9d76409c92a2ca2ffd6b71f32b0b490a4886770e7c1b90f12611
2023-12-04 13:12:45 +00:00
drh 2ff73a5f3e Better pre-scan size estimations for objects in the JSON parser resulting
in fewer reallocations and memmove operations.

FossilOrigin-Name: 526b27f90897f5e35dfff7257daf6c4ce4798d649b09b8aecfb02df0449e3c51
2023-12-04 01:14:23 +00:00
drh b7fd951be4 Back off on the use of strlen() for situations where sqlite3_value_bytes()
will work as well, for performance.

FossilOrigin-Name: 79fb54fbb8b9c30f47cdbd437d24a21542716241e822749e5e28c9fbc449bfa8
2023-12-04 00:31:58 +00:00
drh 9af45dc482 Remove dead code. Improved reporting of errors in JSON inputs.
FossilOrigin-Name: 2eaa738e6b5c1b67b3e57c868d9c3a30eea38a0b3b8b02482f06d57a45b10921
2023-12-03 23:38:24 +00:00
drh 16e8a5b2f3 Avoid problems when the path argument to json_tree() contains embedded U+0000
characters.

FossilOrigin-Name: 9f055091af01a5dddba1a7e9868ad030c8f206237e1569215cb161e53e54aa71
2023-12-03 23:30:59 +00:00
drh a3bf077b60 Ensure that OOM conditions in the generation of the "bad JSON path" error
message result in an SQLITE_NOMEM error.

FossilOrigin-Name: aa0e02b5c26a2ef3d6216a0ed8bc01382be43173485f898cb63f2a8c559f2e74
2023-12-03 20:11:35 +00:00
drh 0a18a5807a Enable incorrect JSONB to be rendered into text without hitting an
assertion for a bad whitespace escape in a string.

FossilOrigin-Name: 4d6a9a217df6792b41766b774fb0c0553b45f9104c26a0955bf4a30862d7d7bf
2023-12-03 19:59:45 +00:00
drh 78fa0186b8 Do not let bad hexadecimal digits in malformed JSONB cause an assertion fault.
FossilOrigin-Name: 8dec1ba1e5076ff596756e00c1e2ada0245f168a503dd1cadadf848331acfac3
2023-12-03 11:54:39 +00:00
drh eb18ae3089 Minor code changes for consistency and to simplify testing.
FossilOrigin-Name: df272bd837910ad9e03e222716a1201a601399664365f1dcf73d5932372518ed
2023-12-03 00:51:30 +00:00
drh c78c3c91ae Implement strict JSONB checking in the json_valid() function.
FossilOrigin-Name: 0f26d38880fcbc207abcc94dbc170a7428bab1b4f0b7731aaf5bee0224000994
2023-12-02 21:39:34 +00:00
drh 8f8d481485 Fix harmless compiler warnings reported by MSVC.
FossilOrigin-Name: 419652c0c82980bd043584dcd2976f91dfff7b926b216d597698299850b855c0
2023-12-02 20:37:45 +00:00
dan c22d2b7b7f Fix various compiler warnings and other problems with the new code on this branch.
FossilOrigin-Name: 3a623cfa173b4035c759cb84985d11d8727053beb383648503987d6ab15c0ef0
2023-12-02 20:35:04 +00:00
drh c1e85742da Code and comment cleanup. Everything should work the same.
FossilOrigin-Name: c640754df0d3ffdad994745f0d0e10c8f19f424b87f6a6e6e269491a0350b950
2023-12-02 20:25:36 +00:00
drh 53c2160db0 Fix harmless compiler warnings. Refactor some identifier names for
clearer presentation.

FossilOrigin-Name: 7e3941502789c5afaf19b08112f464abf5e3cba7f92fc9290af2a0f96127ad9a
2023-12-02 18:17:38 +00:00
dan 94c521295a When tokendata=1 queries require multiple segment-cursors, allow those cursors to share a single array of in-memory tombstone pages.
FossilOrigin-Name: e0175d07e4094db5ea4b0378a5ff480dafb6ba9da86a113fa767c4c89c3c866f
2023-12-02 18:14:07 +00:00
drh a11aaff05a Take extra care to ensure that JSONB values that are in cache are actually
owned by the JSON subsystem, and that ownership of such values is not handed
back to the bytecode engine.

FossilOrigin-Name: 1304534001e9ef66c6b12752b69d790bfa3427cc803f87cc48ca22ae12df0fdf
2023-12-02 18:04:27 +00:00
dan c44041e03b Ensure that tokendata=1 queries avoid loading large doclists for queries like "common AND uncommon", just as tokendata=0 queries do.
FossilOrigin-Name: 7bda09ab404a110d57449e149a3281fca8dc4cacf7bd9832ea2a1356ad20fe8e
2023-12-02 17:32:16 +00:00
drh 05db513435 Protect a memcpy() against OOM conditions.
FossilOrigin-Name: 26144d1c25ae0435db568009ba05e485d23d146f2b1f29f3a426c87860316aed
2023-12-02 16:11:22 +00:00
drh 2c26bde4ff Do not allow a JsonParse object to be considered "editable" after an OOM.
FossilOrigin-Name: c6bacf57bd6fe0fee00c9d41163a270b60997c20659949971bbf5c6c62622bfe
2023-12-02 15:59:48 +00:00
drh 4cd397c0d9 Fix potential unsigned integer underflow in jsonAppendString().
FossilOrigin-Name: d2fba2cbdc3870d34228c1a9446eced884325acc183900d7dd0b96132570fb4a
2023-12-02 15:06:43 +00:00
drh 82136d90f8 Minor fix to the header comment on jsonXlateTextToBlob().
FossilOrigin-Name: c3677ba410208c07b711f5f526eb5cf039a8eee49f632c7ae04fa55cdfbb9058
2023-12-02 14:55:46 +00:00
drh f0b8b16317 Performance optimization in jsonAppendString().
FossilOrigin-Name: fdf00e96239c73fb67e2acecc5b95f55a1fc51c3deed4512613c0d6070ce5805
2023-12-02 14:16:47 +00:00
drh 679c90850c Simplification and optimization of the JSON parser.
FossilOrigin-Name: f5ec9485119a2a6cb33eb864c7ca9b41d4a2ed08ab6ad9a6b0dd9358ab253576
2023-12-02 13:36:52 +00:00
drh 768b6e32f6 Remove a NEVER that can be true if a virtual table column is declared to have
a DEFAULT.  See
[forum:/forumpost/3d4de8917627d058|forum post 3d4de8917627d058].

FossilOrigin-Name: 8abc2ccaf8106f20243568cd7fa74174386eb85d7ea381201e97e2fd527033e0
2023-12-02 12:23:34 +00:00
drh 6df61985d4 Unroll a loop in the parser for a performance increase.
FossilOrigin-Name: a6dc29e4d5e13949e0fcd9d5dde575c2670eb10a230ab9df3806fc8c3016c540
2023-12-02 01:38:53 +00:00
drh 5ec9c916ad Fix harmless compiler warnings and enhance performance the parser.
FossilOrigin-Name: 285633da6d188547e52f07779e209c9e5f3dc33ce0668e14858f3337889ef4b8
2023-12-02 01:06:33 +00:00
drh 3af20cf3a0 Performance optimization in the JSON parser.
FossilOrigin-Name: 68d191f40e708962ec88e0c245b4496bc4a671300484b1cc0f3fc7e6d199a6e6
2023-12-01 22:01:26 +00:00
dan f4c2962558 Remove old code for tokendata=1 queries.
FossilOrigin-Name: b0a489e8e1bf0290c2117ab32d78b1cc7d67bcb226b55ec044c8367ebde3815b
2023-12-01 20:37:11 +00:00
dan ebd173a79f Merge latest trunk with this branch.
FossilOrigin-Name: 8258967411d3ff212424b25fec79ded0d8ae83e773cd35a0bbf300c94923f25b
2023-12-01 20:10:20 +00:00
dan b5effc0605 Different approach to querying a tokendata=1 table. Saves cpu and memory.
FossilOrigin-Name: c523f40895866e6fc979a26483dbea8206126b4bbdf4b73b77263c09e13c855e
2023-12-01 20:09:59 +00:00
drh 03075fa868 JSON cache is now more effective.
FossilOrigin-Name: 443a3f3a8e64d81cad8300a30e2cc57c4e39f69b5669ac8b550c590ae9f1134a
2023-12-01 18:49:02 +00:00
drh 063d0d4c3a Fix up the JSON cache to work better.
FossilOrigin-Name: 1fdbc39521f63aedc6f08ecaafa54ea467b8c6316a692a18ad01eecbf22a0977
2023-12-01 18:46:14 +00:00
drh 5bfa7e65d1 Cache is working better, but does not preserve the hasJson5 flag.
FossilOrigin-Name: a12add7ab9f5aee5bb2ede0c4d22e599dd28f7a107dce72b2ea48ef92d233e8a
2023-12-01 13:28:13 +00:00
drh ca1ce7773c First attempt to get the JSON text-to-binary cache working. All test cases
pass, but the cache seems not to help much.

FossilOrigin-Name: 25ed295f300fea6185104a73721076bccd2b2a6e411c78564266fa6dca4ff70c
2023-12-01 12:57:12 +00:00
drh 4b9ed1b256 Remove all trace of JsonNode from the JSON implementation. The JSONB format
is used as the internal binary encoding for searching and editing.

FossilOrigin-Name: 11ebb5f712cc7a515e2e0f2be8c1d71de20c97fe5b74c4f4d72c84fd21182d35
2023-11-30 23:36:14 +00:00
drh 38aeb97f27 Convert json_valid() over to using only JSONB as its internal format.
FossilOrigin-Name: 7b5756fa6d00b093bf083a8d7a5ef5485f7a09e4eac473785c8380688f861a1b
2023-11-30 20:57:48 +00:00
stephan 68003d9f18 Add a basic batch-mode SQL runner for the SAH Pool VFS, for use in comparing it against WebSQL. Bring the WebSQL batch runner up to date, noting that it cannot run without addition of an "origin trial" activation key from Google because that's now the only way to enable WebSQL in Chrome (that part is not checked in because that key is private). Minor code-adjacent cleanups.
FossilOrigin-Name: 883990e7938c1f63906300a6113f0fadce143913b7c384e8aeb5f886f0be7c62
2023-11-30 20:34:24 +00:00
drh 276042bd23 Convert json_type() to use JSONB internally.
FossilOrigin-Name: 83074835b900ce85cf67059e674ce959801505c37592671af25ca0af7ed483f1
2023-11-30 19:29:56 +00:00
drh 0ab1e25468 Convert json_insert(), json_replace(), and json_set() over to using only
JSONB internally.

FossilOrigin-Name: 4e2083e86f19ef7634f0b253fb924e52014b43ed0ce8acc51c36f3c5682180a6
2023-11-30 19:11:14 +00:00
drh 48222bef66 New JSON test cases showing insert or set with missing substructure.
FossilOrigin-Name: 6802b6459d0d16c961ff41d240a6c88287f197d8f609090f79308707490a49c2
2023-11-30 16:16:10 +00:00
stephan bac2fe9f44 Update some OPFS-related help text in WASM tests. Minor cleanups in speedtest1-worker.js.
FossilOrigin-Name: 263f6d3a7784ef7d032dbf7a3265aca8dd70bf50797f28f6b2e8ddb6a301f83a
2023-11-30 10:00:25 +00:00
dan 89fcfbb424 Fix signed integer overflow in fts5.
FossilOrigin-Name: 60e46c7ec68fd8caaed960ca06d98fb06855b2d0bb860dd2fb7b5e89a5e9c7b4
2023-11-29 16:22:39 +00:00
drh ed088f5f8d In the recovery extension, if a payload size is unreasonably large, it is
probably corrupt, so truncate it.

FossilOrigin-Name: 988c3179e978a3a6d42541e9c7a2ab98150383671810926503376ed808f150ff
2023-11-29 13:47:46 +00:00
dan 0d4a888485 Merge latest trunk updates into this branch.
FossilOrigin-Name: 554fc13f2ca5f2ebd9ad0206034c25b556ff40db3106051c5e539f2e142e88ea
2023-11-28 19:43:08 +00:00
dan 41c9e0b767 Add documentation for new fts5 auxiliary function APIs.
FossilOrigin-Name: 9be8969edd49e3da96fb8ac2279aff6fe2e215d6ac55162b4734aca1b6316580
2023-11-22 21:15:05 +00:00
dan af54826e4a Defer building xInstToken() hash-table until it is to be used.
FossilOrigin-Name: 9b005085ff4a53cda0a1dff0c836630d6d3b95b9c40658ffd2a886f3e1b37faa
2023-11-22 20:02:55 +00:00
dan 5c268bbf67 Fix tokendata=1 and xInstToken() APIs for detail=none and detail=column tables.
FossilOrigin-Name: 37b271c19d772bd06524db816ded03377b426efed7a7783c8a96f6fb156ecd86
2023-11-22 19:02:54 +00:00
dan a0764f63a8 When querying a tokendata=1 fts5 table, do not use a prefix cursor for the case where the term has only one variant.
FossilOrigin-Name: d711c96ba855686d6881a50498418de3492144f005684b5ae55bca24413dce47
2023-11-16 21:11:56 +00:00
dan 50b0e25a55 Add implementation of xInstToken() API.
FossilOrigin-Name: a34b26fe7f60b74e7ae5cf64900920a3d352a20da2496401bcbc27041689cd07
2023-11-15 11:45:19 +00:00
dan e108029332 Add new fts5 API xQueryToken().
FossilOrigin-Name: 828566392b3ea8db603cb1ae5eccbc8ac035efaa284bc7c15ba89874f634aec9
2023-11-13 14:29:12 +00:00
dan 43d05ccc31 Add declarations for new API functions.
FossilOrigin-Name: b8a48cc18c94d15017f898c820fdd784efbaac20d7a45c4d97269333e8f2ec60
2023-11-08 14:55:20 +00:00
dan b4fc827c0f Merge latest trunk into this branch.
FossilOrigin-Name: 3a869cf1f84b0e9bdcc4de53685430ab41eafacbba1ca7b87e727aa98811c6c5
2023-11-06 19:16:38 +00:00
dan 4cad31912e Merge trunk changes into this branch.
FossilOrigin-Name: ac5570614ebb77feff4943c7a78d877508e31087b550f337c11b45f1016e3c55
2023-11-06 16:32:50 +00:00
dan 03204e9106 Add the tokendata=1 option to ignore trailing token-data when querying an fts5 table.
FossilOrigin-Name: 122935182ad5869ce3a4c6d796c38a0509f6f3384dd1b3e60a3f2f0f366cc5f5
2023-10-11 21:08:12 +00:00
dan 1846de49a4 Fixes for fts5 expression parser module to allow embedded 0x00 bytes in tokens.
FossilOrigin-Name: 342c8d0783f449817d3f565ff6b9f010a6c690beeea32f1861640810490a8b5f
2023-10-03 19:06:52 +00:00
dan eb28787b5f Update fts5_decode() to allow for embedded 0x00 bytes in tokens.
FossilOrigin-Name: e051120067fd87f57b498e505e3960cf4d14e8e33bad940618cc0823253254f7
2023-10-03 17:07:54 +00:00
dan a35ae44150 Changes so that fts5 can handle tokens with embedded '\0' bytes.
FossilOrigin-Name: c027c092c4af53bd6ae3cc6e2b4439167d9eeb0f9de549b6a2c2a72a67ee886c
2023-09-30 18:13:35 +00:00
140 changed files with 8189 additions and 3136 deletions
+8 -1
View File
@@ -447,6 +447,7 @@ TESTSRC += \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/qpvtab.c \
$(TOP)/ext/misc/randomjson.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
@@ -600,6 +601,7 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_STRICT_SUBTYPE=1
FUZZERSHELL_OPT =
FUZZCHECK_OPT += -I$(TOP)/test
FUZZCHECK_OPT += -I$(TOP)/ext/recover
@@ -630,7 +632,9 @@ FUZZCHECK_OPT += \
-DSQLITE_MAX_MMAP_SIZE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_PRINTF_PRECISION_LIMIT=1000 \
-DSQLITE_PRIVATE=""
-DSQLITE_PRIVATE="" \
-DSQLITE_STRICT_SUBTYPE=1 \
-DSQLITE_STATIC_RANDOMJSON
FUZZCHECK_SRC += $(TOP)/test/fuzzcheck.c
FUZZCHECK_SRC += $(TOP)/test/ossfuzz.c
@@ -638,6 +642,7 @@ FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZCHECK_SRC += $(TOP)/test/vt02.c
FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c
DBFUZZ_OPT =
ST_OPT = -DSQLITE_OS_KV_OPTIONAL
@@ -1291,6 +1296,8 @@ TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
TESTFIXTURE_FLAGS += -DSQLITE_STATIC_RANDOMJSON
TESTFIXTURE_FLAGS += -DSQLITE_STRICT_SUBTYPE=1
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
+10 -3
View File
@@ -1584,6 +1584,7 @@ TESTEXT = \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\prefixes.c \
$(TOP)\ext\misc\qpvtab.c \
$(TOP)\ext\misc\randomjson.c \
$(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\remember.c \
$(TOP)\ext\misc\series.c \
@@ -1692,6 +1693,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_STRICT_SUBTYPE=1
!ENDIF
# <<mark>>
@@ -1728,6 +1730,8 @@ FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_MAX_MMAP_SIZE=0
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_PRIVATE=""
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_STRICT_SUBTYPE=1
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_STATIC_RANDOMJSON
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_PRINTF_PRECISION_LIMIT=1000
@@ -1744,6 +1748,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
@@ -1823,8 +1828,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) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -I$(TOP)\ext\consio $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.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)
@@ -2433,6 +2438,8 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_STATIC_RANDOMJSON
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_STRICT_SUBTYPE=1
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
@@ -2543,7 +2550,7 @@ smoketest: $(TESTPROGS)
shelltest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\permutations.test shell
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE_TCL_DEP)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
+10 -10
View File
@@ -159,7 +159,7 @@ extension and only later escaped to the wild as an independent library.)
Test scripts and programs are found in the **test/** subdirectory.
Additional test code is found in other source repositories.
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
See [How SQLite Is Tested](https://www.sqlite.org/testing.html) for
additional information.
The **ext/** subdirectory contains code for extensions. The
@@ -183,7 +183,7 @@ manually-edited files and automatically-generated files.
The SQLite interface is defined by the **sqlite3.h** header file, which is
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
[Tcl script](https://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
The manifest.uuid file contains the SHA3 hash of the particular check-in
and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
contains the current SQLite version number. The sqlite3.h header is really
@@ -250,14 +250,14 @@ individual source file exceeds 32K lines in length.
## How It All Fits Together
SQLite is modular in design.
See the [architectural description](http://www.sqlite.org/arch.html)
See the [architectural description](https://www.sqlite.org/arch.html)
for details. Other documents that are useful in
(helping to understand how SQLite works include the
[file format](http://www.sqlite.org/fileformat2.html) description,
the [virtual machine](http://www.sqlite.org/opcode.html) that runs
[file format](https://www.sqlite.org/fileformat2.html) description,
the [virtual machine](https://www.sqlite.org/opcode.html) that runs
prepared statements, the description of
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
[how transactions work](https://www.sqlite.org/atomiccommit.html), and
the [overview of the query planner](https://www.sqlite.org/optoverview.html).
Years of effort have gone into optimizing SQLite, both
for small size and high performance. And optimizations tend to result in
@@ -353,7 +353,7 @@ hidden by also modifying the makefiles.
## Contacts
The main SQLite website is [http:/sqlite.org/](http://sqlite.org/)
The main SQLite website is [https://sqlite.org/](https://sqlite.org/)
with geographically distributed backups at
[http://www2.sqlite.org/](http://www2.sqlite.org) and
[http://www3.sqlite.org/](http://www3.sqlite.org).
[https://www2.sqlite.org/](https://www2.sqlite.org) and
[https://www3.sqlite.org/](https://www3.sqlite.org).
+1 -1
View File
@@ -1 +1 @@
3.45.0
3.45.2
+1
View File
@@ -990,6 +990,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_STRICT_SUBTYPE=1
!ENDIF
+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.45.0])
AC_INIT([sqlite],[3.45.2])
#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
Vendored
+9 -9
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.45.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.45.2.
#
#
# 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.45.0'
PACKAGE_STRING='sqlite 3.45.0'
PACKAGE_VERSION='3.45.2'
PACKAGE_STRING='sqlite 3.45.2'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1472,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.45.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.45.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1537,7 +1537,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.45.0:";;
short | recursive ) echo "Configuration of sqlite 3.45.2:";;
esac
cat <<\_ACEOF
@@ -1668,7 +1668,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.45.0
sqlite configure 3.45.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2087,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.45.0, which was
It was created by sqlite $as_me 3.45.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12481,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.45.0, which was
This file was extended by sqlite $as_me 3.45.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12547,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.45.0
sqlite config.status 3.45.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+290
View File
@@ -0,0 +1,290 @@
# The JSONB Format
This document describes SQLite's JSONB binary encoding of
JSON.
## 1.0 What Is JSONB?
Beginning with version 3.45.0 (circa 2024-01-01), SQLite supports an
alternative binary encoding of JSON which we call "JSONB". JSONB is
a binary format that stored as a BLOB.
The advantage of JSONB over ordinary text RFC 8259 JSON is that JSONB
is both slightly smaller (by between 5% and 10% in most cases) and
can be processed in less than half the number of CPU cycles. The built-in
[JSON SQL functions] of SQLite can accept either ordinary text JSON
or the binary JSONB encoding for any of their JSON inputs.
The "JSONB" name is inspired by [PostgreSQL](https://postgresql.org), but the
on-disk format for SQLite's JSONB is not the same as PostgreSQL's.
The two formats have the same name, but they have wildly different internal
representations and are not in any way binary compatible.
The central idea behind this JSONB specification is that each element
begins with a header that includes the size and type of that element.
The header takes the place of punctuation such as double-quotes,
curly-brackes, square-brackets, commas, and colons. Since the size
and type of each element is contained in its header, the element can
be read faster since it is no longer necessary to carefully scan forward
looking for the closing delimiter. The payload of JSONB is the same
as for corresponding text JSON. The same payload bytes occur in the
same order. The only real difference between JSONB and ordinary text
JSON is that JSONB includes a binary header on
each element and omits delimiter and separator punctuation.
### 1.1 Internal Use Only
The details of the JSONB are not intended to be visible to application
developers. Application developers should look at JSONB as an opaque BLOB
used internally by SQLite. Nevertheless, we want the format to be backwards
compatible across all future versions of SQLite. To that end, the format
is documented by this file in the source tree. But this file should be
used only by SQLite core developers, not by developers of applications
that only use SQLite.
## 2.0 The Purpose Of This Document
JSONB is not intended as an external format to be used by
applications. JSONB is designed for internal use by SQLite only.
Programmers do not need to understand the JSONB format in order to
use it effectively.
Applications should access JSONB only through the [JSON SQL functions],
not by looking at individual bytes of the BLOB.
However, JSONB is intended to be portable and backwards compatible
for all future versions of SQLite. In other words, you should not have
to export and reimport your SQLite database files when you upgrade to
a newer SQLite version. For that reason, the JSONB format needs to
be well-defined.
This document is therefore similar in purpose to the
[SQLite database file format] document that describes the on-disk
format of an SQLite database file. Applications are not expected
to directly read and write the bits and bytes of SQLite database files.
The SQLite database file format is carefully documented so that it
can be stable and enduring. In the same way, the JSONB representation
of JSON is documented here so that it too can be stable and enduring,
not so that applications can read or writes individual bytes.
## 3.0 Encoding
JSONB is a direct translation of the underlying text JSON. The difference
is that JSONB uses a binary encoding that is faster to parse compared to
the detailed syntax of text JSON.
Each JSON element is encoded as a header and a payload. The header
determines type of element (string, numeric, boolean, null, object, or
array) and the size of the payload. The header can be between 1 and
9 bytes in size. The payload can be any size from zero bytes up to the
maximum allowed BLOB size.
### 3.1 Payload Size
The upper four bits of the first byte of the header determine size of the
header and possibly also the size of the payload.
If the upper four bits have a value between 0 and 11, then the header is
exactly one byte in size and the payload size is determined by those
upper four bits. If the upper four bits have a value between 12 and 15,
that means that the total header size is 2, 3, 5, or 9 bytes and the
payload size is unsigned big-endian integer that is contained in the
subsequent bytes. The size integer is the one byte that following the
initial header byte if the upper four bits
are 12, two bytes if the upper bits are 13, four bytes if the upper bits
are 14, and eight bytes if the upper bits are 15. The current design
of SQLite does not support BLOB values larger than 2GiB, so the eight-byte
variant of the payload size integer will never be used by the current code.
The eight-byte payload size integer is included in the specification
to allow for future expansion.
The header for an element does *not* need to be in its simplest
form. For example, consider the JSON numeric value "`1`".
That element can be encode in five different ways:
* `0x13 0x31`
* `0xc3 0x01 0x31`
* `0xd3 0x00 0x01 0x31`
* `0xe3 0x00 0x00 0x00 0x01 0x31`
* `0xf3 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x31`
The shortest encoding is preferred, of course, and usually happens with
primitive elements such as numbers. However the total size of an array
or object might not be known exactly when the header of the element is
first generated. It is convenient to reserve space for the largest
possible header and then go back and fill in the correct payload size
at the end. This technique can result in array or object headers that
are larger than absolutely necessary.
### 3.2 Element Type
The least-significant four bits of the first byte of the header (the first
byte masked against 0x0f) determine element type. The following codes are
used:
<ol>
<li type="0"><p><b>NULL</b> &rarr;
The element is a JSON "null". The payload size for a true JSON NULL must
must be zero. Future versions of SQLite might extend the JSONB format
with elements that have a zero element type but a non-zero size. In that
way, legacy versions of SQLite will interpret the element as a NULL
for backwards compatibility while newer versions will interpret the
element in some other way.
<li value="1"><p><b>TRUE</b> &rarr;
The element is a JSON "true". The payload size must be zero for a actual
"true" value. Elements with type 1 and a non-zero payload size are
reserved for future expansion. Legacy implementations that see an element
type of 1 with a non-zero payload size should continue to interpret that
element as "true" for compatibility.
<li value="2"><p><b>FALSE</b> &rarr;
The element is a JSON "false". The payload size must be zero for a actual
"false" value. Elements with type 2 and a non-zero payload size are
reserved for future expansion. Legacy implementations that see an element
type of 2 with a non-zero payload size should continue to interpret that
element as "false" for compatibility.
<li value="3"><p><b>INT</b> &rarr;
The element is a JSON integer value in the canonical
RFC 8259 format, without extensions. The payload is the ASCII
text representation of that numeric value.
<li value="4"><p><b>INT5</b> &rarr;
The element is a JSON integer value that is not in the
canonical format. The payload is the ASCII
text representation of that numeric value. Because the payload is in a
non-standard format, it will need to be translated when the JSONB is
converted into RFC 8259 text JSON.
<li value="5"><p><b>FLOAT</b> &rarr;
The element is a JSON floating-point value in the canonical
RFC 8259 format, without extensions. The payload is the ASCII
text representation of that numeric value.
<li value="6"><p><b>FLOAT5</b> &rarr;
The element is a JSON floating-point value that is not in the
canonical format. The payload is the ASCII
text representation of that numeric value. Because the payload is in a
non-standard format, it will need to be translated when the JSONB is
converted into RFC 8259 text JSON.
<li value="7"><p><b>TEXT</b> &rarr;
The element is a JSON string value that does not contain
any escapes nor any characters that need to be escaped for either SQL or
JSON. The payload is the UTF8 text representation of the string value.
The payload does <i>not</i> include string delimiters.
<li value="8"><p><b>TEXTJ</b> &rarr;
The element is a JSON string value that contains
RFC 8259 character escapes (such as "<tt>\n</tt>" or "<tt>\u0020</tt>").
Those escapes will need to be translated into actual UTF8 if this element
is [json_extract|extracted] into SQL.
The payload is the UTF8 text representation of the escaped string value.
The payload does <i>not</i> include string delimiters.
<li value="9"><p><b>TEXT5</b> &rarr;
The element is a JSON string value that contains
character escapes, including some character escapes that part of JSON5
and which are not found in the canonical RFC 8259 spec.
Those escapes will need to be translated into standard JSON prior to
rendering the JSON as text, or into their actual UTF8 characters if this
element is [json_extract|extracted] into SQL.
The payload is the UTF8 text representation of the escaped string value.
The payload does <i>not</i> include string delimiters.
<li value="10"><p><b>TEXTRAW</b> &rarr;
The element is a JSON string value that contains
UTF8 characters that need to be escaped if this string is rendered into
standard JSON text.
The payload does <i>not</i> include string delimiters.
<li value="11"><p><b>ARRAY</b> &rarr;
The element is a JSON array. The payload contains
JSONB elements that comprise values contained within the array.
<li value="12"><p><b>OBJECT</b> &rarr;
The element is a JSON object. The payload contains
pairs of JSONB elements that comprise entries for the JSON object.
The first element in each pair must be a string (types 7 through 10).
The second element of each pair may be any types, including nested
arrays or objects.
<li value="13"><p><b>RESERVED-13</b> &rarr;
Reserved for future expansion. Legacy implements that encounter this
element type should raise an error.
<li value="14"><p><b>RESERVED-14</b> &rarr;
Reserved for future expansion. Legacy implements that encounter this
element type should raise an error.
<li value="15"><p><b>RESERVED-15</b> &rarr;
Reserved for future expansion. Legacy implements that encounter this
element type should raise an error.
</ol>
Element types outside the range of 0 to 12 are reserved for future
expansion. The current implement raises an error if see an element type
other than those listed above. However, future versions of SQLite might
use of the three remaining element types to implement indexing or similar
optimizations, to speed up lookup against large JSON arrays and/or objects.
### 3.3 Design Rationale For Element Types
A key goal of JSONB is that it should be quick to translate
to and from text JSON and/or be constructed from SQL values.
When converting from text into JSONB, we do not want the
converter subroutine to burn CPU cycles converting elements
values into some standard format which might never be used.
Format conversion is "lazy" - it is deferred until actually
needed. This has implications for the JSONB format design:
1. Numeric values are stored as text, not a numbers. The values are
a direct copy of the text JSON values from which they are derived.
2. There are multiple element types depending on the details of value
formats. For example, INT is used for pure RFC-8259 integer
literals and INT5 exists for JSON5 extensions such as hexadecimal
notation. FLOAT is used for pure RFC-8259 floating point literals
and FLOAT5 is used for JSON5 extensions. There are four different
representations of strings, depending on where the string came from
and how special characters within the string are escaped.
A second goal of JSONB is that it should be capable of serving as the
"parse tree" for JSON when a JSON value is being processed by the
various [JSON SQL functions] built into SQLite. Before JSONB was
developed, operations such [json_replace()] and [json_patch()]
and similar worked in three stages:
1. Translate the text JSON into a internal format that is
easier to scan and edit.
2. Perform the requested operation on the JSON.
3. Translate the internal format back into text.
JSONB seeks to serve as the internal format directly - bypassing
the first and third stages of that process. Since most of the CPU
cycles are spent on the first and third stages, that suggests that
JSONB processing will be much faster than text JSON processing.
So when processing JSONB, only the second stage of the three-stage
process is required. But when processing text JSON, it is still necessary
to do stages one and three. If JSONB is to be used as the internal
binary representation, this is yet another reason to store numeric
values as text. Storing numbers as text minimizes the amount of
conversion work needed for stages one and three. This is also why
there are four different representations of text in JSONB. Different
text representations are used for text coming from different sources
(RFC-8259 JSON, JSON5, or SQL string values) and conversions only
happen if and when they are actually needed.
### 3.4 Valid JSONB BLOBs
A valid JSONB BLOB consists of a single JSON element. The element must
exactly fill the BLOB. This one element is often a JSON object or array
and those usually contain additional elements as its payload, but the
element can be a primite value such a string, number, boolean, or null.
When the built-in JSON functions are attempting to determine if a BLOB
argument is a JSONB or just a random BLOB, they look at the header of
the outer element to see that it is well-formed and that the element
completely fills the BLOB. If these conditions are met, then the BLOB
is accepted as a JSONB value.
+14 -1
View File
@@ -24,9 +24,14 @@
# include <stdlib.h>
# include <limits.h>
# include <assert.h>
# include "console_io.h"
# include "sqlite3.h"
#endif
#ifndef HAVE_CONSOLE_IO_H
# include "console_io.h"
#endif
#if defined(_MSC_VER)
# pragma warning(disable : 4204)
#endif
#ifndef SQLITE_CIO_NO_TRANSLATE
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
@@ -125,6 +130,10 @@ static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
# endif
}
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
# define ENABLE_VIRTUAL_TERMINAL_PROCESSING (0x4)
# endif
# if CIO_WIN_WC_XLATE
/* Define console modes for use with the Windows Console API. */
# define SHELL_CONI_MODE \
@@ -675,4 +684,8 @@ SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
}
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
#if defined(_MSC_VER)
# pragma warning(default : 4204)
#endif
#undef SHELL_INVALID_FILE_PTR
+1 -1
View File
@@ -28,7 +28,7 @@
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
** translation for Windows is effected for the build.
*/
#define HAVE_CONSOLE_IO_H 1
#ifndef SQLITE_INTERNAL_LINKAGE
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
# include <stdio.h>
+11 -20
View File
@@ -4006,7 +4006,7 @@ static int fts3ShadowName(const char *zName){
** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual
** table.
*/
static int fts3Integrity(
static int fts3IntegrityMethod(
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 */
@@ -4014,30 +4014,21 @@ static int fts3Integrity(
char **pzErr /* Write error message here */
){
Fts3Table *p = (Fts3Table*)pVtab;
char *zSql;
int rc;
char *zErr = 0;
int bOk = 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 ){
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
assert( rc!=SQLITE_CORRUPT_VTAB || bOk==0 );
if( rc!=SQLITE_OK && rc!=SQLITE_CORRUPT_VTAB ){
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
" FTS%d table %s.%s: %s",
p->bFts4 ? 4 : 3, zSchema, zTabname, zErr);
p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
}else if( bOk==0 ){
*pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
p->bFts4 ? 4 : 3, zSchema, zTabname);
}
sqlite3_free(zErr);
sqlite3Fts3SegmentsClose(p);
return SQLITE_OK;
}
@@ -4068,7 +4059,7 @@ static const sqlite3_module fts3Module = {
/* xRelease */ fts3ReleaseMethod,
/* xRollbackTo */ fts3RollbackToMethod,
/* xShadowName */ fts3ShadowName,
/* xIntegrity */ fts3Integrity,
/* xIntegrity */ fts3IntegrityMethod,
};
/*
+2
View File
@@ -653,5 +653,7 @@ int sqlite3FtsUnicodeIsdiacritic(int);
int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*);
int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */
+3 -3
View File
@@ -5294,7 +5294,7 @@ static u64 fts3ChecksumIndex(
** If an error occurs (e.g. an OOM or IO error), return an SQLite error
** code. The final value of *pbOk is undefined in this case.
*/
static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
int rc = SQLITE_OK; /* Return code */
u64 cksum1 = 0; /* Checksum based on FTS index contents */
u64 cksum2 = 0; /* Checksum based on %_content contents */
@@ -5372,7 +5372,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
sqlite3_finalize(pStmt);
}
*pbOk = (cksum1==cksum2);
*pbOk = (rc==SQLITE_OK && cksum1==cksum2);
return rc;
}
@@ -5412,7 +5412,7 @@ static int fts3DoIntegrityCheck(
){
int rc;
int bOk = 0;
rc = fts3IntegrityCheck(p, &bOk);
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
return rc;
}
+3 -1
View File
@@ -223,10 +223,12 @@ proc main {data} {
Fts5ExtensionApi {
set struct [get_fts5_struct $data "^struct Fts5ExtensionApi" "^.;"]
set map [list]
set lKey [list]
foreach {k v} [get_struct_members $data] {
if {[string match x* $k]==0} continue
lappend map $k "<a href=#$k>$k</a>"
lappend lKey $k
}
foreach k [lsort -decr $lKey] { lappend map $k "<a href=#$k>$k</a>" }
output [string map $map $struct]
}
+59 -9
View File
@@ -88,8 +88,11 @@ struct Fts5PhraseIter {
** created with the "columnsize=0" option.
**
** xColumnText:
** This function attempts to retrieve the text of column iCol of the
** current document. If successful, (*pz) is set to point to a buffer
** If parameter iCol is less than zero, or greater than or equal to the
** number of columns in the table, SQLITE_RANGE is returned.
**
** Otherwise, this function attempts to retrieve the text of column iCol of
** the current document. If successful, (*pz) is set to point to a buffer
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
** if an error occurs, an SQLite error code is returned and the final values
@@ -99,8 +102,10 @@ struct Fts5PhraseIter {
** Returns the number of phrases in the current query expression.
**
** xPhraseSize:
** Returns the number of tokens in phrase iPhrase of the query. Phrases
** are numbered starting from zero.
** If parameter iCol is less than zero, or greater than or equal to the
** number of phrases in the current query, as returned by xPhraseCount,
** 0 is returned. Otherwise, this function returns the number of tokens in
** phrase iPhrase of the query. Phrases are numbered starting from zero.
**
** xInstCount:
** Set *pnInst to the total number of occurrences of all phrases within
@@ -116,12 +121,13 @@ struct Fts5PhraseIter {
** Query for the details of phrase match iIdx within the current row.
** Phrase matches are numbered starting from zero, so the iIdx argument
** should be greater than or equal to zero and smaller than the value
** output by xInstCount().
** output by xInstCount(). If iIdx is less than zero or greater than
** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
** first token of the phrase. Returns SQLITE_OK if successful, or an error
** code (i.e. SQLITE_NOMEM) if an error occurs.
** first token of the phrase. SQLITE_OK is returned if successful, or an
** error code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -147,6 +153,10 @@ struct Fts5PhraseIter {
** Invoking Api.xUserData() returns a copy of the pointer passed as
** the third argument to pUserData.
**
** If parameter iPhrase is less than zero, or greater than or equal to
** the number of phrases in the query, as returned by xPhraseCount(),
** this function returns SQLITE_RANGE.
**
** If the callback function returns any value other than SQLITE_OK, the
** query is abandoned and the xQueryPhrase function returns immediately.
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
@@ -261,9 +271,42 @@ struct Fts5PhraseIter {
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
**
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase iPhrase of the current
** query. Before returning, output parameter *ppToken is set to point
** to a buffer containing the requested token, and *pnToken to the
** size of this buffer in bytes.
**
** If iPhrase or iToken are less than zero, or if iPhrase is greater than
** or equal to the number of phrases in the query as reported by
** xPhraseCount(), or if iToken is equal to or greater than the number of
** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
are both zeroed.
**
** The output text is not a copy of the query text that specified the
** token. It is the output of the tokenizer module. For tokendata=1
** tables, this includes any embedded 0x00 and trailing data.
**
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase hit iIdx within the
** current row. If iIdx is less than zero or greater than or equal to the
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
** bytes. This API is not available if the specified token matches a
** prefix query term. In that case both output variables are always set
** to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 2 */
int iVersion; /* Currently always set to 3 */
void *(*xUserData)(Fts5Context*);
@@ -298,6 +341,13 @@ struct Fts5ExtensionApi {
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
/* Below this point are iVersion>=3 only */
int (*xQueryToken)(Fts5Context*,
int iPhrase, int iToken,
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
};
/*
+26 -7
View File
@@ -196,6 +196,7 @@ struct Fts5Config {
char *zContent; /* content table */
char *zContentRowid; /* "content_rowid=" option value */
int bColumnsize; /* "columnsize=" option value (dflt==1) */
int bTokendata; /* "tokendata=" option value (dflt==0) */
int eDetail; /* FTS5_DETAIL_XXX value */
char *zContentExprlist;
Fts5Tokenizer *pTok;
@@ -384,17 +385,19 @@ struct Fts5IndexIter {
/*
** Values used as part of the flags argument passed to IndexQuery().
*/
#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */
#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */
#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */
#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */
#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */
#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */
#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */
#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */
/* The following are used internally by the fts5_index.c module. They are
** defined here only to make it easier to avoid clashes with the flags
** above. */
#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010
#define FTS5INDEX_QUERY_NOOUTPUT 0x0020
#define FTS5INDEX_QUERY_SKIPHASH 0x0040
#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010
#define FTS5INDEX_QUERY_NOOUTPUT 0x0020
#define FTS5INDEX_QUERY_SKIPHASH 0x0040
#define FTS5INDEX_QUERY_NOTOKENDATA 0x0080
#define FTS5INDEX_QUERY_SCANONETERM 0x0100
/*
** Create/destroy an Fts5Index object.
@@ -463,6 +466,10 @@ void *sqlite3Fts5StructureRef(Fts5Index*);
void sqlite3Fts5StructureRelease(void*);
int sqlite3Fts5StructureTest(Fts5Index*, void*);
/*
** Used by xInstToken():
*/
int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
/*
** Insert or remove data to or from the index. Each time a document is
@@ -540,6 +547,13 @@ int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin);
int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid);
void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter*);
/* Used to populate hash tables for xInstToken in detail=none/column mode. */
int sqlite3Fts5IndexIterWriteTokendata(
Fts5IndexIter*, const char*, int, i64 iRowid, int iCol, int iOff
);
/*
** End of interface to code in fts5_index.c.
**************************************************************************/
@@ -645,6 +659,7 @@ void sqlite3Fts5HashScanNext(Fts5Hash*);
int sqlite3Fts5HashScanEof(Fts5Hash*);
void sqlite3Fts5HashScanEntry(Fts5Hash *,
const char **pzTerm, /* OUT: term (nul-terminated) */
int *pnTerm, /* OUT: Size of term in bytes */
const u8 **ppDoclist, /* OUT: pointer to doclist */
int *pnDoclist /* OUT: size of doclist in bytes */
);
@@ -771,6 +786,10 @@ int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**);
int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
int sqlite3Fts5ExprQueryToken(Fts5Expr*, int, int, const char**, int*);
int sqlite3Fts5ExprInstToken(Fts5Expr*, i64, int, int, int, int, const char**, int*);
void sqlite3Fts5ExprClearTokens(Fts5Expr*);
/*******************************************
** The fts5_expr.c API above this point is used by the other hand-written
** C code in this module. The interfaces below this point are called by
+4 -2
View File
@@ -252,8 +252,10 @@ static void fts5HighlightFunction(
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
ctx.iRangeEnd = -1;
rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn);
if( ctx.zIn ){
if( rc==SQLITE_RANGE ){
sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
rc = SQLITE_OK;
}else if( ctx.zIn ){
if( rc==SQLITE_OK ){
rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
}
+3
View File
@@ -68,6 +68,7 @@ void sqlite3Fts5BufferAppendBlob(
){
if( nData ){
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
assert( pBuf->p!=0 );
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
@@ -169,6 +170,7 @@ int sqlite3Fts5PoslistNext64(
i64 *piOff /* IN/OUT: Current offset */
){
int i = *pi;
assert( a!=0 || i==0 );
if( i>=n ){
/* EOF */
*piOff = -1;
@@ -176,6 +178,7 @@ int sqlite3Fts5PoslistNext64(
}else{
i64 iOff = *piOff;
u32 iVal;
assert( a!=0 );
fts5FastGetVarint32(a, i, iVal);
if( iVal<=1 ){
if( iVal==0 ){
+10
View File
@@ -398,6 +398,16 @@ static int fts5ConfigParseSpecial(
return rc;
}
if( sqlite3_strnicmp("tokendata", zCmd, nCmd)==0 ){
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
*pzErr = sqlite3_mprintf("malformed tokendata=... directive");
rc = SQLITE_ERROR;
}else{
pConfig->bTokendata = (zArg[0]=='1');
}
return rc;
}
*pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
return SQLITE_ERROR;
}
+164 -44
View File
@@ -100,7 +100,9 @@ struct Fts5ExprNode {
struct Fts5ExprTerm {
u8 bPrefix; /* True for a prefix term */
u8 bFirst; /* True if token must be first in column */
char *zTerm; /* nul-terminated term */
char *pTerm; /* Term data */
int nQueryTerm; /* Effective size of term in bytes */
int nFullTerm; /* Size of term in bytes incl. tokendata */
Fts5IndexIter *pIter; /* Iterator for this term */
Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */
};
@@ -967,7 +969,7 @@ static int fts5ExprNearInitAll(
p->pIter = 0;
}
rc = sqlite3Fts5IndexQuery(
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
pExpr->pIndex, p->pTerm, p->nQueryTerm,
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
pNear->pColset,
@@ -1604,7 +1606,7 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
Fts5ExprTerm *pSyn;
Fts5ExprTerm *pNext;
Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
sqlite3_free(pTerm->zTerm);
sqlite3_free(pTerm->pTerm);
sqlite3Fts5IterClose(pTerm->pIter);
for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){
pNext = pSyn->pSynonym;
@@ -1702,6 +1704,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
typedef struct TokenCtx TokenCtx;
struct TokenCtx {
Fts5ExprPhrase *pPhrase;
Fts5Config *pConfig;
int rc;
};
@@ -1735,8 +1738,12 @@ static int fts5ParseTokenize(
rc = SQLITE_NOMEM;
}else{
memset(pSyn, 0, (size_t)nByte);
pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
memcpy(pSyn->zTerm, pToken, nToken);
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
if( pCtx->pConfig->bTokendata ){
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
}
memcpy(pSyn->pTerm, pToken, nToken);
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
}
@@ -1761,7 +1768,11 @@ static int fts5ParseTokenize(
if( rc==SQLITE_OK ){
pTerm = &pPhrase->aTerm[pPhrase->nTerm++];
memset(pTerm, 0, sizeof(Fts5ExprTerm));
pTerm->zTerm = sqlite3Fts5Strndup(&rc, pToken, nToken);
pTerm->pTerm = sqlite3Fts5Strndup(&rc, pToken, nToken);
pTerm->nFullTerm = pTerm->nQueryTerm = nToken;
if( pCtx->pConfig->bTokendata && rc==SQLITE_OK ){
pTerm->nQueryTerm = (int)strlen(pTerm->pTerm);
}
}
}
@@ -1828,6 +1839,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
memset(&sCtx, 0, sizeof(TokenCtx));
sCtx.pPhrase = pAppend;
sCtx.pConfig = pConfig;
rc = fts5ParseStringFromToken(pToken, &z);
if( rc==SQLITE_OK ){
@@ -1875,12 +1887,15 @@ int sqlite3Fts5ExprClonePhrase(
Fts5Expr **ppNew
){
int rc = SQLITE_OK; /* Return code */
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */
pOrig = pExpr->apExprPhrase[iPhrase];
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
rc = SQLITE_RANGE;
}else{
pOrig = pExpr->apExprPhrase[iPhrase];
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
}
if( rc==SQLITE_OK ){
pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
sizeof(Fts5ExprPhrase*));
@@ -1893,7 +1908,7 @@ int sqlite3Fts5ExprClonePhrase(
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
}
if( rc==SQLITE_OK ){
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
sqlite3_int64 nByte;
@@ -1907,26 +1922,27 @@ int sqlite3Fts5ExprClonePhrase(
}
}
if( pOrig->nTerm ){
int i; /* Used to iterate through phrase terms */
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
Fts5ExprTerm *p;
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
const char *zTerm = p->zTerm;
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
0, 0);
tflags = FTS5_TOKEN_COLOCATED;
}
if( rc==SQLITE_OK ){
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
if( rc==SQLITE_OK ){
if( pOrig->nTerm ){
int i; /* Used to iterate through phrase terms */
sCtx.pConfig = pExpr->pConfig;
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
Fts5ExprTerm *p;
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
rc = fts5ParseTokenize((void*)&sCtx,tflags,p->pTerm,p->nFullTerm,0,0);
tflags = FTS5_TOKEN_COLOCATED;
}
if( rc==SQLITE_OK ){
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
}
}
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
}
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
}
if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
@@ -2296,11 +2312,13 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
if( parseGrowPhraseArray(pParse) ){
fts5ExprPhraseFree(pPhrase);
}else{
Fts5ExprTerm *p = &pNear->apPhrase[0]->aTerm[ii];
Fts5ExprTerm *pTo = &pPhrase->aTerm[0];
pParse->apPhrase[pParse->nPhrase++] = pPhrase;
pPhrase->nTerm = 1;
pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
&pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
);
pTo->pTerm = sqlite3Fts5Strndup(&pParse->rc, p->pTerm, p->nFullTerm);
pTo->nQueryTerm = p->nQueryTerm;
pTo->nFullTerm = p->nFullTerm;
pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
);
@@ -2485,16 +2503,17 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
/* Determine the maximum amount of space required. */
for(p=pTerm; p; p=p->pSynonym){
nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
nByte += pTerm->nQueryTerm * 2 + 3 + 2;
}
zQuoted = sqlite3_malloc64(nByte);
if( zQuoted ){
int i = 0;
for(p=pTerm; p; p=p->pSynonym){
char *zIn = p->zTerm;
char *zIn = p->pTerm;
char *zEnd = &zIn[p->nQueryTerm];
zQuoted[i++] = '"';
while( *zIn ){
while( zIn<zEnd ){
if( *zIn=='"' ) zQuoted[i++] = '"';
zQuoted[i++] = *zIn++;
}
@@ -2572,8 +2591,10 @@ static char *fts5ExprPrintTcl(
zRet = fts5PrintfAppend(zRet, " {");
for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
char *zTerm = pPhrase->aTerm[iTerm].zTerm;
zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
Fts5ExprTerm *p = &pPhrase->aTerm[iTerm];
zRet = fts5PrintfAppend(zRet, "%s%.*s", iTerm==0?"":" ",
p->nQueryTerm, p->pTerm
);
if( pPhrase->aTerm[iTerm].bPrefix ){
zRet = fts5PrintfAppend(zRet, "*");
}
@@ -2974,6 +2995,17 @@ static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
return 0;
}
/*
** pToken is a buffer nToken bytes in size that may or may not contain
** an embedded 0x00 byte. If it does, return the number of bytes in
** the buffer before the 0x00. If it does not, return nToken.
*/
static int fts5QueryTerm(const char *pToken, int nToken){
int ii;
for(ii=0; ii<nToken && pToken[ii]; ii++){}
return ii;
}
static int fts5ExprPopulatePoslistsCb(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
@@ -2985,22 +3017,33 @@ static int fts5ExprPopulatePoslistsCb(
Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx;
Fts5Expr *pExpr = p->pExpr;
int i;
int nQuery = nToken;
i64 iRowid = pExpr->pRoot->iRowid;
UNUSED_PARAM2(iUnused1, iUnused2);
if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
if( nQuery>FTS5_MAX_TOKEN_SIZE ) nQuery = FTS5_MAX_TOKEN_SIZE;
if( pExpr->pConfig->bTokendata ){
nQuery = fts5QueryTerm(pToken, nQuery);
}
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++;
for(i=0; i<pExpr->nPhrase; i++){
Fts5ExprTerm *pTerm;
Fts5ExprTerm *pT;
if( p->aPopulator[i].bOk==0 ) continue;
for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
int nTerm = (int)strlen(pTerm->zTerm);
if( (nTerm==nToken || (nTerm<nToken && pTerm->bPrefix))
&& memcmp(pTerm->zTerm, pToken, nTerm)==0
for(pT=&pExpr->apExprPhrase[i]->aTerm[0]; pT; pT=pT->pSynonym){
if( (pT->nQueryTerm==nQuery || (pT->nQueryTerm<nQuery && pT->bPrefix))
&& memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0
){
int rc = sqlite3Fts5PoslistWriterAppend(
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
);
if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
int iCol = p->iOff>>32;
int iTokOff = p->iOff & 0x7FFFFFFF;
rc = sqlite3Fts5IndexIterWriteTokendata(
pT->pIter, pToken, nToken, iRowid, iCol, iTokOff
);
}
if( rc ) return rc;
break;
}
@@ -3135,3 +3178,80 @@ int sqlite3Fts5ExprPhraseCollist(
return rc;
}
/*
** Does the work of the fts5_api.xQueryToken() API method.
*/
int sqlite3Fts5ExprQueryToken(
Fts5Expr *pExpr,
int iPhrase,
int iToken,
const char **ppOut,
int *pnOut
){
Fts5ExprPhrase *pPhrase = 0;
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
return SQLITE_RANGE;
}
pPhrase = pExpr->apExprPhrase[iPhrase];
if( iToken<0 || iToken>=pPhrase->nTerm ){
return SQLITE_RANGE;
}
*ppOut = pPhrase->aTerm[iToken].pTerm;
*pnOut = pPhrase->aTerm[iToken].nFullTerm;
return SQLITE_OK;
}
/*
** Does the work of the fts5_api.xInstToken() API method.
*/
int sqlite3Fts5ExprInstToken(
Fts5Expr *pExpr,
i64 iRowid,
int iPhrase,
int iCol,
int iOff,
int iToken,
const char **ppOut,
int *pnOut
){
Fts5ExprPhrase *pPhrase = 0;
Fts5ExprTerm *pTerm = 0;
int rc = SQLITE_OK;
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
return SQLITE_RANGE;
}
pPhrase = pExpr->apExprPhrase[iPhrase];
if( iToken<0 || iToken>=pPhrase->nTerm ){
return SQLITE_RANGE;
}
pTerm = &pPhrase->aTerm[iToken];
if( pTerm->bPrefix==0 ){
if( pExpr->pConfig->bTokendata ){
rc = sqlite3Fts5IterToken(
pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
);
}else{
*ppOut = pTerm->pTerm;
*pnOut = pTerm->nFullTerm;
}
}
return rc;
}
/*
** Clear the token mappings for all Fts5IndexIter objects mannaged by
** the expression passed as the only argument.
*/
void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
int ii;
for(ii=0; ii<pExpr->nPhrase; ii++){
Fts5ExprTerm *pT;
for(pT=&pExpr->apExprPhrase[ii]->aTerm[0]; pT; pT=pT->pSynonym){
sqlite3Fts5IndexIterClearTokendata(pT->pIter);
}
}
}
+30 -19
View File
@@ -36,10 +36,15 @@ struct Fts5Hash {
/*
** Each entry in the hash table is represented by an object of the
** following type. Each object, its key (a nul-terminated string) and
** its current data are stored in a single memory allocation. The
** key immediately follows the object in memory. The position list
** data immediately follows the key data in memory.
** following type. Each object, its key, and its current data are stored
** in a single memory allocation. The key immediately follows the object
** in memory. The position list data immediately follows the key data
** in memory.
**
** The key is Fts5HashEntry.nKey bytes in size. It consists of a single
** byte identifying the index (either the main term index or a prefix-index),
** followed by the term data. For example: "0token". There is no
** nul-terminator - in this case nKey=6.
**
** The data that follows the key is in a similar, but not identical format
** to the doclist data stored in the database. It is:
@@ -174,8 +179,7 @@ static int fts5HashResize(Fts5Hash *pHash){
unsigned int iHash;
Fts5HashEntry *p = apOld[i];
apOld[i] = p->pHashNext;
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
(int)strlen(fts5EntryKey(p)));
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), p->nKey);
p->pHashNext = apNew[iHash];
apNew[iHash] = p;
}
@@ -259,7 +263,7 @@ int sqlite3Fts5HashWrite(
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
char *zKey = fts5EntryKey(p);
if( zKey[0]==bByte
&& p->nKey==nToken
&& p->nKey==nToken+1
&& memcmp(&zKey[1], pToken, nToken)==0
){
break;
@@ -289,9 +293,9 @@ int sqlite3Fts5HashWrite(
zKey[0] = bByte;
memcpy(&zKey[1], pToken, nToken);
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
p->nKey = nToken;
p->nKey = nToken+1;
zKey[nToken+1] = '\0';
p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
p->nData = nToken+1 + sizeof(Fts5HashEntry);
p->pHashNext = pHash->aSlot[iHash];
pHash->aSlot[iHash] = p;
pHash->nEntry++;
@@ -408,12 +412,17 @@ static Fts5HashEntry *fts5HashEntryMerge(
*ppOut = p1;
p1 = 0;
}else{
int i = 0;
char *zKey1 = fts5EntryKey(p1);
char *zKey2 = fts5EntryKey(p2);
while( zKey1[i]==zKey2[i] ) i++;
int nMin = MIN(p1->nKey, p2->nKey);
if( ((u8)zKey1[i])>((u8)zKey2[i]) ){
int cmp = memcmp(zKey1, zKey2, nMin);
if( cmp==0 ){
cmp = p1->nKey - p2->nKey;
}
assert( cmp!=0 );
if( cmp>0 ){
/* p2 is smaller */
*ppOut = p2;
ppOut = &p2->pScanNext;
@@ -455,7 +464,7 @@ static int fts5HashEntrySort(
Fts5HashEntry *pIter;
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
if( pTerm==0
|| (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm))
|| (pIter->nKey>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm))
){
Fts5HashEntry *pEntry = pIter;
pEntry->pScanNext = 0;
@@ -494,12 +503,11 @@ int sqlite3Fts5HashQuery(
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
assert( p->nKey+1==(int)strlen(zKey) );
if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break;
if( nTerm==p->nKey && memcmp(zKey, pTerm, nTerm)==0 ) break;
}
if( p ){
int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1;
int nHashPre = sizeof(Fts5HashEntry) + nTerm;
int nList = p->nData - nHashPre;
u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10));
if( pRet ){
@@ -560,19 +568,22 @@ int sqlite3Fts5HashScanEof(Fts5Hash *p){
void sqlite3Fts5HashScanEntry(
Fts5Hash *pHash,
const char **pzTerm, /* OUT: term (nul-terminated) */
int *pnTerm, /* OUT: Size of term in bytes */
const u8 **ppDoclist, /* OUT: pointer to doclist */
int *pnDoclist /* OUT: size of doclist in bytes */
){
Fts5HashEntry *p;
if( (p = pHash->pScan) ){
char *zKey = fts5EntryKey(p);
int nTerm = (int)strlen(zKey);
int nTerm = p->nKey;
fts5HashAddPoslistSize(pHash, p, 0);
*pzTerm = zKey;
*ppDoclist = (const u8*)&zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
*pnTerm = nTerm;
*ppDoclist = (const u8*)&zKey[nTerm];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm);
}else{
*pzTerm = 0;
*pnTerm = 0;
*ppDoclist = 0;
*pnDoclist = 0;
}
+787 -75
View File
File diff suppressed because it is too large Load Diff
+97 -54
View File
@@ -118,7 +118,7 @@ struct Fts5FullTable {
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
@@ -656,12 +656,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
}
idxStr[iIdxStr] = '\0';
/* Set idxFlags flags for the ORDER BY clause */
/* Set idxFlags flags for the ORDER BY clause
**
** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
*/
if( pInfo->nOrderBy==1 ){
int iSort = pInfo->aOrderBy[0].iColumn;
if( iSort==(pConfig->nCol+1) && bSeenMatch ){
idxFlags |= FTS5_BI_ORDER_RANK;
}else if( iSort==-1 ){
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
idxFlags |= FTS5_BI_ORDER_ROWID;
}
if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
@@ -913,6 +916,16 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
);
assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
/* If this cursor uses FTS5_PLAN_MATCH and this is a tokendata=1 table,
** clear any token mappings accumulated at the fts5_index.c level. In
** other cases, specifically FTS5_PLAN_SOURCE and FTS5_PLAN_SORTED_MATCH,
** we need to retain the mappings for the entire query. */
if( pCsr->ePlan==FTS5_PLAN_MATCH
&& ((Fts5Table*)pCursor->pVtab)->pConfig->bTokendata
){
sqlite3Fts5ExprClearTokens(pCsr->pExpr);
}
if( pCsr->ePlan<3 ){
int bSkip = 0;
if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
@@ -1573,7 +1586,10 @@ static int fts5SpecialInsert(
}else if( 0==sqlite3_stricmp("flush", zCmd) ){
rc = sqlite3Fts5FlushToDisk(&pTab->p);
}else{
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
rc = sqlite3Fts5FlushToDisk(&pTab->p);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError);
}
@@ -1898,7 +1914,10 @@ static int fts5ApiColumnText(
){
int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
if( iCol<0 || iCol>=pTab->pConfig->nCol ){
rc = SQLITE_RANGE;
}else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
|| pCsr->ePlan==FTS5_PLAN_SPECIAL
){
*pz = 0;
@@ -1923,8 +1942,9 @@ static int fts5CsrPoslist(
int rc = SQLITE_OK;
int bLive = (pCsr->pSorter==0);
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
rc = SQLITE_RANGE;
}else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
Fts5PoslistPopulator *aPopulator;
int i;
@@ -1948,15 +1968,21 @@ static int fts5CsrPoslist(
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
}
if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
Fts5Sorter *pSorter = pCsr->pSorter;
int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
*pn = pSorter->aIdx[iPhrase] - i1;
*pa = &pSorter->aPoslist[i1];
if( rc==SQLITE_OK ){
if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
Fts5Sorter *pSorter = pCsr->pSorter;
int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
*pn = pSorter->aIdx[iPhrase] - i1;
*pa = &pSorter->aPoslist[i1];
}else{
*pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
}
}else{
*pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
*pa = 0;
*pn = 0;
}
return rc;
}
@@ -2063,12 +2089,6 @@ static int fts5ApiInst(
){
if( iIdx<0 || iIdx>=pCsr->nInstCount ){
rc = SQLITE_RANGE;
#if 0
}else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
*piPhrase = pCsr->aInst[iIdx*3];
*piCol = pCsr->aInst[iIdx*3 + 2];
*piOff = -1;
#endif
}else{
*piPhrase = pCsr->aInst[iIdx*3];
*piCol = pCsr->aInst[iIdx*3 + 1];
@@ -2323,13 +2343,56 @@ static int fts5ApiPhraseFirstColumn(
return rc;
}
/*
** xQueryToken() API implemenetation.
*/
static int fts5ApiQueryToken(
Fts5Context* pCtx,
int iPhrase,
int iToken,
const char **ppOut,
int *pnOut
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
return sqlite3Fts5ExprQueryToken(pCsr->pExpr, iPhrase, iToken, ppOut, pnOut);
}
/*
** xInstToken() API implemenetation.
*/
static int fts5ApiInstToken(
Fts5Context *pCtx,
int iIdx,
int iToken,
const char **ppOut, int *pnOut
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
|| SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
){
if( iIdx<0 || iIdx>=pCsr->nInstCount ){
rc = SQLITE_RANGE;
}else{
int iPhrase = pCsr->aInst[iIdx*3];
int iCol = pCsr->aInst[iIdx*3 + 1];
int iOff = pCsr->aInst[iIdx*3 + 2];
i64 iRowid = fts5CursorRowid(pCsr);
rc = sqlite3Fts5ExprInstToken(
pCsr->pExpr, iRowid, iPhrase, iCol, iOff, iToken, ppOut, pnOut
);
}
}
return rc;
}
static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
);
static const Fts5ExtensionApi sFts5Api = {
2, /* iVersion */
3, /* iVersion */
fts5ApiUserData,
fts5ApiColumnCount,
fts5ApiRowCount,
@@ -2349,6 +2412,8 @@ static const Fts5ExtensionApi sFts5Api = {
fts5ApiPhraseNext,
fts5ApiPhraseFirstColumn,
fts5ApiPhraseNextColumn,
fts5ApiQueryToken,
fts5ApiInstToken
};
/*
@@ -2615,9 +2680,7 @@ static int fts5RenameMethod(
){
int rc;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
pTab->bInSavepoint = 1;
rc = sqlite3Fts5StorageRename(pTab->pStorage, zName);
pTab->bInSavepoint = 0;
return rc;
}
@@ -2634,26 +2697,12 @@ int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
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;
}
rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
if( rc==SQLITE_OK ){
pTab->iSavepoint = iSavepoint+1;
}
return rc;
}
@@ -2685,8 +2734,8 @@ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
int rc = SQLITE_OK;
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
fts5TripCursors(pTab);
pTab->p.pConfig->pgsz = 0;
if( (iSavepoint+1)<=pTab->iSavepoint ){
pTab->p.pConfig->pgsz = 0;
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
}
return rc;
@@ -2914,7 +2963,7 @@ static int fts5ShadowName(const char *zName){
** if anything is found amiss. Return a NULL pointer if everything is
** OK.
*/
static int fts5Integrity(
static int fts5IntegrityMethod(
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 */
@@ -2922,27 +2971,21 @@ static int fts5Integrity(
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);
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
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);
zSchema, zTabname, sqlite3_errstr(rc));
}
sqlite3_free(zErr);
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
return SQLITE_OK;
}
@@ -2972,7 +3015,7 @@ static int fts5Init(sqlite3 *db){
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
/* xShadowName */ fts5ShadowName,
/* xIntegrity */ fts5Integrity
/* xIntegrity */ fts5IntegrityMethod
};
int rc;
+1 -1
View File
@@ -673,7 +673,7 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
}
if( rc==SQLITE_OK ){
rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, pConfig->pzErrmsg);
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
+207 -1
View File
@@ -244,6 +244,9 @@ static int SQLITE_TCLAPI xF5tApi(
{ "xGetAuxdataInt", 1, "CLEAR" }, /* 15 */
{ "xPhraseForeach", 4, "IPHRASE COLVAR OFFVAR SCRIPT" }, /* 16 */
{ "xPhraseColumnForeach", 3, "IPHRASE COLVAR SCRIPT" }, /* 17 */
{ "xQueryToken", 2, "IPHRASE ITERM" }, /* 18 */
{ "xInstToken", 2, "IDX ITERM" }, /* 19 */
{ 0, 0, 0}
};
@@ -500,6 +503,38 @@ static int SQLITE_TCLAPI xF5tApi(
break;
}
CASE(18, "xQueryToken") {
const char *pTerm = 0;
int nTerm = 0;
int iPhrase = 0;
int iTerm = 0;
if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, objv[3], &iTerm) ) return TCL_ERROR;
rc = p->pApi->xQueryToken(p->pFts, iPhrase, iTerm, &pTerm, &nTerm);
if( rc==SQLITE_OK ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(pTerm, nTerm));
}
break;
}
CASE(19, "xInstToken") {
const char *pTerm = 0;
int nTerm = 0;
int iIdx = 0;
int iTerm = 0;
if( Tcl_GetIntFromObj(interp, objv[2], &iIdx) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, objv[3], &iTerm) ) return TCL_ERROR;
rc = p->pApi->xInstToken(p->pFts, iIdx, iTerm, &pTerm, &nTerm);
if( rc==SQLITE_OK ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(pTerm, nTerm));
}
break;
}
default:
assert( 0 );
break;
@@ -1117,6 +1152,176 @@ static int SQLITE_TCLAPI f5tRegisterTok(
return TCL_OK;
}
typedef struct OriginTextCtx OriginTextCtx;
struct OriginTextCtx {
sqlite3 *db;
fts5_api *pApi;
};
typedef struct OriginTextTokenizer OriginTextTokenizer;
struct OriginTextTokenizer {
Fts5Tokenizer *pTok; /* Underlying tokenizer object */
fts5_tokenizer tokapi; /* API implementation for pTok */
};
/*
** Delete the OriginTextCtx object indicated by the only argument.
*/
static void f5tOrigintextTokenizerDelete(void *pCtx){
OriginTextCtx *p = (OriginTextCtx*)pCtx;
ckfree((char*)p);
}
static int f5tOrigintextCreate(
void *pCtx,
const char **azArg,
int nArg,
Fts5Tokenizer **ppOut
){
OriginTextCtx *p = (OriginTextCtx*)pCtx;
OriginTextTokenizer *pTok = 0;
void *pTokCtx = 0;
int rc = SQLITE_OK;
pTok = (OriginTextTokenizer*)sqlite3_malloc(sizeof(OriginTextTokenizer));
if( pTok==0 ){
rc = SQLITE_NOMEM;
}else if( nArg<1 ){
rc = SQLITE_ERROR;
}else{
/* Locate the underlying tokenizer */
rc = p->pApi->xFindTokenizer(p->pApi, azArg[0], &pTokCtx, &pTok->tokapi);
}
/* Create the new tokenizer instance */
if( rc==SQLITE_OK ){
rc = pTok->tokapi.xCreate(pTokCtx, &azArg[1], nArg-1, &pTok->pTok);
}
if( rc!=SQLITE_OK ){
sqlite3_free(pTok);
pTok = 0;
}
*ppOut = (Fts5Tokenizer*)pTok;
return rc;
}
static void f5tOrigintextDelete(Fts5Tokenizer *pTokenizer){
OriginTextTokenizer *p = (OriginTextTokenizer*)pTokenizer;
if( p->pTok ){
p->tokapi.xDelete(p->pTok);
}
sqlite3_free(p);
}
typedef struct OriginTextCb OriginTextCb;
struct OriginTextCb {
void *pCtx;
const char *pText;
int nText;
int (*xToken)(void *, int, const char *, int, int, int);
char *aBuf; /* Buffer to use */
int nBuf; /* Allocated size of aBuf[] */
};
static int xOriginToken(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Pointer to buffer containing token */
int nToken, /* Size of token in bytes */
int iStart, /* Byte offset of token within input text */
int iEnd /* Byte offset of end of token within input */
){
OriginTextCb *p = (OriginTextCb*)pCtx;
int ret = 0;
if( nToken==(iEnd-iStart) && 0==memcmp(pToken, &p->pText[iStart], nToken) ){
/* Token exactly matches document text. Pass it through as is. */
ret = p->xToken(p->pCtx, tflags, pToken, nToken, iStart, iEnd);
}else{
int nReq = nToken + 1 + (iEnd-iStart);
if( nReq>p->nBuf ){
sqlite3_free(p->aBuf);
p->aBuf = sqlite3_malloc(nReq*2);
if( p->aBuf==0 ) return SQLITE_NOMEM;
p->nBuf = nReq*2;
}
memcpy(p->aBuf, pToken, nToken);
p->aBuf[nToken] = '\0';
memcpy(&p->aBuf[nToken+1], &p->pText[iStart], iEnd-iStart);
ret = p->xToken(p->pCtx, tflags, p->aBuf, nReq, iStart, iEnd);
}
return ret;
}
static int f5tOrigintextTokenize(
Fts5Tokenizer *pTokenizer,
void *pCtx,
int flags, /* Mask of FTS5_TOKENIZE_* flags */
const char *pText, int nText,
int (*xToken)(void *, int, const char *, int, int, int)
){
OriginTextTokenizer *p = (OriginTextTokenizer*)pTokenizer;
OriginTextCb cb;
int ret;
memset(&cb, 0, sizeof(cb));
cb.pCtx = pCtx;
cb.pText = pText;
cb.nText = nText;
cb.xToken = xToken;
ret = p->tokapi.xTokenize(p->pTok,(void*)&cb,flags,pText,nText,xOriginToken);
sqlite3_free(cb.aBuf);
return ret;
}
/*
** sqlite3_fts5_register_origintext DB
**
** Description...
*/
static int SQLITE_TCLAPI f5tRegisterOriginText(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db = 0;
fts5_api *pApi = 0;
int rc;
fts5_tokenizer tok = {0, 0, 0};
OriginTextCtx *pCtx = 0;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
if( f5tDbAndApi(interp, objv[1], &db, &pApi) ) return TCL_ERROR;
pCtx = (OriginTextCtx*)ckalloc(sizeof(OriginTextCtx));
pCtx->db = db;
pCtx->pApi = pApi;
tok.xCreate = f5tOrigintextCreate;
tok.xDelete = f5tOrigintextDelete;
tok.xTokenize = f5tOrigintextTokenize;
rc = pApi->xCreateTokenizer(
pApi, "origintext", (void*)pCtx, &tok, f5tOrigintextTokenizerDelete
);
Tcl_ResetResult(interp);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Entry point.
*/
@@ -1133,7 +1338,8 @@ int Fts5tcl_Init(Tcl_Interp *interp){
{ "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 },
{ "sqlite3_fts5_token_hash", f5tTokenHash, 0 },
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 }
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 }
};
int i;
F5tTokenizerContext *pContext;
+1 -1
View File
@@ -629,7 +629,7 @@ static int fts5VocabFilterMethod(
if( pEq ){
zTerm = (const char *)sqlite3_value_text(pEq);
nTerm = sqlite3_value_bytes(pEq);
f = 0;
f = FTS5INDEX_QUERY_NOTOKENDATA;
}else{
if( pGe ){
zTerm = (const char *)sqlite3_value_text(pGe);
+34
View File
@@ -61,6 +61,12 @@ proc fts5_test_collist {cmd} {
set res
}
proc fts5_collist {cmd iPhrase} {
set res [list]
$cmd xPhraseColumnForeach $iPhrase c { lappend res $c }
set res
}
proc fts5_test_columnsize {cmd} {
set res [list]
for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
@@ -69,6 +75,10 @@ proc fts5_test_columnsize {cmd} {
set res
}
proc fts5_columntext {cmd iCol} {
$cmd xColumnText $iCol
}
proc fts5_test_columntext {cmd} {
set res [list]
for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
@@ -125,6 +135,13 @@ proc fts5_test_queryphrase {cmd} {
set res
}
proc fts5_queryphrase {cmd iPhrase} {
set cnt [list]
for {set j 0} {$j < [$cmd xColumnCount]} {incr j} { lappend cnt 0 }
$cmd xQueryPhrase $iPhrase [list test_queryphrase_cb cnt]
set cnt
}
proc fts5_test_phrasecount {cmd} {
$cmd xPhraseCount
}
@@ -154,6 +171,9 @@ proc fts5_aux_test_functions {db} {
fts5_test_queryphrase
fts5_test_phrasecount
fts5_columntext
fts5_queryphrase
fts5_collist
} {
sqlite3_fts5_create_function $db $f $f
}
@@ -438,6 +458,20 @@ proc detail_is_none {} { detail_check ; expr {$::detail == "none"} }
proc detail_is_col {} { detail_check ; expr {$::detail == "col" } }
proc detail_is_full {} { detail_check ; expr {$::detail == "full"} }
proc foreach_tokenizer_mode {prefix script} {
set saved $::testprefix
foreach {d mapping} {
"" {}
"-origintext" {, tokenize="origintext unicode61", tokendata=1}
} {
set s [string map [list %TOKENIZER% $mapping] $script]
set ::testprefix "$prefix$d"
reset_db
sqlite3_fts5_register_origintext db
uplevel $s
}
set ::testprefix $saved
}
#-------------------------------------------------------------------------
# Convert a poslist of the type returned by fts5_test_poslist() to a
+44 -24
View File
@@ -22,6 +22,7 @@ ifcapable !fts5 {
}
foreach_detail_mode $::testprefix {
foreach_tokenizer_mode $::testprefix {
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
@@ -44,7 +45,7 @@ do_execsql_test 1.1 {
#
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL% %TOKENIZER%);
}
do_execsql_test 2.1 {
INSERT INTO t1 VALUES('a b c', 'd e f');
@@ -73,8 +74,9 @@ do_execsql_test 2.4 {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL% %TOKENIZER%);
}
foreach {i x y} {
1 {g f d b f} {h h e i a}
@@ -97,8 +99,9 @@ foreach {i x y} {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
}
foreach {i x y} {
@@ -121,8 +124,9 @@ foreach {i x y} {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
}
foreach {i x y} {
@@ -145,8 +149,9 @@ foreach {i x y} {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
}
@@ -181,6 +186,7 @@ do_execsql_test 6.6 {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
expr srand(0)
do_execsql_test 7.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x,y,z);
@@ -222,6 +228,7 @@ for {set i 1} {$i <= 10} {incr i} {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 8.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x, prefix="1,2,3");
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
@@ -236,6 +243,7 @@ do_execsql_test 8.1 {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
expr srand(0)
@@ -280,8 +288,9 @@ for {set i 1} {$i <= 10} {incr i} {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 10.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL% %TOKENIZER%);
}
set d10 {
1 {g f d b f} {h h e i a}
@@ -314,19 +323,19 @@ do_execsql_test 10.4.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
#-------------------------------------------------------------------------
#
do_catchsql_test 11.1 {
CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rank, detail=%DETAIL%);
CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rank, detail=%DETAIL% %TOKENIZER%);
} {1 {reserved fts5 column name: rank}}
do_catchsql_test 11.2 {
CREATE VIRTUAL TABLE rank USING fts5(a, b, c, detail=%DETAIL%);
CREATE VIRTUAL TABLE rank USING fts5(a, b, c, detail=%DETAIL% %TOKENIZER%);
} {1 {reserved fts5 table name: rank}}
do_catchsql_test 11.3 {
CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rowid, detail=%DETAIL%);
CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rowid, detail=%DETAIL% %TOKENIZER%);
} {1 {reserved fts5 column name: rowid}}
#-------------------------------------------------------------------------
#
do_execsql_test 12.1 {
CREATE VIRTUAL TABLE t2 USING fts5(x,y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t2 USING fts5(x,y, detail=%DETAIL% %TOKENIZER%);
} {}
do_catchsql_test 12.2 {
@@ -341,8 +350,9 @@ do_test 12.3 {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 13.1 {
CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1(rowid, x) VALUES(1, 'o n e'), (2, 't w o');
} {}
@@ -365,8 +375,9 @@ do_execsql_test 13.6 {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 14.1 {
CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
WITH d(x,y) AS (
SELECT NULL, 'xyz xyz xyz xyz xyz xyz'
@@ -449,8 +460,9 @@ do_catchsql_test 16.2 {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 17.1 {
CREATE VIRTUAL TABLE b2 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE b2 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
INSERT INTO b2 VALUES('a');
INSERT INTO b2 VALUES('b');
INSERT INTO b2 VALUES('c');
@@ -466,8 +478,9 @@ do_test 17.2 {
if {[string match n* %DETAIL%]==0} {
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 17.3 {
CREATE VIRTUAL TABLE c2 USING fts5(x, y, detail=%DETAIL%);
CREATE VIRTUAL TABLE c2 USING fts5(x, y, detail=%DETAIL% %TOKENIZER%);
INSERT INTO c2 VALUES('x x x', 'x x x');
SELECT rowid FROM c2 WHERE c2 MATCH 'y:x';
} {1}
@@ -476,8 +489,9 @@ if {[string match n* %DETAIL%]==0} {
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 17.1 {
CREATE VIRTUAL TABLE uio USING fts5(ttt, detail=%DETAIL%);
CREATE VIRTUAL TABLE uio USING fts5(ttt, detail=%DETAIL% %TOKENIZER%);
INSERT INTO uio VALUES(NULL);
INSERT INTO uio SELECT NULL FROM uio;
INSERT INTO uio SELECT NULL FROM uio;
@@ -524,8 +538,8 @@ do_execsql_test 17.9 {
#--------------------------------------------------------------------
#
do_execsql_test 18.1 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%);
CREATE VIRTUAL TABLE t2 USING fts5(c, d, detail=%DETAIL%);
CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL% %TOKENIZER%);
CREATE VIRTUAL TABLE t2 USING fts5(c, d, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1 VALUES('abc*', NULL);
INSERT INTO t2 VALUES(1, 'abcdefg');
}
@@ -540,8 +554,9 @@ do_execsql_test 18.3 {
# fts5 table in the temp schema.
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 19.0 {
CREATE VIRTUAL TABLE temp.t1 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE temp.t1 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t1 VALUES('x y z');
INSERT INTO t1 VALUES('w x 1');
SELECT rowid FROM t1 WHERE t1 MATCH 'x';
@@ -551,8 +566,9 @@ do_execsql_test 19.0 {
# Test that 6 and 7 byte varints can be read.
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 20.0 {
CREATE VIRTUAL TABLE temp.tmp USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE temp.tmp USING fts5(x, detail=%DETAIL% %TOKENIZER%);
}
set ::ids [list \
0 [expr 1<<36] [expr 2<<36] [expr 1<<43] [expr 2<<43]
@@ -570,7 +586,7 @@ do_test 20.1 {
#
do_execsql_test 21.0 {
CREATE TEMP TABLE t8(a, b);
CREATE VIRTUAL TABLE ft USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE ft USING fts5(x, detail=%DETAIL% %TOKENIZER%);
}
do_execsql_test 21.1 {
@@ -581,7 +597,7 @@ do_execsql_test 21.1 {
}
do_execsql_test 22.0 {
CREATE VIRTUAL TABLE t9 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE t9 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t9(rowid, x) VALUES(2, 'bbb');
BEGIN;
INSERT INTO t9(rowid, x) VALUES(1, 'aaa');
@@ -596,7 +612,7 @@ do_execsql_test 22.1 {
#-------------------------------------------------------------------------
do_execsql_test 23.0 {
CREATE VIRTUAL TABLE t10 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE t10 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
CREATE TABLE t11(x);
}
do_execsql_test 23.1 {
@@ -608,7 +624,7 @@ do_execsql_test 23.2 {
#-------------------------------------------------------------------------
do_execsql_test 24.0 {
CREATE VIRTUAL TABLE t12 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE t12 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
INSERT INTO t12 VALUES('aaaa');
}
do_execsql_test 24.1 {
@@ -618,6 +634,9 @@ do_execsql_test 24.1 {
INSERT INTO t12 VALUES('aaaa');
END;
}
execsql_pp {
SELECT rowid, hex(block) FROM t12_data
}
do_execsql_test 24.2 {
INSERT INTO t12(t12) VALUES('integrity-check');
}
@@ -627,7 +646,7 @@ do_execsql_test 24.3 {
#-------------------------------------------------------------------------
do_execsql_test 25.0 {
CREATE VIRTUAL TABLE t13 USING fts5(x, detail=%DETAIL%);
CREATE VIRTUAL TABLE t13 USING fts5(x, detail=%DETAIL% %TOKENIZER%);
}
do_execsql_test 25.1 {
BEGIN;
@@ -638,6 +657,7 @@ SELECT * FROM t13('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
}
}
}
expand_all_sql db
+43
View File
@@ -334,4 +334,47 @@ do_execsql_test 11.2 {
SELECT fts5_hitcount(x1) FROM x1('one') LIMIT 1;
} {5}
#-------------------------------------------------------------------------
# Test that xColumnText returns SQLITE_RANGE when it should.
#
reset_db
fts5_aux_test_functions db
do_execsql_test 12.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
INSERT INTO t1 VALUES('one', 'two', 'three');
INSERT INTO t1 VALUES('one', 'one', 'one');
INSERT INTO t1 VALUES('two', 'two', 'two');
INSERT INTO t1 VALUES('three', 'three', 'three');
}
do_catchsql_test 12.1.1 {
SELECT fts5_columntext(t1, -1) FROM t1('two');
} {1 SQLITE_RANGE}
do_catchsql_test 12.1.2 {
SELECT fts5_columntext(t1, 3) FROM t1('two');
} {1 SQLITE_RANGE}
do_catchsql_test 12.1.2 {
SELECT fts5_columntext(t1, 1) FROM t1('one AND two');
} {0 two}
do_catchsql_test 12.2.1 {
SELECT fts5_queryphrase(t1, -1) FROM t1('one AND two');
} {1 SQLITE_RANGE}
do_catchsql_test 12.2.2 {
SELECT fts5_queryphrase(t1, 2) FROM t1('one AND two');
} {1 SQLITE_RANGE}
do_catchsql_test 12.2.3 {
SELECT fts5_queryphrase(t1, 1) FROM t1('one AND two');
} {0 {{1 2 1}}}
do_catchsql_test 12.3.1 {
SELECT fts5_collist(t1, -1) FROM t1('one AND two');
} {1 SQLITE_RANGE}
do_catchsql_test 12.3.2 {
SELECT fts5_collist(t1, 2) FROM t1('one AND two');
} {1 SQLITE_RANGE}
do_catchsql_test 12.3.3 {
SELECT fts5_collist(t1, 1) FROM t1('one AND two');
} {0 1}
finish_test
+35
View File
@@ -293,4 +293,39 @@ do_catchsql_test 7.2.5 {
SELECT * FROM t1('abc') ORDER BY rank;
} {1 {recursively defined fts5 content table}}
#---------------------------------------------------------------------------
# Check that if the content table is a view, and that view contains an
# error, a reasonable error message is returned if the user tries to
# read from the view via the fts5 table.
#
reset_db
do_execsql_test 8.1 {
CREATE VIEW a1 AS
SELECT 1 AS r, text_value(1) AS t
UNION ALL
SELECT 2 AS r, text_value(2) AS t;
CREATE VIRTUAL TABLE t1 USING fts5(t, content='a1', content_rowid='r');
}
foreach {tn sql} {
1 "SELECT * FROM t1"
2 "INSERT INTO t1(t1) VALUES('rebuild')"
3 "SELECT * FROM t1 WHERE rowid=1"
} {
do_catchsql_test 8.2.$tn $sql {1 {no such function: text_value}}
}
proc text_value {i} {
if {$i==1} { return "one" }
if {$i==2} { return "two" }
return "many"
}
db func text_value text_value
do_execsql_test 8.3.1 { SELECT * FROM t1 } {one two}
do_execsql_test 8.3.2 { INSERT INTO t1(t1) VALUES('rebuild') }
do_execsql_test 8.3.3 { SELECT * FROM t1 WHERE rowid=1 } {one}
do_execsql_test 8.3.4 { SELECT rowid FROM t1('two') } {2}
finish_test
+485
View File
@@ -966,6 +966,491 @@ do_catchsql_test 6.2 {
UPDATE t1 SET content=randomblob(500) WHERE t1;
} {1 {constraint failed}}
#-------------------------------------------------------------------------
reset_db
do_test 7.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 40960 pagesize 4096 filename crash-d8b4a99207c10b.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 96: 00 00 00 00 0d 00 00 00 0d 0b 62 00 0f 97 0f 40 ..........b....@
| 112: 0e d5 0e 75 0e 18 0d c0 0d 66 0d 0f 0c a4 0c 44 ...u.....f.....D
| 128: 0b ec 0b a7 0b 62 00 00 00 00 00 00 00 00 00 00 .....b..........
| 2912: 00 00 43 0d 06 17 11 11 08 75 74 61 62 6c 65 74 ..C......utablet
| 2928: 34 74 34 43 52 45 41 54 45 20 56 49 52 54 55 41 4t4CREATE VIRTUA
| 2944: 4c 20 54 41 42 4c 45 20 74 34 20 55 53 49 4e 47 L TABLE t4 USING
| 2960: 20 66 74 73 35 76 6f 63 61 62 28 27 74 32 27 2c fts5vocab('t2',
| 2976: 20 27 72 6f 77 27 29 43 0c 06 17 11 11 08 75 74 'row')C......ut
| 2992: 61 62 6c 65 74 33 74 33 43 52 45 41 54 45 20 56 ablet3t3CREATE V
| 3008: 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 33 20 IRTUAL TABLE t3
| 3024: 55 53 49 4e 47 20 66 74 73 35 76 6f 63 61 62 28 USING fts5vocab(
| 3040: 27 74 31 27 2c 20 27 72 6f 77 27 29 56 0b 06 17 't1', 'row')V...
| 3056: 1f 1f 01 7d 74 61 62 6c 65 74 32 5f 63 6f 6e 66 ....tablet2_conf
| 3072: 69 67 74 32 5f 63 6f 6e 66 69 67 0a 43 52 45 41 igt2_config.CREA
| 3088: 54 45 20 54 41 42 4c 45 20 27 74 32 5f 63 6f 6e TE TABLE 't2_con
| 3104: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
| 3120: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
| 3136: 4f 57 49 44 5e 0a 07 17 21 21 01 81 07 74 61 62 OWID^...!!...tab
| 3152: 6c 65 74 32 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 let2_contentt2_c
| 3168: 6f 6e 74 65 6e 74 09 43 52 45 41 54 45 20 54 41 ontent.CREATE TA
| 3184: 42 4c 45 20 27 74 32 5f 63 6f 6e 74 65 6e 74 27 BLE 't2_content'
| 3200: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 3216: 41 52 59 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c ARY KEY, c0, c1,
| 3232: 20 63 32 29 69 09 07 17 19 19 01 81 2d 74 61 62 c2)i.......-tab
| 3248: 6c 65 74 32 5f 69 64 78 74 32 5f 69 64 78 08 43 let2_idxt2_idx.C
| 3264: 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 32 5f REATE TABLE 't2_
| 3280: 69 64 78 27 28 73 65 67 69 64 2c 20 74 65 72 6d idx'(segid, term
| 3296: 2c 20 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 , pgno, PRIMARY
| 3312: 4b 45 59 28 73 65 67 69 64 2c 20 74 65 72 6d 29 KEY(segid, term)
| 3328: 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 55 ) WITHOUT ROWIDU
| 3344: 08 07 17 1b 1b 01 81 01 74 61 62 6c 65 74 32 5f ........tablet2_
| 3360: 64 61 74 61 74 32 5f 64 61 74 61 07 43 52 45 41 datat2_data.CREA
| 3376: 54 45 20 54 41 42 4c 45 20 27 74 32 5f 64 61 74 TE TABLE 't2_dat
| 3392: 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 a'(id INTEGER PR
| 3408: 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b IMARY KEY, block
| 3424: 20 42 4c 4f 42 29 58 07 07 17 11 11 08 81 1d 74 BLOB)X........t
| 3440: 61 62 6c 65 74 32 74 32 43 52 45 41 54 45 20 56 ablet2t2CREATE V
| 3456: 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 32 20 IRTUAL TABLE t2
| 3472: 55 53 49 4e 47 20 66 74 73 35 28 27 61 27 2c 5b USING fts5('a',[
| 3488: 62 5d 2c 22 63 22 2c 64 65 74 61 69 6c 3d 6e 6f b],.c.,detail=no
| 3504: 6e 65 2c 63 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 ne,columnsize=0)
| 3520: 56 06 06 17 1f 1f 01 7d 74 61 62 6c 65 74 31 5f V.......tablet1_
| 3536: 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 69 67 06 configt1_config.
| 3552: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
| 3568: 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 49 4d 41 _config'(k PRIMA
| 3584: 52 59 20 4b 45 59 2c 20 76 29 20 57 49 54 48 4f RY KEY, v) WITHO
| 3600: 55 54 20 52 4f 57 49 44 5b 05 07 17 21 21 01 81 UT ROWID[...!!..
| 3616: 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 69 7a 65 .tablet1_docsize
| 3632: 74 31 5f 64 6f 63 73 69 7a 65 05 43 52 45 41 54 t1_docsize.CREAT
| 3648: 45 20 54 41 42 4c 45 20 27 74 31 5f 64 6f 63 73 E TABLE 't1_docs
| 3664: 69 7a 65 27 28 69 64 20 49 4e 54 45 47 45 52 20 ize'(id INTEGER
| 3680: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 7a 20 PRIMARY KEY, sz
| 3696: 42 4c 4f 42 29 5e 04 07 17 21 21 01 81 07 74 61 BLOB)^...!!...ta
| 3712: 62 6c 65 74 31 5f 63 6f 6e 74 65 6e 74 74 31 5f blet1_contentt1_
| 3728: 63 6f 6e 74 65 6e 74 04 43 52 45 41 54 45 20 54 content.CREATE T
| 3744: 41 42 4c 45 20 27 74 31 5f 63 6f 6e 74 65 6e 74 ABLE 't1_content
| 3760: 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 '(id INTEGER PRI
| 3776: 4d 41 52 59 20 4b 45 59 2c 20 63 30 2c 20 63 31 MARY KEY, c0, c1
| 3792: 2c 20 63 32 29 69 03 07 17 19 19 01 81 2d 74 61 , c2)i.......-ta
| 3808: 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 64 78 03 blet1_idxt1_idx.
| 3824: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
| 3840: 5f 69 64 78 27 28 73 65 67 69 64 2c 20 74 65 72 _idx'(segid, ter
| 3856: 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 m, pgno, PRIMARY
| 3872: 20 4b 45 59 28 73 65 67 69 64 2c 20 74 65 72 6d KEY(segid, term
| 3888: 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 )) WITHOUT ROWID
| 3904: 55 02 07 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 U........tablet1
| 3920: 5f 64 61 74 61 74 31 5f 64 61 74 61 02 43 52 45 _datat1_data.CRE
| 3936: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 61 ATE TABLE 't1_da
| 3952: 74 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 ta'(id INTEGER P
| 3968: 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 RIMARY KEY, bloc
| 3984: 6b 20 42 4c 4f 42 29 67 01 07 17 11 11 08 81 3b k BLOB)g.......;
| 4000: 74 61 62 6c 65 74 31 74 31 43 52 45 41 54 45 20 tablet1t1CREATE
| 4016: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31 VIRTUAL TABLE t1
| 4032: 20 55 53 49 4e 47 20 66 74 73 35 28 61 2c 62 20 USING fts5(a,b
| 4048: 75 6e 69 6e 64 65 78 65 64 2c 63 2c 74 6f 6b 65 unindexed,c,toke
| 4064: 6e 69 7a 65 3d 22 70 6f 72 74 65 72 20 61 73 63 nize=.porter asc
| 4080: 69 69 22 2c 74 6f 6b 65 6e 64 61 74 61 3d 31 29 ii.,tokendata=1)
| page 2 offset 4096
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
| 3984: 01 02 02 01 01 68 02 08 03 01 02 03 01 01 69 02 .....h........i.
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 7f f1 03 ........7.......
| 4016: 00 74 00 00 00 2e 02 30 61 01 02 02 01 01 62 01 .t.....0a.....b.
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
| 4048: 01 01 68 01 06 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 03 0f ec 00 0f fa 0f f3 0f ec 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
| page 5 offset 16384
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| page 7 offset 24576
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 0f 9e 00 00 ................
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 8 offset 28672
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 9 offset 32768
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
| page 10 offset 36864
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end crash-d8b4a99207c10b.db
}]} {}
do_catchsql_test 7.1 {
SELECT snippet(t1, -1, '.', '..', '[', ']'),
highlight(t1, 2, '[', ']')
FROM t1('g + h')
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank;
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 8.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 20480 pagesize 4096 filename crash-d57c01958e48ab.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 96: 00 00 00 00 0d 00 00 00 05 0e 10 00 0f 97 0f 40 ...............@
| 112: 0e d5 0e 68 0e 10 01 00 00 00 00 00 00 00 00 00 ...h............
| 3600: 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 74 31 5f V.......tablet1_
| 3616: 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 69 67 05 configt1_config.
| 3632: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
| 3648: 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 49 4d 41 _config'(k PRIMA
| 3664: 52 59 20 4b 45 59 2c 20 76 29 20 57 49 54 48 4f RY KEY, v) WITHO
| 3680: 55 54 20 52 4f 57 49 44 6b 04 07 17 21 21 01 81 UT ROWIDk...!!..
| 3696: 21 74 61 62 6c 65 74 31 5f 64 6f 63 73 69 7a 65 !tablet1_docsize
| 3712: 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 45 41 54 t1_docsize.CREAT
| 3728: 45 20 54 41 42 4c 45 20 27 74 31 5f 64 6f 63 73 E TABLE 't1_docs
| 3744: 69 7a 65 27 28 69 64 20 49 4e 54 45 47 45 52 20 ize'(id INTEGER
| 3760: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 7a 20 PRIMARY KEY, sz
| 3776: 42 4c 4f 42 2c 20 6f 72 69 67 69 6e 20 49 4e 54 BLOB, origin INT
| 3792: 45 47 45 52 29 69 03 07 17 19 19 01 81 2d 74 61 EGER)i.......-ta
| 3808: 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 64 78 03 blet1_idxt1_idx.
| 3824: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
| 3840: 5f 69 64 78 27 28 73 65 67 69 64 2c 20 74 65 72 _idx'(segid, ter
| 3856: 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 m, pgno, PRIMARY
| 3872: 20 4b 45 59 28 73 65 67 69 64 2c 20 74 65 72 6d KEY(segid, term
| 3888: 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 )) WITHOUT ROWID
| 3904: 55 02 07 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 U........tablet1
| 3920: 5f 64 61 74 61 74 31 5f 64 61 74 61 02 43 52 45 _datat1_data.CRE
| 3936: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 61 ATE TABLE 't1_da
| 3952: 74 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 ta'(id INTEGER P
| 3968: 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 RIMARY KEY, bloc
| 3984: 6b 20 42 4c 4f 42 29 67 01 07 17 11 11 08 81 3b k BLOB)g.......;
| 4000: 74 61 62 6c 65 74 31 74 31 43 52 45 41 54 45 20 tablet1t1CREATE
| 4016: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31 VIRTUAL TABLE t1
| 4032: 20 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 USING fts5(a, b
| 4048: 2c 20 63 6f 6e 74 65 6e 74 3d 27 27 2c 20 63 6f , content='', co
| 4064: 6e 74 65 6e 74 6c 65 73 73 5f 64 65 6c 65 74 65 ntentless_delete
| 4080: 3d 31 2c 20 74 6f 6b 65 6e 64 61 74 61 3d 31 29 =1, tokendata=1)
| page 2 offset 4096
| 0: 0d 0f eb 00 03 0e 17 00 0f e2 0e 17 0e 31 00 00 .............1..
| 16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3600: 00 00 00 00 00 00 00 18 0a 03 00 36 00 00 00 00 ...........6....
| 3616: ff 00 00 01 01 01 01 00 01 01 01 01 01 01 00 00 ................
| 3632: 07 83 29 84 80 80 80 80 01 04 00 86 56 00 00 01 ..).........V...
| 3648: 96 04 30 61 61 61 01 02 02 01 04 02 04 01 08 02 ..0aaa..........
| 3664: 04 04 04 01 10 02 04 04 04 04 04 04 04 01 20 02 .............. .
| 3680: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 01 ................
| 3696: 40 02 04 04 04 04 04 04 04 04 04 04 04 04 04 04 @...............
| 3712: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
| 3728: 04 01 81 00 02 04 04 04 04 04 04 04 04 04 04 04 ................
| 3744: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
| 3760: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
| 3776: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
| 3792: 04 04 04 04 02 02 62 63 01 06 01 01 02 01 03 62 ......bc.......b
| 3808: 62 62 02 02 03 01 04 03 06 01 08 03 06 06 06 01 bb..............
| 3824: 10 03 06 06 06 06 06 06 06 01 20 03 06 06 06 06 .......... .....
| 3840: 06 06 06 06 06 06 06 06 06 06 06 01 40 03 06 06 ............@...
| 3856: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 ................
| 3872: 06 06 06 06 06 06 06 06 06 06 16 06 06 02 02 63 ...............c
| 3888: 64 02 06 01 01 02 01 03 63 63 63 03 02 05 01 04 d.......ccc.....
| 3904: 05 0a 01 08 05 0a 0a 0a 01 10 05 0a 0a 0a 0a 0a ................
| 3920: 0a 0a 01 20 05 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a ... ............
| 3936: 0a 0a 0a 0a 02 02 64 65 03 06 01 01 02 01 03 64 ......de.......d
| 3952: 64 64 04 02 09 01 04 09 12 01 08 09 12 12 12 01 dd..............
| 3968: 10 09 12 12 12 12 12 12 12 02 02 65 66 04 06 01 ...........ef...
| 3984: 01 02 01 03 65 65 65 05 02 11 01 04 11 22 01 08 ....eee.........
| 4000: 11 22 22 22 02 02 66 67 05 06 01 01 02 01 03 66 ......fg.......f
| 4016: 56 66 06 02 21 01 04 21 42 02 02 67 68 06 06 01 Vf..!..!B..gh...
| 4032: 01 02 cb 03 67 67 67 07 02 41 02 02 68 69 07 06 ....ggg..A..hi..
| 4048: 01 01 02 04 81 13 09 50 09 2e 09 1c 09 12 09 0c .......P........
| 4064: 09 08 07 01 03 00 14 07 81 77 07 00 00 00 15 22 .........w......
| 4080: 00 00 00 00 ff 00 00 01 00 00 00 00 00 00 05 0c ................
| page 3 offset 8192
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 07 0f c8 00 0f f8 0f f0 0f e8 0f e0 ................
| 16: 0f d8 0f d0 0f c8 00 00 00 00 00 00 00 00 00 00 ................
| 4032: 00 00 00 00 00 00 00 00 06 07 04 00 10 09 7f 01 ................
| 4048: 06 06 04 00 10 09 3f 01 06 05 04 00 10 09 1f 01 ......?.........
| 4064: 06 04 04 00 10 09 0f 01 06 03 04 00 10 09 07 01 ................
| 4080: 06 02 04 00 10 09 03 01 06 01 04 00 10 09 01 01 ................
| page 5 offset 16384
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end crash-d57c01958e48ab.db
}]} {}
do_catchsql_test 8.1 {
SELECT rowid FROM t1('a* NOT ý‘') ;
} {0 {1 2 3 4 5 6 7}}
#-------------------------------------------------------------------------
reset_db
do_test 9.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-c76a16c24c8ba6.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
| page 3 offset 8192
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 4 offset 12288
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 5 offset 16384
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
| 64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a .......x.W.>.$..
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 NABLE GEOPOLYXBI
| 3616: 4e 41 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c NARY....9..ENABL
| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45 E GEOPOLYXNOCASE
| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45 ....)..ENABLE GE
| 3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23 OPOLYXRTRIM....#
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3c 67 ...C..COMPILER<g
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
| page 6 offset 20480
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 0e e0 ................
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
| page 7 offset 24576
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| page 8 offset 28672
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e9 0f d6 00 00 ................
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
| 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 00 00 00 00 uild....opti....
| end crash-c76a16c24c8ba6.db
}]} {}
#.testctrl prng_seed 1 db
#.testctrl internal_functions
#.testctrl json_selfcheck on
#
do_execsql_test 9.1 {
UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
SAVEPOINT a;
UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
}
do_catchsql_test 9.2 {
DELETE FROM t1;
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
+150
View File
@@ -0,0 +1,150 @@
# 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 fts5faultH
sqlite3_fts5_register_origintext db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(
x, tokenize="origintext unicode61", tokendata=1
);
BEGIN;
INSERT INTO t1 VALUES('oNe tWo thRee');
INSERT INTO t1 VALUES('One Two Three');
INSERT INTO t1 VALUES('onE twO threE');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES('one two three');
INSERT INTO t1 VALUES('one two three');
INSERT INTO t1 VALUES('one two three');
COMMIT;
}
do_faultsim_test 1 -faults oom* -prep {
} -body {
execsql {
SELECT rowid FROM t1('three');
}
} -test {
faultsim_integrity_check
faultsim_test_result {0 {1 2 3 4 5 6}}
}
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(
x, tokenize="origintext unicode61", tokendata=1
);
INSERT INTO t1(t1, rank) VALUES('pgsz', 64);
BEGIN;
INSERT INTO t1(rowid, x) VALUES(10, 'aaa bbb BBB');
INSERT INTO t1(rowid, x) VALUES(12, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(13, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(14, 'bbb BBB bbb');
INSERT INTO t1(rowid, x) VALUES(15, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(16, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(17, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(18, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(19, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(20, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(21, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(22, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(23, 'bbb bbb bbb');
INSERT INTO t1(rowid, x) VALUES(24, 'aaa bbb BBB');
COMMIT;
}
do_faultsim_test 2 -faults oom* -prep {
} -body {
execsql {
SELECT rowid FROM t1('BBB AND AAA');
}
} -test {
faultsim_integrity_check
faultsim_test_result {0 {10 24}}
}
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE t1 USING fts5(
x, tokenize="origintext unicode61", tokendata=1
);
INSERT INTO t1(t1, rank) VALUES('pgsz', 64);
INSERT INTO t1(rowid, x) VALUES(9, 'bbb Bbb BBB');
BEGIN;
INSERT INTO t1(rowid, x) VALUES(10, 'aaa bbb BBB');
INSERT INTO t1(rowid, x) VALUES(11, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(12, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(13, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(14, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(15, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(16, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(17, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(18, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(19, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(20, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(21, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(22, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(23, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(24, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(25, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(26, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(27, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(28, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(29, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(30, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(31, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(32, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(33, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(34, 'bbb Bbb BBB');
INSERT INTO t1(rowid, x) VALUES(35, 'aaa bbb BBB');
COMMIT;
}
do_faultsim_test 3.1 -faults oom* -prep {
} -body {
execsql {
SELECT rowid FROM t1('BBB AND AAA');
}
} -test {
faultsim_integrity_check
faultsim_test_result {0 {10 35}}
}
do_faultsim_test 3.2 -faults oom* -prep {
} -body {
execsql {
SELECT count(*) FROM t1('BBB');
}
} -test {
faultsim_integrity_check
faultsim_test_result {0 27}
}
finish_test
+26
View File
@@ -355,4 +355,30 @@ do_execsql_test 11.4 {
PRAGMA integrity_check(t2);
} {ok}
#-------------------------------------------------------------------
reset_db
do_execsql_test 12.1 {
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
INSERT INTO x1 VALUES('one', 'two');
INSERT INTO x1 VALUES('three', 'four');
INSERT INTO x1 VALUES('five', 'six');
}
do_execsql_test 12.2 {
PRAGMA integrity_check
} {ok}
db close
sqlite3 db test.db -readonly 1
explain_i {
PRAGMA integrity_check
}
do_execsql_test 12.3 {
PRAGMA integrity_check
} {ok}
finish_test
+35 -1
View File
@@ -91,7 +91,6 @@ do_execsql_test 2.2.1 {
INSERT INTO vt0(c0) VALUES ('xyz');
}
breakpoint
do_execsql_test 2.2.2 {
ALTER TABLE t0 RENAME TO t1;
}
@@ -500,6 +499,41 @@ do_execsql_test 17.5 {
SELECT c0 FROM t0 WHERE c0 GLOB '*faul*';
} {assertionfaultproblem}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 18.0 {
BEGIN;
CREATE VIRTUAL TABLE t1 USING fts5(text);
ALTER TABLE t1 RENAME TO t2;
}
do_execsql_test 18.1 {
DROP TABLE t2;
}
do_execsql_test 18.2 {
COMMIT;
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 19.0 {
CREATE VIRTUAL TABLE t1 USING fts5(text);
CREATE TABLE t2(text);
BEGIN;
INSERT INTO t1 VALUES('one');
INSERT INTO t1 VALUES('two');
INSERT INTO t1 VALUES('three');
INSERT INTO t1 VALUES('one');
INSERT INTO t1 VALUES('two');
INSERT INTO t1 VALUES('three');
SAVEPOINT one;
INSERT INTO t2 VALUES('one');
INSERT INTO t2 VALUES('two');
INSERT INTO t2 VALUES('three');
ROLLBACK TO one;
COMMIT;
}
finish_test
+297
View File
@@ -0,0 +1,297 @@
# 2014 Jan 08
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests focused on phrase queries.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5origintext
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach_detail_mode $testprefix {
sqlite3_fts5_register_origintext db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", detail=%DETAIL%
);
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
}
do_execsql_test 1.1 {
INSERT INTO ft VALUES('Hello world');
}
do_execsql_test 1.2 {
INSERT INTO ft(ft) VALUES('integrity-check');
}
proc b {x} { string map [list "\0" "."] $x }
db func b b
do_execsql_test 1.3 {
select b(term) from vocab;
} {
hello.Hello
world
}
do_execsql_test 1.4 {
SELECT rowid FROM ft('Hello');
} {1}
#-------------------------------------------------------------------------
reset_db
# Return a random integer between 0 and n-1.
#
proc random {n} {
expr {abs(int(rand()*$n))}
}
proc select_one {list} {
set n [llength $list]
lindex $list [random $n]
}
proc term {} {
set first_letter {
a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
}
set term [select_one $first_letter]
append term [random 100]
}
proc document {} {
set nTerm [expr [random 5] + 5]
set doc ""
for {set ii 0} {$ii < $nTerm} {incr ii} {
lappend doc [term]
}
set doc
}
db func document document
sqlite3_fts5_register_origintext db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", detail=%DETAIL%
);
INSERT INTO ft(ft, rank) VALUES('pgsz', 128);
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
}
do_test 2.1 {
for {set ii 0} {$ii < 500} {incr ii} {
execsql { INSERT INTO ft VALUES( document() ) }
}
} {}
do_execsql_test 2.2 {
INSERT INTO ft(ft) VALUES('integrity-check');
}
do_execsql_test 2.3 {
INSERT INTO ft(ft, rank) VALUES('merge', 16);
}
do_execsql_test 2.4 {
INSERT INTO ft(ft) VALUES('integrity-check');
}
do_execsql_test 2.5 {
INSERT INTO ft(ft) VALUES('optimize');
}
#-------------------------------------------------------------------------
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", detail=%DETAIL%
);
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
INSERT INTO ft(rowid, x) VALUES(1, 'hello');
INSERT INTO ft(rowid, x) VALUES(2, 'Hello');
INSERT INTO ft(rowid, x) VALUES(3, 'HELLO');
}
#proc b {x} { string map [list "\0" "."] $x }
#db func b b
#execsql_pp { SELECT b(term) FROM vocab }
do_execsql_test 3.1.1 { SELECT rowid FROM ft('hello') } 1
do_execsql_test 3.1.2 { SELECT rowid FROM ft('Hello') } 2
do_execsql_test 3.1.3 { SELECT rowid FROM ft('HELLO') } 3
do_execsql_test 3.2 {
CREATE VIRTUAL TABLE ft2 USING fts5(x,
tokenize="origintext unicode61",
tokendata=1,
detail=%DETAIL%
);
CREATE VIRTUAL TABLE vocab2 USING fts5vocab(ft2, instance);
INSERT INTO ft2(rowid, x) VALUES(1, 'hello');
INSERT INTO ft2(rowid, x) VALUES(2, 'Hello');
INSERT INTO ft2(rowid, x) VALUES(3, 'HELLO');
INSERT INTO ft2(rowid, x) VALUES(10, 'helloooo');
}
#proc b {x} { string map [list "\0" "."] $x }
#db func b b
#execsql_pp { SELECT b(term) FROM vocab }
do_execsql_test 3.3.1 { SELECT rowid FROM ft2('hello') } {1 2 3}
do_execsql_test 3.3.2 { SELECT rowid FROM ft2('Hello') } {1 2 3}
do_execsql_test 3.3.3 { SELECT rowid FROM ft2('HELLO') } {1 2 3}
do_execsql_test 3.3.4 { SELECT rowid FROM ft2('hello*') } {1 2 3 10}
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
proc querytoken {cmd iPhrase iToken} {
set txt [$cmd xQueryToken $iPhrase $iToken]
string map [list "\0" "."] $txt
}
sqlite3_fts5_create_function db querytoken querytoken
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize='origintext unicode61', tokendata=1, detail=%DETAIL%
);
INSERT INTO ft VALUES('one two three four');
}
do_execsql_test 4.1 {
SELECT rowid, querytoken(ft, 0, 0) FROM ft('TwO')
} {1 two.TwO}
do_execsql_test 4.2 {
SELECT rowid, querytoken(ft, 0, 0) FROM ft('one TWO ThreE')
} {1 one}
do_execsql_test 4.3 {
SELECT rowid, querytoken(ft, 1, 0) FROM ft('one TWO ThreE')
} {1 two.TWO}
if {"%DETAIL%"=="full"} {
# Phrase queries are only supported for detail=full.
#
do_execsql_test 4.4 {
SELECT rowid, querytoken(ft, 0, 2) FROM ft('"one TWO ThreE"')
} {1 three.ThreE}
do_catchsql_test 4.5 {
SELECT rowid, querytoken(ft, 0, 3) FROM ft('"one TWO ThreE"')
} {1 SQLITE_RANGE}
do_catchsql_test 4.6 {
SELECT rowid, querytoken(ft, 1, 0) FROM ft('"one TWO ThreE"')
} {1 SQLITE_RANGE}
do_catchsql_test 4.7 {
SELECT rowid, querytoken(ft, -1, 0) FROM ft('"one TWO ThreE"')
} {1 SQLITE_RANGE}
}
#-------------------------------------------------------------------------
#
reset_db
sqlite3_fts5_register_origintext db
proc insttoken {cmd iIdx iToken} {
set txt [$cmd xInstToken $iIdx $iToken]
string map [list "\0" "."] $txt
}
sqlite3_fts5_create_function db insttoken insttoken
fts5_aux_test_functions db
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize='origintext unicode61', tokendata=1, detail=%DETAIL%
);
INSERT INTO ft VALUES('one ONE One oNe oNE one');
}
do_execsql_test 5.1 {
SELECT insttoken(ft, 0, 0),
insttoken(ft, 1, 0),
insttoken(ft, 2, 0),
insttoken(ft, 3, 0),
insttoken(ft, 4, 0),
insttoken(ft, 5, 0)
FROM ft('one');
} {
one one.ONE one.One one.oNe one.oNE one
}
do_execsql_test 5.2 {
SELECT insttoken(ft, 1, 0) FROM ft('one');
} {
one.ONE
}
do_execsql_test 5.3 {
SELECT fts5_test_poslist(ft) FROM ft('one');
} {
{0.0.0 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5}
}
#-------------------------------------------------------------------------
# Test the xInstToken() API with:
#
# * a non tokendata=1 table.
# * prefix queries.
#
reset_db
sqlite3_fts5_register_origintext db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, y, tokenize='origintext unicode61', detail=%DETAIL%
);
INSERT INTO ft VALUES('One Two', 'Three two');
INSERT INTO ft VALUES('three Three', 'one One');
}
proc tokens {cmd} {
set ret [list]
for {set iTok 0} {$iTok < [$cmd xInstCount]} {incr iTok} {
set txt [$cmd xInstToken $iTok 0]
set txt [string map [list "\0" "."] $txt]
lappend ret $txt
}
set ret
}
sqlite3_fts5_create_function db tokens tokens
do_execsql_test 6.1 {
SELECT rowid, tokens(ft) FROM ft('One');
} {1 one.One 2 one.One}
do_execsql_test 6.2 {
SELECT rowid, tokens(ft) FROM ft('on*');
} {1 {{}} 2 {{} {}}}
do_execsql_test 6.3 {
SELECT rowid, tokens(ft) FROM ft('Three*');
} {1 {{}} 2 {{}}}
}
finish_test
+146
View File
@@ -0,0 +1,146 @@
# 2014 Jan 08
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests focused on phrase queries.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5origintext2
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
sqlite3_fts5_register_origintext db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", tokendata=1
);
}
do_execsql_test 1.1 {
BEGIN;
INSERT INTO ft VALUES('Hello');
INSERT INTO ft VALUES('hello');
INSERT INTO ft VALUES('HELLO');
INSERT INTO ft VALUES('today');
INSERT INTO ft VALUES('today');
INSERT INTO ft VALUES('today');
INSERT INTO ft VALUES('World');
INSERT INTO ft VALUES('world');
INSERT INTO ft VALUES('WORLD');
COMMIT;
}
do_execsql_test 1.2 { SELECT rowid FROM ft('hello'); } {1 2 3}
do_execsql_test 1.3 { SELECT rowid FROM ft('today'); } {4 5 6}
do_execsql_test 1.4 { SELECT rowid FROM ft('world'); } {7 8 9}
do_execsql_test 1.5 {
SELECT count(*) FROM ft_data
} 3
do_execsql_test 1.6 {
DELETE FROM ft;
INSERT INTO ft(ft, rank) VALUES('pgsz', 64);
BEGIN;
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
)
INSERT INTO ft SELECT 'Hello Hello Hello Hello Hello Hello Hello' FROM s;
INSERT INTO ft VALUES ('hELLO hELLO hELLO');
INSERT INTO ft VALUES('today today today today today today today');
INSERT INTO ft VALUES('today today today today today today today');
INSERT INTO ft VALUES('today today today today today today today');
INSERT INTO ft VALUES('today today today today today today today');
INSERT INTO ft VALUES('today today today today today today today');
INSERT INTO ft VALUES('today today today today today today today');
INSERT INTO ft VALUES('World World World World World World World');
INSERT INTO ft VALUES('world world world world world world world');
INSERT INTO ft VALUES('WORLD WORLD WORLD WORLD WORLD WORLD WORLD');
INSERT INTO ft VALUES('World World World World World World World');
INSERT INTO ft VALUES('world world world world world world world');
INSERT INTO ft VALUES('WORLD WORLD WORLD WORLD WORLD WORLD WORLD');
COMMIT;
}
do_execsql_test 1.7 {
SELECT count(*) FROM ft_data;
} 23
do_execsql_test 1.8 { SELECT rowid FROM ft('hello') WHERE rowid>100; } {101}
do_execsql_test 1.9 {
DELETE FROM ft;
INSERT INTO ft(ft) VALUES('optimize');
SELECT count(*) FROM ft_data;
} {2}
do_execsql_test 1.10 {
BEGIN;
INSERT INTO ft VALUES('Hello');
INSERT INTO ft VALUES('hello');
INSERT INTO ft VALUES('HELLO');
INSERT INTO ft VALUES('today');
INSERT INTO ft VALUES('today');
INSERT INTO ft VALUES('today');
INSERT INTO ft VALUES('World');
INSERT INTO ft VALUES('world');
INSERT INTO ft VALUES('WORLD');
}
do_execsql_test 1.11 { SELECT rowid FROM ft('hello'); } {1 2 3}
do_execsql_test 1.12 { SELECT rowid FROM ft('today'); } {4 5 6}
do_execsql_test 1.13 { SELECT rowid FROM ft('world'); } {7 8 9}
do_execsql_test 1.14 { SELECT rowid FROM ft('hello') ORDER BY rank; } {1 2 3}
#------------------------------------------------------------------------
reset_db
sqlite3_fts5_register_origintext db
proc tokens {cmd} {
set ret [list]
for {set iTok 0} {$iTok < [$cmd xInstCount]} {incr iTok} {
set txt [$cmd xInstToken $iTok 0]
set txt [string map [list "\0" "."] $txt]
lappend ret $txt
}
set ret
}
sqlite3_fts5_create_function db tokens tokens
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE x1 USING fts5(
v, tokenize="origintext unicode61", tokendata=1, detail=none
);
INSERT INTO x1 VALUES('xxx Xxx XXX yyy YYY yyy');
INSERT INTO x1 VALUES('xxx yyy xxx yyy yyy yyy');
}
do_execsql_test 2.1 {
SELECT tokens(x1) FROM x1('xxx');
} {
{xxx xxx.Xxx xxx.XXX} {xxx xxx}
}
do_execsql_test 2.2 {
UPDATE x1_content SET c0 = 'xxx xxX xxx yyy yyy yyy' WHERE id=1;
}
do_execsql_test 2.3 {
SELECT tokens(x1) FROM x1('xxx');
} {
{xxx {} xxx} {xxx xxx}
}
finish_test
+101
View File
@@ -0,0 +1,101 @@
# 2023 November 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.
#
#***********************************************************************
#
# Tests focused on phrase queries.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5origintext3
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach_detail_mode $testprefix {
reset_db
sqlite3_fts5_register_origintext db
fts5_aux_test_functions db
proc insttoken {cmd iIdx iToken} {
set txt [$cmd xInstToken $iIdx $iToken]
string map [list "\0" "."] $txt
}
sqlite3_fts5_create_function db insttoken insttoken
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
);
}
do_execsql_test 1.1 {
INSERT INTO ft VALUES('Hello world HELLO WORLD hello');
}
do_execsql_test 1.2 {
SELECT fts5_test_poslist(ft) FROM ft('hello');
} {{0.0.0 0.0.2 0.0.4}}
do_execsql_test 1.3 {
SELECT
insttoken(ft, 0, 0),
insttoken(ft, 1, 0),
insttoken(ft, 2, 0)
FROM ft('hello');
} {hello.Hello hello.HELLO hello}
do_execsql_test 1.4 {
SELECT
insttoken(ft, 0, 0),
insttoken(ft, 1, 0),
insttoken(ft, 2, 0)
FROM ft('hello') ORDER BY rank;
} {hello.Hello hello.HELLO hello}
do_execsql_test 1.5 {
CREATE VIRTUAL TABLE ft2 USING fts5(
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
);
INSERT INTO ft2(rowid, x) VALUES(1, 'ONE one two three ONE');
INSERT INTO ft2(rowid, x) VALUES(2, 'TWO one two three TWO');
INSERT INTO ft2(rowid, x) VALUES(3, 'THREE one two three THREE');
}
do_execsql_test 1.6 {
SELECT insttoken(ft2, 0, 0), rowid FROM ft2('three') ORDER BY rank;
} {three.THREE 3 three 1 three 2}
do_execsql_test 1.7 {
INSERT INTO ft2(rowid, x) VALUES(10, 'aaa bbb BBB');
INSERT INTO ft2(rowid, x) VALUES(12, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(13, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(14, 'bbb BBB bbb');
INSERT INTO ft2(rowid, x) VALUES(15, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(16, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(17, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(18, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(19, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(20, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(21, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(22, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(23, 'bbb bbb bbb');
INSERT INTO ft2(rowid, x) VALUES(24, 'aaa bbb BBB');
}
do_execsql_test 1.8 { SELECT rowid FROM ft2('aaa AND bbb'); } {10 24}
do_execsql_test 1.9 { SELECT rowid FROM ft2('bbb AND aaa'); } {10 24}
}
finish_test
+80
View File
@@ -0,0 +1,80 @@
# 2023 November 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.
#
#***********************************************************************
#
# Tests focused on phrase queries.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5origintext4
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
# The tests below verify that a doclist-index is used to limit the number
# of pages loaded into the cache. It does this by querying sqlite3_db_status()
# for the amount of memory used by the pager cache.
#
# memsubsys1 effectively limits the page-cache to 24 pages. Which masks
# the effect tested by the tests in this file. And "mmap" prevents the
# cache from being used, also preventing these tests from working.
#
if {[permutation]=="memsubsys1" || [permutation]=="mmap"} {
finish_test
return
}
sqlite3_fts5_register_origintext db
do_execsql_test 1.0 {
PRAGMA page_size = 4096;
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", tokendata=1
);
}
do_execsql_test 1.1 {
BEGIN;
INSERT INTO ft SELECT 'the first thing';
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<90000
)
INSERT INTO ft SELECT 'The second thing' FROM s;
INSERT INTO ft SELECT 'the first thing';
COMMIT;
INSERT INTO ft(ft) VALUES('optimize');
}
foreach {tn sql expr} {
1 { SELECT rowid FROM ft('the') } {$mem > 250000}
2 { SELECT rowid FROM ft('first') } {$mem < 50000}
3 { SELECT rowid FROM ft('the first') } {$mem < 50000}
} {
db close
sqlite3 db test.db
sqlite3_fts5_register_origintext db
execsql $sql
do_test 1.2.$tn {
set mem [lindex [sqlite3_db_status db CACHE_USED 0] 1]
expr $expr
} 1
}
proc b {x} { string map [list "\0" "."] $x }
db func b b
# execsql_pp { SELECT segid, b(term), pgno from ft_idx }
finish_test
+273
View File
@@ -0,0 +1,273 @@
# 2023 Dec 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.
#
#***********************************************************************
#
# Tests for tables that use both tokendata=1 and contentless_delete=1.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5origintext
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
# Return a random integer between 0 and n-1.
#
proc random {n} { expr {abs(int(rand()*$n))} }
# Select an element of the list passed as the only argument at random and
# return it.
#
proc select_one {list} {
set n [llength $list]
lindex $list [random $n]
}
# Given a term that consists entirely of alphabet characters, return all
# permutations of the term using upper and lower case characters. e.g.
#
# "abc" -> {CBA cBA CbA cbA CBa cBa Cba cba}
#
proc casify {term {lRet {{}}}} {
if {$term==""} { return $lRet }
set t [string range $term 1 end]
set f1 [string toupper [string range $term 0 0]]
set f2 [string tolower [string range $term 0 0]]
set ret [list]
foreach x $lRet {
lappend ret "$x$f1"
lappend ret "$x$f2"
}
return [casify $t $ret]
}
proc vocab {} {
list abc def ghi jkl mno pqr stu vwx yza
}
# Return a random 3 letter term.
#
proc term {} {
if {[info exists ::expanded_vocab]==0} {
foreach v [vocab] { lappend ::expanded_vocab {*}[casify $v] }
}
select_one $::expanded_vocab
}
# Return a document - between 3 and 10 terms.
#
proc document {} {
set nTerm [expr [random 3] + 7]
set doc ""
for {set ii 0} {$ii < $nTerm} {incr ii} {
lappend doc [term]
}
set doc
}
db func document document
#-------------------------------------------------------------------------
expr srand(6)
set NDOC 200
set NLOOP 50
sqlite3_fts5_register_origintext db
proc tokens {cmd} {
set ret [list]
for {set iTok 0} {$iTok < [$cmd xInstCount]} {incr iTok} {
set txt [$cmd xInstToken $iTok 0]
set txt [string map [list "\0" "."] $txt]
lappend ret $txt
}
set ret
}
sqlite3_fts5_create_function db tokens tokens
proc rankfunc {cmd} {
$cmd xRowid
}
sqlite3_fts5_create_function db rankfunc rankfunc
proc ctrl_tokens {term args} {
set ret [list]
set term [string tolower $term]
foreach doc $args {
foreach a $doc {
if {[string tolower $a]==$term} {
if {$a==$term} {
lappend ret $a
} else {
lappend ret [string tolower $a].$a
}
}
}
}
set ret
}
db func ctrl_tokens ctrl_tokens
proc do_all_vocab_test {tn} {
foreach ::v [concat [vocab] nnn] {
set answer [execsql {
SELECT id, ctrl_tokens($::v, x) FROM ctrl WHERE x LIKE '%' || $::v || '%'
}]
do_execsql_test $tn.$::v.1 {
SELECT rowid, tokens(ft) FROM ft($::v)
} $answer
do_execsql_test $tn.$::v.2 {
SELECT rowid, tokens(ft) FROM ft($::v) ORDER BY rank
} $answer
}
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft USING fts5(
x, tokenize="origintext unicode61", content=, contentless_delete=1,
tokendata=1
);
CREATE TABLE ctrl(id INTEGER PRIMARY KEY, x TEXT);
INSERT INTO ft(ft, rank) VALUES('pgsz', 64);
INSERT INTO ft(ft, rank) VALUES('rank', 'rankfunc()');
}
do_test 1.1 {
for {set ii 0} {$ii < $NDOC} {incr ii} {
set doc [document]
execsql {
INSERT INTO ft(rowid, x) VALUES($ii, $doc);
INSERT INTO ctrl(id, x) VALUES($ii, $doc);
}
}
} {}
#execsql_pp { SELECT * FROM ctrl }
#execsql_pp { SELECT * FROM ft }
#fts5_aux_test_functions db
#execsql_pp { SELECT rowid, tokens(ft), fts5_test_poslist(ft) FROM ft('ghi'); }
do_all_vocab_test 1.2
for {set ii 0} {$ii < $NLOOP} {incr ii} {
set lRowid [execsql { SELECT id FROM ctrl WHERE random() % 2 }]
foreach r $lRowid {
execsql { DELETE FROM ft WHERE rowid = $r }
execsql { DELETE FROM ctrl WHERE rowid = $r }
set doc [document]
execsql { INSERT INTO ft(rowid, x) VALUES($r, $doc) }
execsql { INSERT INTO ctrl(id, x) VALUES($r, $doc) }
}
do_all_vocab_test 1.3.$ii
}
#-------------------------------------------------------------------------
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft2 USING fts5(
x, y, tokenize="origintext unicode61", content=, contentless_delete=1,
tokendata=1
);
CREATE TABLE ctrl2(id INTEGER PRIMARY KEY, x TEXT, y TEXT);
INSERT INTO ft2(ft2, rank) VALUES('pgsz', 64);
INSERT INTO ft2(ft2, rank) VALUES('rank', 'rankfunc()');
}
do_test 2.1 {
for {set ii 0} {$ii < $NDOC} {incr ii} {
set doc1 [document]
set doc2 [document]
execsql {
INSERT INTO ft2(rowid, x, y) VALUES($ii, $doc, $doc2);
INSERT INTO ctrl2(id, x, y) VALUES($ii, $doc, $doc2);
}
}
} {}
proc do_all_vocab_test2 {tn} {
foreach ::v [vocab] {
set answer [execsql {
SELECT id, ctrl_tokens($::v, x, y) FROM ctrl2
WHERE x LIKE '%' || $::v || '%' OR y LIKE '%' || $::v || '%';
}]
do_execsql_test $tn.$::v.1 {
SELECT rowid, tokens(ft2) FROM ft2($::v)
} $answer
do_execsql_test $tn.$::v.2 {
SELECT rowid, tokens(ft2) FROM ft2($::v) ORDER BY rank
} $answer
}
}
do_all_vocab_test2 2.2
for {set ii 0} {$ii < $NLOOP} {incr ii} {
set lRowid [execsql { SELECT id FROM ctrl2 WHERE random() % 2 }]
foreach r $lRowid {
execsql { DELETE FROM ft2 WHERE rowid = $r }
execsql { DELETE FROM ctrl2 WHERE rowid = $r }
set doc1 [document]
set doc2 [document]
execsql { INSERT INTO ft2(rowid, x, y) VALUES($r, $doc, $doc1) }
execsql { INSERT INTO ctrl2(id, x, y) VALUES($r, $doc, $doc2) }
}
do_all_vocab_test 2.3.$ii
}
#-------------------------------------------------------------------------
unset -nocomplain ::expanded_vocab
proc vocab {} {
list abcde fghij klmno
}
proc do_all_vocab_test3 {tn} {
foreach ::v [concat [vocab] nnn] {
set answer [execsql {
SELECT rowid, ctrl_tokens($::v, w) FROM ctrl3 WHERE w LIKE '%' || $::v || '%'
}]
do_execsql_test $tn.$::v.1 {
SELECT rowid, tokens(ft3) FROM ft3($::v)
} $answer
do_execsql_test $tn.$::v.2 {
SELECT rowid, tokens(ft3) FROM ft3($::v) ORDER BY rank
} $answer
}
}
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE ft3 USING fts5(
w, tokenize="origintext unicode61", content=, contentless_delete=1,
tokendata=1
);
INSERT INTO ft3(ft3, rank) VALUES('rank', 'rankfunc()');
CREATE TABLE ctrl3(w);
}
do_execsql_test 3.1 {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<2
)
INSERT INTO ctrl3 SELECT document() FROM s;
INSERT INTO ft3(rowid, w) SELECT rowid, w FROM ctrl3;
}
do_all_vocab_test3 3.2
finish_test
+67 -62
View File
@@ -86,71 +86,76 @@ do_execsql_test 2.8 {
# Tests with large/small rowid values.
#
reset_db
expr srand(0)
set vocab {
Popper Poppins Popsicle Porfirio Porrima Porsche
Porter Portia Portland Portsmouth Portugal Portuguese
Poseidon Post PostgreSQL Potemkin Potomac Potsdam
Pottawatomie Potter Potts Pound Poussin Powell
PowerPC PowerPoint Powers Powhatan Poznan Prada
Prado Praetorian Prague Praia Prakrit Pratchett
Pratt Pravda Praxiteles Preakness Precambrian Preminger
Premyslid Prensa Prentice Pres Presbyterian Presbyterianism
}
proc newdoc {} {
for {set i 0} {$i<8} {incr i} {
lappend ret [lindex $::vocab [expr int(abs(rand()) * [llength $::vocab])]]
foreach {tn cfg} {
1 ""
2 "INSERT INTO fff(fff, rank) VALUES('secure-delete', 1)"
} {
reset_db
expr srand(0)
set vocab {
Popper Poppins Popsicle Porfirio Porrima Porsche
Porter Portia Portland Portsmouth Portugal Portuguese
Poseidon Post PostgreSQL Potemkin Potomac Potsdam
Pottawatomie Potter Potts Pound Poussin Powell
PowerPC PowerPoint Powers Powhatan Poznan Prada
Prado Praetorian Prague Praia Prakrit Pratchett
Pratt Pravda Praxiteles Preakness Precambrian Preminger
Premyslid Prensa Prentice Pres Presbyterian Presbyterianism
}
set ret
}
db func newdoc newdoc
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE fff USING fts5(y);
INSERT INTO fff(fff, rank) VALUES('pgsz', 64);
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
INSERT INTO fff(fff, rank) VALUES('secure-delete', 1);
}
proc lshuffle {in} {
set out [list]
while {[llength $in]>0} {
set idx [expr int(abs(rand()) * [llength $in])]
lappend out [lindex $in $idx]
set in [lreplace $in $idx $idx]
}
set out
}
#dump fff
set iTest 1
foreach ii [lshuffle [db eval {SELECT rowid FROM fff}]] {
#if {$iTest==1} { dump fff }
#if {$iTest==1} { breakpoint }
do_execsql_test 3.1.$iTest.$ii {
DELETE FROM fff WHERE rowid=$ii;
}
#if {$iTest==1} { dump fff }
if {($iTest % 20)==0} {
do_execsql_test 3.1.$iTest.$ii.ic {
INSERT INTO fff(fff) VALUES('integrity-check');
proc newdoc {} {
for {set i 0} {$i<8} {incr i} {
lappend ret [lindex $::vocab [expr int(abs(rand()) * [llength $::vocab])]]
}
set ret
}
db func newdoc newdoc
do_execsql_test 3.$tn.0 {
CREATE VIRTUAL TABLE fff USING fts5(y);
INSERT INTO fff(fff, rank) VALUES('pgsz', 64);
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
}
execsql $cfg
proc lshuffle {in} {
set out [list]
while {[llength $in]>0} {
set idx [expr int(abs(rand()) * [llength $in])]
lappend out [lindex $in $idx]
set in [lreplace $in $idx $idx]
}
set out
}
#dump fff
set iTest 1
foreach ii [lshuffle [db eval {SELECT rowid FROM fff}]] {
#if {$iTest==1} { dump fff }
#if {$iTest==1} { breakpoint }
do_execsql_test 3.$tn.1.$iTest.$ii {
DELETE FROM fff WHERE rowid=$ii;
}
#if {$iTest==1} { dump fff }
if {($iTest % 20)==0} {
do_execsql_test 3.$tn.1.$iTest.$ii.ic {
INSERT INTO fff(fff) VALUES('integrity-check');
}
}
#if {$iTest==1} { break }
incr iTest
}
#if {$iTest==1} { break }
incr iTest
}
#execsql_pp { SELECT rowid FROM fff('post') ORDER BY rowid ASC }
+3 -1
View File
@@ -343,7 +343,9 @@ do_execsql_test 17.0 {
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
COMMIT;
}
do_execsql_test 17.1 { SELECT * FROM t2('y:a*') WHERE rowid BETWEEN 10 AND 20 }
do_execsql_test 17.1 {
SELECT * FROM t2('y:a*') WHERE rowid BETWEEN 10 AND 20
}
do_execsql_test 17.2 {
BEGIN;
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
+1 -1
View File
@@ -42,7 +42,7 @@ proc fts5_test_bothlist {cmd} {
}
sqlite3_fts5_create_function db fts5_test_bothlist fts5_test_bothlist
proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] }
proc fts5_rowid {cmd} { expr [$cmd xRowid] }
sqlite3_fts5_create_function db fts5_rowid fts5_rowid
do_execsql_test 1.$tok.0.1 "
+24
View File
@@ -280,6 +280,30 @@ do_catchsql_test 5.2 {
INSERT INTO t1 SELECT randomblob(3000) FROM v1
} {1 {query aborted}}
#-------------------------------------------------------------------------
reset_db
sqlite3_fts5_may_be_corrupt 1
do_execsql_test 6.0 {
BEGIN TRANSACTION;
CREATE VIRTUAL TABLE t1 USING fts5(a,b unindexed,c,tokenize="porter ascii",tokendata=1);
REPLACE INTO t1_data VALUES(1,X'03090009');
REPLACE INTO t1_data VALUES(10,X'000000000103030003010101020101030101');
REPLACE INTO t1_data VALUES(137438953473,X'0000002e023061010202010162010203010163010204010167010601020201016801060102030101690106010204040606060808');
REPLACE INTO t1_data VALUES(274877906945,X'0000001f013067020802010202010168020803010203010169020804010204040909');
REPLACE INTO t1_data VALUES(412316860417,X'0000002e023061030202010162030203010163030204010167030601020201016803060102030101690306010204040606060808');
COMMIT;
}
do_execsql_test 6.1 {
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1', 'row');
}
do_catchsql_test 6.2 {
SELECT * FROM t3;
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
+6
View File
@@ -107,6 +107,12 @@
# undef SQLITE_OMIT_UTF16 1
#endif
/**********************************************************************/
/* SQLITE_S... */
#ifndef SQLITE_STRICT_SUBTYPE
# define SQLITE_STRICT_SUBTYPE 1
#endif
/**********************************************************************/
/* SQLITE_T... */
#ifndef SQLITE_TEMP_STORE
+17 -17
View File
@@ -256,7 +256,7 @@ public final class CApi {
sqlite3_bind_nio_buffer().
*/
@Experimental
public static int sqlite3_bind_blob(
/*public*/ static int sqlite3_bind_blob(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data,
int begin, int n
){
@@ -269,7 +269,7 @@ public final class CApi {
final two arguments.
*/
@Experimental
public static int sqlite3_bind_blob(
/*public*/ static int sqlite3_bind_blob(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data
){
return sqlite3_bind_nio_buffer(stmt, ndx, data, 0, -1);
@@ -346,7 +346,7 @@ public final class CApi {
@see https://docs.oracle.com/javase/8/docs/api/java/nio/Buffer.html
*/
@Experimental
public static native int sqlite3_bind_nio_buffer(
/*public*/ static native int sqlite3_bind_nio_buffer(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data,
int beginPos, int howMany
);
@@ -356,7 +356,7 @@ public final class CApi {
contents, up to its limit() (as opposed to its capacity()).
*/
@Experimental
public static int sqlite3_bind_nio_buffer(
/*public*/ static int sqlite3_bind_nio_buffer(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable java.nio.ByteBuffer data
){
return sqlite3_bind_nio_buffer(stmt, ndx, data, 0, -1);
@@ -600,7 +600,7 @@ public final class CApi {
sqlite3_blob_read() (0 on success).
*/
@Experimental
public static int sqlite3_blob_read_nio_buffer(
/*public*/ static int sqlite3_blob_read_nio_buffer(
@NotNull sqlite3_blob src, int srcOffset,
@NotNull java.nio.ByteBuffer tgt, int tgtOffset, int howMany
){
@@ -624,7 +624,7 @@ public final class CApi {
for any reason.
*/
@Experimental
public static java.nio.ByteBuffer sqlite3_blob_read_nio_buffer(
/*public*/ static java.nio.ByteBuffer sqlite3_blob_read_nio_buffer(
@NotNull sqlite3_blob src, int srcOffset, int howMany
){
if( !JNI_SUPPORTS_NIO || src==null ) return null;
@@ -645,7 +645,7 @@ public final class CApi {
Overload alias for sqlite3_blob_read_nio_buffer().
*/
@Experimental
public static int sqlite3_blob_read(
/*public*/ static int sqlite3_blob_read(
@NotNull sqlite3_blob src, int srcOffset,
@NotNull java.nio.ByteBuffer tgt,
int tgtOffset, int howMany
@@ -668,7 +668,7 @@ public final class CApi {
the result of the underlying call to sqlite3_blob_read().
*/
@Experimental
public static int sqlite3_blob_read(
/*public*/ static int sqlite3_blob_read(
@NotNull sqlite3_blob src,
@NotNull java.nio.ByteBuffer tgt
){
@@ -727,7 +727,7 @@ public final class CApi {
returns the result of the underlying call to sqlite3_blob_read().
*/
@Experimental
public static int sqlite3_blob_write_nio_buffer(
/*public*/ static int sqlite3_blob_write_nio_buffer(
@NotNull sqlite3_blob tgt, int tgtOffset,
@NotNull java.nio.ByteBuffer src,
int srcOffset, int howMany
@@ -756,7 +756,7 @@ public final class CApi {
of b.
*/
@Experimental
public static int sqlite3_blob_write(
/*public*/ static int sqlite3_blob_write(
@NotNull sqlite3_blob tgt, int tgtOffset,
@NotNull java.nio.ByteBuffer src
){
@@ -770,7 +770,7 @@ public final class CApi {
of tgt.
*/
@Experimental
public static int sqlite3_blob_write(
/*public*/ static int sqlite3_blob_write(
@NotNull sqlite3_blob tgt,
@NotNull java.nio.ByteBuffer src
){
@@ -926,7 +926,7 @@ public final class CApi {
would return null for the same inputs.
*/
@Experimental
public static native java.nio.ByteBuffer sqlite3_column_nio_buffer(
/*public*/ static native java.nio.ByteBuffer sqlite3_column_nio_buffer(
@NotNull sqlite3_stmt stmt, int ndx
);
@@ -1848,7 +1848,7 @@ public final class CApi {
then this function behaves like sqlite3_result_error_toobig().
*/
@Experimental
public static native void sqlite3_result_nio_buffer(
/*public*/ static native void sqlite3_result_nio_buffer(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob,
int begin, int n
);
@@ -1858,7 +1858,7 @@ public final class CApi {
as the result blob content.
*/
@Experimental
public static void sqlite3_result_nio_buffer(
/*public*/ static void sqlite3_result_nio_buffer(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob
){
sqlite3_result_nio_buffer(cx, blob, 0, -1);
@@ -1963,7 +1963,7 @@ public final class CApi {
sqlite3_result_nio_buffer().
*/
@Experimental
public static void sqlite3_result_blob(
/*public*/ static void sqlite3_result_blob(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob,
int begin, int n
){
@@ -1975,7 +1975,7 @@ public final class CApi {
sqlite3_result_nio_buffer().
*/
@Experimental
public static void sqlite3_result_blob(
/*public*/ static void sqlite3_result_blob(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob
){
sqlite3_result_nio_buffer(cx, blob);
@@ -2387,7 +2387,7 @@ public final class CApi {
would return null for the same input.
*/
@Experimental
public static native java.nio.ByteBuffer sqlite3_value_nio_buffer(
/*public*/ static native java.nio.ByteBuffer sqlite3_value_nio_buffer(
@NotNull sqlite3_value v
);
@@ -625,10 +625,20 @@ public class TesterFts5 {
"SELECT fts5_columntext(ft, 1) FROM ft('x') ORDER BY rowid",
"[x, x, x y z, x z, x y z, x]"
);
do_execsql_test(db,
"SELECT fts5_columntext(ft, 2) FROM ft('x') ORDER BY rowid",
"[null, null, null, null, null, null]"
);
boolean threw = false;
try{
/* columntext() used to return NULLs when given an out-of bounds column
but now results in a range error. */
do_execsql_test(db,
"SELECT fts5_columntext(ft, 2) FROM ft('x') ORDER BY rowid",
"[null, null, null, null, null, null]"
);
}catch(Exception e){
threw = true;
affirm( e.getMessage().matches(".*column index out of range") );
}
affirm( threw );
threw = false;
/* Test fts5_columntotalsize() */
do_execsql_test(db,
+22
View File
@@ -38,6 +38,24 @@ static void noopfunc(
sqlite3_result_value(context, argv[0]);
}
/*
** Implementation of the multitype_text() function.
**
** The function returns its argument. The result will always have a
** TEXT value. But if the original input is numeric, it will also
** have that numeric value.
*/
static void multitypeTextFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
(void)argc;
(void)sqlite3_value_text(argv[0]);
sqlite3_result_value(context, argv[0]);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
@@ -64,5 +82,9 @@ int sqlite3_noop_init(
rc = sqlite3_create_function(db, "noop_nd", 1,
SQLITE_UTF8,
0, noopfunc, 0, 0);
if( rc ) return rc;
rc = sqlite3_create_function(db, "multitype_text", 1,
SQLITE_UTF8,
0, multitypeTextFunc, 0, 0);
return rc;
}
+59 -21
View File
@@ -26,9 +26,14 @@
**
** .load ./randomjson
** SELECT random_json(1);
** SELECT random_json5(1);
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#ifdef SQLITE_STATIC_RANDOMJSON
# include "sqlite3.h"
#else
# include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#endif
#include <assert.h>
#include <string.h>
#include <stdlib.h>
@@ -51,17 +56,18 @@ static unsigned int prngInt(Prng *p){
return p->x ^ p->y;
}
static const char *azJsonAtoms[] = {
/* JSON /* JSON-5 */
static char *azJsonAtoms[] = {
/* JSON JSON-5 */
"0", "0",
"1", "1",
"-1", "-1",
"2", "+2",
"3", "3",
"2.5", "2.5",
"3DDDD", "3DDDD",
"2.5DD", "2.5DD",
"0.75", ".75",
"-4.0e2", "-4.e2",
"5.0e-3", "+5e-3",
"6.DDe+0DD", "6.DDe+0DD",
"0", "0x0",
"512", "0x200",
"256", "+0x100",
@@ -73,12 +79,14 @@ static const char *azJsonAtoms[] = {
"-9.0e999", "-Infinity",
"9.0e999", "+Infinity",
"null", "NaN",
"-0.0005123", "-0.0005123",
"-0.0005DD", "-0.0005DD",
"4.35e-3", "+4.35e-3",
"\"gem\\\"hay\"", "\"gem\\\"hay\"",
"\"icy'joy\"", "'icy\\'joy\'",
"\"keylog\"", "\"key\\\nlog\"",
"\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"",
"\"oat\\r\\n\"", "\"oat\\r\\n\"",
"\"\\fpan\\b\"", "\"\\fpan\\b\"",
"{}", "{}",
"[]", "[]",
"[]", "[/*empty*/]",
@@ -89,19 +97,20 @@ static const char *azJsonAtoms[] = {
"\"day\"", "\"day\"",
"\"end\"", "'end'",
"\"fly\"", "\"fly\"",
"\"\\u00XX\\u00XX\"", "\"\\xXX\\xXX\"",
"\"y\\uXXXXz\"", "\"y\\uXXXXz\"",
"\"\"", "\"\"",
};
static const char *azJsonTemplate[] = {
static char *azJsonTemplate[] = {
/* JSON JSON-5 */
"{\"a\":%,\"b\":%,\"c\":%}", "{a:%,b:%,c:%}",
"{\"a\":%,\"b\":%,\"cDD\":%}", "{a:%,b:%,cDD:%}",
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}",
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,\"\":%}",
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,'':%}",
"{\"d\":%}", "{d:%}",
"{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}",
"{\"$g\":%,\"_h_\":%}", "{$g:%,_h_:%,}",
"{\"$g\":%,\"_h_\":%,\"a b c d\":%}", "{$g:%,_h_:%,\"a b c d\":%}",
"{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}",
"{\"a b c d\":%,\"e\":%,\"f\":%,\"x\":%,\"y\":%}",
"{\"a b c d\":%,e:%,f:%,x:%,y:%}",
"{\"\\u00XX\":%,\"\\uXXXX\":%}", "{\"\\xXX\":%,\"\\uXXXX\":%}",
"{\"Z\":%}", "{Z:%,}",
"[%]", "[%,]",
"[%,%]", "[%,%]",
@@ -122,15 +131,13 @@ static void jsonExpand(
unsigned int r /* Growth probability 0..1000. 0 means no growth */
){
unsigned int i, j, k;
const char *z;
char *z;
char *zX;
size_t n;
char zBuf[200];
j = 0;
if( zSrc==0 ){
k = prngInt(p)%(count(azJsonTemplate)/2);
k = k*2 + eType;
zSrc = azJsonTemplate[k];
}
if( zSrc==0 ) zSrc = "%";
if( strlen(zSrc)>=STRSZ/10 ) r = 0;
for(i=0; zSrc[i]; i++){
if( zSrc[i]!='%' ){
@@ -149,9 +156,36 @@ static void jsonExpand(
z = azJsonTemplate[k];
}
n = strlen(z);
if( (zX = strstr(z,"XX"))!=0 ){
unsigned int y = prngInt(p);
if( (y&0xff)==((y>>8)&0xff) ) y += 0x100;
while( (y&0xff)==((y>>16)&0xff) || ((y>>8)&0xff)==((y>>16)&0xff) ){
y += 0x10000;
}
memcpy(zBuf, z, n+1);
z = zBuf;
zX = strstr(z,"XX");
while( zX!=0 ){
zX[0] = "0123456789abcdef"[y%16]; y /= 16;
zX[1] = "0123456789abcdef"[y%16]; y /= 16;
zX = strstr(zX, "XX");
}
}else if( (zX = strstr(z,"DD"))!=0 ){
unsigned int y = prngInt(p);
memcpy(zBuf, z, n+1);
z = zBuf;
zX = strstr(z,"DD");
while( zX!=0 ){
zX[0] = "0123456789"[y%10]; y /= 10;
zX[1] = "0123456789"[y%10]; y /= 10;
zX = strstr(zX, "DD");
}
}
assert( strstr(z, "XX")==0 );
assert( strstr(z, "DD")==0 );
if( j+n<STRSZ ){
memcpy(&zDest[j], z, n);
j += n;
j += (int)n;
}
}
zDest[STRSZ-1] = 0;
@@ -178,7 +212,7 @@ static void randJsonFunc(
}
#ifdef _WIN32
__declspec(dllexport)
__declspec(dllexport)
#endif
int sqlite3_randomjson_init(
sqlite3 *db,
@@ -188,7 +222,11 @@ int sqlite3_randomjson_init(
static int cOne = 1;
static int cZero = 0;
int rc = SQLITE_OK;
#ifdef SQLITE_STATIC_RANDOMJSON
(void)pApi; /* Unused parameter */
#else
SQLITE_EXTENSION_INIT2(pApi);
#endif
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "random_json", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
+16 -2
View File
@@ -350,6 +350,20 @@ totype_atof_calc:
return z>=zEnd && nDigits>0 && eValid && nonNum==0;
}
/*
** Convert a floating point value to an integer. Or, if this cannot be
** done in a way that avoids 'outside the range of representable values'
** warnings from UBSAN, return 0.
**
** This function is a modified copy of internal SQLite function
** sqlite3RealToI64().
*/
static sqlite3_int64 totypeDoubleToInt(double r){
if( r<-9223372036854774784.0 ) return 0;
if( r>+9223372036854774784.0 ) return 0;
return (sqlite3_int64)r;
}
/*
** tointeger(X): If X is any value (integer, double, blob, or string) that
** can be losslessly converted into an integer, then make the conversion and
@@ -365,7 +379,7 @@ static void tointegerFunc(
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_FLOAT: {
double rVal = sqlite3_value_double(argv[0]);
sqlite3_int64 iVal = (sqlite3_int64)rVal;
sqlite3_int64 iVal = totypeDoubleToInt(rVal);
if( rVal==(double)iVal ){
sqlite3_result_int64(context, iVal);
}
@@ -440,7 +454,7 @@ static void torealFunc(
case SQLITE_INTEGER: {
sqlite3_int64 iVal = sqlite3_value_int64(argv[0]);
double rVal = (double)iVal;
if( iVal==(sqlite3_int64)rVal ){
if( iVal==totypeDoubleToInt(rVal) ){
sqlite3_result_double(context, rVal);
}
break;
+1
View File
@@ -582,6 +582,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
bNextPage = 1;
}else{
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
}
/* If this is a leaf intkey cell, load the rowid */
+1 -1
View File
@@ -236,7 +236,7 @@ static int test_sqlite3_recover_init(
zDb = Tcl_GetString(objv[2]);
if( zDb[0]=='\0' ) zDb = 0;
pNew = ckalloc(sizeof(TestRecover));
pNew = (TestRecover*)ckalloc(sizeof(TestRecover));
if( bSql==0 ){
zUri = Tcl_GetString(objv[3]);
pNew->p = sqlite3_recover_init(db, zDb, zUri);
+29 -22
View File
@@ -694,11 +694,9 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
** Clear the Rtree.pNodeBlob object
*/
static void nodeBlobReset(Rtree *pRtree){
if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
sqlite3_blob *pBlob = pRtree->pNodeBlob;
pRtree->pNodeBlob = 0;
sqlite3_blob_close(pBlob);
}
sqlite3_blob *pBlob = pRtree->pNodeBlob;
pRtree->pNodeBlob = 0;
sqlite3_blob_close(pBlob);
}
/*
@@ -717,7 +715,7 @@ static int nodeAcquire(
** increase its reference count and return it.
*/
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
if( pParent && pParent!=pNode->pParent ){
if( pParent && ALWAYS(pParent!=pNode->pParent) ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -742,7 +740,6 @@ static int nodeAcquire(
&pRtree->pNodeBlob);
}
if( rc ){
nodeBlobReset(pRtree);
*ppNode = 0;
/* If unable to open an sqlite3_blob on the desired row, that can only
** be because the shadow tables hold erroneous data. */
@@ -802,6 +799,7 @@ static int nodeAcquire(
}
*ppNode = pNode;
}else{
nodeBlobReset(pRtree);
if( pNode ){
pRtree->nNodeRef--;
sqlite3_free(pNode);
@@ -946,6 +944,7 @@ static void nodeGetCoord(
int iCoord, /* Which coordinate to extract */
RtreeCoord *pCoord /* OUT: Space to write result to */
){
assert( iCell<NCELL(pNode) );
readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
}
@@ -1135,7 +1134,9 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
sqlite3_finalize(pCsr->pReadAux);
sqlite3_free(pCsr);
pRtree->nCursor--;
nodeBlobReset(pRtree);
if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){
nodeBlobReset(pRtree);
}
return SQLITE_OK;
}
@@ -1720,7 +1721,11 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
int rc = SQLITE_OK;
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
if( rc==SQLITE_OK && ALWAYS(p) ){
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
if( p->iCell>=NCELL(pNode) ){
rc = SQLITE_ABORT;
}else{
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
}
}
return rc;
}
@@ -1738,6 +1743,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
if( rc ) return rc;
if( NEVER(p==0) ) return SQLITE_OK;
if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT;
if( i==0 ){
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else if( i<=pRtree->nDim2 ){
@@ -3219,8 +3225,7 @@ constraint:
*/
static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
Rtree *pRtree = (Rtree *)pVtab;
assert( pRtree->inWrTrans==0 );
pRtree->inWrTrans++;
pRtree->inWrTrans = 1;
return SQLITE_OK;
}
@@ -3234,6 +3239,9 @@ static int rtreeEndTransaction(sqlite3_vtab *pVtab){
nodeBlobReset(pRtree);
return SQLITE_OK;
}
static int rtreeRollback(sqlite3_vtab *pVtab){
return rtreeEndTransaction(pVtab);
}
/*
** The xRename method for rtree module virtual tables.
@@ -3352,7 +3360,7 @@ static sqlite3_module rtreeModule = {
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
rtreeEndTransaction, /* xRollback - rollback transaction */
rtreeRollback, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
rtreeSavepoint, /* xSavepoint */
@@ -3452,7 +3460,7 @@ static int rtreeSqlInit(
}
sqlite3_free(zSql);
}
if( pRtree->nAux ){
if( pRtree->nAux && rc!=SQLITE_NOMEM ){
pRtree->zReadAuxSql = sqlite3_mprintf(
"SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1",
zDb, zPrefix);
@@ -4141,15 +4149,13 @@ static int rtreeCheckTable(
check.zTab = zTab;
/* Find the number of auxiliary columns */
if( check.rc==SQLITE_OK ){
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
if( pStmt ){
nAux = sqlite3_column_count(pStmt) - 2;
sqlite3_finalize(pStmt);
}else
if( check.rc!=SQLITE_NOMEM ){
check.rc = SQLITE_OK;
}
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
if( pStmt ){
nAux = sqlite3_column_count(pStmt) - 2;
sqlite3_finalize(pStmt);
}else
if( check.rc!=SQLITE_NOMEM ){
check.rc = SQLITE_OK;
}
/* Find number of dimensions in the rtree table. */
@@ -4204,6 +4210,7 @@ static int rtreeIntegrity(
if( rc==SQLITE_OK && *pzErr ){
*pzErr = sqlite3_mprintf("In RTree %s.%s:\n%z",
pRtree->zDb, pRtree->zName, *pzErr);
if( (*pzErr)==0 ) rc = SQLITE_NOMEM;
}
return rc;
}
+273
View File
@@ -0,0 +1,273 @@
# 2024-02-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.
#
#***********************************************************************
#
# ROLLBACK in the middle of an RTREE query
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set testprefix rtreeJ
ifcapable !rtree { finish_test ; return }
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2);
INSERT INTO t1 VALUES(1, 1, 1), (2, 2, 2);
} {}
do_execsql_test 1.1 {
SELECT * FROM t1
} {1 1.0 1.0 2 2.0 2.0}
# If a ROLLBACK occurs that backs out changes to the RTREE, then
# all pending queries to the RTREE are aborted.
#
do_test 1.2 {
db eval {
BEGIN;
INSERT INTO t1 VALUES(3, 3, 3);
INSERT INTO t1 VALUES(4, 4, 4);
}
set rc [catch {
db eval { SELECT * FROM t1 } {
if {$id==1} {
db eval { ROLLBACK }
}
lappend res $id $x1 $x2
}
} msg]
list $rc $msg
} {1 {query aborted}}
do_execsql_test 1.3 {
SELECT * FROM t1;
} {1 1.0 1.0 2 2.0 2.0}
# A COMMIT of changes to the RTREE does not affect pending queries
#
do_test 1.4 {
set res {}
db eval {
BEGIN;
INSERT INTO t1 VALUES(5, 5, 5);
INSERT INTO t1 VALUES(6, 6, 6);
}
db eval { SELECT * FROM t1 } {
if {$id==1} {
db eval { COMMIT }
}
lappend res $id $x1 $x2
}
set res
} {1 1.0 1.0 2 2.0 2.0 5 5.0 5.0 6 6.0 6.0}
do_execsql_test 1.5 {
SELECT * FROM t1;
} {1 1.0 1.0 2 2.0 2.0 5 5.0 5.0 6 6.0 6.0}
do_execsql_test 1.6 {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,1,1),(2,2,2),(3,3,3),(4,4,4);
CREATE TABLE t2(x);
SELECT * FROM t1;
} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0 4 4.0 4.0}
# A rollback that does not affect the rtree table because
# the rtree table has not been written to does not cause
# a query abort.
#
do_test 1.7 {
set res {}
db eval {
BEGIN;
INSERT INTO t2(x) VALUES(12345);
}
db eval { SELECT * FROM t1 } {
if {$id==1} {
db eval { ROLLBACK }
}
lappend res $id $x1 $x2
}
set res
} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0 4 4.0 4.0}
# ROLLBACK TO that affects the RTREE does cause a query abort.
#
do_test 1.8 {
db eval {
DELETE FROM t1 WHERE rowid>1;
BEGIN;
DELETE FROM t2;
INSERT INTO t2(x) VALUES(23456);
SAVEPOINT 'one';
INSERT INTO t1 VALUES(2,2,2),(3,3,3);
}
set rc [catch {
db eval { SELECT * FROM t1 } {
if {$id==1} {
db eval { ROLLBACK TO 'one'; }
}
lappend res $id $x1 $x2
}
} msg]
list $rc $msg
} {1 {query aborted}}
do_execsql_test 1.9 {
COMMIT;
SELECT * FROM t1;
} {1 1.0 1.0}
# ROLLBACK TO that does not affect the RTREE does not cause a query abort.
#
do_execsql_test 1.10 {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,1,1),(2,2,2),(3,3,3);
BEGIN;
DELETE FROM t2;
INSERT INTO t2(x) VALUES(34567);
SAVEPOINT 'one';
INSERT INTO t2(x) VALUES('a string');
SELECT * FROM t1;
} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0}
do_test 1.11 {
set rc [catch {
set res {}
db eval { SELECT * FROM t1 } {
if {$id==2} {
# db eval { ROLLBACK TO 'one'; }
}
lappend res $id $x1 $x2
}
set res
} msg]
list $rc $msg
} {0 {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0}}
do_execsql_test 1.12 {
COMMIT;
SELECT * FROM t1;
} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0}
#----------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2);
INSERT INTO t1 VALUES(1, 1, 1), (2, 2, 2);
CREATE TABLE t2(x);
} {}
do_test 2.1 {
db eval {
BEGIN;
INSERT INTO t1 VALUES(3, 3, 3);
PRAGMA writable_schema = RESET;
}
set rc [catch {
db eval { SELECT x1, x2 FROM t1 } {
if {$x1==1} {
db eval { ROLLBACK }
}
lappend res $x1 $x2
}
} msg]
list $rc $msg
} {1 {query aborted}}
do_execsql_test 2.1 {
CREATE TABLE bak_node(nodeno, data);
CREATE TABLE bak_parent(nodeno, parentnode);
CREATE TABLE bak_rowid(rowid, nodeno);
}
proc save_t1 {} {
db eval {
DELETE FROM bak_node;
DELETE FROM bak_parent;
DELETE FROM bak_rowid;
INSERT INTO bak_node SELECT * FROM t1_node;
INSERT INTO bak_parent SELECT * FROM t1_parent;
INSERT INTO bak_rowid SELECT * FROM t1_rowid;
}
}
proc restore_t1 {} {
db eval {
DELETE FROM t1_node;
DELETE FROM t1_parent;
DELETE FROM t1_rowid;
INSERT INTO t1_node SELECT * FROM bak_node;
INSERT INTO t1_parent SELECT * FROM bak_parent;
INSERT INTO t1_rowid SELECT * FROM bak_rowid;
}
}
do_test 2.3 {
save_t1
db eval {
INSERT INTO t1 VALUES(3, 3, 3);
}
set rc [catch {
db eval { SELECT rowid, x1, x2 FROM t1 } {
if {$x1==1} {
restore_t1
}
lappend res $x1 $x2
}
} msg]
list $rc $msg
} {1 {query aborted}}
do_execsql_test 2.4 {
SELECT * FROM t1
} {1 1.0 1.0 2 2.0 2.0}
do_test 2.5 {
save_t1
db eval {
INSERT INTO t1 VALUES(3, 3, 3);
}
set rc [catch {
db eval { SELECT x1 FROM t1 } {
if {$x1==1} {
restore_t1
}
lappend res $x1 $x2
}
} msg]
list $rc $msg
} {1 {query aborted}}
do_execsql_test 2.6 {
SELECT * FROM t1
} {1 1.0 1.0 2 2.0 2.0}
do_test 2.7 {
save_t1
db eval {
INSERT INTO t1 VALUES(3, 3, 3);
}
set ::res [list]
set rc [catch {
db eval { SELECT 'abc' FROM t1 } {
if {$::res==[list]} {
restore_t1
set ::bDone 1
}
lappend res abc
}
} msg]
set res
} {abc abc abc}
do_execsql_test 2.6 {
SELECT * FROM t1
} {1 1.0 1.0 2 2.0 2.0}
finish_test
+1 -3
View File
@@ -2348,9 +2348,7 @@ void sqlite3session_delete(sqlite3_session *pSession){
** associated hash-tables. */
sessionDeleteTable(pSession, pSession->pTable);
/* Assert that all allocations have been freed and then free the
** session object itself. */
// assert( pSession->nMalloc==0 );
/* Free the session object. */
sqlite3_free(pSession);
}
+137 -45
View File
@@ -42,7 +42,9 @@
# 1) Consolidate the code generation for sqlite3*.*js into a script
# which generates the makefile code, rather than using $(call) and
# $(eval), or at least centralize the setup of the numerous vars
# related to each build variant $(JS_BUILD_MODES).
# related to each build variant $(JS_BUILD_MODES). (Update: an
# external script was attempted but it's even less legible than the
# $(eval) indirection going on in this file.
#
default: all
#default: quick
@@ -51,9 +53,39 @@ MAKEFILE := $(lastword $(MAKEFILE_LIST))
CLEAN_FILES :=
DISTCLEAN_FILES := ./--dummy--
release: oz
# JS_BUILD_MODES exists solely to reduce repetition in documentation
# below.
########################################################################
# JS_BUILD_NAMES exists for documentation purposes only. It enumerates
# the core build styles:
#
# - sqlite3 = canonical library build
#
# - sqlite3-wasmfs = WASMFS-capable library build
#
JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
########################################################################
# JS_BUILD_MODES exists for documentation purposes only. It enumerates
# the various "flavors" of build, each of which requires slight
# customization of the output:
#
# - vanilla = plain-vanilla JS for use in browsers. This is the
# canonical build mode.
#
# - esm = ES6 module, a.k.a. ESM, for use in browsers.
#
# - bundler-friendly = esm slightly tweaked for "bundler"
# tools. Bundlers are invariably based on node.js, so these builds
# are intended to be read at build-time by node.js but with a final
# target of browsers.
#
# - node = for use by node.js for node.js, as opposed to by node.js on
# behalf o browser-side code (use bundler-friendly for that). Note
# that persistent storage (OPFS) is not available in these builds.
#
JS_BUILD_MODES := vanilla esm bunder-friendly node
########################################################################
# Emscripten SDK home dir and related binaries...
EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/emsdk $(HOME)/src/emsdk))
emcc.bin ?= $(word 1,$(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) $(shell which emcc))
@@ -93,11 +125,14 @@ else
maybe-wasm-strip = $(wasm-strip)
endif
########################################################################
# dir.top = the top dir of the canonical build tree, where
# sqlite3.[ch] live.
dir.top := ../..
# Reminder: some Emscripten flags require absolute paths but we want
# relative paths for most stuff simply to reduce noise. The
# $(abspath...) GNU make function can transform relative paths to
# absolute.
# Maintenance reminder: some Emscripten flags require absolute paths
# but we want relative paths for most stuff simply to reduce
# noise. The $(abspath...) GNU make function can transform relative
# paths to absolute.
dir.wasm := $(patsubst %/,%,$(dir $(MAKEFILE)))
dir.api := api
dir.jacc := jaccwabyt
@@ -143,12 +178,14 @@ endif
# Set up sqlite3.c and sqlite3.h...
#
# To build with SEE (https://sqlite.org/see), either put sqlite3-see.c
# in the top of this build tree or pass
# sqlite3.c=PATH_TO_sqlite3-see.c to the build. Note that only
# encryption modules with no 3rd-party dependencies will currently
# work here: AES256-OFB, AES128-OFB, and AES128-CCM. Not
# coincidentally, those 3 modules are included in the sqlite3-see.c
# bundle.
# in $(dir.top) or pass sqlite3.c=PATH_TO_sqlite3-see.c to the $(MAKE)
# invocation. Note that only encryption modules with no 3rd-party
# dependencies will currently work here: AES256-OFB, AES128-OFB, and
# AES128-CCM. Not coincidentally, those 3 modules are included in the
# sqlite3-see.c bundle. Note, however, that distributing an SEE build
# of the WASM on a public site is in violation of the SEE license
# because it effectively provides a usable copy of the SEE build to
# all visitors.
#
# A custom sqlite3.c must not have any spaces in its name.
# $(sqlite3.canonical.c) must point to the sqlite3.c in
@@ -193,6 +230,10 @@ SQLITE_OPT = \
# can be used to find errant uses of sqlite3_js_vfs_create_file()
# in client code.
########################################################################@
# It's important that sqlite3.h be built to completion before any
# other parts of the build run, thus we use .NOTPARALLEL to disable
# parallel build of that file and its dependants.
.NOTPARALLEL: $(sqlite3.h)
$(sqlite3.h):
$(MAKE) -C $(dir.top) sqlite3.c
@@ -242,6 +283,7 @@ ifneq (,$(sqlite3_wasm_extra_init.c))
cflags.wasm_extra_init := -DSQLITE_WASM_EXTRA_INIT
endif
#########################################################################
# bin.version-info = binary to output various sqlite3 version info for
# embedding in the JS files and in building the distribution zip file.
# It must NOT be in $(dir.tmp) because we need it to survive the
@@ -251,11 +293,12 @@ bin.version-info := $(dir.top)/version-info
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
$(MAKE) -C $(dir.top) version-info
#########################################################################
# bin.stripcomments is used for stripping C/C++-style comments from JS
# files. The JS files contain large chunks of documentation which we
# don't need for all builds. That app's -k flag is of particular
# importance here, as it allows us to retain the opening comment
# blocks, which contain the license header and version info.
# block(s), which contain the license header and version info.
bin.stripccomments := $(dir.tool)/stripccomments
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
$(CC) -o $@ $<
@@ -287,6 +330,9 @@ DISTCLEAN_FILES += $(bin.stripccomments)
# c-pp.c was written specifically for the sqlite project's JavaScript
# builds but is maintained as a standalone project:
# https://fossil.wanderinghorse.net/r/c-pp
#
# Note that the SQLITE_... build flags used here have NO EFFECT on the
# JS/WASM build. They are solely for use with $(bin.c-pp) itself.
bin.c-pp := ./c-pp
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
@@ -347,6 +393,7 @@ emcc_opt_full := $(emcc_opt) -g3
# -Oz when small deliverable size is a priority.
########################################################################
########################################################################
# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
# -sEXPORTED_FUNCTION flag.
EXPORTED_FUNCTIONS.api.main := $(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api)
@@ -358,6 +405,7 @@ EXPORTED_FUNCTIONS.api := $(dir.tmp)/EXPORTED_FUNCTIONS.api
$(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
cat $(EXPORTED_FUNCTIONS.api.in) > $@
########################################################################
# sqlite3-license-version.js = generated JS file with the license
# header and version info.
sqlite3-license-version.js := $(dir.tmp)/sqlite3-license-version.js
@@ -370,20 +418,35 @@ sqlite3-api-build-version.js := $(dir.tmp)/sqlite3-api-build-version.js
# sqlite3-api.jses = the list of JS files which make up
# $(sqlite3-api.js.in), in the order they need to be assembled.
sqlite3-api.jses := $(sqlite3-license-version.js)
# sqlite3-api-prologue.js: initial boostrapping bits:
sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
# whwhasm.js and jaccwabyt.js: Low-level utils, mostly replacing
# Emscripten glue:
sqlite3-api.jses += $(dir.common)/whwasmutil.js
sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
# sqlite3-api-glue.js Glues the previous part together:
sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.js
# $(sqlite3-api-build-version.js) = library version info
sqlite3-api.jses += $(sqlite3-api-build-version.js)
# sqlite3-api-oo1.js = the oo1 API:
sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.js
# sqlite3-api-worker.js = the Worker1 API:
sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.js
# sqlite3-v-helper = helper APIs for VFSes and VTABLEs:
sqlite3-api.jses += $(dir.api)/sqlite3-v-helper.js
# sqlite3-vfs-opfs.c-pp.js = the first OPFS VFS:
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
# sqlite3-vfs-opfs-sahpool.c-pp.js = the second OPFS VFS:
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs-sahpool.c-pp.js
# sqlite3-api-cleanup.js = "finalizes" the build and cleans up
# any extraneous global symbols which are needed temporarily
# by the previous files.
sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
########################################################################
# SOAP.js is an external API file which is part of our distribution
# but not part of the sqlite3-api.js amalgamation.
# but not part of the sqlite3-api.js amalgamation. It's a component of
# the first OPFS VFS and necessarily an external file.
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js))
sqlite3-api.ext.jses += $(SOAP.js.bld)
@@ -438,7 +501,9 @@ endif
# emcc flags for .c/.o.
emcc.cflags :=
emcc.cflags += -std=c99 -fPIC
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c).
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c), primarily
# for variadic macros and snprintf() to implement
# sqlite3_wasm_enum_json().
emcc.cflags += -I. -I$(dir.top)
########################################################################
# emcc flags specific to building .js/.wasm files...
@@ -459,14 +524,16 @@ emcc.jsflags += -sIMPORTED_MEMORY
emcc.jsflags += -sSTRICT_JS=0
# STRICT_JS disabled due to:
# https://github.com/emscripten-core/emscripten/issues/18610
# TL;DR: does not work with MODULARIZE or EXPORT_ES6 as of version 3.1.31.
# TL;DR: does not work with MODULARIZE or EXPORT_ES6 as of version
# 3.1.31. The fix for that in newer emcc's is to throw a built-time
# error if STRICT_JS is used together with those options.
# -sENVIRONMENT values for the various build modes:
emcc.environment.vanilla := web,worker
emcc.environment.bundler-friendly := $(emcc.environment.vanilla)
emcc.environment.esm := $(emcc.environment.vanilla)
emcc.environment.node := node
# Note that adding "node" to the list for the other builds causes
# Note that adding ",node" to the list for the other builds causes
# Emscripten to generate code which confuses node: it cannot reliably
# determine whether the build is for a browser or for node.
@@ -518,13 +585,14 @@ emcc.jsflags += -sSTACK_SIZE=512KB
# extern-post-js.js. However... using a temporary symbol name here
# and then adding sqlite3InitModule() ourselves results in 2 global
# symbols: we cannot "delete" the Emscripten-defined
# $(sqlite3.js.init-func) because it's declared with "var".
# $(sqlite3.js.init-func) from vanilla builds (as opposed to ESM
# builds) because it's declared with "var".
sqlite3.js.init-func := sqlite3InitModule
emcc.jsflags += -sEXPORT_NAME=$(sqlite3.js.init-func)
emcc.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
#emcc.jsflags += -sSTRICT # fails due to missing __syscall_...()
#emcc.jsflags += -sALLOW_UNIMPLEMENTED_SYSCALLS
#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API
#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. fiddle needs the FS API
#emcc.jsflags += -sABORTING_MALLOC # only for experimentation
emcc.jsflags += -sALLOW_TABLE_GROWTH
# ^^^^ -sALLOW_TABLE_GROWTH is required for installing new SQL UDFs
@@ -568,15 +636,25 @@ emcc.jsflags += -sLLD_REPORT_UNDEFINED
# -g3 debugging info, _huge_.
########################################################################
########################################################################
# $(sqlite3-api-build-version.js) injects the build version info into
# the bundle in JSON form.
$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
@echo "Making $@..."
@{ \
echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
echo -n ' sqlite3.version = '; \
$(bin.version-info) --json; \
echo ';'; \
echo '});'; \
echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
echo -n ' sqlite3.version = '; \
$(bin.version-info) --json; \
echo ';'; \
echo '});'; \
} > $@
########################################################################
# $(sqlite3-license-version.js) contains the license header and
# in-comment build version info.
#
# Maintenance reminder: there are awk binaries out there which do not
# support -e SCRIPT.
$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
$(MAKEFILE)
@echo "Making $@..."; { \
@@ -584,8 +662,8 @@ $(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js)
echo '/*'; \
echo '** This code was built from sqlite3 version...'; \
echo "**"; \
awk -e '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' \
-e '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
awk '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' $(sqlite3.h); \
awk '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
echo "**"; \
echo "** Using the Emscripten SDK version $(emcc.version)."; \
echo '*/'; \
@@ -594,7 +672,11 @@ $(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js)
########################################################################
# --post-js and --pre-js are emcc flags we use to append/prepend JS to
# the generated emscripten module file. These rules set up the core
# pre/post files for use by the various builds.
# pre/post files for use by the various builds. --pre-js is used to
# inject code which needs to run as part of the pre-WASM-load phase.
# --post-js injects code which runs after the WASM module is loaded
# and includes the entirety of the library plus some
# Emscripten-specific post-bootstrapping code.
pre-js.js.in := $(dir.api)/pre-js.c-pp.js
post-js.js.in := $(dir.tmp)/post-js.c-pp.js
post-jses.js := \
@@ -612,18 +694,26 @@ $(post-js.js.in): $(post-jses.js) $(MAKEFILE)
########################################################################
# call-make-pre-post is a $(call)able which creates rules for
# pre-js-$(1)-$(2).js. $1 = the base name of the JS file on whose
# behalf this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is
# pre-js.$(1)-$(2).js. $1 = the base name of the JS file on whose
# behalf this pre-js is for (one of: $(JS_BUILD_NAMES)). $2 is
# the build mode: one of $(JS_BUILD_MODES). This sets up
# --[extern-][pre/post]-js flags in $(pre-post-$(1)-$(2).flags) and
# dependencies in $(pre-post-$(1)-$(2).deps). The resulting files get
# filtered using $(C-PP.FILTER). Any flags necessary for such
# filtering need to be set in $(c-pp.D.$(1)-$(2)) before $(call)ing
# this.
#
# Maintenance note: a shell script was written to generate these rules
# with the hope that it would make them more legible and maintainable,
# but embedding makefile code in another language makes it even less
# legible than having the level of $(eval) indirection which we have
# here.
define call-make-pre-post
pre-post-$(1)-$(2).flags ?=
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
pre-js.js.$(1)-$(2).intermediary := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).js
#$$(error $$(pre-js.js.$(1)-$(2).intermediary) $$(pre-js.js.$(1)-$(2)))
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2).intermediary),$$(c-pp.D.$(1)-$(2))))
post-js.js.$(1)-$(2) := $$(dir.tmp)/post-js.$(1)-$(2).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
extern-post-js.js.$(1)-$(2) := $$(dir.tmp)/extern-post-js.$(1)-$(2).js
@@ -634,8 +724,8 @@ pre-post-common.flags.$(1)-$(2) := \
--extern-post-js=$$(extern-post-js.js.$(1)-$(2))
pre-post-jses.$(1)-$(2).deps := $$(pre-post-jses.deps.common) \
$$(post-js.js.$(1)-$(2)) $$(extern-post-js.js.$(1)-$(2))
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(1)-$(2)) $$(MAKEFILE)
cp $$(pre-js.js.$(1)-$(2)) $$@
$$(pre-js.js.$(1)-$(2)): $$(pre-js.js.$(1)-$(2).intermediary) $$(MAKEFILE)
cp $$(pre-js.js.$(1)-$(2).intermediary) $$@
@if [ sqlite3-wasmfs = $(1) ]; then \
echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
elif [ sqlite3 != $(1) ]; then \
@@ -643,10 +733,10 @@ $$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(1)-$(2)) $$(MAKEFILE)
fi >> $$@
pre-post-$(1)-$(2).deps := \
$$(pre-post-jses.$(1)-$(2).deps) \
$$(dir.tmp)/pre-js-$(1)-$(2).js
$$(dir.tmp)/pre-js.$(1)-$(2).js
pre-post-$(1)-$(2).flags += \
$$(pre-post-common.flags.$(1)-$(2)) \
--pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
--pre-js=$$(dir.tmp)/pre-js.$(1)-$(2).js
endef
# /post-js and pre-js
########################################################################
@@ -683,8 +773,8 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
# Upstream RFE:
# https://github.com/emscripten-core/emscripten/issues/18237
#
# Maintenance reminder: Mac sed works differently than GNU sed, so
# don't use sed for this.
# Maintenance reminder: Mac sed works differently than GNU sed, so we
# use awk instead of sed for this.
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
if [ x1 = x$(1) ]; then \
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.RECIPE."; \
@@ -700,6 +790,7 @@ if [ x1 = x$(1) ]; then \
fi
endef
########################################################################
# extern-post-js* and extern-pre-js* are files for use with
# Emscripten's --extern-pre-js and --extern-post-js flags.
extern-pre-js.js := $(dir.api)/extern-pre-js.js
@@ -711,11 +802,12 @@ pre-post-common.flags := \
# pre-post-jses.deps.* = a list of dependencies for the
# --[extern-][pre/post]-js files.
pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
########################################################################
# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
# for one of the build modes.
#
# $1 = one of: sqlite3, sqlite3-wasmfs
# $1 = one of: $(JS_BUILD_NAMES)
# $2 = build mode name: one of $(JS_BUILD_MODES)
# $3 = 1 for ESM build mode, else 0
# $4 = resulting sqlite-api JS/MJS file
@@ -726,7 +818,8 @@ pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
# Maintenance reminder: be careful not to introduce spaces around args
# ($1, $2), otherwise string concatenation will malfunction.
#
# emcc.environment.$(2) must be set to a value for the -sENVIRONMENT flag.
# emcc.environment.$(2) must be set to a value for emcc's
# -sENVIRONMENT flag.
#
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
# CFLAGS to a given build mode.
@@ -781,8 +874,7 @@ sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0,\
$(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,esm,1,\
$(sqlite3-api.mjs), $(sqlite3.mjs), \
-Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META))
$(sqlite3-api.mjs), $(sqlite3.mjs), -Dtarget=es6-module))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,bundler-friendly,1,\
$(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly))
@@ -798,7 +890,7 @@ $(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,node,1,\
# -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for
# "bundler-friendly" ESM module build. These have some restrictions
# on how URL() objects are constructed in some contexts: URLs which
# refer to files which are part of this project must be references
# refer to files which are part of this project must be referenced
# as string literals so that bundlers' static-analysis tools can
# find those files and include them in their bundles.
#
@@ -854,7 +946,7 @@ dir.sql := sql
speedtest1 := ../../speedtest1
speedtest1.c := ../../test/speedtest1.c
speedtest1.sql := $(dir.sql)/speedtest1.sql
speedtest1.cliflags := --size 25 --big-transactions
speedtest1.cliflags := --size 10 --big-transactions
$(speedtest1):
$(MAKE) -C ../.. speedtest1
$(speedtest1.sql): $(speedtest1) $(MAKEFILE)
@@ -1087,4 +1179,4 @@ endif
# Run local web server for the test/demo pages.
httpd:
althttpd -max-age 1 -enable-sab -page index.html
althttpd -max-age 1 -enable-sab 1 -page index.html
+4 -1
View File
@@ -1,3 +1,4 @@
//#ifnot omit-oo1
/*
2022-07-22
@@ -1940,4 +1941,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}/*main-window-only bits*/
});
//#else
/* Built with the omit-oo1 flag. */
//#endif ifnot omit-oo1
+4
View File
@@ -1,3 +1,4 @@
//#ifnot omit-oo1
/**
2022-07-22
@@ -689,3 +690,6 @@ sqlite3.initWorker1API = function(){
globalThis.postMessage({type:'sqlite3-api',result:'worker1-ready'});
}.bind({sqlite3});
});
//#else
/* Built with the omit-oo1 flag. */
//#endif ifnot omit-oo1
+7 -1
View File
@@ -147,6 +147,12 @@
# define SQLITE_OS_KV_OPTIONAL 1
#endif
/**********************************************************************/
/* SQLITE_S... */
#ifndef SQLITE_STRICT_SUBTYPE
# define SQLITE_STRICT_SUBTYPE 1
#endif
/**********************************************************************/
/* SQLITE_T... */
#ifndef SQLITE_TEMP_STORE
@@ -1097,7 +1103,7 @@ const char * sqlite3_wasm_enum_json(void){
M(xShadowName, "i(s)");
} _StructBinder;
#undef CurrentStruct
/**
** Workaround: in order to map the various inner structs from
** sqlite3_index_info, we have to uplift those into constructs we
@@ -1,3 +1,4 @@
//#ifnot omit-oo1
/*
2022-08-24
@@ -199,10 +200,11 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
msg = Object.create(null);
msg.type = arguments[0];
msg.args = arguments[1];
msg.dbId = msg.args.dbId;
}else{
toss("Invalid arugments for sqlite3Worker1Promiser()-created factory.");
}
if(!msg.dbId) msg.dbId = dbId;
if(!msg.dbId && msg.type!=='open') msg.dbId = dbId;
msg.messageId = genMsgId(msg);
msg.departureTime = performance.now();
const proxy = Object.create(null);
@@ -275,3 +277,6 @@ globalThis.sqlite3Worker1Promiser.defaultConfig = {
,
onerror: (...args)=>console.error('worker1 promiser error',...args)
};
//#else
/* Built with the omit-oo1 flag. */
//#endif ifnot omit-oo1
+4
View File
@@ -1,3 +1,4 @@
//#ifnot omit-oo1
/*
2022-05-23
@@ -48,3 +49,6 @@ import {default as sqlite3InitModule} from './sqlite3-bundler-friendly.mjs';
}
//#endif
sqlite3InitModule().then(sqlite3 => sqlite3.initWorker1API());
//#else
/* Built with the omit-oo1 flag. */
//#endif ifnot omit-oo1
+86
View File
@@ -0,0 +1,86 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="common/testing.css"/>
<title>sqlite3-api batch SQL runner for the SAHPool VFS</title>
</head>
<body>
<header id='titlebar'><span>sqlite3-api batch SQL runner for the SAHPool VFS</span></header>
<div>
<span class='input-wrapper'>
<input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
<label for='cb-reverse-log-order' id='lbl-reverse-log-order'>Reverse log order</label>
</span>
</div>
<div id='test-output' class='reverse'></div>
<script>
(function(){
const E = (sel)=>document.querySelector(sel);
const eOut = E('#test-output');
const log2 = function(cssClass,...args){
let ln;
if(1 || cssClass){
ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' ')));
}else{
// This doesn't work with the "reverse order" option!
ln = document.createTextNode(args.join(' ')+'\n');
}
eOut.append(ln);
};
const log = (...args)=>{
//console.log(...args);
log2('', ...args);
};
const logErr = function(...args){
console.error(...args);
log2('error', ...args);
};
const logWarn = function(...args){
console.warn(...args);
log2('warning', ...args);
};
const cbReverseLog = E('#cb-reverse-log-order');
const lblReverseLog = E('#lbl-reverse-log-order');
if(cbReverseLog.checked){
lblReverseLog.classList.add('warning');
eOut.classList.add('reverse');
}
cbReverseLog.addEventListener('change', function(){
if(this.checked){
eOut.classList.add('reverse');
lblReverseLog.classList.add('warning');
}else{
eOut.classList.remove('reverse');
lblReverseLog.classList.remove('warning');
}
}, false);
const w = new Worker('batch-runner-sahpool.js?sqlite3.dir=jswasm');
w.onmessage = function(msg){
msg = msg.data;
switch(msg.type){
case 'stdout': log(...msg.data); break;
case 'warn': logWarn(...msg.data); break;
case 'error': logErr(...msg.data); break;
default:
logErr("Unhandled worker message type:",msg);
break;
}
};
})();
</script>
<style>
#test-output {
white-space: break-spaces;
overflow: auto;
}
</style>
</body>
</html>
+341
View File
@@ -0,0 +1,341 @@
/*
2023-11-30
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic batch SQL runner for the SAHPool VFS. This file must be run in
a worker thread. This is not a full-featured app, just a way to get some
measurements for batch execution of SQL for the OPFS SAH Pool VFS.
*/
'use strict';
const wMsg = function(msgType,...args){
postMessage({
type: msgType,
data: args
});
};
const toss = function(...args){throw new Error(args.join(' '))};
const warn = (...args)=>{ wMsg('warn',...args); };
const error = (...args)=>{ wMsg('error',...args); };
const log = (...args)=>{ wMsg('stdout',...args); }
let sqlite3;
const urlParams = new URL(globalThis.location.href).searchParams;
const cacheSize = (()=>{
if(urlParams.has('cachesize')) return +urlParams.get('cachesize');
return 200;
})();
/** Throws if the given sqlite3 result code is not 0. */
const checkSqliteRc = (dbh,rc)=>{
if(rc) toss("Prepare failed:",sqlite3.capi.sqlite3_errmsg(dbh));
};
const sqlToDrop = [
"SELECT type,name FROM sqlite_schema ",
"WHERE name NOT LIKE 'sqlite\\_%' escape '\\' ",
"AND name NOT LIKE '\\_%' escape '\\'"
].join('');
const clearDbSqlite = function(db){
// This would be SO much easier with the oo1 API, but we specifically want to
// inject metrics we can't get via that API, and we cannot reliably (OPFS)
// open the same DB twice to clear it using that API, so...
const rc = sqlite3.wasm.exports.sqlite3_wasm_db_reset(db.handle);
log("reset db rc =",rc,db.id, db.filename);
};
const App = {
db: undefined,
cache:Object.create(null),
log: log,
warn: warn,
error: error,
metrics: {
fileCount: 0,
runTimeMs: 0,
prepareTimeMs: 0,
stepTimeMs: 0,
stmtCount: 0,
strcpyMs: 0,
sqlBytes: 0
},
fileList: undefined,
execSql: async function(name,sql){
const db = this.db;
const banner = "========================================";
this.log(banner,
"Running",name,'('+sql.length,'bytes)');
const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
let pStmt = 0, pSqlBegin;
const metrics = db.metrics = Object.create(null);
metrics.prepTotal = metrics.stepTotal = 0;
metrics.stmtCount = 0;
metrics.malloc = 0;
metrics.strcpy = 0;
if(this.gotErr){
this.error("Cannot run SQL: error cleanup is pending.");
return;
}
// Run this async so that the UI can be updated for the above header...
const endRun = ()=>{
metrics.evalSqlEnd = performance.now();
metrics.evalTimeTotal = (metrics.evalSqlEnd - metrics.evalSqlStart);
this.log("metrics:",JSON.stringify(metrics, undefined, ' '));
this.log("prepare() count:",metrics.stmtCount);
this.log("Time in prepare_v2():",metrics.prepTotal,"ms",
"("+(metrics.prepTotal / metrics.stmtCount),"ms per prepare())");
this.log("Time in step():",metrics.stepTotal,"ms",
"("+(metrics.stepTotal / metrics.stmtCount),"ms per step())");
this.log("Total runtime:",metrics.evalTimeTotal,"ms");
this.log("Overhead (time - prep - step):",
(metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
this.log(banner,"End of",name);
this.metrics.prepareTimeMs += metrics.prepTotal;
this.metrics.stepTimeMs += metrics.stepTotal;
this.metrics.stmtCount += metrics.stmtCount;
this.metrics.strcpyMs += metrics.strcpy;
this.metrics.sqlBytes += sql.length;
};
const runner = function(resolve, reject){
++this.metrics.fileCount;
metrics.evalSqlStart = performance.now();
const stack = wasm.scopedAllocPush();
try {
let t, rc;
let sqlByteLen = sql.byteLength;
const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
t = performance.now();
pSqlBegin = wasm.scopedAlloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
metrics.malloc = performance.now() - t;
metrics.byteLength = sqlByteLen;
let pSql = pSqlBegin;
const pSqlEnd = pSqlBegin + sqlByteLen;
t = performance.now();
wasm.heap8().set(sql, pSql);
wasm.poke(pSql + sqlByteLen, 0);
//log("SQL:",wasm.cstrToJs(pSql));
metrics.strcpy = performance.now() - t;
let breaker = 0;
while(pSql && wasm.peek8(pSql)){
wasm.pokePtr(ppStmt, 0);
wasm.pokePtr(pzTail, 0);
t = performance.now();
rc = capi.sqlite3_prepare_v2(
db.handle, pSql, sqlByteLen, ppStmt, pzTail
);
metrics.prepTotal += performance.now() - t;
checkSqliteRc(db.handle, rc);
pStmt = wasm.peekPtr(ppStmt);
pSql = wasm.peekPtr(pzTail);
sqlByteLen = pSqlEnd - pSql;
if(!pStmt) continue/*empty statement*/;
++metrics.stmtCount;
t = performance.now();
rc = capi.sqlite3_step(pStmt);
capi.sqlite3_finalize(pStmt);
pStmt = 0;
metrics.stepTotal += performance.now() - t;
switch(rc){
case capi.SQLITE_ROW:
case capi.SQLITE_DONE: break;
default: checkSqliteRc(db.handle, rc); toss("Not reached.");
}
}
resolve(this);
}catch(e){
if(pStmt) capi.sqlite3_finalize(pStmt);
this.gotErr = e;
reject(e);
}finally{
capi.sqlite3_exec(db.handle,"rollback;",0,0,0);
wasm.scopedAllocPop(stack);
}
}.bind(this);
const p = new Promise(runner);
return p.catch(
(e)=>this.error("Error via execSql("+name+",...):",e.message)
).finally(()=>{
endRun();
});
},
/**
Loads batch-runner.list and populates the selection list from
it. Returns a promise which resolves to nothing in particular
when it completes. Only intended to be run once at the start
of the app.
*/
loadSqlList: async function(){
const infile = 'batch-runner.list';
this.log("Loading list of SQL files:", infile);
let txt;
try{
const r = await fetch(infile);
if(404 === r.status){
toss("Missing file '"+infile+"'.");
}
if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
txt = await r.text();
}catch(e){
this.error(e.message);
throw e;
}
App.fileList = txt.split(/\n+/).filter(x=>!!x);
this.log("Loaded",infile);
},
/** Fetch ./fn and return its contents as a Uint8Array. */
fetchFile: async function(fn, cacheIt=false){
if(cacheIt && this.cache[fn]) return this.cache[fn];
this.log("Fetching",fn,"...");
let sql;
try {
const r = await fetch(fn);
if(!r.ok) toss("Fetch failed:",r.statusText);
sql = new Uint8Array(await r.arrayBuffer());
}catch(e){
this.error(e.message);
throw e;
}
this.log("Fetched",sql.length,"bytes from",fn);
if(cacheIt) this.cache[fn] = sql;
return sql;
}/*fetchFile()*/,
/**
Converts this.metrics() to a form which is suitable for easy conversion to
CSV. It returns an array of arrays. The first sub-array is the column names.
The 2nd and subsequent are the values, one per test file (only the most recent
metrics are kept for any given file).
*/
metricsToArrays: function(){
const rc = [];
Object.keys(this.dbs).sort().forEach((k)=>{
const d = this.dbs[k];
const m = d.metrics;
delete m.evalSqlStart;
delete m.evalSqlEnd;
const mk = Object.keys(m).sort();
if(!rc.length){
rc.push(['db', ...mk]);
}
const row = [k.split('/').pop()/*remove dir prefix from filename*/];
rc.push(row);
row.push(...mk.map((kk)=>m[kk]));
});
return rc;
},
metricsToBlob: function(colSeparator='\t'){
const ar = [], ma = this.metricsToArrays();
if(!ma.length){
this.error("Metrics are empty. Run something.");
return;
}
ma.forEach(function(row){
ar.push(row.join(colSeparator),'\n');
});
return new Blob(ar);
},
/**
Fetch file fn and eval it as an SQL blob. This is an async
operation and returns a Promise which resolves to this
object on success.
*/
evalFile: async function(fn){
const sql = await this.fetchFile(fn);
return this.execSql(fn,sql);
}/*evalFile()*/,
/**
Fetches the handle of the db associated with
this.e.selImpl.value, opening it if needed.
*/
initDb: function(){
const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
const stack = wasm.scopedAllocPush();
let pDb = 0;
const d = Object.create(null);
d.filename = "/batch.db";
try{
const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
const ppDb = wasm.scopedAllocPtr();
const rc = capi.sqlite3_open_v2(d.filename, ppDb, oFlags, this.PoolUtil.vfsName);
pDb = wasm.peekPtr(ppDb)
if(rc) toss("sqlite3_open_v2() failed with code",rc);
capi.sqlite3_exec(pDb, "PRAGMA cache_size="+cacheSize, 0, 0, 0);
this.log("cache_size =",cacheSize);
}catch(e){
if(pDb) capi.sqlite3_close_v2(pDb);
throw e;
}finally{
wasm.scopedAllocPop(stack);
}
d.handle = pDb;
this.log("Opened db:",d.filename,'@',d.handle);
return d;
},
closeDb: function(){
if(this.db.handle){
this.sqlite3.capi.sqlite3_close_v2(this.db.handle);
this.db.handle = undefined;
}
},
run: async function(sqlite3){
delete this.run;
this.sqlite3 = sqlite3;
const capi = sqlite3.capi, wasm = sqlite3.wasm;
this.log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
this.log("WASM heap size =",wasm.heap8().length);
let timeStart;
sqlite3.installOpfsSAHPoolVfs({
clearOnInit: true, initialCapacity: 4,
name: 'batch-sahpool',
verbosity: 2
}).then(PoolUtil=>{
App.PoolUtil = PoolUtil;
App.db = App.initDb();
})
.then(async ()=>this.loadSqlList())
.then(async ()=>{
timeStart = performance.now();
for(let i = 0; i < App.fileList.length; ++i){
const fn = App.fileList[i];
await App.evalFile(fn);
if(App.gotErr) throw App.gotErr;
}
})
.then(()=>{
App.metrics.runTimeMs = performance.now() - timeStart;
App.log("total metrics:",JSON.stringify(App.metrics, undefined, ' '));
App.log("Reload the page to run this again.");
App.closeDb();
App.PoolUtil.removeVfs();
})
.catch(e=>this.error("ERROR:",e));
}/*run()*/
}/*App*/;
let sqlite3Js = 'sqlite3.js';
if(urlParams.has('sqlite3.dir')){
sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
}
importScripts(sqlite3Js);
globalThis.sqlite3InitModule().then(async function(sqlite3_){
log("Done initializing. Running batch runner...");
sqlite3 = sqlite3_;
App.run(sqlite3_);
});
+20 -4
View File
@@ -72,7 +72,6 @@
App.logHtml("reset db rc =",rc,db.id, db.filename);
};
const E = (s)=>document.querySelector(s);
const App = {
e: {
@@ -91,6 +90,15 @@
db: Object.create(null),
dbs: Object.create(null),
cache:{},
metrics: {
fileCount: 0,
runTimeMs: 0,
prepareTimeMs: 0,
stepTimeMs: 0,
stmtCount: 0,
strcpyMs: 0,
sqlBytes: 0
},
log: console.log.bind(console),
warn: console.warn.bind(console),
cls: function(){this.e.output.innerHTML = ''},
@@ -117,7 +125,6 @@
"Running",name,'('+sql.length,'bytes) using',db.id);
const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
let pStmt = 0, pSqlBegin;
const stack = wasm.scopedAllocPush();
const metrics = db.metrics = Object.create(null);
metrics.prepTotal = metrics.stepTotal = 0;
metrics.stmtCount = 0;
@@ -142,6 +149,11 @@
this.logHtml("Overhead (time - prep - step):",
(metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
this.logHtml(banner,"End of",name);
this.metrics.prepareTimeMs += metrics.prepTotal;
this.metrics.stepTimeMs += metrics.stepTotal;
this.metrics.stmtCount += metrics.stmtCount;
this.metrics.strcpyMs += metrics.strcpy;
this.metrics.sqlBytes += sql.length;
};
let runner;
@@ -214,7 +226,9 @@
}.bind(this);
}else{/*sqlite3 db...*/
runner = function(resolve, reject){
++this.metrics.fileCount;
metrics.evalSqlStart = performance.now();
const stack = wasm.scopedAllocPush();
try {
let t;
let sqlByteLen = sql.byteLength;
@@ -269,7 +283,7 @@
let p;
if(1){
p = new Promise(function(res,rej){
setTimeout(()=>runner(res, rej), 50)/*give UI a chance to output the "running" banner*/;
setTimeout(()=>runner(res, rej), 0)/*give UI a chance to output the "running" banner*/;
});
}else{
p = new Promise(runner);
@@ -401,7 +415,7 @@
});
return new Blob(ar);
},
downloadMetrics: function(){
const b = this.metricsToBlob();
if(!b) return;
@@ -576,6 +590,8 @@
const timeTotal = performance.now() - timeStart;
who.logHtml("Run-remaining time:",timeTotal,"ms ("+(timeTotal/1000/60)+" minute(s))");
who.clearStorage();
App.metrics.runTimeMs = timeTotal;
who.logHtml("Total metrics:",JSON.stringify(App.metrics,undefined,' '));
}, false);
}/*run()*/
}/*App*/;
+8 -7
View File
@@ -20,7 +20,7 @@
the main (UI) thread.
*/
let logHtml;
if(self.window === self /* UI thread */){
if(globalThis.window === globalThis /* UI thread */){
console.log("Running demo from main UI thread.");
logHtml = function(cssClass,...args){
const ln = document.createElement('div');
@@ -250,7 +250,7 @@
}/*demo1()*/;
log("Loading and initializing sqlite3 module...");
if(self.window!==self) /*worker thread*/{
if(globalThis.window!==globalThis) /*worker thread*/{
/*
If sqlite3.js is in a directory other than this script, in order
to get sqlite3.js to resolve sqlite3.wasm properly, we have to
@@ -262,19 +262,20 @@
that's not needed.
URL arguments passed as part of the filename via importScripts()
are simply lost, and such scripts see the self.location of
are simply lost, and such scripts see the globalThis.location of
_this_ script.
*/
let sqlite3Js = 'sqlite3.js';
const urlParams = new URL(self.location.href).searchParams;
const urlParams = new URL(globalThis.location.href).searchParams;
if(urlParams.has('sqlite3.dir')){
sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
}
importScripts(sqlite3Js);
}
self.sqlite3InitModule({
// We can redirect any stdout/stderr from the module
// like so...
globalThis.sqlite3InitModule({
/* We can redirect any stdout/stderr from the module like so, but
note that doing so makes use of Emscripten-isms, not
well-defined sqlite APIs. */
print: log,
printErr: error
}).then(function(sqlite3){
+3 -6
View File
@@ -46,6 +46,9 @@
file:// URLs.</li>
<li>Any OPFS-related pages or tests require:
<ul>
<li>An OPFS-capable browser released after February
2023. Some tests will work with Chromium-based browsers
going back to around v102.</li>
<li>That the web server emit the so-called
<a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a>
and
@@ -53,12 +56,6 @@
headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the
<code>-enable-sab</code> flag for that.
</li>
<li>A very recent version of a Chromium-based browser
(v102 at least, possibly newer). OPFS support in the
other major browsers is pending. Development and testing
is currently done against a dev-channel release of
Chrome (v111 as of 2023-02-10).
</li>
</ul>
</li>
</ul>
+3 -6
View File
@@ -31,6 +31,9 @@
file:// URLs.</li>
<li>Any OPFS-related pages or tests require:
<ul>
<li>An OPFS-capable browser released after February
2023. Some tests will work with Chromium-based browsers
going back to around v102.</li>
<li>That the web server emit the so-called
<a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a>
and
@@ -38,12 +41,6 @@
headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the
<code>-enable-sab</code> flag for that.
</li>
<li>A very recent version of a
Chromium-based browser (v102 at least, possibly newer). OPFS
support in the other major browsers is pending. Development
and testing is currently done against a dev-channel release
of Chrome (v111 as of 2023-02-10).
</li>
</ul>
</li>
</ul>
+2 -3
View File
@@ -206,9 +206,8 @@ const MyBinder = StructBinderFactory({
It also offers a number of other settings, but all are optional except
for the ones shown above. Those three config options abstract away
details which are specific to a given WASM environment. They provide
the WASM "heap" memory (a byte array), the memory allocator, and the
deallocator. In a conventional Emscripten setup, that config might
simply look like:
the WASM "heap" memory, the memory allocator, and the deallocator. In
a conventional Emscripten setup, that config might simply look like:
>
```javascript
+1 -1
View File
@@ -350,7 +350,7 @@
eControls.classList.remove('hidden');
break;
case 'stdout': log(msg.data); break;
case 'stdout': logErr(msg.data); break;
case 'stderr': logErr(msg.data); break;
case 'run-start':
eControls.disabled = true;
log("Running speedtest1 with argv =",msg.data.join(' '));
+5 -18
View File
@@ -7,9 +7,9 @@
}
importScripts(speedtestJs);
/**
If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns
an empty string.
If this build includes WASMFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it
returns an empty string.
*/
const wasmfsDir = function f(wasmUtil){
if(undefined !== f._) return f._;
@@ -47,6 +47,7 @@
};
const log = (...args)=>logMsg('stdout',args);
const logErr = (...args)=>logMsg('stderr',args);
const realSahName = 'opfs-sahpool-speedtest1';
const runSpeedtest = async function(cliFlagsArray){
const scope = App.wasm.scopedAllocPush();
@@ -57,7 +58,6 @@
];
App.logBuffer.length = 0;
const ndxSahPool = argv.indexOf('opfs-sahpool');
const realSahName = 'opfs-sahpool-speedtest1';
if(ndxSahPool>0){
argv[ndxSahPool] = realSahName;
log("Updated argv for opfs-sahpool: --vfs",realSahName);
@@ -73,7 +73,7 @@
clearOnInit: true,
verbosity: 2
}).then(PoolUtil=>{
log("opfs-sahpool successfully installed as",realSahName);
log("opfs-sahpool successfully installed as",PoolUtil.vfsName);
App.sqlite3.$SAHPoolUtil = PoolUtil;
//console.log("sqlite3.oo1.OpfsSAHPoolDb =", App.sqlite3.oo1.OpfsSAHPoolDb);
});
@@ -102,19 +102,6 @@
}
};
const sahpSanityChecks = function(sqlite3){
log("Attempting OpfsSAHPoolDb sanity checks...");
const db = new sqlite3.oo1.OpfsSAHPoolDb('opfs-sahpoool.db');
const fn = db.filename;
db.exec([
'create table t(a);',
'insert into t(a) values(1),(2),(3);'
]);
db.close();
sqlite3.wasm.sqlite3_wasm_vfs_unlink(sqlite3_vfs_find("opfs-sahpool"), fn);
log("SAH sanity checks done.");
};
const EmscriptenModule = {
print: log,
printErr: logErr,
+6
View File
@@ -360,6 +360,7 @@ TESTSRC += \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/qpvtab.c \
$(TOP)/ext/misc/randomjson.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
@@ -526,12 +527,15 @@ FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZCHECK_OPT += -DSQLITE_STRICT_SUBTYPE=1
FUZZCHECK_OPT += -DSQLITE_STATIC_RANDOMJSON
FUZZSRC += $(TOP)/test/fuzzcheck.c
FUZZSRC += $(TOP)/test/ossfuzz.c
FUZZSRC += $(TOP)/test/vt02.c
FUZZSRC += $(TOP)/test/fuzzinvariants.c
FUZZSRC += $(TOP)/ext/recover/dbdata.c
FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZSRC += $(TOP)/ext/misc/randomjson.c
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_OPT = -DSQLITE_THREADSAFE=0
@@ -898,6 +902,8 @@ TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
TESTFIXTURE_FLAGS += -DSQLITE_STATIC_RANDOMJSON
TESTFIXTURE_FLAGS += -DSQLITE_STRICT_SUBTYPE=1
testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
+145 -128
View File
@@ -1,13 +1,13 @@
C Enhance\sjson_set()\sand\sjson_insert()\sso\sthat\sthey\screate\smissing\nsubstructure.
D 2023-11-30T19:06:27.003
C Version\s3.45.2
D 2024-03-12T11:06:23.127
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 890caf094636c308bc981032baf8f9208bf307755f9197ae4218a9fbcec2e449
F Makefile.in 24be65ae641c5727bbc247d60286a15ecc24fb80f14f8fb2d32533bf0ec96e79
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 59bb36dba001f0b38212be0794fb838f25371008b180929bcf08aa799694c168
F README.md 963d30019abf0cc06b263cd2824bce022893f3f93a531758f6f04ff2194a16a8
F VERSION 73573d4545343f001bf5dc5461173a7c78c203dd046cabcf99153878cf25d3a6
F Makefile.msc df56c06ef05add5ebcdcc9d4823fb2ec66ac16b06acb6971a7420859025886fa
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
F VERSION 0aec26ad81430ff6a34a47daacf854d2fe0d0aae2b822230f949082f0adfffe7
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -15,14 +15,14 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 34f8c222846db1b354720c8a78a4fa7dec9176ea447c0fffdf442b7f74e8b1df
F autoconf/Makefile.msc ac338c36a338f6b49475da71930f45145a181d6b551578d5a7a64f113ef27b2c
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
F autoconf/tea/Makefile.in 106a96f2f745d41a0f6193f1de98d7355830b65d45032c18cd7c90295ec24196
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
F autoconf/tea/configure.ac 4c32b08691a5b296206b38422b53b92b65be3d3f6b3dd6552a50981a61f5acda
F autoconf/tea/configure.ac a86f4955f600af734b106207db9cc03322877864356585e83df84fd4e5c7a586
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in b9eb6dd37f64e08e637d576b3c83259814b9cddd78bec4af2e5abfc6c5c750ce
@@ -33,12 +33,13 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure bcb1042e92775424a1021d2f4c89c78a699a6225df01fa8c593df7df0be6ad10 x
F configure 8dc5fe9688a74fbe82d21598a69d575a12faa8fcf471e95cc7dea514da63b411 x
F configure.ac f25bd7843120f2c2b8bc9db5a92b0502bbdd28e68907415c3d42fc8e57c657b9
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/compile-for-windows.md 50b27d77be96195c66031a3181cb8684ed822327ea834e07f9c014213e5e3bcf
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
F doc/lemon.html 44a53a1d2b42d7751f7b2f478efb23c978e258d794bfd172442307a755b9fa44
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/testrunner.md 8d36ec692cf4994bb66d84a4645b9afa1ce9d47dc12cbf8d437c5a5fb6ddeedb
@@ -50,8 +51,8 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/consio/console_io.c 097323f60037d70523421f0248958d2280851f8ff2f9a443d4ee1474c4769118 x
F ext/consio/console_io.h 3228dff1717481202a24f6dcf45ce0b75e7a778bf6877089518a44e1473b76a3
F ext/consio/console_io.c f32b757c9ee7fdf68e7586bee306f8368759e7cd12febb2a6839199b1c1af395 x
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test 0dd5cb096d66bed593e33053a3b364f6ef52ed72064bf5cf298364636dbf3cd6
@@ -62,9 +63,9 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c d01dfb641fc04efeeadcb94d7a8342eb07d71c1a3a3852ec8ab5e64c1fcdfff9
F ext/fts3/fts3.c fd64a588471ce00b19da08acb0d6f904277a21ac1d15141d5913c83591afa027
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h be688580701d41340de73384e3acc8c55be12a438583207444bd5e20f9ef426c
F ext/fts3/fts3Int.h 968f7d7cae541a6926146e9fd3fb2b2ccbd3845b7890a8ed03de0c06ac776682
F ext/fts3/fts3_aux.c 7eab82a9cf0830f6551ba3abfdbe73ed39e322a4d3940ee82fbf723674ecd9f3
F ext/fts3/fts3_expr.c 903bfb9433109fffb10e910d7066c49cbf8eeae316adc93f0499c4da7dfc932a
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
@@ -80,7 +81,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c c1de4ae28356ad98ccb8b2e3388a7fdcce7607b5523738c9afb6275dab765154
F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
F ext/fts3/fts3_write.c 5bb4721330ca589f906e72bb824dd4080b313c6d4c4231fa541e9db32dc67982
F ext/fts3/fts3_write.c c2d7a8dfb6e7a00c6c88ce626785cf4c50ed18eba34b5fbd53cacd60af96d0f2
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
@@ -88,28 +89,28 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 05501612cc655504c5dce8ba765ab621d50fc478490089beaa0d75e00b23e520
F ext/fts5/fts5Int.h 78a63cc0795186cde5384816a9403a68c65774b35d952e05b81a1b4b158e07c8
F ext/fts5/fts5_aux.c ee770eec0af8646db9e18fc01a0dad7345b5f5e8cbba236704cfae2d777022ad
F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5
F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d934c7b081
F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6
F ext/fts5/fts5_hash.c 076058f93327051952a752dc765df1acfe783eb11b419b30652aa1fc1f987902
F ext/fts5/fts5_index.c 458cbed8a3e17617cbf7e80cdfb7612000b9bb3781f286b345fb9655858658cf
F ext/fts5/fts5_main.c a07ed863b8bd9e6fefb62db2fd40a3518eb30a5f7dcfda5be915dd2db45efa2f
F ext/fts5/fts5_storage.c 5d10b9bdcce5b90656cad13c7d12ad4148677d4b9e3fca0481fca56d6601426d
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
F ext/fts5/extract_api_docs.tcl bc3a0ca78be7d3df08e7602c00ca48021ebae40682d75eb001bfdf6e54ffb44e
F ext/fts5/fts5.h ecba24fed7b359b3a53016bb07e411b3b4c9cdf163aa141006536423a63b611e
F ext/fts5/fts5Int.h defa43c0932265138ee910ca416e6baccf8b774e0f3d610e74be1ab2880e9834
F ext/fts5/fts5_aux.c 4584e88878e54828bf7d4d0d83deedd232ec60628b7731be02bad6adb62304b1
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
F ext/fts5/fts5_config.c 8072a207034b51ae9b7694121d1b5715c794e94b275e088f70ae532378ca5cdf
F ext/fts5/fts5_expr.c e91156ebdcc08d837f4f324168f69f3c0d7fdef0e521fd561efb48ef3297b696
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
F ext/fts5/fts5_index.c ee0f4d50bc0c58a7c5ef7d645e7e38e1e59315b8ea9d722ae00c5f949ee65379
F ext/fts5/fts5_main.c cd56ed9619e9bc55ae603ecafd5965c3684bb4c1de7dd00893c307ddf98afe88
F ext/fts5/fts5_storage.c f9e31b0d155e9b2c92d5d3a09ad7a56b937fbf1c7f962e10f4ca6281349f3934
F ext/fts5/fts5_tcl.c fdf7e2bb9a9186cfcaf2d2ce11d338309342b7a7593c2812bc54455db53da5d2
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
F ext/fts5/fts5_tokenize.c 83cfcede3898001cab84432a36ce1503e3080cf9b1c682b022ec82e267ea4c13
F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c aed56169ae5c1aa9b8189c779ffeef04ed516d3c712c06914e6d91a6759f4e4a
F ext/fts5/fts5_vocab.c 209e0c151e108d5f3621fa24b91e9b02f3750ee6c3f9ccec312df39481b68a09
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl a9de9c2209cc4e7ae3c753e783504e67206c6c1467d08f209cd0c5923d3e8d8b
F ext/fts5/test/fts5aa.test ba5158eba7d61359becdfca895ef471072c7bf7b20e5e60dcb4d024c8419c926
F ext/fts5/test/fts5_common.tcl 3378732aae2a7d9a4b9b5c40bde678d4259ca16bd490883325aecc4747bcb384
F ext/fts5/test/fts5aa.test 4db81519863244a3cab35795fe65ab6b592e7970c7409eba098b23ebbfc08d95
F ext/fts5/test/fts5ab.test bd932720c748383277456b81f91bc00453de2174f9762cd05f95d0495dc50390
F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
@@ -123,7 +124,7 @@ F ext/fts5/test/fts5ak.test f459a64c9d38698af72a7c657ab6349bca96150241dd69fcce75
F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
F ext/fts5/test/fts5aux.test 3f194345fcd581f49f7fbb2e5495400efcc7d2835b77816328d8283c942f41b8
F ext/fts5/test/fts5aux.test ed3596469f85a6cff5f6060e0cd9e3f9602051d8db2b497f5d12c85d39f20a62
F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
@@ -135,7 +136,7 @@ F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f3
F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
F ext/fts5/test/fts5conflict.test bf6030a77dbb1bedfcc42e589ed7980846c995765d77460551e448b56d741244
F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4
F ext/fts5/test/fts5content.test 219a4e49386b9b197b9b7cadca97ea10ddff858ecd8b763a1cb8bb07575afc2a
F ext/fts5/test/fts5content.test 282b373c58c8e798568ec2ced18b23f29bffa8d61317a0e51a035000ad6cd731
F ext/fts5/test/fts5contentless.test 1cd1237894eeff11feb1ff8180044eac0b17dde22c181f7a722f2dcbfdb3377c
F ext/fts5/test/fts5contentless2.test 14c83bdacf8230f5f7ca74ecf2926b87d8a7cb788a69ce9937020428ac4fe192
F ext/fts5/test/fts5contentless3.test 353d871c5ea08992aed3e2ebda0b1bdc35116cd24fe330fe7cf05be1e2b49fd7
@@ -145,7 +146,7 @@ F ext/fts5/test/fts5corrupt.test b6d4034b682bb3387bc44c510c71b3c67d4349e4df13949
F ext/fts5/test/fts5corrupt2.test 99e7e23a58b4d89eb7167c6de1669cbc595cd3c79ab333e0eb56405473319e77
F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5corrupt5.test 38a238df26c4de471e1c4b98f8de6c902bc692577a1c08d0ff4f2251f3559644
F ext/fts5/test/fts5corrupt5.test 0a33d1028837aaf37e55a0538060a8a0cc2e47fee112d1e09b52d50bde03c37d
F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
F ext/fts5/test/fts5corrupt7.test 80ad7f683a8bda2404731bb77e8c3dbbb620c1f6cc583cca8239f6accd6338c0
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
@@ -170,11 +171,12 @@ F ext/fts5/test/fts5faultD.test e7ed7895abfe6bc98a5e853826f6b74956e7ba7f594f1860
F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e4710c77eb8ce7075
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
F ext/fts5/test/fts5faultG.test d2e5a4d9a34e08dcaadcaeafef74d10cbc2abdd11aa2659a18af0294bf2812d3
F ext/fts5/test/fts5faultH.test b5c3b62642b7d321504a0a4f424eb80b4f6927969173334c8ca20df388557622
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test dc7bc7e0cdeb42cfce31294ad2f8fcf43192bfd0145bb7f3ecc5465d8c72696f
F ext/fts5/test/fts5integrity.test 0d249d351163e17e2227aa9850e68193f88a7813d16cc7d51287e554bf915b3d
F ext/fts5/test/fts5integrity.test f1723fe9fb9381b26c946ab4d7505041434df2c449d1cd53f45c7bf8c098dfa2
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
@@ -182,7 +184,7 @@ F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fc
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
F ext/fts5/test/fts5misc.test 5ca82f2a5ee016b0842043155d1382f98a34d0d86b2791165a44d7807f6e0f54
F ext/fts5/test/fts5misc.test 89dc46e37951b7f6653809f4abf6b1ca2f1fa62259efaf719339288f76fb6be9
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
@@ -190,6 +192,11 @@ F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
F ext/fts5/test/fts5optimize2.test 93e742c36b487d8874621360af5b1ce4d39b04fb9e71ce9bc34015c5fc811785
F ext/fts5/test/fts5optimize3.test bf9c91bb927d0fb2b9a06318a217a0419183ac5913842e062c7e0b98ea5d0fca
F ext/fts5/test/fts5origintext.test d2796fa08ee7aecfabdc0c45bb8a2fb16a00ea8757e63fbc153b718dbe430a39
F ext/fts5/test/fts5origintext2.test f3b9436de540828d01f0672df855b09ebc0863e126d5b56234701d71dfa73634
F ext/fts5/test/fts5origintext3.test 0d25933506600452a5ab3873cbb418ed5f2de2446c3672b9997b1ea104b0e7f0
F ext/fts5/test/fts5origintext4.test 0c4e4514b68d9ddb15e5a538d9d234da85747a3fd62432265dbdba5c8708e457
F ext/fts5/test/fts5origintext5.test a037bdf7235a22033c4663837bdb12d9738245464a3ac2f60c71fc40d07ede7d
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd116514f79c49c5a
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
@@ -204,7 +211,7 @@ F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff17101300
F ext/fts5/test/fts5savepoint.test 050796b24929325cdbbb2fbfe2794816ae95d298e940ae15032200c2f4a73725
F ext/fts5/test/fts5secure.test a02f771742fb2b1b9bdcb4bf523bcf2d0aa1ff597831d40fe3e72aaa6d0ec40f
F ext/fts5/test/fts5secure2.test 2e961d7eef939f294c56b5d895cac7f1c3a60b934ee2cfd5e5e620bdf1ba6bbc
F ext/fts5/test/fts5secure3.test c7e1080a6912f2a3ac68f2e05b88b72a99de38543509b2bbf427cac5c9c1c610
F ext/fts5/test/fts5secure3.test 6d066828d225b0dbe5db818d4d6165df7bb70210e68a577e858e8762400d5a23
F ext/fts5/test/fts5secure4.test 0d10a80590c07891478700af7793b232962042677432b9846cf7fc8337b67c97
F ext/fts5/test/fts5secure5.test c07a68ced5951567ac116c22f2d2aafae497e47fe9fcb6a335c22f9c7a4f2c3a
F ext/fts5/test/fts5secure6.test 74bf04733cc523bccca519bb03d3b4e2ed6f6e3db7c59bf6be82c88a0ac857fd
@@ -212,10 +219,10 @@ F ext/fts5/test/fts5secure7.test fd03d0868d64340a1db8615b02e5508fea409de13910114
F ext/fts5/test/fts5secure8.test eb3579e9d58b0acad97e8082dee1f99b2d393198f03500b453c2b25761c0c298
F ext/fts5/test/fts5securefault.test dbca2b6a1c16700017f5051138991b705410889933f2a37c57ae8a23b296b10b
F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
F ext/fts5/test/fts5simple2.test 8dd2389ee75e21a1429fe87e5f8c7d9a97ad1470304a8a2d3ba4b8c3c345fecd
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
F ext/fts5/test/fts5synonym2.test 8f891fc49cc1e8daed727051e77e1f42849c784a6a54bef82564761b2cb3e016
F ext/fts5/test/fts5synonym2.test e2f6ff68c4fbe12a866a3a87510f553d9dac99bcb74c10b56487c4c0a562fcf5
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
@@ -232,7 +239,7 @@ F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db638
F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
F ext/fts5/test/fts5version.test d6e5a5897550afeccc2f8531d87404dc1c289ee89385dd4318dbdd75e71d7a67
F ext/fts5/test/fts5vocab.test 7ed80d9af1ddaaa1637da05e406327b5aac250848bc604c1c1cc667908b87760
F ext/fts5/test/fts5vocab2.test 681980e92e031c9f3fe8d9c149189e876c108da2fb0fb3a25bd8a9b94bff8f68
F ext/fts5/test/fts5vocab2.test 1b1f0059f762ffb404213d35dac013e010621f08128589b6ec7bec59d9a710f3
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
F ext/fts5/tool/fts5txt2db.tcl c0d43c8590656f8240e622b00957b3a0facc49482411a9fdc2870b45c0c82f9f
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
@@ -244,7 +251,7 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c 6040c0de97644a1fb14bb589ee9f2f4208f6e6b165d14a0e33ed24945b118838
F ext/jni/src/c/sqlite3-jni.c c1292e690a20c7787a63e8d8ac6e2dfed49c97282ed056a7cfda5da461f0b7d8
F ext/jni/src/c/sqlite3-jni.h 913ab8e8fee432ae40f0e387c8231118d17053714703f5ded18202912a8a3fbf
F ext/jni/src/org/sqlite/jni/annotation/Experimental.java 8603498634e41d0f7c70f661f64e05df64376562ea8f126829fd1e0cdd47e82b
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java 38e7e58a69b26dc100e458b31dfa3b2a7d67bc36d051325526ef1987d5bc8a24
@@ -255,7 +262,7 @@ F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
F ext/jni/src/org/sqlite/jni/capi/CApi.java d428a1fd3b827f01c55d10d21ff35e33e7dac9e8a1d92a8b5c7d7255e67407d8
F ext/jni/src/org/sqlite/jni/capi/CApi.java 27bbd944ea8c147afd25b93f17dc397f3627611ebe2878944a32ffeffc98e99e
F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 57e2d275dcebe690b1fc1f3d34eb96879b2d7039bce30b563aee547bf45d8a8b
F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab
@@ -291,7 +298,7 @@ F ext/jni/src/org/sqlite/jni/fts5/Fts5Context.java 338637e6e5a2cc385d962b220f3c1
F ext/jni/src/org/sqlite/jni/fts5/Fts5ExtensionApi.java 7da0fbb5728f7c056a43e6407f13dd0c7c9c445221267786a109b987f5fc8a9d
F ext/jni/src/org/sqlite/jni/fts5/Fts5PhraseIter.java 28045042d593a1f1b9b80d54ec77cbf1d8a1bc95e442eceefa9a3a6f56600b0e
F ext/jni/src/org/sqlite/jni/fts5/Fts5Tokenizer.java 3c8f677ffb85b8782f865d6fcbc16200b3375d0e3c29ed541a494fde3011bf49
F ext/jni/src/org/sqlite/jni/fts5/TesterFts5.java eaee4d641229a098eb704b96a45c9a23c6514dc39009d3611e265bab33834deb
F ext/jni/src/org/sqlite/jni/fts5/TesterFts5.java 51e16bf9050af7cb246d17d6a19c001cfc916bf20f425c96625aaccaf74688e8
F ext/jni/src/org/sqlite/jni/fts5/XTokenizeCallback.java 1efd1220ea328a32f2d2a1b16c735864159e929480f71daad4de9d5944839167
F ext/jni/src/org/sqlite/jni/fts5/fts5_api.java a8e88c3783d21cec51b0748568a96653fead88f8f4953376178d9c7385b197ea
F ext/jni/src/org/sqlite/jni/fts5/fts5_extension_function.java 9e2b954d210d572552b28aca523b272fae14bd41e318921b22f65b728d5bf978
@@ -382,13 +389,13 @@ F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2
F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58f34edd
F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1ab
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
F ext/misc/randomjson.c 7dd13664155319d47b9facc0d8dbf45e13062966a47168e54e3f26d48240d7ea
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
F ext/misc/regexp.c 4bdd0045912f81c84908bd535ec5ad3b1c8540b4287c70ab84070963624047db
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
@@ -401,7 +408,7 @@ F ext/misc/spellfix.c c0aa7b80d6df45f7da59d912b38752bcac1af53a5766966160e6c5cdd3
F ext/misc/sqlar.c 53e7d48f68d699a24f1a92e68e71eca8b3a9ff991fe9588c2a05bde103c6e7b7
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
F ext/misc/totype.c 75ed9827d19cc3b434fc2aeb60725d4d46e1534373615612a4d1cfdcc3d60922
F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
@@ -460,7 +467,7 @@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69
F ext/rbu/sqlite3rbu.c d4ddf8f0e93772556e452a6c2814063cf47efb760a0834391a9d0cd9859fa4b9
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
F ext/recover/dbdata.c fc7147a68422cbbbaa481ee92ae1752cc25f5a24302bece1c70dcb76345bd736
F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949
F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
@@ -476,7 +483,7 @@ F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 1a34e2d04533d919a30ae4d5caeb1643f6684e9ccd7597ca27721d8af81f4ade
F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
F ext/repair/checkindex.c af5c66463f51462d8a6f796b2c44ef8cfa1116bbdc35a15da07c67a705388bfd
@@ -488,7 +495,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c 0dd4775e896cee6067979d67aff7c998e75c2c9d9cd8d62a1a790c09cde7adca
F ext/rtree/rtree.c 2e1452a9338fe4db057fa677277bed86b65c667ed48b9b59144adae99f85a7cb
F ext/rtree/rtree.c bdf97fac91b37b3a6041ab4a0dd06e81c7ba1541601733b40f97fb51e76e79ce
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 2b5b8c719c6a4abe377f57766f428a49af36a93061cb146cccfdc3b30000c0a4
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -508,6 +515,7 @@ F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd
F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7bd7aaf90
F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4
F ext/rtree/rtreeJ.test 93227ccd4d6c328f5ac46a902b8880041509dd2d68f6ce71560f0d8ab5bb507a
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 202ca70df1f0645ef9d5a2170e62d378a28098d9407f0569e85c9c1cf1bd020a
F ext/rtree/rtreecheck.test 934546ad9b563e090ee0c5cbdc69ad014189ad76e5df7320526797a9a345661f
@@ -561,14 +569,14 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
F ext/session/sessionstat1.test b039e38e2ba83767b464baf39b297cc0b1cc6f3292255cb467ea7e12d0d0280c
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c 7b0f9bf6479aebd49e5f34cdaeb1479cde843cf5189bca6f32db4f36c130b414
F ext/session/sqlite3session.c 829d468f0f3d2710aace56b0116a7ca3f414683ce78e3125ae5e21547a895078
F ext/session/sqlite3session.h 4cf19a51975746d7cff2fdd74db8b769c570958e1c3639ac150d824ac1553b3e
F ext/session/test_session.c 7b94ad945cd4afe6c73ee935aeb3d44b4446186e1729362af616c7695a5283d9
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 0e362f3fc04eab6628cbe4f1e35f4ab4a200881f6b5f753b27fb45eabeddd9d2
F ext/wasm/GNUmakefile 8a4d5ca21d7f21c4751ef732f2bb837c915641ee8ad25753929998fa44847e61
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -587,19 +595,21 @@ F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
F ext/wasm/api/sqlite3-api-glue.js 119b91c8a7ce6648679eb66fcdd1ed07ef7fd892eb501d658fbfefcc962012d9
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
F ext/wasm/api/sqlite3-api-worker1.js 88770ac01fc756f89a3e060eec17111d6c1688e89ebfd34cb9d9e54d25affbb9
F ext/wasm/api/sqlite3-api-worker1.js fd46628ef147dd5856c88f63a9a279a40f744f1fdfddd55251ad8fbc3d8200ae
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 595953994aa3ae2287c889c4da39ab3d6f17b6461ecf4bec334b7a3faafddb02
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 46c4afa6c50d7369252c104f274ad977a97e91ccfafc38b400fe36e90bdda88e
F ext/wasm/api/sqlite3-wasm.c d0e09eb5ed3743c00294e30019e591c3aa150572ae7ffe8a8994568a7377589f
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 569d4e859968e65f55dec5fac0b879828a23c8b179162cc7812fec19f844dd21
F ext/wasm/api/sqlite3-worker1.c-pp.js a541112aa51e16705f13a99bb943c64efe178aa28c86704a955f8fd9afe4ba37
F ext/wasm/api/sqlite3-wasm.c dfd1f1a225b267e8fd641dcd6c7d579fbe2b731aeaa123324135efac830a2bcf
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js f234191fe6bf41a5a1e59c9f43ed816e74a522b3d60d3f556f66c3085c448503
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
F ext/wasm/batch-runner.js 0dad6a02ad796f1003d3b7048947d275c4d6277f63767b8e685c27df8fdac93e
F ext/wasm/batch-runner.js 05ec254f5dbfe605146d9640b3db17d6ef8c3fbef6aa8396051ca72bb5884e3f
F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25b4
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
@@ -607,7 +617,7 @@ F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a7
F ext/wasm/common/whwasmutil.js 4c64594eecc7af4ae64259e95a71ba2a7edf118881aaff0bba86d0c7164e78e4
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js 38aa8faec4d0ace1c973bc8a7a1533584463ebeecd4c420daa7d9687beeb9cb5
F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32e7be5bf
F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
F ext/wasm/demo-worker1-promiser.html 1de7c248c7c2cfd4a5783d2aa154bce62d74c6de98ab22f5786620b3354ed15f
@@ -621,17 +631,17 @@ F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d695
F ext/wasm/fiddle/fiddle-worker.js e0153f9af6500805c6f09c0b3cfdb7d857e9d6863dbee9d50d1628fccf5f4b4d
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74eb8069d412e
F ext/wasm/index.html 4e7847b909f4ae0da8c829b150b79454050e53b3658431f138636257729cd42b
F ext/wasm/index-dist.html e91d76e4581185238fd3d42ed86ec600f7023ed3e3a944c5c356f25304bf1263
F ext/wasm/index.html b31ce41c0da476d5ffcef23069b9d3415b419d65af5779096ebcfbcbade453a9
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe
F ext/wasm/speedtest1-worker.html e33e2064bda572c0c3ebaec7306c35aa758d9d27e245d67e807f8cc4a9351cc5
F ext/wasm/speedtest1-worker.js 315d26198c46be7c85e26fda15d80ef882424276abde25ffd8b026fb02a35d8c
F ext/wasm/speedtest1-worker.html 864b65ed78ce24847a348c180e7f267621a02ca027068a1863ec1c90187c1852
F ext/wasm/speedtest1-worker.js 4d2ea70a3c24e05bdca78025202841f33d298c4fa9541a0070c3228661f89ecd
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
@@ -648,7 +658,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 51fd5fc8565007266e6bfd9e299199c752b171707a667b8914a204b38258e1b1
F main.mk ef8d6b0e76b27d2b32d7b71ea30a2b2626b668f998a4f32f6171c9623a310a53
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -661,16 +671,16 @@ F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc
F src/analyze.c d4cc28738c29e009640ec20ebb6936ba6fcefff0d11aa93398d9bb9a5ead6c1f
F src/analyze.c 0f15753308c3bca7674f31fa7e0807ffcb8b120c36eef7d00b62b33079ddc854
F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39
F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c f3b09c5414de3a11db73e11e1d66f4c5e53c9e89876ff3b531a887ab656ca303 x
F src/btree.c 5410768087e524f331816c751c4b1f714693fa864a448337e443e49cc397aeaf
F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240
F src/btreeInt.h 3e2589726c4f105e653461814f65857465da68be1fac688de340c43b873f4062
F src/build.c 189e4517d67f09f0a3e0d8e1faa6e2ef0c2e95f6ac82e33c912cb7efa2a359cc
F src/build.c e7d9044592eeeea8e78d8ae53ca8d31fd6e92ca0d4f53e2f2e8ccf7352e0b04b
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
@@ -678,27 +688,27 @@ F src/date.c 3b8d02977d160e128469de38493b4085f7c5cf4073193459909a6af3cf6d7c91
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
F src/expr.c e9a491c7f156e5b25641c28af11b735a424e108a21b9f83b6f3e51c99a8141d9
F src/expr.c 3381ee4c9aa7ccde22a2a7f35ce343925a7a25d96bdc943649131f9decdebad2
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
F src/func.c 472f6dcfa39cf54f89a6aec76c79c225fb880a6c14469c15d361331662b9bf43
F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb
F src/global.c 765a0656d6cbf043cb272ff0ae38f39cc46713539ffe6793258ed3eb4b188b52
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
F src/json.c 92cc05dcf87cdace6fbf2a76e0cb2b030f04ddb1819e024af4ce8885261b4cef
F src/insert.c eb33ea46dcab93e90f112fced343aaf41f59cbd2e951d5066f1f9302be1c2f34
F src/json.c 29a42bc92c2384653b8b5e5ad26bdee4e2334544c7cfb78ceb4a3ca81d674686
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9
F src/main.c 438b95162acfa17b7d218f586f5bde11d6ae82bcf030c9611fc537556870ad6b
F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
F src/memdb.c 559c42e61eb70cd6d4bc692b042497133c6d96c09a3d514d92f3dac72268e223
F src/memdb.c 16679def118b5fd75292a253166d3feba3ec9c6189205bf209643ecdb2174ecc
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
F src/mutex.c 1b4c7e5e3621b510e0c18397210be27cd54c8084141144fbbafd003fde948e88
@@ -712,33 +722,33 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 97bdcd43315da7aaec9fea2da1ff7c9de458f93dd363e073f2742403a7f2e011
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
F src/os_unix.c fa9b81b642e60e77ffaf98bd1a2e5fde16c1c2317614ec178bf3bd5864772356
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 987ab3a2cd9065d62e9955474470ff733445e2357432a67e3d0f5a8f9313e334
F src/pager.h f4d33fec8052603758792045493423b8871a996da2d0973927b7d36cd6070473
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
F src/pragma.c b5b4cff830575e6188cd56a295a57448d2b9dbc53f0dae58e22b97354cda3781
F src/pragma.c b61a1a1801befe6763e787b96988deb156a56e82a2b4dea004bc78e4551c9d5c
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
F src/printf.c 9da63b9ae1c14789bcae12840f5d800fd9302500cd2d62733fac77f0041b4750
F src/printf.c d3392b2a20ee314ddeef34fb43c904bf4619eb20ff9a9e07e3950a7e4dcd6912
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916
F src/resolve.c 446bcb8ebf0ea7066c2ca99e5336f0dbc9230ac76f80fafd1bfa82fe7871af2d
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 85857bedd2913d888aa571755b48c54cd2e6e7fcb0087e19b226ee0368cfda1e
F src/shell.c.in 7bb83293775e1a5586d65212997442bc7acc70a2f1b781745da64ec3c2e4ea97
F src/sqlite.h.in d93a4821d2f792467a60f7dc81268d1bb8634f40c31694ef254cab4f9921f96a
F src/select.c f1a81ff4f8e9e76c224e2ab3a4baa799add0db22158c7fcede65d8cc4a6fa2da
F src/shell.c.in f7cc8711aee604bc078a93d777ad7246980485c57fa3047408b0f842ba03c14d
F src/sqlite.h.in 020d7b7307dda51420dc48b47e5334eaface77baba6bd9818375d392eb3ab5b5
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h 6b82eb99a9d2887e873fb29e56befb7c50cf4624df615d23a28f071dc8abf5f6
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/sqliteInt.h 59e83fc2b01e7c7f550a9ab77fd5876a49f37acbf4cc01c031fc7947f95959d6
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
F src/test1.c f9620e8f0d0fa4edb239201a732c4dd1562f0cdd9741955c89332d49e14a5edd
F src/test1.c 310f43eb17a9252a7790726ca652e4ea3197da17c19eec93b8578863a49dc7b4
F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
@@ -757,7 +767,7 @@ F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf
F src/test_demovfs.c 38a459d1c78fd9afa770445b224c485e079018d6ac07332ff9bd07b54d2b8ce9
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
F src/test_fs.c 56cc17e4fdc57efa61695026e2ba96e910b17060d7ee01d775ec048791522e2f
F src/test_func.c 24df3a346c012b1fc9e1001d346db6054deb426db0a7437e92490630e71c9b0a
F src/test_func.c 4d2dc7e3e0946e55091784ddaf0302294f2ee300614f6f3e19a4b38df77d5167
F src/test_hexio.c 9478e56a0f08e07841a014a93b20e4ba2709ab56d039d1ca8020e26846aa19bd
F src/test_init.c f2cc4774b7c9140f76e45ecbb2ae219f68e3acbbe248c0179db666a70eae9f08
F src/test_intarray.c 26ffba666beb658d73cd925d9b4fb56913a3ca9aaeac122b3691436abb192b92
@@ -794,27 +804,27 @@ F src/tokenize.c 23d9f4539880b40226254ad9072f4ecf12eb1902e62aea47aac29928afafcfd
F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
F src/trigger.c 0905b96b04bb6658509f711a8207287f1315cdbc3df1a1b13ba6483c8e341c81
F src/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c b22cc9f203a8c0b9ee5338a67f8860347d14845864c10248bebe84518a781677
F src/upsert.c 2e60567a0e9e8520c18671b30712a88dc73534474304af94f32bb5f3ef65ac65
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
F src/util.c c346e2a811285f6bad8a87c862070207855159a783993d03ca20dea2c74ace04
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c f73bead140670fac1aa4227188827ada52387a5fe0ccff0dd5af2a906754d904
F src/vdbe.c b2a45392265cb83f60251406039bf5255462d4a6d8deb05b2eaccab5abb2e20b
F src/vdbe.h 88e19a982df9027ec1c177c793d1a5d34dc23d8f06e3b2d997f43688b05ee0eb
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
F src/vdbeaux.c c5a471b34e9c4cfc0295a3e10734fd197670ffaebcb742f284c8e17e8026ceea
F src/vdbeaux.c 56900c9a41f23260c8346f212bd6005eb9171f9a2f70d0cfb1441a078a0e4b84
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
F src/vdbemem.c 0012d5f01cc866833847c2f3ae4c318ac53a1cb3d28acad9c35e688039464cf0
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
F src/vtab.c 154725ebecd3bc02f7fbd7ad3974334f73fff76e02a964e828e48a7c5fb7efff
F src/vtab.c 11948e105f56e84099ca17f1f434b1944539ea84de26d0d767eadfbc670ce1ea
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c e5247a3406531b705b44630e9ccf9ca0e5c74955ef19c06fbb146d765c500c20
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 1fdc69ce1333e9bd6d7d3df9fa5af1373a3f5bfdd52108d1dbc0ca85a55f777e
F src/whereInt.h 4b38c5889514e3aead3f27d0ee9a26e47c3f150efc59e2a8b4e3bc8835e4d7a1
F src/where.c 56277e7110e6c81918434908bb7d597b917adfa9a176f5d95eb954b93dbc57b8
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2
@@ -823,8 +833,8 @@ F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867d
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggfault.test 777f269d0da5b0c2524c7ff6d99ae9a93db4f1b1839a914dd2a12e3035c29829
F test/aggnested.test ce85a6af7d59c3109e35c5f03b2cd11da1a9b1417371e2f942102d0f0d77fd62
F test/aggorderby.test e6b98dbbf3ababa96892435d387de2dcf602ef02c2b848d2d817473066f154ba
F test/aggnested.test 610b0ce2c3e8f3daee25f9752800ee8d785db10da4aa1fbeea0ea1aabaf1d704
F test/aggorderby.test cc3abf5de64d46ff66395ca8c2346b66c2576d5aedb7bffc5b0742508856e3bf
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
F test/alter.test 3c00eff1e2036b9f93e9cd0f3d3e63750ac87ecb5bc71b9d7bd07cbf2ac4c494
@@ -1161,6 +1171,7 @@ F test/fts3fault2.test 7b2741e5095367238380b0fcdb837f36c24484c7a5f353659b387df63
F test/fts3fault3.test 4a39a1618546776255dc1de306213b600aef87eca589ca8428a70c00fd11961b
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3fuzz001.test c78afcd8ad712ea0b8d2ed50851a8aab3bc9dc52c64a536291e07112f519357c
F test/fts3integrity.test 0c6fe7353d7b24d78862f4272ee9df4da2f32b3ff30fa3396945cda8119580a8
F test/fts3join.test 1a4d786539b2b79a41c28ef2ac22cacd92a8ee830249b68a7dee4a020848e3bb
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
@@ -1187,7 +1198,7 @@ F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b6721d7f
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4intck1.test 43774c641fdf6607c6ee90c3db8af065a37434d55d6eaf13bafe515e8b0c5729
F test/fts4intck1.test 54e7f28e34b72fb0c614d414bb1f568154d463c5a00b20944e893df858372ed4
F test/fts4langid.test 4be912f42454998e239a2e877600263e0394afbaba03e06cedcc5a08693a345a
F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
F test/fts4merge.test 57d093660a5093ae6e9fbd2d17592a88b45bbd66db2703c4b640b28828dbe38b
@@ -1205,10 +1216,10 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 3a29323b640c0552f6e9f1577407ced3a68e7d8c0bc04b61dd6040fa593a3a02
F test/func.test 504d202650c7940b5aa98364dd68f242df87f39f829e51074a55d79fc7bc7414
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
F test/func4.test e8ef9b2bd6a192a213cbd5cf31a3b35e25cd6ff2fdaeea0b58d63be31b03d220
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
F test/func7.test adbfc910385a6ffd15dc47be3c619ef070c542fcb7488964badb17b2d9a4d080
@@ -1221,7 +1232,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 69b8549e112fb815931a8c14c7955a0c407ae91a79356eecb82458384f2cb989
F test/fuzzcheck.c e6a40f53ac5624aa5b7c4f31c385f09ba088d524cecc4512fd3057caeed8f530
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1320,19 +1331,21 @@ F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ff
F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9e1946
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json/README.md 63e3e589e1df8fd3cc1588ba1faaff659214003f8b77a15af5c6452b35e30ee2
F test/json/README.md de59d5ba0bd2796d797115688630a6405bbf43a2891bad445ac6b9f38b83f236
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
F test/json/json-q1-b.txt 606818a5fba6d9e418c9f4ea7d8418af026775042dad81439b72447a147a462c
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
F test/json/json-speed-check.sh b060a9a6c696c0a807d8929400fa11bd7113edc58b0d66b9795f424f8d0db326 x
F test/json101.test 70587d7d35ef9e2126364ba70f0c951f70827cfbd28649d779ff3df7e8f87547
F test/json/json-speed-check.sh 912ee03e700a65c827ee0c7b4752c21ec5ef69cf7679d2f482ca817042bead52 x
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
F test/json101.test 30db5b055b103ccabc53a29cfe6cda3345d07e171aeb25403dafa04f19e98b19
F test/json102.test 557a46e16df1aa9bdbc4076a71a45814ea0e7503d6621d87d42a8c04cbc2b0ef
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
F test/json105.test e64a8d73677fbae67886642cd5076e2ef3efe89f8483b87595cf9c030216c9bd
F test/json105.test 043838b56e68f3252a0dcf5be1689016f6f3f05056f8dcfcdc9d074f4d932988
F test/json106.test 1d46a9294e2ced35c7f87cebbcb9626d01abab04f1969d7ded7b6f6a1d9be0f2
F test/json107.test 59054e815c8f6b67d634d44ace421cf975828fb5651c4460aa66015c8e19d562
F test/json501.test ab168a12eb6eb14d479f8c1cdae3ac062fd5a4679f17f976e96f1af518408330
F test/json502.test 98c38e3c4573841028a1381dfb81d4c3f9b105d39668167da10d055e503f6d0b
F test/jsonb01.test cace70765b36a36aec9a85a41ea65667d3bbf647d4400ddc3ac76f8fe7d94f90
F test/json502.test 84634d3dbb521d2814e43624025b760c6198456c8197bbec6c977c0236648f5b
F test/jsonb01.test f4cdfb4cf5a0c940091b17675ed9583f45add0c938f07d65b0de0e19d3a9a101
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
@@ -1383,7 +1396,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
F test/memdb1.test 2c4e9cc10d21c6bf4e217d72b7f6b8ba9b2605971bb2c5e6df76018e189f98f5
F test/memdb1.test 2fb27d5dadd4e7784d2229e570f6368b059fc0b7fe88ca25e46e17150ba8ad4c
F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e
@@ -1405,10 +1418,11 @@ F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee45
F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test 5c1f768828094b0dd94e55ae7f10489a1ded74772682be2c4c78679d0acaf7ef
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
F test/mmapcorrupt.test 0d89724591f22a376019f3df60d075b838dd2ba6dae6effb0be465c49cf86d4a
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
@@ -1425,7 +1439,7 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 796c7b7157f55c93b4e672b724e9c923a6fc6aa72ac419379a623e2350472e22
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
F test/notnull2.test 1ee4acbd614d3cf5f1c4a52f5af7fc771b82352f1a51a86afeaa02c9df1d82ef
F test/notnull2.test 2ac7b4e04917148c7a1a9ed36df20150175ce942f07f5714375b29acbaca7106
F test/notnullfault.test fc4bb7845582a2b3db376001ef49118393b1b11abe0d24adb03db057ee2b73d5
F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
F test/nulls1.test 7a5e4346ee4285034100b4cd20e6784f16a9d6c927e44ecdf10034086bbee9c9
@@ -1466,14 +1480,14 @@ F test/pendingrace.test 6aa33756b950c4529f79c4f3817a9a1e4025bd0d9961571a05c0279b
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test f7caf8dd5c7b1da74842a48df116f7f193399c656d4ffc805cd0d9658568c675
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 57a36226218c03cfb381019fe43234b2cefbd8a1f12825514f906a17ccf7991e
F test/pragma.test cddd4b534d7fb5cf113d1308dea4231f3548e8a7f3a65d7d1cf4810c87090b5a
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
F test/pragma4.test ca5e4dfc46adfe490f75d73734f70349d95a199e6510973899e502eef2c8b1f8
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
F test/printf.test 512152dca7f2f578f045a5a732e7bee08e4f47a8a212f83ce46791b518eba70f
F test/printf.test 685fec5a0c5af2490ab0632775a301554361d674211d690f5bee0a97b05333de
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
@@ -1572,11 +1586,12 @@ F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test c7127a5e780ffc9e14c476773127fdf292c6db226529c44c1676f37b3793123f
F test/shell2.test 35226c070a8c7f64fd016dfac2a0db2a40f709b3131f61daacd9dad61536c9cb
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
F test/shell4.test 9abd0c12a7e20a4c49e84d5be208d2124fa6c09e728f56f1f4bee0f02853935f
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
F test/shell4.test 947029e5a9efae9054d424b309fc0311439c0c3a0866ebfa3b8a771120708220
F test/shell5.test 263bfd6a49049295277e3f5bdc221390dc5e72f39954b23d43204ed81993304f
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 3fd093d481aaa94dc77fb73f1044c1f19c7efe3477a395cc4f7450133bc54915
F test/shell9.test f457a96c088344908e0518dbabffd02eda8ac2a8733f278679e5f47c103efbab
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1654,9 +1669,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 68454ef88508c196d19e8694daa27bff7107a91857799eaa12f417188ae53ede
F test/testrunner.tcl e18d71f2e797da808ba6d31335e504ed6b2791581b89287a72b697a2f31b1ea1
F test/testrunner_data.tcl e4d5017290a6d5c11785e36cc94c67d8bb950c8cdc2dbe4c1db2a3a583812560
F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf
F test/testrunner.tcl 8e2a5c7550b78d3283eee6103104ae2bcf56aa1df892dbd1608f27b93ebf4de8
F test/testrunner_data.tcl 7ffd951527bbc614e723fd8d123b6834321878530696adecfdf6035100bac64e
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1852,9 +1867,9 @@ F test/tt3_stress.c f9a769ca8b026ecc76ee93ca8c9700a5619f8e51c581107c4053ba6ac97f
F test/tt3_vacuum.c 71b254cde1fc49d6c8c44efd54f4668f3e57d7b3a8f4601ade069f75a999ba39
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/types3.test c9db8f9e80309edfa4252585cf16bcab7ed31f39eeb904d21e831199a3613fb0
F test/unhex.test b7f1b806207cb77fa31c3e434fe92fba524464e3e9356809bfcc28f15af1a8b7
F test/unionall.test eb9afa030897af75fd2f0dd28354ef63c8a5897b6c76aa1f15acae61a12eabcf
F test/unionall.test 5b1c4186a661e4bf762875caf4c61d8fda3dd04a6fa9005187f6ba8900c2913f
F test/unionall2.test 71e8fa08d5699d50dc9f9dc0c9799c2e7a6bb7931a330d369307a4df7f157fa1
F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
@@ -1875,7 +1890,7 @@ F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
F test/upsert5.test fff0dcfce73c649204543088d8e5bde01172676063ec9b8f8fc7f195abc386fe
F test/upsert5.test 9953b180d02d1369cdbb6c73c900834e5fef8cb78e98e07511c8762ec21cc176
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
F test/uri.test c1abaaaa28e9422d61e5f3f9cbc8ef993ec49fe802f581520731708561d49384
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
@@ -1959,7 +1974,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
F test/where.test 59abb854eee24f166b5f7ba9d17eb250abc59ce0a66c48912ffb10763648196d
F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
@@ -2106,8 +2121,8 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c fcccbc07da942b4534d0c769e9fcc21c67cbd7086ddc1c8f13372c40a83d4634
F tool/sqlite3_analyzer.c.in f88615bf33098945e0a42f17733f472083d150b58bdaaa5555a7129d0a51621c
F tool/sqldiff.c 985452ffc8554baee0f945d078859d393a22abc0bbf553a9f12acae1b6e1fdd0
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
@@ -2145,8 +2160,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 04c0d5644372446c924a2e31a26edf51ddc563a1990d170b0ed4739e3e8b239b
R 4a2861d7ab7860f80e426ce44e32c50f
P b26f24441f84a30deb9a562ab6c6de7543fbc3b3b93c34277964c9c21d734153
R 155ffa116058b8f4537c03201d4943ec
T +sym-release *
T +sym-version-3.45.2 *
U drh
Z 1fffc27f10fd5ca429d5618946ebb513
Z ed4a58f9c6cbbc2b817c3b07c0b5f709
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
cc7a641ab5ae739d31c24f0ad0caeb15a481a63fa8f13720718ea922c25862ff
d8cd6d49b46a395b13955387d05e9e1a2a47e54fb99f3c9b59835bbefad6af77
+21 -5
View File
@@ -264,9 +264,9 @@ static void openStatTable(
typedef struct StatAccum StatAccum;
typedef struct StatSample StatSample;
struct StatSample {
tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
#ifdef SQLITE_ENABLE_STAT4
tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anLt; /* sqlite_stat4.nLt */
union {
i64 iRowid; /* Rowid in main table of the key */
@@ -424,9 +424,9 @@ static void statInit(
/* Allocate the space required for the StatAccum object */
n = sizeof(*p)
+ sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
+ sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
+ sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
#ifdef SQLITE_ENABLE_STAT4
n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */
if( mxSample ){
n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
+ sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
@@ -447,9 +447,9 @@ static void statInit(
p->nKeyCol = nKeyCol;
p->nSkipAhead = 0;
p->current.anDLt = (tRowcnt*)&p[1];
p->current.anEq = &p->current.anDLt[nColUp];
#ifdef SQLITE_ENABLE_STAT4
p->current.anEq = &p->current.anDLt[nColUp];
p->mxSample = p->nLimit==0 ? mxSample : 0;
if( mxSample ){
u8 *pSpace; /* Allocated space not yet assigned */
@@ -716,7 +716,9 @@ static void statPush(
if( p->nRow==0 ){
/* This is the first call to this function. Do initialization. */
#ifdef SQLITE_ENABLE_STAT4
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
#endif
}else{
/* Second and subsequent calls get processed here */
#ifdef SQLITE_ENABLE_STAT4
@@ -725,15 +727,17 @@ static void statPush(
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
** to the current row of the index. */
#ifdef SQLITE_ENABLE_STAT4
for(i=0; i<iChng; i++){
p->current.anEq[i]++;
}
#endif
for(i=iChng; i<p->nCol; i++){
p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT4
if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
#endif
p->current.anEq[i] = 1;
#endif
}
}
@@ -867,7 +871,9 @@ static void statGet(
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
sqlite3_str_appendf(&sStat, " %llu", iVal);
#ifdef SQLITE_ENABLE_STAT4
assert( p->current.anEq[i] );
#endif
}
sqlite3ResultStrAccum(context, &sStat);
}
@@ -1556,6 +1562,16 @@ static void decodeIntArray(
while( z[0]!=0 && z[0]!=' ' ) z++;
while( z[0]==' ' ) z++;
}
/* Set the bLowQual flag if the peak number of rows obtained
** from a full equality match is so large that a full table scan
** seems likely to be faster than using the index.
*/
if( aLog[0] > 66 /* Index has more than 100 rows */
&& aLog[0] <= aLog[nOut-1] /* And only a single value seen */
){
pIndex->bLowQual = 1;
}
}
}
Executable → Regular
+12 -4
View File
@@ -5161,7 +5161,6 @@ static int accessPayload(
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
@@ -6281,7 +6280,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
}
pPage = pCur->pPage;
assert( pPage->isInit );
if( sqlite3FaultSim(412) ) pPage->isInit = 0;
if( !pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
if( !pPage->leaf ){
int idx = pCur->ix;
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
@@ -6954,7 +6956,10 @@ static int fillInCell(
n = nHeader + nPayload;
testcase( n==3 );
testcase( n==4 );
if( n<4 ) n = 4;
if( n<4 ){
n = 4;
pPayload[nPayload] = 0;
}
*pnSize = n;
assert( nSrc<=nPayload );
testcase( nSrc<nPayload );
@@ -9400,7 +9405,10 @@ int sqlite3BtreeInsert(
if( flags & BTREE_PREFORMAT ){
rc = SQLITE_OK;
szNew = p->pBt->nPreformatSize;
if( szNew<4 ) szNew = 4;
if( szNew<4 ){
szNew = 4;
newCell[3] = 0;
}
if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
CellInfo info;
pPage->xParseCell(pPage, newCell, &info);
+14 -6
View File
@@ -720,7 +720,7 @@ void sqlite3ColumnSetExpr(
*/
Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0;
if( NEVER(!IsOrdinaryTable(pTab)) ) return 0;
if( !IsOrdinaryTable(pTab) ) return 0;
if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
@@ -873,6 +873,9 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
deleteTable(db, pTable);
}
void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){
sqlite3DeleteTable(db, (Table*)pTable);
}
/*
@@ -1410,7 +1413,8 @@ void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
/*
** Clean up the data structures associated with the RETURNING clause.
*/
static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){
Returning *pRet = (Returning*)pArg;
Hash *pHash;
pHash = &(db->aDb[1].pSchema->trigHash);
sqlite3HashInsert(pHash, pRet->zName, 0);
@@ -1452,8 +1456,7 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
pParse->u1.pReturning = pRet;
pRet->pParse = pParse;
pRet->pReturnEL = pList;
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet);
testcase( pParse->earlyCleanup );
if( db->mallocFailed ) return;
sqlite3_snprintf(sizeof(pRet->zName), pRet->zName,
@@ -1652,7 +1655,8 @@ char sqlite3AffinityType(const char *zIn, Column *pCol){
assert( zIn!=0 );
while( zIn[0] ){
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
u8 x = *(u8*)zIn;
h = (h<<8) + sqlite3UpperToLower[x];
zIn++;
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
aff = SQLITE_AFF_TEXT;
@@ -5517,7 +5521,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
if( iDb<0 ) return;
z = sqlite3NameFromToken(db, pObjName);
if( z==0 ) return;
zDb = db->aDb[iDb].zDbSName;
zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
pTab = sqlite3FindTable(db, z, zDb);
if( pTab ){
reindexTable(pParse, pTab, 0);
@@ -5527,6 +5531,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
pIndex = sqlite3FindIndex(db, z, zDb);
sqlite3DbFree(db, z);
if( pIndex ){
iDb = sqlite3SchemaToIndex(db, pIndex->pTable->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
return;
@@ -5692,4 +5697,7 @@ void sqlite3WithDelete(sqlite3 *db, With *pWith){
sqlite3DbFree(db, pWith);
}
}
void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){
sqlite3WithDelete(db, (With*)pWith);
}
#endif /* !defined(SQLITE_OMIT_CTE) */
+16 -9
View File
@@ -1223,9 +1223,7 @@ void sqlite3ExprAddFunctionOrderBy(
assert( ExprUseXList(pExpr) );
if( pExpr->x.pList==0 || NEVER(pExpr->x.pList->nExpr==0) ){
/* Ignore ORDER BY on zero-argument aggregates */
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3ExprListDelete,
pOrderBy);
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pOrderBy);
return;
}
if( IsWindowFunc(pExpr) ){
@@ -1406,6 +1404,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
void sqlite3ExprDeleteGeneric(sqlite3 *db, void *p){
if( ALWAYS(p) ) sqlite3ExprDeleteNN(db, (Expr*)p);
}
/*
** Clear both elements of an OnOrUsing object
@@ -1431,9 +1432,7 @@ void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
** pExpr to the pParse->pConstExpr list with a register number of 0.
*/
void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3ExprDelete,
pExpr);
sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
}
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
@@ -2239,6 +2238,9 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
}
void sqlite3ExprListDeleteGeneric(sqlite3 *db, void *pList){
if( ALWAYS(pList) ) exprListDeleteNN(db, (ExprList*)pList);
}
/*
** Return the bitwise-OR of all Expr.flags fields in the given
@@ -2738,9 +2740,10 @@ int sqlite3ExprCanBeNull(const Expr *p){
case TK_COLUMN:
assert( ExprUseYTab(p) );
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
NEVER(p->y.pTab==0) || /* Reference to column of index on expr */
(p->iColumn>=0
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
&& ALWAYS(p->iColumn<p->y.pTab->nCol)
&& p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
@@ -5322,8 +5325,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
if( inReg!=target ){
u8 op;
if( ALWAYS(pExpr)
&& (ExprHasProperty(pExpr,EP_Subquery) || pExpr->op==TK_REGISTER)
Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr);
testcase( pX!=pExpr );
if( ALWAYS(pX)
&& (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER)
){
op = OP_Copy;
}else{
@@ -6819,6 +6824,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}else{
pItem->bOBPayload = 1;
}
pItem->bUseSubtype =
(pItem->pFunc->funcFlags & SQLITE_SUBTYPE)!=0;
}else{
pItem->iOBTab = -1;
}
+3 -3
View File
@@ -1101,13 +1101,13 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
double r1, r2;
const char *zVal;
r1 = sqlite3_value_double(pValue);
sqlite3_str_appendf(pStr, "%!.15g", r1);
sqlite3_str_appendf(pStr, "%!0.15g", r1);
zVal = sqlite3_str_value(pStr);
if( zVal ){
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
if( r1!=r2 ){
sqlite3_str_reset(pStr);
sqlite3_str_appendf(pStr, "%!.20e", r1);
sqlite3_str_appendf(pStr, "%!0.20e", r1);
}
}
break;
@@ -1409,7 +1409,7 @@ static void replaceFunc(
}
if( zPattern[0]==0 ){
assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
sqlite3_result_value(context, argv[0]);
sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT);
return;
}
nPattern = sqlite3_value_bytes(argv[1]);
+3
View File
@@ -244,6 +244,9 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
#ifdef SQLITE_DEBUG
0, /* bJsonSelfcheck */
#endif
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
+1 -1
View File
@@ -1086,7 +1086,7 @@ void sqlite3Insert(
pNx->iDataCur = iDataCur;
pNx->iIdxCur = iIdxCur;
if( pNx->pUpsertTarget ){
if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){
goto insert_cleanup;
}
}
+1510 -1966
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -4659,6 +4659,28 @@ int sqlite3_test_control(int op, ...){
break;
}
#endif
/* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff);
**
** Activate or deactivate validation of JSONB that is generated from
** text. Off by default, as the validation is slow. Validation is
** only available if compiled using SQLITE_DEBUG.
**
** If onOff is initially 1, then turn it on. If onOff is initially
** off, turn it off. If onOff is initially -1, then change onOff
** to be the current setting.
*/
case SQLITE_TESTCTRL_JSON_SELFCHECK: {
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
int *pOnOff = va_arg(ap, int*);
if( *pOnOff<0 ){
*pOnOff = sqlite3Config.bJsonSelfcheck;
}else{
sqlite3Config.bJsonSelfcheck = (u8)((*pOnOff)&0xff);
}
#endif
break;
}
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
+8
View File
@@ -799,6 +799,14 @@ unsigned char *sqlite3_serialize(
pOut = 0;
}else{
sz = sqlite3_column_int64(pStmt, 0)*szPage;
if( sz==0 ){
sqlite3_reset(pStmt);
sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
sz = sqlite3_column_int64(pStmt, 0)*szPage;
}
}
if( piSize ) *piSize = sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
pOut = 0;
+18 -6
View File
@@ -4434,9 +4434,15 @@ static int unixShmSystemLock(
pShmNode = pFile->pInode->pShmNode;
/* Assert that the correct mutex or mutexes are held. */
if( pShmNode->nRef==0 ){
assert( ofst==UNIX_SHM_DMS && n==1 && unixMutexHeld() );
/* Assert that the parameters are within expected range and that the
** correct mutex or mutexes are held. */
assert( pShmNode->nRef>=0 );
assert( (ofst==UNIX_SHM_DMS && n==1)
|| (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK))
);
if( ofst==UNIX_SHM_DMS ){
assert( pShmNode->nRef>0 || unixMutexHeld() );
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
}else{
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int ii;
@@ -5089,7 +5095,7 @@ static int unixShmLock(
for(iMutex=ofst; iMutex<ofst+n; iMutex++){
if( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ){
rc = sqlite3_mutex_try(pShmNode->aMutex[iMutex]);
if( rc!=SQLITE_OK ) break;
if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes;
}else{
sqlite3_mutex_enter(pShmNode->aMutex[iMutex]);
}
@@ -5098,7 +5104,7 @@ static int unixShmLock(
sqlite3_mutex_enter(pShmNode->pShmMutex);
#endif
if( rc==SQLITE_OK ){
if( ALWAYS(rc==SQLITE_OK) ){
if( flags & SQLITE_SHM_UNLOCK ){
/* Case (a) - unlock. */
int bUnlock = 1;
@@ -5177,6 +5183,7 @@ static int unixShmLock(
/* Drop the mutexes acquired above. */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
leave_shmnode_mutexes:
for(iMutex--; iMutex>=ofst; iMutex--){
sqlite3_mutex_leave(pShmNode->aMutex[iMutex]);
}
@@ -5434,11 +5441,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->mmapSizeMax>0 ){
/* Ensure that there is always at least a 256 byte buffer of addressable
** memory following the returned page. If the database is corrupt,
** SQLite may overread the page slightly (in practice only a few bytes,
** but 256 is safe, round, number). */
const int nEofBuffer = 256;
if( pFd->pMapRegion==0 ){
int rc = unixMapfile(pFd, -1);
if( rc!=SQLITE_OK ) return rc;
}
if( pFd->mmapSize >= iOff+nAmt ){
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
}
+6 -1
View File
@@ -4521,6 +4521,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->mmapSizeMax>0 ){
/* Ensure that there is always at least a 256 byte buffer of addressable
** memory following the returned page. If the database is corrupt,
** SQLite may overread the page slightly (in practice only a few bytes,
** but 256 is safe, round, number). */
const int nEofBuffer = 256;
if( pFd->pMapRegion==0 ){
int rc = winMapfile(pFd, -1);
if( rc!=SQLITE_OK ){
@@ -4529,7 +4534,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
return rc;
}
}
if( pFd->mmapSize >= iOff+nAmt ){
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
assert( pFd->pMapRegion!=0 );
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
+8 -9
View File
@@ -688,7 +688,7 @@ struct Pager {
char *zJournal; /* Name of the journal file */
int (*xBusyHandler)(void*); /* Function to call when busy */
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
int aStat[4]; /* Total cache hits, misses, writes, spills */
u32 aStat[4]; /* Total cache hits, misses, writes, spills */
#ifdef SQLITE_TEST
int nRead; /* Database pages read */
#endif
@@ -818,9 +818,8 @@ int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
int rc;
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
return (rc==SQLITE_OK && iRead==0);
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
return iRead==0;
}
#endif
return 1;
@@ -6832,11 +6831,11 @@ int *sqlite3PagerStats(Pager *pPager){
a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
a[4] = pPager->eState;
a[5] = pPager->errCode;
a[6] = pPager->aStat[PAGER_STAT_HIT];
a[7] = pPager->aStat[PAGER_STAT_MISS];
a[6] = (int)pPager->aStat[PAGER_STAT_HIT] & 0x7fffffff;
a[7] = (int)pPager->aStat[PAGER_STAT_MISS] & 0x7fffffff;
a[8] = 0; /* Used to be pPager->nOvfl */
a[9] = pPager->nRead;
a[10] = pPager->aStat[PAGER_STAT_WRITE];
a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff;
return a;
}
#endif
@@ -6852,7 +6851,7 @@ int *sqlite3PagerStats(Pager *pPager){
** reset parameter is non-zero, the cache hit or miss count is zeroed before
** returning.
*/
void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){
assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
|| eStat==SQLITE_DBSTATUS_CACHE_MISS
@@ -7792,7 +7791,7 @@ int sqlite3PagerWalFramesize(Pager *pPager){
}
#endif
#ifdef SQLITE_USE_SEH
#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
int sqlite3PagerWalSystemErrno(Pager *pPager){
return sqlite3WalSystemErrno(pPager->pWal);
}
+1 -1
View File
@@ -216,7 +216,7 @@ sqlite3_file *sqlite3PagerJrnlFile(Pager*);
const char *sqlite3PagerJournalname(Pager*);
void *sqlite3PagerTempSpace(Pager*);
int sqlite3PagerIsMemdb(Pager*);
void sqlite3PagerCacheStat(Pager *, int, int, int *);
void sqlite3PagerCacheStat(Pager *, int, int, u64*);
void sqlite3PagerClearCache(Pager*);
int sqlite3SectorSize(sqlite3_file *);
+34 -25
View File
@@ -1762,31 +1762,7 @@ void sqlite3Pragma(
int mxCol; /* Maximum non-virtual column number */
if( pObjTab && pObjTab!=pTab ) continue;
if( !IsOrdinaryTable(pTab) ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_vtab *pVTab;
int a1;
if( !IsVirtual(pTab) ) continue;
if( pTab->nCol<=0 ){
const char *zMod = pTab->u.vtab.azArg[0];
if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
}
sqlite3ViewGetColumnNames(pParse, pTab);
if( pTab->u.vtab.p==0 ) continue;
pVTab = pTab->u.vtab.p->pVtab;
if( NEVER(pVTab==0) ) continue;
if( NEVER(pVTab->pModule==0) ) continue;
if( pVTab->pModule->iVersion<4 ) continue;
if( pVTab->pModule->xIntegrity==0 ) continue;
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
pTab->nTabRef++;
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, a1);
#endif
continue;
}
if( !IsOrdinaryTable(pTab) ) continue;
if( isQuick || HasRowid(pTab) ){
pPk = 0;
r2 = 0;
@@ -1921,6 +1897,7 @@ void sqlite3Pragma(
** is REAL, we have to load the actual data using OP_Column
** to reliably determine if the value is a NULL. */
sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3);
sqlite3ColumnDefault(v, pTab, j, 3);
jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk);
VdbeCoverage(v);
}
@@ -2111,6 +2088,38 @@ void sqlite3Pragma(
}
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Second pass to invoke the xIntegrity method on all virtual
** tables.
*/
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
sqlite3_vtab *pVTab;
int a1;
if( pObjTab && pObjTab!=pTab ) continue;
if( IsOrdinaryTable(pTab) ) continue;
if( !IsVirtual(pTab) ) continue;
if( pTab->nCol<=0 ){
const char *zMod = pTab->u.vtab.azArg[0];
if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
}
sqlite3ViewGetColumnNames(pParse, pTab);
if( pTab->u.vtab.p==0 ) continue;
pVTab = pTab->u.vtab.p->pVtab;
if( NEVER(pVTab==0) ) continue;
if( NEVER(pVTab->pModule==0) ) continue;
if( pVTab->pModule->iVersion<4 ) continue;
if( pVTab->pModule->xIntegrity==0 ) continue;
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
pTab->nTabRef++;
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, a1);
continue;
}
#endif
}
{
static const int iLn = VDBE_OFFSET_LINENO(2);
+2 -1
View File
@@ -498,6 +498,7 @@ void sqlite3_str_vappendf(
if( xtype==etFLOAT ){
iRound = -precision;
}else if( xtype==etGENERIC ){
if( precision==0 ) precision = 1;
iRound = precision;
}else{
iRound = precision+1;
@@ -1369,7 +1370,7 @@ void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
/*****************************************************************************
** Reference counted string storage
** Reference counted string/blob storage
*****************************************************************************/
/*
+49 -13
View File
@@ -79,6 +79,8 @@ static void resolveAlias(
assert( iCol>=0 && iCol<pEList->nExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
if( pExpr->pAggInfo ) return;
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( db->mallocFailed ){
@@ -182,6 +184,7 @@ Bitmask sqlite3ExprColUsed(Expr *pExpr){
assert( ExprUseYTab(pExpr) );
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
assert( n < pExTab->nCol );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
){
@@ -758,6 +761,7 @@ static int lookupName(
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
pParse->checkSchema = 1;
pTopNC->nNcErr++;
eNewExprOp = TK_NULL;
}
assert( pFJMatch==0 );
@@ -784,7 +788,7 @@ static int lookupName(
** If a generated column is referenced, set bits for every column
** of the table.
*/
if( pExpr->iColumn>=0 && pMatch!=0 ){
if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){
pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
}
@@ -962,6 +966,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** resolved. This prevents "column" from being counted as having been
** referenced, which might prevent a SELECT from being erroneously
** marked as correlated.
**
** 2024-03-28: Beware of aggregates. A bare column of aggregated table
** can still evaluate to NULL even though it is marked as NOT NULL.
** Example:
**
** CREATE TABLE t1(a INT NOT NULL);
** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1;
**
** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized
** here because at the time this case is hit, we do not yet know whether
** or not t1 is being aggregated. We have to assume the worst and omit
** the optimization. The only time it is safe to apply this optimization
** is within the WHERE clause.
*/
case TK_NOTNULL:
case TK_ISNULL: {
@@ -972,19 +989,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
testcase( ExprHasProperty(pExpr, EP_OuterON) );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
pExpr->flags |= EP_IntValue;
pExpr->op = TK_INTEGER;
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
p->nRef = anRef[i];
}
sqlite3ExprDelete(pParse->db, pExpr->pLeft);
pExpr->pLeft = 0;
if( IN_RENAME_OBJECT ) return WRC_Prune;
if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
/* The expression can be NULL. So the optimization does not apply */
return WRC_Prune;
}
for(i=0, p=pNC; p; p=p->pNext, i++){
if( (p->ncFlags & NC_Where)==0 ){
return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */
}
}
testcase( ExprHasProperty(pExpr, EP_OuterON) );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x80000 ){
sqlite3DebugPrintf(
"NOT NULL strength reduction converts the following to %d:\n",
pExpr->op==TK_NOTNULL
);
sqlite3ShowExpr(pExpr);
}
#endif /* TREETRACE_ENABLED */
pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
pExpr->flags |= EP_IntValue;
pExpr->op = TK_INTEGER;
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
p->nRef = anRef[i];
}
sqlite3ExprDelete(pParse->db, pExpr->pLeft);
pExpr->pLeft = 0;
return WRC_Prune;
}
@@ -1884,7 +1918,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
}
sNC.ncFlags |= NC_Where;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
sNC.ncFlags &= ~NC_Where;
/* Resolve names in table-valued-function arguments */
for(i=0; i<p->pSrc->nSrc; i++){
+45 -24
View File
@@ -184,6 +184,9 @@ Select *sqlite3SelectNew(
void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
void sqlite3SelectDeleteGeneric(sqlite3 *db, void *p){
if( ALWAYS(p) ) clearSelect(db, (Select*)p, 1);
}
/*
** Return a pointer to the right-most SELECT statement in a compound.
@@ -3204,9 +3207,7 @@ multi_select_end:
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
if( pDelete ){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3SelectDelete,
pDelete);
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete);
}
return rc;
}
@@ -3757,8 +3758,7 @@ static int multiSelectOrderBy(
/* Make arrangements to free the 2nd and subsequent arms of the compound
** after the parse has finished */
if( pSplit->pPrior ){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior);
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior);
}
pSplit->pPrior = pPrior;
pPrior->pNext = pSplit;
@@ -4579,9 +4579,7 @@ static int flattenSubquery(
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3ParserAddCleanup(pToplevel,
(void(*)(sqlite3*,void*))sqlite3DeleteTable,
pTabToDel);
sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
@@ -5628,8 +5626,7 @@ static struct Cte *searchWith(
With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
if( bFree ){
pWith = (With*)sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3WithDelete,
pWith = (With*)sqlite3ParserAddCleanup(pParse, sqlite3WithDeleteGeneric,
pWith);
if( pWith==0 ) return 0;
}
@@ -6662,6 +6659,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
assert( pFunc->pFExpr->pLeft!=0 );
assert( pFunc->pFExpr->pLeft->op==TK_ORDER );
assert( ExprUseXList(pFunc->pFExpr->pLeft) );
assert( pFunc->pFunc!=0 );
pOBList = pFunc->pFExpr->pLeft->x.pList;
if( !pFunc->bOBUnique ){
nExtra++; /* One extra column for the OP_Sequence */
@@ -6671,6 +6669,9 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
assert( ExprUseXList(pFunc->pFExpr) );
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
if( pFunc->bUseSubtype ){
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOBList, 0, nExtra);
if( !pFunc->bOBUnique && pParse->nErr==0 ){
pKeyInfo->nKeyField++;
@@ -6697,16 +6698,17 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
assert( ExprUseXList(pF->pFExpr) );
pList = pF->pFExpr->x.pList;
if( pF->iOBTab>=0 ){
/* For an ORDER BY aggregate, calls to OP_AggStep where deferred and
** all content was stored in emphermal table pF->iOBTab. Extract that
** content now (in ORDER BY order) and make all calls to OP_AggStep
/* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs
** were stored in emphermal table pF->iOBTab. Here, we extract those
** inputs (in ORDER BY order) and make all calls to OP_AggStep
** before doing the OP_AggFinal call. */
int iTop; /* Start of loop for extracting columns */
int nArg; /* Number of columns to extract */
int nKey; /* Key columns to be skipped */
int regAgg; /* Extract into this array */
int j; /* Loop counter */
assert( pF->pFunc!=0 );
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
@@ -6723,6 +6725,15 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
for(j=nArg-1; j>=0; j--){
sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j);
}
if( pF->bUseSubtype ){
int regSubtype = sqlite3GetTempReg(pParse);
int iBaseCol = nKey + nArg + (pF->bOBPayload==0 && pF->bOBUnique==0);
for(j=nArg-1; j>=0; j--){
sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, iBaseCol+j, regSubtype);
sqlite3VdbeAddOp2(v, OP_SetSubtype, regSubtype, regAgg+j);
}
sqlite3ReleaseTempReg(pParse, regSubtype);
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
@@ -6777,6 +6788,7 @@ static void updateAccumulator(
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
assert( !IsWindowFunc(pF->pFExpr) );
assert( pF->pFunc!=0 );
pList = pF->pFExpr->x.pList;
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
@@ -6821,6 +6833,9 @@ static void updateAccumulator(
if( pF->bOBPayload ){
regAggSz += nArg;
}
if( pF->bUseSubtype ){
regAggSz += nArg;
}
regAggSz++; /* One extra register to hold result of MakeRecord */
regAgg = sqlite3GetTempRange(pParse, regAggSz);
regDistinct = regAgg;
@@ -6833,6 +6848,14 @@ static void updateAccumulator(
if( pF->bOBPayload ){
regDistinct = regAgg+jj;
sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP);
jj += nArg;
}
if( pF->bUseSubtype ){
int kk;
int regBase = pF->bOBPayload ? regDistinct : regAgg;
for(kk=0; kk<nArg; kk++, jj++){
sqlite3VdbeAddOp2(v, OP_GetSubtype, regBase+kk, regAgg+jj);
}
}
}else if( pList ){
nArg = pList->nExpr;
@@ -7037,7 +7060,8 @@ static SrcItem *isSelfJoinView(
/*
** Deallocate a single AggInfo object
*/
static void agginfoFree(sqlite3 *db, AggInfo *p){
static void agginfoFree(sqlite3 *db, void *pArg){
AggInfo *p = (AggInfo*)pArg;
sqlite3DbFree(db, p->aCol);
sqlite3DbFree(db, p->aFunc);
sqlite3DbFreeNN(db, p);
@@ -7111,7 +7135,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
pSub->selFlags |= SF_Aggregate;
pSub->selFlags &= ~SF_Compound;
pSub->nSelectRow = 0;
sqlite3ExprListDelete(db, pSub->pEList);
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList);
pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm);
pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
@@ -7291,9 +7315,8 @@ int sqlite3Select(
sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
}
#endif
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3ExprListDelete,
p->pOrderBy);
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric,
p->pOrderBy);
testcase( pParse->earlyCleanup );
p->pOrderBy = 0;
}
@@ -7485,9 +7508,8 @@ int sqlite3Select(
){
TREETRACE(0x800,pParse,p,
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3ExprListDelete,
pSub->pOrderBy);
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric,
pSub->pOrderBy);
pSub->pOrderBy = 0;
}
@@ -8016,8 +8038,7 @@ int sqlite3Select(
*/
pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
if( pAggInfo ){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))agginfoFree, pAggInfo);
sqlite3ParserAddCleanup(pParse, agginfoFree, pAggInfo);
testcase( pParse->earlyCleanup );
}
if( db->mallocFailed ){
+180 -55
View File
@@ -736,14 +736,14 @@ static int strlenChar(const char *z){
*/
static FILE * openChrSource(const char *zFile){
#if defined(_WIN32) || defined(WIN32)
struct _stat x = {0};
struct __stat64 x = {0};
# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
/* On Windows, open first, then check the stream nature. This order
** is necessary because _stat() and sibs, when checking a named pipe,
** effectively break the pipe as its supplier sees it. */
FILE *rv = fopen(zFile, "rb");
if( rv==0 ) return 0;
if( _fstat(_fileno(rv), &x) != 0
if( _fstat64(_fileno(rv), &x) != 0
|| !STAT_CHR_SRC(x.st_mode)){
fclose(rv);
rv = 0;
@@ -1292,6 +1292,7 @@ struct ShellState {
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
u8 bSafeMode; /* True to prohibit unsafe operations */
u8 bSafeModePersist; /* The long-term value of bSafeMode */
u8 eRestoreState; /* See comments above doAutoDetectRestore() */
ColModeOpts cmOpts; /* Option values affecting columnar mode output */
unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
@@ -3763,6 +3764,7 @@ static void exec_prepared_stmt_columnar(
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ) return;
nColumn = sqlite3_column_count(pStmt);
if( nColumn==0 ) goto columnar_end;
nAlloc = nColumn*4;
if( nAlloc<=0 ) nAlloc = 1;
azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
@@ -3848,7 +3850,6 @@ static void exec_prepared_stmt_columnar(
if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
}
if( seenInterrupt ) goto columnar_end;
if( nColumn==0 ) goto columnar_end;
switch( p->cMode ){
case MODE_Column: {
colSep = " ";
@@ -5319,7 +5320,6 @@ static void open_db(ShellState *p, int openFlags){
break;
}
}
globalDb = p->db;
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
eputf("Error: unable to open database \"%s\": %s\n",
zDbFilename, sqlite3_errmsg(p->db));
@@ -5336,6 +5336,7 @@ static void open_db(ShellState *p, int openFlags){
zDbFilename);
}
}
globalDb = p->db;
sqlite3_db_config(p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, (int)0, (int*)0);
/* Reflect the use or absence of --unsafe-testing invocation. */
@@ -6731,7 +6732,6 @@ static int lintDotCommand(
return SQLITE_ERROR;
}
#if !defined SQLITE_OMIT_VIRTUALTABLE
static void shellPrepare(
sqlite3 *db,
int *pRc,
@@ -6750,12 +6750,8 @@ static void shellPrepare(
/*
** Create a prepared statement using printf-style arguments for the SQL.
**
** This routine is could be marked "static". But it is not always used,
** depending on compile-time options. By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
void shellPreparePrintf(
static void shellPreparePrintf(
sqlite3 *db,
int *pRc,
sqlite3_stmt **ppStmt,
@@ -6778,13 +6774,10 @@ void shellPreparePrintf(
}
}
/* Finalize the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static". But it is not always used,
** depending on compile-time options. By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
/*
** Finalize the prepared statement created using shellPreparePrintf().
*/
void shellFinalize(
static void shellFinalize(
int *pRc,
sqlite3_stmt *pStmt
){
@@ -6800,6 +6793,7 @@ void shellFinalize(
}
}
#if !defined SQLITE_OMIT_VIRTUALTABLE
/* Reset the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static". But it is not always used,
@@ -7866,6 +7860,30 @@ FROM (\
}
}
/*
** Check if the sqlite_schema table contains one or more virtual tables. If
** parameter zLike is not NULL, then it is an SQL expression that the
** sqlite_schema row must also match. If one or more such rows are found,
** print the following warning to the output:
**
** WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled
*/
static int outputDumpWarning(ShellState *p, const char *zLike){
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
shellPreparePrintf(p->db, &rc, &pStmt,
"SELECT 1 FROM sqlite_schema o WHERE "
"sql LIKE 'CREATE VIRTUAL TABLE%%' AND %s", zLike ? zLike : "true"
);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
oputz("/* WARNING: "
"Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */\n"
);
}
shellFinalize(&rc, pStmt);
return rc;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
@@ -8328,6 +8346,7 @@ static int do_meta_command(char *zLine, ShellState *p){
open_db(p, 0);
outputDumpWarning(p, zLike);
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
/* When playing back a "dump", the content might appear in an order
** which causes immediate foreign key constraints to be violated.
@@ -8679,16 +8698,15 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifndef SQLITE_SHELL_FIDDLE
if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
char *zTable = 0; /* Insert data into this table */
char *zSchema = 0; /* within this schema (may default to "main") */
char *zSchema = 0; /* Schema of zTable */
char *zFile = 0; /* Name of file to extra content from */
sqlite3_stmt *pStmt = NULL; /* A statement */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
i64 nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int needCommit; /* True to COMMIT or ROLLBACK at end */
int nSep; /* Number of bytes in p->colSeparator[] */
char *zSql; /* An SQL statement */
char *zFullTabName; /* Table name with schema if applicable */
char *zSql = 0; /* An SQL statement */
ImportCtx sCtx; /* Reader context */
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
@@ -8822,24 +8840,14 @@ static int do_meta_command(char *zLine, ShellState *p){
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
if( zSchema!=0 ){
zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
}else{
zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
}
zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
if( zSql==0 || zFullTabName==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
/* Table does not exist. Create it. */
sqlite3 *dbCols = 0;
char *zRenames = 0;
char *zColDefs;
zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
zSchema ? zSchema : "main", zTable);
while( xRead(&sCtx) ){
zAutoColumn(sCtx.z, &dbCols, 0);
if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -8854,34 +8862,50 @@ static int do_meta_command(char *zLine, ShellState *p){
assert(dbCols==0);
if( zColDefs==0 ){
eputf("%s: empty file\n", sCtx.zFile);
import_fail:
sqlite3_free(zCreate);
sqlite3_free(zSql);
sqlite3_free(zFullTabName);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
if( zCreate==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
if( eVerbose>=1 ){
oputf("%s\n", zCreate);
}
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
if( rc ){
eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
goto import_fail;
}
sqlite3_free(zCreate);
zCreate = 0;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc ){
eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
}
zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);",
zTable, zSchema);
if( zSql==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
nByte = strlen(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
zSql = 0;
if( rc ){
if (pStmt) sqlite3_finalize(pStmt);
eputf("Error: %s\n", sqlite3_errmsg(p->db));
goto import_fail;
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
if( sqlite3_step(pStmt)==SQLITE_ROW ){
nCol = sqlite3_column_int(pStmt, 0);
}else{
nCol = 0;
}
sqlite3_free(zSql);
nCol = sqlite3_column_count(pStmt);
sqlite3_finalize(pStmt);
pStmt = 0;
if( nCol==0 ) return 0; /* no columns, no error */
@@ -8890,7 +8914,12 @@ static int do_meta_command(char *zLine, ShellState *p){
import_cleanup(&sCtx);
shell_out_of_memory();
}
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
if( zSchema ){
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
zSchema, zTable);
}else{
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
}
j = strlen30(zSql);
for(i=1; i<nCol; i++){
zSql[j++] = ',';
@@ -8902,13 +8931,15 @@ static int do_meta_command(char *zLine, ShellState *p){
oputf("Insert using: %s\n", zSql);
}
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
zSql = 0;
if( rc ){
eputf("Error: %s\n", sqlite3_errmsg(p->db));
if (pStmt) sqlite3_finalize(pStmt);
goto import_fail;
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
sqlite3_free(zSql);
sqlite3_free(zFullTabName);
needCommit = sqlite3_get_autocommit(p->db);
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
do{
@@ -10756,6 +10787,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{"fk_no_action", SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN" },
{"imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
{"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
{"json_selfcheck", SQLITE_TESTCTRL_JSON_SELFCHECK ,0,"BOOLEAN" },
{"localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
{"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
{"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
@@ -10974,6 +11006,16 @@ static int do_meta_command(char *zLine, ShellState *p){
isOk = 3;
}
break;
case SQLITE_TESTCTRL_JSON_SELFCHECK:
if( nArg==2 ){
rc2 = -1;
isOk = 1;
}else{
rc2 = booleanValue(azArg[2]);
isOk = 3;
}
sqlite3_test_control(testctrl, &rc2);
break;
}
}
if( isOk==0 && iCtrl>=0 ){
@@ -11380,6 +11422,88 @@ static int line_is_complete(char *zSql, int nSql){
return rc;
}
/*
** This function is called after processing each line of SQL in the
** runOneSqlLine() function. Its purpose is to detect scenarios where
** defensive mode should be automatically turned off. Specifically, when
**
** 1. The first line of input is "PRAGMA foreign_keys=OFF;",
** 2. The second line of input is "BEGIN TRANSACTION;",
** 3. The database is empty, and
** 4. The shell is not running in --safe mode.
**
** The implementation uses the ShellState.eRestoreState to maintain state:
**
** 0: Have not seen any SQL.
** 1: Have seen "PRAGMA foreign_keys=OFF;".
** 2-6: Currently running .dump transaction. If the "2" bit is set,
** disable DEFENSIVE when done. If "4" is set, disable DQS_DDL.
** 7: Nothing left to do. This function becomes a no-op.
*/
static int doAutoDetectRestore(ShellState *p, const char *zSql){
int rc = SQLITE_OK;
if( p->eRestoreState<7 ){
switch( p->eRestoreState ){
case 0: {
const char *zExpect = "PRAGMA foreign_keys=OFF;";
assert( strlen(zExpect)==24 );
if( p->bSafeMode==0 && memcmp(zSql, zExpect, 25)==0 ){
p->eRestoreState = 1;
}else{
p->eRestoreState = 7;
}
break;
};
case 1: {
int bIsDump = 0;
const char *zExpect = "BEGIN TRANSACTION;";
assert( strlen(zExpect)==18 );
if( memcmp(zSql, zExpect, 19)==0 ){
/* Now check if the database is empty. */
const char *zQuery = "SELECT 1 FROM sqlite_schema LIMIT 1";
sqlite3_stmt *pStmt = 0;
bIsDump = 1;
shellPrepare(p->db, &rc, zQuery, &pStmt);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
bIsDump = 0;
}
shellFinalize(&rc, pStmt);
}
if( bIsDump && rc==SQLITE_OK ){
int bDefense = 0;
int bDqsDdl = 0;
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &bDefense);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DQS_DDL, -1, &bDqsDdl);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DQS_DDL, 1, 0);
p->eRestoreState = (bDefense ? 2 : 0) + (bDqsDdl ? 4 : 0);
}else{
p->eRestoreState = 7;
}
break;
}
default: {
if( sqlite3_get_autocommit(p->db) ){
if( (p->eRestoreState & 2) ){
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 1, 0);
}
if( (p->eRestoreState & 4) ){
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DQS_DDL, 0, 0);
}
p->eRestoreState = 7;
}
break;
}
}
}
return rc;
}
/*
** Run a single line of SQL. Return the number of errors.
*/
@@ -11427,6 +11551,8 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
oputf("%s\n", zLineBuf);
}
if( doAutoDetectRestore(p, zSql) ) return 1;
return 0;
}
@@ -12061,10 +12187,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}else if( cli_strcmp(z,"-init")==0 ){
zInitFile = cmdline_option_value(argc, argv, ++i);
}else if( cli_strcmp(z,"-interactive")==0 ){
/* Need to check for interactive override here to so that it can
** affect console setup (for Windows only) and testing thereof.
*/
stdin_is_interactive = 1;
}else if( cli_strcmp(z,"-batch")==0 ){
/* Need to check for batch mode here to so we can avoid printing
** informational messages (like from process_sqliterc) before
@@ -12338,7 +12460,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
return 0;
}else if( cli_strcmp(z,"-interactive")==0 ){
/* already handled */
/* Need to check for interactive override here to so that it can
** affect console setup (for Windows only) and testing thereof.
*/
stdin_is_interactive = 1;
}else if( cli_strcmp(z,"-batch")==0 ){
/* already handled */
}else if( cli_strcmp(z,"-utf8")==0 ){
+8 -3
View File
@@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not dereference the arrays or string pointers
** passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
int sqlite3_exec(
@@ -8039,9 +8041,11 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
**
** ^(Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
** will always return SQLITE_BUSY. The SQLite core only ever uses
** sqlite3_mutex_try() as an optimization so this is acceptable
** behavior.)^
** will always return SQLITE_BUSY. In most cases the SQLite core only uses
** sqlite3_mutex_try() as an optimization, so this is acceptable
** behavior. The exceptions are unix builds that set the
** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working
** sqlite3_mutex_try() is required.)^
**
** ^The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
@@ -8300,6 +8304,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ASSERT 12
#define SQLITE_TESTCTRL_ALWAYS 13
#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
+31 -1
View File
@@ -328,6 +328,19 @@
# undef SQLITE_USE_SEH
#endif
/*
** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly
** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0
*/
#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1
/* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */
# undef SQLITE_DIRECT_OVERFLOW_READ
#else
/* In all other cases, enable */
# define SQLITE_DIRECT_OVERFLOW_READ 1
#endif
/*
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
** 0 means mutexes are permanently disable and the library is never
@@ -1110,6 +1123,7 @@ extern u32 sqlite3TreeTrace;
** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
** 0x00020000 Transform DISTINCT into GROUP BY
** 0x00040000 SELECT tree dump after all code has been generated
** 0x00080000 NOT NULL strength reduction
*/
/*
@@ -2753,6 +2767,7 @@ struct Index {
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
@@ -2866,6 +2881,7 @@ struct AggInfo {
int iOBTab; /* Ephemeral table to implement ORDER BY */
u8 bOBPayload; /* iOBTab has payload columns separate from key */
u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */
u8 bUseSubtype; /* Transfer subtype info through sorter */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
@@ -3433,6 +3449,7 @@ struct NameContext {
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
@@ -3456,6 +3473,7 @@ struct Upsert {
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
u8 isDup; /* True if 2nd or later with same pUpsertIdx */
/* Above this point is the parse tree for the ON CONFLICT clauses.
** The next group of fields stores intermediate data. */
void *pToFree; /* Free memory when deleting the Upsert object */
@@ -4116,6 +4134,9 @@ struct sqlite3_str {
**
** 3. Make a (read-only) copy of a read-only RCStr string using
** sqlite3RCStrRef().
**
** "String" is in the name, but an RCStr object can also be used to hold
** binary data.
*/
struct RCStr {
u64 nRCRef; /* Number of references */
@@ -4174,6 +4195,9 @@ struct Sqlite3Config {
u8 bSmallMalloc; /* Avoid large memory allocations if true */
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
u8 bUseLongDouble; /* Make use of long double */
#ifdef SQLITE_DEBUG
u8 bJsonSelfcheck; /* Double-check JSON parsing */
#endif
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ -4800,6 +4824,7 @@ void sqlite3ExprOrderByAggregateError(Parse*,Expr*);
void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
void sqlite3ExprDeleteGeneric(sqlite3*,void*);
void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
@@ -4809,6 +4834,7 @@ void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
void sqlite3ExprListDeleteGeneric(sqlite3*,void*);
u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3IndexHasDuplicateRootPage(Index*);
int sqlite3Init(sqlite3*, char**);
@@ -4899,6 +4925,7 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
void sqlite3DropTable(Parse*, SrcList*, int, int);
void sqlite3CodeDropTable(Parse*, Table*, int, int);
void sqlite3DeleteTable(sqlite3*, Table*);
void sqlite3DeleteTableGeneric(sqlite3*, void*);
void sqlite3FreeIndex(sqlite3*, Index*);
#ifndef SQLITE_OMIT_AUTOINCREMENT
void sqlite3AutoincrementBegin(Parse *pParse);
@@ -4935,6 +4962,7 @@ int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
void sqlite3SelectDeleteGeneric(sqlite3*,void*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -5161,6 +5189,7 @@ int sqlite3Utf16ByteLen(const void *pData, int nChar);
#endif
int sqlite3Utf8CharLen(const char *pData, int nByte);
u32 sqlite3Utf8Read(const u8**);
int sqlite3Utf8ReadLimited(const u8*, int, u32*);
LogEst sqlite3LogEst(u64);
LogEst sqlite3LogEstAdd(LogEst,LogEst);
LogEst sqlite3LogEstFromDouble(double);
@@ -5507,6 +5536,7 @@ const char *sqlite3JournalModename(int);
void sqlite3CteDelete(sqlite3*,Cte*);
With *sqlite3WithAdd(Parse*,With*,Cte*);
void sqlite3WithDelete(sqlite3*,With*);
void sqlite3WithDeleteGeneric(sqlite3*,void*);
With *sqlite3WithPush(Parse*, With*, u8);
#else
# define sqlite3CteNew(P,T,E,S) ((void*)0)
@@ -5519,7 +5549,7 @@ const char *sqlite3JournalModename(int);
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
void sqlite3UpsertDelete(sqlite3*,Upsert*);
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
int sqlite3UpsertNextIsIPK(Upsert*);
+1 -1
View File
@@ -187,7 +187,7 @@
** max_page_count macro.
*/
#ifndef SQLITE_MAX_PAGE_COUNT
# define SQLITE_MAX_PAGE_COUNT 1073741823
# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */
#endif
/*
+2 -2
View File
@@ -362,7 +362,7 @@ int sqlite3_db_status(
case SQLITE_DBSTATUS_CACHE_MISS:
case SQLITE_DBSTATUS_CACHE_WRITE:{
int i;
int nRet = 0;
u64 nRet = 0;
assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
@@ -375,7 +375,7 @@ int sqlite3_db_status(
*pHighwater = 0; /* IMP: R-42420-56072 */
/* IMP: R-54100-20147 */
/* IMP: R-29431-39229 */
*pCurrent = nRet;
*pCurrent = (int)nRet & 0x7fffffff;
break;
}
+51
View File
@@ -991,6 +991,39 @@ static void intrealFunction(
sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context);
}
/*
** These SQL functions attempt to return a value (their first argument)
** that has been modified to have multiple datatypes. For example both
** TEXT and INTEGER.
*/
static void addTextTypeFunction(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
(void)sqlite3_value_text(argv[0]);
(void)argc;
sqlite3_result_value(context, argv[0]);
}
static void addIntTypeFunction(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
(void)sqlite3_value_int64(argv[0]);
(void)argc;
sqlite3_result_value(context, argv[0]);
}
static void addRealTypeFunction(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
(void)sqlite3_value_double(argv[0]);
(void)argc;
sqlite3_result_value(context, argv[0]);
}
/*
** SQL function: strtod(X)
**
@@ -1103,6 +1136,22 @@ static int SQLITE_TCLAPI test_create_function(
0, intrealFunction, 0, 0);
}
/* The add_text_type(), add_int_type(), and add_real_type() functions
** attempt to return a value that has multiple datatypes.
*/
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "add_text_type", 1, SQLITE_UTF8,
0, addTextTypeFunction, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "add_int_type", 1, SQLITE_UTF8,
0, addIntTypeFunction, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "add_real_type", 1, SQLITE_UTF8,
0, addRealTypeFunction, 0, 0);
}
/* Functions strtod() and dtostr() work as in the shell. These routines
** use the standard C library to convert between floating point and
** text. This is used to compare SQLite's internal conversion routines
@@ -8120,6 +8169,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*);
#endif
extern int sqlite3_qpvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_randomjson_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -8152,6 +8202,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "prefixes", sqlite3_prefixes_init },
#endif
{ "qpvtab", sqlite3_qpvtab_init },
{ "randomjson", sqlite3_randomjson_init },
{ "regexp", sqlite3_regexp_init },
{ "remember", sqlite3_remember_init },
{ "series", sqlite3_series_init },
+2 -1
View File
@@ -694,7 +694,8 @@ static int registerTestFunctions(
{ "test_extract", 2, SQLITE_UTF8, test_extract},
{ "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob},
{ "test_getsubtype", 1, SQLITE_UTF8, test_getsubtype},
{ "test_setsubtype", 2, SQLITE_UTF8, test_setsubtype},
{ "test_setsubtype", 2, SQLITE_UTF8|SQLITE_RESULT_SUBTYPE,
test_setsubtype},
{ "test_frombind", -1, SQLITE_UTF8, test_frombind},
};
int i;
+17 -4
View File
@@ -90,7 +90,8 @@ Upsert *sqlite3UpsertNew(
int sqlite3UpsertAnalyzeTarget(
Parse *pParse, /* The parsing context */
SrcList *pTabList, /* Table into which we are inserting */
Upsert *pUpsert /* The ON CONFLICT clauses */
Upsert *pUpsert, /* The ON CONFLICT clauses */
Upsert *pAll /* Complete list of all ON CONFLICT clauses */
){
Table *pTab; /* That table into which we are inserting */
int rc; /* Result code */
@@ -193,6 +194,14 @@ int sqlite3UpsertAnalyzeTarget(
continue;
}
pUpsert->pUpsertIdx = pIdx;
if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){
/* Really this should be an error. The isDup ON CONFLICT clause will
** never fire. But this problem was not discovered until three years
** after multi-CONFLICT upsert was added, and so we silently ignore
** the problem to prevent breaking applications that might actually
** have redundant ON CONFLICT clauses. */
pUpsert->isDup = 1;
}
break;
}
if( pUpsert->pUpsertIdx==0 ){
@@ -219,9 +228,13 @@ int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
Upsert *pNext;
if( NEVER(pUpsert==0) ) return 0;
pNext = pUpsert->pNextUpsert;
if( pNext==0 ) return 1;
if( pNext->pUpsertTarget==0 ) return 1;
if( pNext->pUpsertIdx==0 ) return 1;
while( 1 /*exit-by-return*/ ){
if( pNext==0 ) return 1;
if( pNext->pUpsertTarget==0 ) return 1;
if( pNext->pUpsertIdx==0 ) return 1;
if( !pNext->isDup ) return 0;
pNext = pNext->pNextUpsert;
}
return 0;
}
+32 -1
View File
@@ -164,7 +164,38 @@ u32 sqlite3Utf8Read(
return c;
}
/*
** Read a single UTF8 character out of buffer z[], but reading no
** more than n characters from the buffer. z[] is not zero-terminated.
**
** Return the number of bytes used to construct the character.
**
** Invalid UTF8 might generate a strange result. No effort is made
** to detect invalid UTF8.
**
** At most 4 bytes will be read out of z[]. The return value will always
** be between 1 and 4.
*/
int sqlite3Utf8ReadLimited(
const u8 *z,
int n,
u32 *piOut
){
u32 c;
int i = 1;
assert( n>0 );
c = z[0];
if( c>=0xc0 ){
c = sqlite3Utf8Trans1[c-0xc0];
if( n>4 ) n = 4;
while( i<n && (z[i] & 0xc0)==0x80 ){
c = (c<<6) + (0x3f & z[i]);
i++;
}
}
*piOut = c;
return i;
}
/*
+5 -2
View File
@@ -141,7 +141,7 @@ void sqlite3ErrorClear(sqlite3 *db){
*/
void sqlite3SystemError(sqlite3 *db, int rc){
if( rc==SQLITE_IOERR_NOMEM ) return;
#ifdef SQLITE_USE_SEH
#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
if( rc==SQLITE_IOERR_IN_PAGE ){
int ii;
int iErr;
@@ -627,6 +627,9 @@ do_atof_calc:
u64 s2;
rr[0] = (double)s;
s2 = (u64)rr[0];
#if defined(_MSC_VER) && _MSC_VER<1700
if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
#endif
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
if( e>0 ){
while( e>=100 ){
@@ -1069,7 +1072,7 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
assert( p->n>0 );
assert( p->n<sizeof(p->zBuf) );
p->iDP = p->n + exp;
if( iRound<0 ){
if( iRound<=0 ){
iRound = p->iDP - iRound;
if( iRound==0 && p->zBuf[i+1]>='5' ){
iRound = 1;

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