Compare commits

..

112 Commits

Author SHA1 Message Date
drh 9b4e7898d7 Add a test case to the fix to PRAGMA integrity_check in the previous check-in.
FossilOrigin-Name: 39a57b596d309d9e2d4c59409fe5d36e0665781ce0307d157ff8b6e883161bbb
2024-05-02 12:00:36 +00:00
drh 78bc1339ac Do not accept a string that looks like a number used as an argument to
PRAGMA integrity_check as a number.  Treat it as a table name that just
happens to look like a number.

FossilOrigin-Name: b04e7a23478f1012e501a810f3e09cca81a66e802f5f72cae80c81120174e2cb
2024-05-02 11:52:31 +00:00
drh 2ae4531c89 Omit the OP_SqlExec to "PRAGMA integrity_check" added by [348fa7aaf7958b3f]
because it is a no-op.  Even if the integrity_check failes, the CREATE TABLE
is stull successful.  The OP_SqlExec just burns CPU cycles for no reason.

FossilOrigin-Name: 532795acd1c800751737fe70148f9ae691e9cf11b836577f8538421d24cab2fe
2024-05-02 11:51:26 +00:00
dan 2ad1e92858 Fix another problem in the recovery extension where a corrupt sqlite_schema table could lead to excessive memory consumption.
FossilOrigin-Name: 1c7e33a8aa0e6122b5ef606e4a7d95e8ecd9440216d4b099fe8f2a40653422be
2024-05-01 16:25:46 +00:00
dan 19ca99eea4 Fix a problem causing the recovery extension to use excessive memory and CPU time in some cases.
FossilOrigin-Name: 8de85170d53e1d2a2abe14508a222377b9493e25f3174b8f0f773427deb8df26
2024-05-01 14:42:20 +00:00
dan 8d5fe073d2 Avoid 32-bit overflow when calculating ncycle for ".scanstats vm".
FossilOrigin-Name: 2858efa06d4fc7b412b892f35f5e9a766b467b4a5b74d602a030d25443f9efb4
2024-04-30 19:34:15 +00:00
drh b11daa50f9 Fix issues in [/info/1e227ad9f413227f|LIMIT/OFFSET support for virtual tables].
The first problem was reported by
[forum:/forumpost/c243b8f856|forum post c243b8f856].  That report prompted
an enhancement to the generate_series() (also included in this merge) which
in turn identified other similar issues.

FossilOrigin-Name: 5f6c079d847e3664ec5acaf1b3e989efe0d548c211ae4a18936162b36df89065
2024-04-26 19:10:15 +00:00
stephan b95c1d0ac9 Internal JS doc touchups. No functional changes.
FossilOrigin-Name: 626b997b4e727554d7ec8b60fb37b2a94cb861a87325da4ae484bd9aa8961ca5
2024-04-26 18:42:50 +00:00
stephan 6c290ccd49 Additional internal docs in the wasm utilities.
FossilOrigin-Name: 5a2245a9ebae6d23cd343e46b9d730f66ec4d5ffc91b83ed11a0fbd2194ad807
2024-04-26 18:24:23 +00:00
dan 4c3ab545a9 Allow virtual table implementations to handle OFFSET but not LIMIT, but not LIMIT but not OFFSET.
FossilOrigin-Name: 90e5c8226a695e838e8c1703a9b8598e654d216799e8806c4d1a1f20c28c6486
2024-04-26 18:13:11 +00:00
dan 297472a2fc Have where.c ignore any plan from a virtual table that tries to use LIMIT/OFFSET without also using all WHERE constraints.
FossilOrigin-Name: 7d30596496c6a7a37b925f13d8d94d5de224ec31bb86594fa4cc07b10082e776
2024-04-26 17:19:59 +00:00
drh d3a4dbe4b8 Further fixes and improvements to the generate_series() enhancements on
this branch.

FossilOrigin-Name: b7d9bd7ee2f4100608063fdf7648f290351465d393bc876a89704f643358853e
2024-04-26 17:09:33 +00:00
drh 84a231eb61 Use hex flag masks rather than decimals in ext/misc/series.c.
FossilOrigin-Name: a94e2cd02873c283d46bf6c21d0306ad454881d7882bb167d043cc79f79a2396
2024-04-26 14:36:28 +00:00
dan 3afd5b6d65 Fix a problem allowing a LIMIT constraint to be passed to a virtual table in cases where there exist WHERE terms that cannot also be passed.
FossilOrigin-Name: 72c8ed9698dd2aadee7b84fd293e8306233f0fe5b5b5731687482444fdf461c7
2024-04-26 14:32:58 +00:00
drh 99ac2324aa Fix handling of LIMIT and OFFSET in virtual tables that are part of
a compound SELECT.

FossilOrigin-Name: 40421c1c4ed5bb1ed79ad7ee37cb5a4f0b7864c1eb94abd8ee357ab2202cad30
2024-04-26 13:38:43 +00:00
drh 317b7416a6 Enhance the generated_series() table-valued-function to respond to
LIMIT and OFFSET.  Use this to add new test cases for LIMIT and OFFSET
on virtual tables in a compound SELECT.

FossilOrigin-Name: 408d47ecaa3b906d0886f76a22b76339ec5878270ffe8d1838c74de09c29a33e
2024-04-26 13:30:48 +00:00
dan d591a5b93d Add test demonstrating the problem at [forum:/forumpost/c243b8f856|forum post c243b8f856]. No fix yet.
FossilOrigin-Name: 1685495c0a00238c9c92cce01af8108204a2fad22433ed3e7bba3c9da9ee0766
2024-04-26 12:01:17 +00:00
drh fed13d50a9 Fix the TreeView display of a LIMIT clause on a compound query. Debugging
code only - not part of production builds.

FossilOrigin-Name: 38f1e5ce4eedd59fbeb0a0d676d26dfe8a3313189ab9b9e4a5a1ed6721b73a14
2024-04-26 11:32:50 +00:00
drh ec14ef80b0 Improvement to the way that affinity is determined for columns of a
compound subquery.  The affinity is the affinity of the left-most
arm of the compound subquery that has an affinity other than NONE, adjusted
to accommodate the data types coming out of the other arms.

FossilOrigin-Name: e6df846f36209bac3e420dd80ce2bbbd87ab7a20b8063fce05f78a3c7ab6027e
2024-04-25 23:26:11 +00:00
drh ddc6bd9f21 Further improvements to the computation of affinity for compound subqueries:
make sure that the selected affinity is compatible with a literal values in
arms to the left of the arm that is used to determine affinity.

FossilOrigin-Name: bbdf22e3d989f42b963f1f2f219dfeac11db786f17ac27097ab72f72e7638a2a
2024-04-25 17:52:10 +00:00
drh 23afc2c4ec Back out the previous change on this branch. In its place: Determine the
affinity of a subquery by the left-most arm of the subquery that has an
affinity other than NONE.  In other words, scan from left to right looking
for an arm of the compound subquery with an affinity of BLOB, TEXT, INTEGER,
or REAL and pick the first one found.  Or stay with NONE if no arm has a
defined affinity.  Test cases added.

FossilOrigin-Name: b8ec8511b1968bbc1472b3e2e21f0fef1d5becebeb31f9d13ee3ca9e13abb1e5
2024-04-25 16:55:53 +00:00
stephan c859f0267c wasm: add a makefile comment about the static sqlite3.h/c version info injected into the JS files possibly differing from the runtime-emited version info when a user provides their own sqlite3.c.
FossilOrigin-Name: d99a01a0f6e1f70f70c9a0625aeaa8a8015eba352bcfb3978eafca6df10ba5a8
2024-04-25 06:52:19 +00:00
drh f8e195159f An experimental minor tweak to the way affinities are computed for compound
subqueries, when the actual affinity is ambiguous.

FossilOrigin-Name: 779723ad792ca24dd07b7a1425303c76b44bb173e718a33c26c9f7644e9912cb
2024-04-24 19:49:52 +00:00
drh 0868d58e2c If a RETURNING clause contains a subquery that references the table that is
being updated in the statement that includes the RETURNING clause, then mark
the subquery as correlated sot hat it is recomputed for each result and not
just computed once and reused.  See
[forum:/forumpost/2c83569ce8945d39|forum post 2c83569ce8945d39].

FossilOrigin-Name: 9ea6bcc8fdf6aadb756ec5bcaaa7af314167f8973bdd32fd23f83bd964f0c21e
2024-04-24 16:36:37 +00:00
dan dfa6289153 Fix a case where a corrupt stat4 record could go unrecognized due to integer overflow.
FossilOrigin-Name: 240a4a48b27a2b1070bba6d7da76a8df8e3f1808e262045d7ad2cf910df08f3d
2024-04-24 14:18:20 +00:00
drh 35b771e221 Add comments linking the assert() added in [cef4d9e3ba586735] to the places
where the precondition that the assert() tests are actually required.

FossilOrigin-Name: 6f0e7e195275aeb4aefd9da20348af35e3ef7f0a6b2768a34824daeace16eff1
2024-04-24 11:51:51 +00:00
dan 5b27ecafbc Avoid slowdown when exprNodeIsConstant() is called on deeply nested SQL functions.
FossilOrigin-Name: 1c0b0345451853846076467831884f951c92ec79476be40ce7f7b766fd2d8fc1
2024-04-24 11:40:47 +00:00
drh b065eceb56 Ensure that temporary SrcItem objects created by trigger processing have
either SrcItem.zName or SrcItem.pSelect defined.  Every SrcItem should have
one or the other.

FossilOrigin-Name: cef4d9e3ba586735598f03eb5e8f29072c9e6f62b0d34ddd2fb3ed1795f6e21c
2024-04-24 11:21:27 +00:00
stephan 99200b2f07 Remove an undocumented feature from the JS Worker1.open API because it relies on broken behavior which has no VFS-agnostic workaround.
FossilOrigin-Name: 3a640038c70c8511e7051af83aa35d163c4f96f05c5064cffd3e4e2e63cd44a9
2024-04-24 06:43:17 +00:00
drh 14602eafa7 Fix a problem with vector IN operators used with an index where the affinities
and collations for the various vector terms are different.

FossilOrigin-Name: 86e8c782e7494377de3c27b750cd83a7eb2302c1182ee2004d3864db50fca557
2024-04-23 12:02:03 +00:00
dan 0309fb919a Fix an uninitialized variable problem in the new code on this branch.
FossilOrigin-Name: 85625b38718c6e4cf7aa97fa3c52153bd25c810b68f19e7924e1f4b709c6a05d
2024-04-23 11:56:20 +00:00
stephan 3ac612dd7d Remove some dead WASM-side code.
FossilOrigin-Name: 0a07ee27bd6021a6fc1d81133012592351530ffcf6ae09322ea74624cff910df
2024-04-23 06:49:47 +00:00
stephan 642e950e63 Minor touchups in JS docs and exception messages.
FossilOrigin-Name: 9e7fc9370dfca121244f7a2941e8de629b277f1799f8de08a43ff1d86f94b6f5
2024-04-23 06:36:28 +00:00
stephan 6e6dfd6a23 When running the 'dist' target in ext/wasm for an SEE-capable build, ensure that the resulting zip file and directory name include '-see'.
FossilOrigin-Name: 04c552b12e3b77b9dfd83838d35ce19a37ed024a8c18a2000ada10cf3d1eb6ad
2024-04-23 05:38:49 +00:00
dan 46435a04fd Add extra tests for aborting conflicts in the sessions module.
FossilOrigin-Name: b4a6d32662acacb7767cfb9b8e040e6eb1f99322cb7d0cd44e6265e9ac2fb2e8
2024-04-22 20:09:17 +00:00
stephan 5d8daf184d Minor cleanups to [8fbda563d2f5].
FossilOrigin-Name: 5ee2594b657b96aea9e482a175820dcbacfa9298da45b38cf17f39ad076d3f7f
2024-04-22 17:03:52 +00:00
stephan 0a42e9913b Extend the JS/WASM SEE build support by (A) filtering SEE-related bits out of the JS when not building with SEE and (B) accepting an optional key/textkey/hexkey option to the sqlite3.oo1.DB and subclass constructors to create/open SEE-encrypted databases with. Demonstrate SEE in the test app using the kvvfs. This obviates the changes made in [5c505ee8a7].
FossilOrigin-Name: 8fbda563d2f56f8dd3f695a5711e4356de79035f332270db45d4b33ed52fdfd2
2024-04-22 16:46:37 +00:00
drh 4f2f6c74ca Extra robustness in the code that causes cursors to return NULL when they
are participating in an OUTER JOIN.

FossilOrigin-Name: 672c2869ef48e08447d37b0d76a1850cdafbe30ca1906ec98c55e3ab496fd9a6
2024-04-22 13:31:24 +00:00
stephan 2469350ad9 For sqlite3.oo1.DB JavaScript classes, bypass execution of any on-open() SQL in SEE-capable builds because it would necessarily run before the client has an opportunity to provide their decryption key, which would leave the db handle in an unusable state and cause the ctor to throw. This currently affects only the OPFS VFSes. We may want to consider extending the ctor options object to optionally accept an SEE key and apply it when opening the db.
FossilOrigin-Name: 5c505ee8a73f4b4a7053d98a12024d98340676f6ae9982311f9f88a9b46c8ae2
2024-04-22 11:48:03 +00:00
drh 2c26adb873 Continuation of the fix at [8c0f69e0e4ae0a44]: If a viaCoroutine FROM clause
term is participating in a RIGHT or FULL JOIN, we have to create an
always-NULL pseudo-cursor for that term when processing the RIGHT join.
dbsqlfuzz 6fd1ff3a64bef4a6c092e8d757548e95698b0df5.

FossilOrigin-Name: e1040e51ebd04f2a076f477b6f240f849afb10f543ebe518e09d6842cc3cb38e
2024-04-22 00:42:47 +00:00
drh db2a33a3dd Fix an indentation problem in debugging routine sqlite3ShowSrcList(). No
changes to production code.

FossilOrigin-Name: 5560df2726fed215c98d602c5f6ebbf3c5ae23f8ba1074291c509bf446fdfe66
2024-04-21 23:35:58 +00:00
dan 5749e1ee43 Slight performance improvement for the new code on this branch.
FossilOrigin-Name: 500c67f1341fe2a7e7333d525c90df201cc73a683b943ad5c1e41d4a4f639043
2024-04-20 19:19:30 +00:00
dan d737feeacf Fix a problem where an expression like (a, b) IN (SELECT ...) might not use an index on (a, b) if the affinities and collation sequences of "a" and "b" are not identical.
FossilOrigin-Name: 4d870fd8b5450047a7486fc023d1ac9439642e8ed91eadfd5026c4cda7cc9179
2024-04-20 15:14:06 +00:00
drh 0526db32e2 Correct handling of OUTER JOIN when on or the other operand is a subquery
implemented using the VALUES-as-coroutine optimization.
dbsqlfuzz bde3bf80aedf25afa56e2997a0545a314765d3f8.

FossilOrigin-Name: 8c0f69e0e4ae0a446838cc193bfd4395fd251f3c7659b35ac388e5a0a7650a66
2024-04-18 16:11:01 +00:00
drh 06915d0145 The first assert() added in [0ebc65481f4a3e79] is not necessarily true in a
corrupt database file.  So add a term to make it true.

FossilOrigin-Name: 6b21cccdeec92db9f6ce3dd7ea5e61b8b46650cc1e550271aa51bdc619f55b11
2024-04-15 20:43:21 +00:00
drh 0221cacea7 If a build fails in testrunner.tcl, do not attempt to run the jobs that
depend on that build.  Instead, report those jobs as having been skipped.

FossilOrigin-Name: b40580be719a129ecd1aa3c69d1086c967d063920fdd48617c864e73c059abc1
2024-04-12 18:46:34 +00:00
drh 6f4e5ee4c9 Fixes and new tests logic to ensure that the btree overflow page cache is
only used when it is consistent.  This resolves the malfunction observed
in [forum:/forumpost/284955a3cd454a15|forum post 284955a3cd454a15].

FossilOrigin-Name: 5dede50d9e7b6942df9f7b00fbfeaa2103c36c5da01d63d88136fb0ef4b7d26d
2024-04-12 15:02:16 +00:00
drh 1d40237bc8 Add assert() statements to help verify the overflow page cache.
FossilOrigin-Name: 0ebc65481f4a3e7974558adea51c620a025bc0e76c0a139e549b56c5abe0cabb
2024-04-12 13:05:36 +00:00
drh ae7ede4a4f New assert() statements to verify the correctness of the BTCF_AtLast flag
on btree cursors.

FossilOrigin-Name: 4efecd6167de71500c90b63155eba1b8567c90e9d1e282fbea54130f9ee21813
2024-04-12 12:32:09 +00:00
drh 366b419d00 Test case for the fix in the previous check-in.
FossilOrigin-Name: 0cf4d835dae260b01178e94e77be6b8a130f2031e898ef79ceba8df6c2bba58f
2024-04-12 11:28:35 +00:00
drh c494fdb580 Mark the BTree cell overflow cache as invalid whenever the rowid goes invalid.
FossilOrigin-Name: 74c9e19c92c887012aebbe96450f6ed7a60ba22d6e3edbaa39a0f989fb7f2901
2024-04-12 02:57:52 +00:00
stephan b6d108f0b3 Fix handling of the SQLITE_OMIT_WAL check in one place. Resolves [forum:87cc13302de160eb|forum post 87cc13302de160eb].
FossilOrigin-Name: 5dae6e6df4921f42e45c6c8de40853ab63f53a4bd1d9088a8cdac957ce62f196
2024-04-11 19:08:12 +00:00
dan 495ce22d49 Fix a "shift exponent is too large" usan error that could occur in the fts3 snippet() function when a query phrase contains more than 64 tokens.
FossilOrigin-Name: 6d2c7ac4ecfc1ec408cb1820985a70650d7cc5613b4b8fd1829f68ea48fce6a3
2024-04-09 19:23:18 +00:00
dan 73a50fa42c Avoid some performance problems in the recover extension when recovering strategically corrupted databases.
FossilOrigin-Name: e66a834bbab9d71e02b70588ad4c71eae2e13b50e299b0269d488402bc4a7fc5
2024-04-09 15:09:54 +00:00
drh d21d5b21db The read-only CHECK-constraint optimization of [34ddf02d3d21151b] inhibits the
xfer optimization for tables with CHECK constraints.  However, the xfer
optimization is required for correct operation of VACUUM INTO on tables that
contain generated columns. Fix this by ignoring CHECK constraints when
qualifying the xfer optimization while running VACUUM.  Problem reported by
[forum:/forumpost/3ec177d68fe7fa2c|forum post 3ec177d68fe7fa2c].

FossilOrigin-Name: a6e26e778812c8409fca77183e24d3b70189c4d02fce10c7e74cd4ccc8c8ea97
2024-04-09 13:57:27 +00:00
dan 1278ac411c Update tests in returning1.test to account for [c7896e88].
FossilOrigin-Name: c02956cd5cbf87027ba201b5d273e0efd429836ee6cabdc2f6d5b8096c876b7b
2024-04-08 17:55:15 +00:00
drh d59afcfbfe Enhance the WHERE-clause push-down optimization so that it is able to
push down WHERE clause terms that contain uncorrelated subqueries.

FossilOrigin-Name: 69ec714b2d698acf9e37635256c01b233ce32f22e8323e226441d5ddd948a940
2024-04-08 11:50:07 +00:00
drh 0389d5f8d0 Fix a harmless compiler warning in the ICU extension due to [acddbc489d5231da].
FossilOrigin-Name: 3d8750e88558f8ea6a1523a5add4ccca3262e31f348b603e56ab193d81908995
2024-04-08 11:45:15 +00:00
drh ac94cf3ece Enhancements to the fuzzer invariant checker to turn optimizations on and
off.

FossilOrigin-Name: 67594481379824823105939fea2ce1fe280667f6db91735ac78b4b6164a78dab
2024-04-08 06:37:19 +00:00
drh 5b613ed41b Merge trunk testing enhancements into the pushdown-subquery branch.
FossilOrigin-Name: 287ff24b26a512ff7648679767e68244f6eef95df6a49c46ed1f2594030ed523
2024-04-07 18:55:57 +00:00
drh fa4c4247a5 Omit all rowid-in-view restrictions from the fuzzinvariant.c test module
as they are no longer necessary, as of the previous check-in.

FossilOrigin-Name: 6431538f0bb3bb8606786f3c3e5c055c4bc387098dd3bdc8a94f6fda61c47f52
2024-04-07 18:36:32 +00:00
drh 1152def76e If SQLITE_ALLOW_ROWID_IN_VIEW is set to 2, then all rowids for views return
a value of NULL.

FossilOrigin-Name: 0a53dde21403aa6de11c5085c16def3f95046c5629daf2675b075e4d6683ef94
2024-04-07 18:23:30 +00:00
drh 660322f96f Merge trunk enhancements into the pushdown-subquery branch.
FossilOrigin-Name: 27865e316f8dfbf4c20290cf1be3024d7518fec46655e34f3fc435e15346c63e
2024-04-07 10:30:29 +00:00
drh 05c6d13027 Add comments to note the name abiguity between the MySQL push-down
optimization and the WHERE-clause push-down optimization.

FossilOrigin-Name: 3d5fb1ec7a0440072d6e3b957903c85d0f32b8b07207a1ef22d1a69cf5e664d1
2024-04-07 10:27:18 +00:00
drh 6951c49779 Do not allow changes to sqlite3ExprIsTableConstant() that support pushdown of
subqueries interfere with the hash-join logic.

FossilOrigin-Name: 8682931f9c6b40e1b09139c10bbe932c38330b5eb0c5c84f2432ad19a6793e37
2024-04-06 18:30:09 +00:00
drh ed27183d83 Merge testing logic fixes on trunk into the pushdown-subquery branch.
FossilOrigin-Name: a4e1f03dcad70e828a4b56e7a332946daf84d6eae078e3ec9a248b8157a53963
2024-04-06 17:42:14 +00:00
drh 8181cc6c10 Improvements to the accurancy of the fuzzinvariants.c testing module when
SQLITE_ALLOW_ROWID_IN_VIEW is defined and the test query involves rowids.

FossilOrigin-Name: c6e873d4db3ef36a0d561e64ead6feada5d1654c0757b4b6e55f671c9db66469
2024-04-06 17:37:30 +00:00
drh de6a4be9b5 Generalize pushdown to allow any uncorrelated subquery to be pushed down.
FossilOrigin-Name: 87c45fb0d5f5ca5d6d1ad27bef83f294231d17d94299e1997364a7975b423e38
2024-04-06 12:19:50 +00:00
drh 743ae4c68b Experimental enhancement in which expressions of the form "expr IN table"
can be pushed down into subexpressions.

FossilOrigin-Name: 2cbd7838fd6ffdf210f34671cd2e3e749a076a3a6f155bbe5f910a67db31c5b1
2024-04-05 20:01:28 +00:00
drh b411c4d69e Check-in [a9657c87c53c1922] is wrong: the IndexedExpr.bMaybeNullRow flag is
required for virtual columns if they are part of an outer join.  Add a
test case (derived from dbsqlfuzz b9e65e2f110df998f1306571fae7af6c01e4d92b)
to prove it.

FossilOrigin-Name: 4484ec6d26b31305e31de89bdbae26344d8083a7e7de20861430d31737d9979c
2024-04-05 13:56:05 +00:00
drh 65a1d7a284 When compiling with SQLITE_ALLOW_ROWID_IN_VIEW, if the RETURNING clause of
an UPDATE of a view specifies a rowid, then return NULL for the value of
that rowid.  dbsqlfuzz 7863696e9e5ec10b29bcf5ab2681cd6c82a78a4a.

FossilOrigin-Name: c7896e88850669e18e89d44c4169d4f4a5d4b904bea6ccb2ac64f93b6d348a42
2024-04-05 11:23:51 +00:00
stephan 7fd9b53308 Optimize sqlite3.oo1.DB.exec() for the rowMode='object' case to avoid converting the object property keys (column names) from native code to JS for each row. This speeds up large data sets considerably and addresses the report in [forum:3632183d2470617d|forum post 3632183d2470617d].
FossilOrigin-Name: 8b41ef8690001eb299f5b7182c28f5318333bff5b505e1d59d6e6f4556b1c759
2024-04-04 22:53:09 +00:00
drh f895173c5f Add the "interstage-heuristic" that attempts to avoid wildly inefficient
queries that use table scans instead of index lookups because the output
row estimates are inaccurate.

FossilOrigin-Name: 7bf49e2c54c9f6f336416f01c0e76aaf70f1e2f3fd612232e5a33ae5dabe0900
2024-04-04 14:26:42 +00:00
drh 634f434686 Fix an ASAN problem in part of the test harness. No changes to SQLite itself.
FossilOrigin-Name: 797cda7ddcceb140330d58892c3e73d28df72b638df00fd48f07dfcba7706c5f
2024-04-04 13:36:48 +00:00
drh efe9500af7 Fix test cases due to an error message change.
FossilOrigin-Name: c49ec239eddde6f07f8d528cccd6224c4c80b240dc8f5c974186e3bb08afb83b
2024-04-04 13:07:43 +00:00
stephan 13f5910889 Fix exception propagation when the opfs-sahpool VFS fails to initialize to address report in [forum:be0141c639|forum post be0141c639].
FossilOrigin-Name: cdb3a90055afe371962ec6c0931f1b08797aaeaab0358ef64b1cabda0a855b33
2024-04-04 12:36:33 +00:00
drh 307f290b32 Add an optional 3rd argument to the icu_load_collation() function that
specifies the "strength" of the comparison.

FossilOrigin-Name: acddbc489d5231dacf29890d1aa562da499026690f55c256a07d04a3190faacc
2024-04-02 21:55:45 +00:00
drh 8ce73ce15b Fix typos in comments. Provided ".wheretrace" debugging output for the
interstage heuristic module.  Do omit automatic index loops in the
interstage heuristic.

FossilOrigin-Name: 186dcae19e249db36de15f295999cff25063b54ee3d5d481cd2ba99b6d13148e
2024-04-02 14:12:29 +00:00
drh 7f7d0b19f8 Add a heuristic in between the two solver() passes of the query planner that
tries to prevent a very slow query plan in cases where the output row count
estimate is imprecise.

FossilOrigin-Name: 8018417b0143ea11535f2457bf3e4b3755717c554a17df1076425b4251b5f2c6
2024-04-02 11:44:44 +00:00
drh 9352cfa30b Improved comments in the query planner logic that computes the cost for a
particular step in a query plan.  No code changes.

FossilOrigin-Name: 0b2ac2cdc767db764e3ea8bbc33898cac4e1ec27fe8c9b60ce08a1785f921e6d
2024-04-01 15:38:15 +00:00
stephan 69dbd7a4e7 Make explicit that sqlite3_keyword_name()'s index is 0-based, per forum request. Doc changes only.
FossilOrigin-Name: 090943dc31e7a3af5c11c1c0953cb82ae3ca07ba000189bb85deaecc76921504
2024-03-30 14:11:30 +00:00
stephan cfd4507c83 Document that the order of an update hook call is unspecied vis-a-vis the final result of the operation which triggers that hook. Doc changes only.
FossilOrigin-Name: 3d4b1f0791384d3e531d6757daecf67e5b873954de61f37032474e3ae23cd22b
2024-03-28 10:58:18 +00:00
dan 6921a2d205 Update comments in fts5.h.
FossilOrigin-Name: 862945d5c432c27377e90d93d64c4655eefcc369d086eb51edef925fb3d80b57
2024-03-27 20:34:14 +00:00
dan ed517a7082 Add extra tests to vtabL.test.
FossilOrigin-Name: fe209099f5c348f1280b9b827ffbf6a6742ebdd1a23ef189445147894b1832ba
2024-03-26 18:07:39 +00:00
dan dcc121999c Avoid expanding integer values in columns with real affinity to the full 8-byte representation when editing records as part of a DROP COLUMN command.
FossilOrigin-Name: a49296de0061931badaf3db6b965131a78b1c6c21b1eeb62815ea7adf767d0b3
2024-03-26 11:14:52 +00:00
drh a509a90958 The RAISE() operator is not a constant expression and cannot participate in
the VALUE-as-coroutine optimization.
dbsqlfuzz 74cf7c9904360322a6c917e4934b127543d1cd51

FossilOrigin-Name: 6a06dc73847716c88d65651d1bf0e002002303881df1389beac884d0032eae08
2024-03-25 20:35:14 +00:00
dan ca3b9096c4 Add further tests for sqlite3_declare_vtab().
FossilOrigin-Name: f3c4433f6b33087494c8d38ff9dbb008a1bd30b424ca9aaa51c1956d75a86249
2024-03-25 20:00:40 +00:00
drh 1872f8d844 Simplifications to the sqlite3_declare_vtab() implementation. Changes
some conditionals into assert() statements, for coverage.

FossilOrigin-Name: ff7b898a6f9cb9aecb51bd6b63e253b4b7486ac9367f59c3c0491d78cfb39993
2024-03-25 19:31:03 +00:00
dan eb5bd4db91 Fix a theoretical OOB memory access in sqlite3_stmt_scanstatus_v2().
FossilOrigin-Name: 87be9580747b405c2c534beadb0f95cee0d4f34e0245f90e157a6b7ada38e092
2024-03-25 18:30:15 +00:00
drh 791b6f36cc Revert the previous change. Instead, do a pre-check of the CREATE TABLE
statement that is the second argument to sqlite3_declare_vtab() and if
the first two keywords are not "CREATE" and "TABLE", then raise an
SQLITE_MISUSE error.

FossilOrigin-Name: 6a2ff8351244da2336055454dfad2dd40534b7cfb51e840f7f8cf2ddacf8649e
2024-03-25 18:24:28 +00:00
drh f7aab656ff Remove an ALWAYS() from a condition that can be true.
FossilOrigin-Name: 715fcf033a6c0c64fa3076d58be8c39246aebef922c1a44a31831b40e165015e
2024-03-25 17:43:11 +00:00
drh ed6c9aa6ab Fix an inaccuracy in automatic indexes that was exposed by the fix
at [80c4223098c1827f].

FossilOrigin-Name: fdc9406f1c8ba4a7341c1e408f6042ddc788cf65f98e1de2ee101390bfb0abae
2024-03-25 14:44:10 +00:00
drh bcf97e70f5 Fix the pragma4.test script so that it works with SQLITE_OMIT_VIRTUALTABLE.
FossilOrigin-Name: f8fe6fb69c4164d087783a0d6990112afabea78daa4d8985eb6df7df6f45ac27
2024-03-25 13:18:46 +00:00
drh 99b4e6e254 Fix recent test case changes so that they also work on Windows.
FossilOrigin-Name: 38578b5af2e97c420f3106bc486318604aecbaa327365bbc2e9518be84491495
2024-03-25 12:28:06 +00:00
drh 41c9945c74 Use the SQLITE_CONSTRAINT return value from xBestIndex to prohibit bad
query plans in the pragma virtual table.

FossilOrigin-Name: b1259d4448f744861e416f42328c1450854370e5c77102d2a5abe5cf6c7f12bd
2024-03-25 11:34:42 +00:00
drh 4397d28378 Improvements to the vtablog.c extension: Eliminate memory leaks.
More diagnostic output for xBestIndex.

FossilOrigin-Name: 92e9a71bc4daa261d7c9a81fb66f7d7c0f0a74eb9e0c9dec8b4651acc5217bff
2024-03-25 10:55:08 +00:00
stephan 55051d661c Flag sqlite3_trace() and sqlite3_profile() as deprecated so that the doc generator for funclist.html sees them as such, and add 'Deprecated' to their page's title for consistency with other deprecated APIs. Comment changes only. Addresses [forum:0901025836|forum post 0901025836].
FossilOrigin-Name: 87c54f93f5711739741ed0ff3c1a6fe24ffc8a025b43523bf78c1f6be8c1b4cd
2024-03-25 10:28:10 +00:00
drh d2b3b72a2b Improvements to the vtablog.c extension, for better logging of virtual
table interactions.

FossilOrigin-Name: e253bb36a5f4f601c9b08858b55a9ce198239ace8efa8dab7c0ec019028967c1
2024-03-25 00:38:55 +00:00
drh cf84ae0189 Fix the xBestIndex method of the pragma virtual table so that it correctly
gives a higher cost to plans where the schema hidden parameter is
unconstrained.  Fix for the problem reported by
[forum:/forumpost/85b6a8b6705fb77a|forum post 85b6a8b6705fb77a].

FossilOrigin-Name: bc516ff5202ee6e9834266bf755fe26e30ac557dcc7975ca7a06dfe33874fcd2
2024-03-24 21:10:45 +00:00
drh 4a402b80c5 Improved "wheretrace" debugging output for calls to xBestIndex. No changes
to release code.

FossilOrigin-Name: 33966bb06ce9a8e90734de59a8d43c523f60870d20be64789638da4c84a8b81b
2024-03-24 20:26:59 +00:00
drh a631eb378d Do not automatically assume that ROWID is NOT NULL when compiled with
SQLITE_ALLOW_ROWID_IN_VIEW.
dbsqlfuzz 31b38eeb63a4e1562de665078f52b7b47a7543cf

FossilOrigin-Name: 80c4223098c1827ff3a564f1f9a4203164a943e9a83eef99df68378fa3c4764b
2024-03-24 16:33:31 +00:00
drh d9eee787bd Fix an adverse interaction between CREATE TABLE AS and the new
[/info/a120c9235f125e05|VALUES-as-coroutine] optimization.
dbsqlfuzz c2c5e7e08b7e489d270a26d895077a03f678c33b

FossilOrigin-Name: 84b6fdea0bf07c73df0ca8ef110db066164a5f34606e6c069a060476e04ef44e
2024-03-23 15:17:38 +00:00
drh 378bf82e2b Fix incorrect boundary assert()s on the new OP_IfSizeBetween opcode.
FossilOrigin-Name: 8eda4797c573382cbb989a4ab4b1f19d8fd538dbc9818d86a9aa6189cfa90f37
2024-03-22 10:32:14 +00:00
drh 2faaf3830e Test case for the assert() problem fixed by [9ba3cff9d48fe8fc].
FossilOrigin-Name: 865f0de7a17ce6059b8f0708002cff5f13b9dba3ebc41896ee0fdc21ae4f3740
2024-03-21 22:18:24 +00:00
stephan 006a9b51aa Add comments (only, no code) to the JS sqlite3_config() bindings reminding us why SQLITE_CONFIG_ROWID_IN_VIEW is specifically not included. JNI does not need this treatment because it explicitly supports only a very small subset of config options.
FossilOrigin-Name: 4fea396221e84f9532f9327226691621a23bd966a860329fc579141c69cf7f64
2024-03-21 15:52:52 +00:00
drh 529ed1a3a3 Enhancements to testrunner.tcl:
(1) Add the "--config CONFIGS" option, to that only configuration named
on the comma-separated list CONFIGS are run.
(2) Add the "--omit CONFIGS" to omit configuration on the CONFIGS list
(3) Add the Android configuration to "release"

FossilOrigin-Name: 4ccb372967fab779b29be8f01c879a99ef247981466f81f55e18e3961fbd7d5a
2024-03-21 11:46:52 +00:00
dan af64a22762 Have os_unix.c reuse cached file-descriptors in the case when a read-write fd is requested on a read-only file and a read-only fd returned.
FossilOrigin-Name: a678e85402af08c1e387bf30ff2205f84dd7da749755da565d70f831c007a3d9
2024-03-21 11:37:36 +00:00
drh 296ae1e467 Fix all test cases so that they work with SQLITE_ALLOW_ROWID_IN_VIEW.
FossilOrigin-Name: 66c69e2f20f7692e0f34743ae97b09c4d8d11b874cdc5381795f2d1e0410f724
2024-03-21 10:35:33 +00:00
dan 219b4f2061 Change EXPLAIN QUERY PLAN output to say "USE TEMP B-TREE FOR LAST TERM OF ORDER BY", or "LAST N TERMS OF ORDER BY", instead of "RIGHT PART OF ORDER BY".
FossilOrigin-Name: 7e13a2c7583dbcb660adde6b0465da037365971c56726b8f18a541d8803ffeed
2024-03-20 16:56:12 +00:00
dan e555bd4f02 Change EXPLAIN QUERY PLAN output to say "USE TEMP B-TREE FOR LAST TERM OF ORDER BY", or "LAST N TERMS OF ORDER BY", instead of "RIGHT PART OF ORDER BY".
FossilOrigin-Name: cd547c500442f3f58c05d6da8a67c3238560c5204ea62ec14afa844cc8fb94f0
2024-03-20 16:27:08 +00:00
drh daee74c3ac Fix the SQLITE_ALLOW_ROWID_IN_VIEW bug-compatibility option so that it works
again.  Add the SQLITE_CONFIG_ROWID_IN_VIEW sqlite3_config() value
to optionally disable the bug-compatibility mode at start-time.  Enable
testing of SQLITE_ALLOW_ROWID_IN_VIEW.

FossilOrigin-Name: b6802565df0f63286a7ef26c92d3ed817895f244920a24909cd855090fdfa08c
2024-03-20 10:45:13 +00:00
drh 27ea83f66e Make sure the new u1.nRow value is copied when making a copy of a SrcItem
object.  This fixes a problem in [ac6f095e13e43d66] from yesterady.

FossilOrigin-Name: 262f8f9d80d37160e4126634b99aa48fce2073e61f6365e8bdbe1cc4fa560a96
2024-03-19 19:42:56 +00:00
86 changed files with 3292 additions and 501 deletions
+1 -1
View File
@@ -446,7 +446,7 @@ static void fts3SnippetDetails(
}
mCover |= mPhrase;
for(j=0; j<pPhrase->nToken; j++){
for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
mHighlight |= (mPos>>j);
}
+2 -2
View File
@@ -55,8 +55,8 @@ struct Fts5PhraseIter {
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
** Return a copy of the context pointer the extension function was
** registered with.
** Return a copy of the pUserData pointer passed to the xCreateFunction()
** API when the extension function was registered.
**
** xColumnTotalSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
+35 -2
View File
@@ -471,7 +471,7 @@ static void icuLoadCollation(
UCollator *pUCollator; /* ICU library collation object */
int rc; /* Return code from sqlite3_create_collation_x() */
assert(nArg==2);
assert(nArg==2 || nArg==3);
(void)nArg; /* Unused parameter */
zLocale = (const char *)sqlite3_value_text(apArg[0]);
zName = (const char *)sqlite3_value_text(apArg[1]);
@@ -486,7 +486,39 @@ static void icuLoadCollation(
return;
}
assert(p);
if(nArg==3){
const char *zOption = (const char*)sqlite3_value_text(apArg[2]);
static const struct {
const char *zName;
UColAttributeValue val;
} aStrength[] = {
{ "PRIMARY", UCOL_PRIMARY },
{ "SECONDARY", UCOL_SECONDARY },
{ "TERTIARY", UCOL_TERTIARY },
{ "DEFAULT", UCOL_DEFAULT_STRENGTH },
{ "QUARTERNARY", UCOL_QUATERNARY },
{ "IDENTICAL", UCOL_IDENTICAL },
};
unsigned int i;
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
if( sqlite3_stricmp(zOption,aStrength[i].zName)==0 ){
ucol_setStrength(pUCollator, aStrength[i].val);
break;
}
}
if( i>=sizeof(aStrength)/sizeof(aStrength[0]) ){
sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p));
sqlite3_str_appendf(pStr,
"unknown collation strength \"%s\" - should be one of:",
zOption);
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
sqlite3_str_appendf(pStr, " %s", aStrength[i].zName);
}
sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
sqlite3_free(sqlite3_str_finish(pStr));
return;
}
}
rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
icuCollationColl, icuCollationDel
);
@@ -509,6 +541,7 @@ int sqlite3IcuInit(sqlite3 *db){
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
{"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
{"icu_load_collation",3,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
{"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
+77 -25
View File
@@ -376,13 +376,13 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** parameter. (idxStr is not used in this implementation.) idxNum
** is a bitmask showing which constraints are available:
**
** 1: start=VALUE
** 2: stop=VALUE
** 4: step=VALUE
**
** Also, if bit 8 is set, that means that the series should be output
** in descending order rather than in ascending order. If bit 16 is
** set, then output must appear in ascending order.
** 0x01: start=VALUE
** 0x02: stop=VALUE
** 0x04: step=VALUE
** 0x08: descending order
** 0x10: ascending order
** 0x20: LIMIT VALUE
** 0x40: OFFSET VALUE
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
@@ -396,26 +396,44 @@ static int seriesFilter(
series_cursor *pCur = (series_cursor *)pVtabCursor;
int i = 0;
(void)idxStrUnused;
if( idxNum & 1 ){
if( idxNum & 0x01 ){
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
}else{
pCur->ss.iBase = 0;
}
if( idxNum & 2 ){
if( idxNum & 0x02 ){
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
}else{
pCur->ss.iTerm = 0xffffffff;
}
if( idxNum & 4 ){
if( idxNum & 0x04 ){
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
if( pCur->ss.iStep==0 ){
pCur->ss.iStep = 1;
}else if( pCur->ss.iStep<0 ){
if( (idxNum & 16)==0 ) idxNum |= 8;
if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
}
}else{
pCur->ss.iStep = 1;
}
if( idxNum & 0x20 ){
sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
sqlite3_int64 iTerm;
if( idxNum & 0x40 ){
sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
if( iOffset>0 ){
pCur->ss.iBase += pCur->ss.iStep*iOffset;
}
}
if( iLimit>=0 ){
iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
if( pCur->ss.iStep<0 ){
if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
}else{
if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
}
}
}
for(i=0; i<argc; i++){
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
/* If any of the constraints have a NULL value, then return no rows.
@@ -426,7 +444,7 @@ static int seriesFilter(
break;
}
}
if( idxNum & 8 ){
if( idxNum & 0x08 ){
pCur->ss.isReversing = pCur->ss.iStep > 0;
}else{
pCur->ss.isReversing = pCur->ss.iStep < 0;
@@ -446,10 +464,13 @@ static int seriesFilter(
**
** The query plan is represented by bits in idxNum:
**
** (1) start = $value -- constraint exists
** (2) stop = $value -- constraint exists
** (4) step = $value -- constraint exists
** (8) output in descending order
** 0x01 start = $value -- constraint exists
** 0x02 stop = $value -- constraint exists
** 0x04 step = $value -- constraint exists
** 0x08 output is in descending order
** 0x10 output is in ascending order
** 0x20 LIMIT $value -- constraint exists
** 0x40 OFFSET $value -- constraint exists
*/
static int seriesBestIndex(
sqlite3_vtab *pVTab,
@@ -457,10 +478,12 @@ static int seriesBestIndex(
){
int i, j; /* Loop over constraints */
int idxNum = 0; /* The query plan bitmask */
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
int bStartSeen = 0; /* EQ constraint seen on the START column */
#endif
int unusableMask = 0; /* Mask of unusable constraints */
int nArg = 0; /* Number of arguments that seriesFilter() expects */
int aIdx[3]; /* Constraints on start, stop, and step */
int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
const struct sqlite3_index_constraint *pConstraint;
/* This implementation assumes that the start, stop, and step columns
@@ -468,28 +491,54 @@ static int seriesBestIndex(
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
aIdx[0] = aIdx[1] = aIdx[2] = -1;
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
int iCol; /* 0 for start, 1 for stop, 2 for step */
int iMask; /* bitmask for those column */
int op = pConstraint->op;
if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
&& op<=SQLITE_INDEX_CONSTRAINT_OFFSET
){
if( pConstraint->usable==0 ){
/* do nothing */
}else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
aIdx[3] = i;
idxNum |= 0x20;
}else{
assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
aIdx[4] = i;
idxNum |= 0x40;
}
continue;
}
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
assert( iCol>=0 && iCol<=2 );
iMask = 1 << iCol;
if( iCol==0 ) bStartSeen = 1;
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
bStartSeen = 1;
}
#endif
if( pConstraint->usable==0 ){
unusableMask |= iMask;
continue;
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
}else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
idxNum |= iMask;
aIdx[iCol] = i;
}
}
for(i=0; i<3; i++){
if( aIdx[3]==0 ){
/* Ignore OFFSET if LIMIT is omitted */
idxNum &= ~0x60;
aIdx[4] = 0;
}
for(i=0; i<5; i++){
if( (j = aIdx[i])>=0 ){
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
pIdxInfo->aConstraintUsage[j].omit =
!SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
}
}
/* The current generate_column() implementation requires at least one
@@ -510,19 +559,22 @@ static int seriesBestIndex(
** this plan is unusable */
return SQLITE_CONSTRAINT;
}
if( (idxNum & 3)==3 ){
if( (idxNum & 0x03)==0x03 ){
/* Both start= and stop= boundaries are available. This is the
** the preferred case */
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
pIdxInfo->estimatedRows = 1000;
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
if( pIdxInfo->aOrderBy[0].desc ){
idxNum |= 8;
idxNum |= 0x08;
}else{
idxNum |= 16;
idxNum |= 0x10;
}
pIdxInfo->orderByConsumed = 1;
}
}else if( (idxNum & 0x21)==0x21 ){
/* We have start= and LIMIT */
pIdxInfo->estimatedRows = 2500;
}else{
/* If either boundary is missing, we have to generate a huge span
** of numbers. Make this case very expensive so that the query
+154 -40
View File
@@ -38,8 +38,9 @@ SQLITE_EXTENSION_INIT1
typedef struct vtablog_vtab vtablog_vtab;
struct vtablog_vtab {
sqlite3_vtab base; /* Base class - must be first */
char *zDb; /* Schema name. argv[1] of xConnect/xCreate */
char *zName; /* Table name. argv[2] of xConnect/xCreate */
int nRow; /* Number of rows in the table */
int iInst; /* Instance number for this vtablog table */
int nCursor; /* Number of cursors created */
};
@@ -167,15 +168,14 @@ static int vtablogConnectCreate(
char **pzErr,
int isCreate
){
static int nInst = 0;
vtablog_vtab *pNew;
int i;
int rc;
int iInst = ++nInst;
char *zSchema = 0;
char *zNRow = 0;
printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst);
printf("%s.%s.%s():\n", argv[1], argv[2],
isCreate ? "xCreate" : "xConnect");
printf(" argc=%d\n", argc);
for(i=0; i<argc; i++){
printf(" argv[%d] = ", i);
@@ -189,17 +189,18 @@ static int vtablogConnectCreate(
for(i=3; i<argc; i++){
const char *z = argv[i];
if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){
return SQLITE_ERROR;
rc = SQLITE_ERROR;
goto vtablog_end_connect;
}
if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){
return SQLITE_ERROR;
rc = SQLITE_ERROR;
goto vtablog_end_connect;
}
}
if( zSchema==0 ){
*pzErr = sqlite3_mprintf("no schema defined");
return SQLITE_ERROR;
zSchema = sqlite3_mprintf("%s","CREATE TABLE x(a,b);");
}
printf(" schema = '%s'\n", zSchema);
rc = sqlite3_declare_vtab(db, zSchema);
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
@@ -208,8 +209,14 @@ static int vtablogConnectCreate(
memset(pNew, 0, sizeof(*pNew));
pNew->nRow = 10;
if( zNRow ) pNew->nRow = atoi(zNRow);
pNew->iInst = iInst;
printf(" nrow = %d\n", pNew->nRow);
pNew->zDb = sqlite3_mprintf("%s", argv[1]);
pNew->zName = sqlite3_mprintf("%s", argv[2]);
}
vtablog_end_connect:
sqlite3_free(zSchema);
sqlite3_free(zNRow);
return rc;
}
static int vtablogCreate(
@@ -237,7 +244,9 @@ static int vtablogConnect(
*/
static int vtablogDisconnect(sqlite3_vtab *pVtab){
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
printf("vtablogDisconnect(%d)\n", pTab->iInst);
printf("%s.%s.xDisconnect()\n", pTab->zDb, pTab->zName);
sqlite3_free(pTab->zDb);
sqlite3_free(pTab->zName);
sqlite3_free(pVtab);
return SQLITE_OK;
}
@@ -247,7 +256,9 @@ static int vtablogDisconnect(sqlite3_vtab *pVtab){
*/
static int vtablogDestroy(sqlite3_vtab *pVtab){
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
printf("vtablogDestroy(%d)\n", pTab->iInst);
printf("%s.%s.xDestroy()\n", pTab->zDb, pTab->zName);
sqlite3_free(pTab->zDb);
sqlite3_free(pTab->zName);
sqlite3_free(pVtab);
return SQLITE_OK;
}
@@ -258,7 +269,8 @@ static int vtablogDestroy(sqlite3_vtab *pVtab){
static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
vtablog_vtab *pTab = (vtablog_vtab*)p;
vtablog_cursor *pCur;
printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor);
printf("%s.%s.xOpen(cursor=%d)\n", pTab->zDb, pTab->zName,
++pTab->nCursor);
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
@@ -273,7 +285,7 @@ static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
static int vtablogClose(sqlite3_vtab_cursor *cur){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor);
printf("%s.%s.xClose(cursor=%d)\n", pTab->zDb, pTab->zName, pCur->iCursor);
sqlite3_free(cur);
return SQLITE_OK;
}
@@ -285,8 +297,9 @@ static int vtablogClose(sqlite3_vtab_cursor *cur){
static int vtablogNext(sqlite3_vtab_cursor *cur){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n",
pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1);
printf("%s.%s.xNext(cursor=%d) rowid %d -> %d\n",
pTab->zDb, pTab->zName, pCur->iCursor,
(int)pCur->iRowid, (int)pCur->iRowid+1);
pCur->iRowid++;
return SQLITE_OK;
}
@@ -310,8 +323,8 @@ static int vtablogColumn(
}else{
sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid);
}
printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n",
pTab->iInst, pCur->iCursor, i, zVal);
printf("%s.%s.xColumn(cursor=%d, i=%d): [%s]\n",
pTab->zDb, pTab->zName, pCur->iCursor, i, zVal);
sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT);
return SQLITE_OK;
}
@@ -323,8 +336,8 @@ static int vtablogColumn(
static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
printf("vtablogRowid(tab=%d, cursor=%d): %d\n",
pTab->iInst, pCur->iCursor, (int)pCur->iRowid);
printf("%s.%s.xRowid(cursor=%d): %d\n",
pTab->zDb, pTab->zName, pCur->iCursor, (int)pCur->iRowid);
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
@@ -337,8 +350,8 @@ static int vtablogEof(sqlite3_vtab_cursor *cur){
vtablog_cursor *pCur = (vtablog_cursor*)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
int rc = pCur->iRowid >= pTab->nRow;
printf("vtablogEof(tab=%d, cursor=%d): %d\n",
pTab->iInst, pCur->iCursor, rc);
printf("%s.%s.xEof(cursor=%d): %d\n",
pTab->zDb, pTab->zName, pCur->iCursor, rc);
return rc;
}
@@ -417,7 +430,7 @@ static int vtablogFilter(
){
vtablog_cursor *pCur = (vtablog_cursor *)cur;
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor);
printf("%s.%s.xFilter(cursor=%d):\n", pTab->zDb, pTab->zName, pCur->iCursor);
pCur->iRowid = 0;
return SQLITE_OK;
}
@@ -430,12 +443,37 @@ static int vtablogFilter(
*/
static int vtablogBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
sqlite3_index_info *p
){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("vtablogBestIndex(tab=%d):\n", pTab->iInst);
pIdxInfo->estimatedCost = (double)500;
pIdxInfo->estimatedRows = 500;
int i;
printf("%s.%s.xBestIndex():\n", pTab->zDb, pTab->zName);
printf(" colUsed: 0x%016llx\n", p->colUsed);
printf(" nConstraint: %d\n", p->nConstraint);
for(i=0; i<p->nConstraint; i++){
printf(
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
i,
p->aConstraint[i].iColumn,
p->aConstraint[i].iTermOffset,
p->aConstraint[i].op,
p->aConstraint[i].usable,
sqlite3_vtab_collation(p,i));
}
printf(" nOrderBy: %d\n", p->nOrderBy);
for(i=0; i<p->nOrderBy; i++){
printf(" orderby[%d]: col=%d desc=%d\n",
i,
p->aOrderBy[i].iColumn,
p->aOrderBy[i].desc);
}
p->estimatedCost = (double)500;
p->estimatedRows = 500;
printf(" idxNum=%d\n", p->idxNum);
printf(" idxStr=NULL\n");
printf(" orderByConsumed=%d\n", p->orderByConsumed);
printf(" estimatedCost=%g\n", p->estimatedCost);
printf(" estimatedRows=%lld\n", p->estimatedRows);
return SQLITE_OK;
}
@@ -454,7 +492,7 @@ static int vtablogUpdate(
){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
int i;
printf("vtablogUpdate(tab=%d):\n", pTab->iInst);
printf("%s.%s.xUpdate():\n", pTab->zDb, pTab->zName);
printf(" argc=%d\n", argc);
for(i=0; i<argc; i++){
printf(" argv[%d]=", i);
@@ -464,12 +502,88 @@ static int vtablogUpdate(
return SQLITE_OK;
}
static int vtablogBegin(sqlite3_vtab *tab){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xBegin()\n", pTab->zDb, pTab->zName);
return SQLITE_OK;
}
static int vtablogSync(sqlite3_vtab *tab){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xSync()\n", pTab->zDb, pTab->zName);
return SQLITE_OK;
}
static int vtablogCommit(sqlite3_vtab *tab){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xCommit()\n", pTab->zDb, pTab->zName);
return SQLITE_OK;
}
static int vtablogRollback(sqlite3_vtab *tab){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xRollback()\n", pTab->zDb, pTab->zName);
return SQLITE_OK;
}
static int vtablogSavepoint(sqlite3_vtab *tab, int N){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xSavepoint(%d)\n", pTab->zDb, pTab->zName, N);
return SQLITE_OK;
}
static int vtablogRelease(sqlite3_vtab *tab, int N){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xRelease(%d)\n", pTab->zDb, pTab->zName, N);
return SQLITE_OK;
}
static int vtablogRollbackTo(sqlite3_vtab *tab, int N){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xRollbackTo(%d)\n", pTab->zDb, pTab->zName, N);
return SQLITE_OK;
}
static int vtablogFindMethod(
sqlite3_vtab *tab,
int nArg,
const char *zName,
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg
){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xFindMethod(nArg=%d, zName=%s)\n",
pTab->zDb, pTab->zName, nArg, zName);
return SQLITE_OK;
}
static int vtablogRename(sqlite3_vtab *tab, const char *zNew){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xRename('%s')\n", pTab->zDb, pTab->zName, zNew);
sqlite3_free(pTab->zName);
pTab->zName = sqlite3_mprintf("%s", zNew);
return SQLITE_OK;
}
/* Any table name that contains the text "shadow" is seen as a
** shadow table. Nothing else is.
*/
static int vtablogShadowName(const char *zName){
printf("vtablog.xShadowName('%s')\n", zName);
return sqlite3_strglob("*shadow*", zName)==0;
}
static int vtablogIntegrity(
sqlite3_vtab *tab,
const char *zSchema,
const char *zTabName,
int mFlags,
char **pzErr
){
vtablog_vtab *pTab = (vtablog_vtab*)tab;
printf("%s.%s.xIntegrity(mFlags=0x%x)\n", pTab->zDb, pTab->zName, mFlags);
return 0;
}
/*
** This following structure defines all the methods for the
** vtablog virtual table.
*/
static sqlite3_module vtablogModule = {
0, /* iVersion */
4, /* iVersion */
vtablogCreate, /* xCreate */
vtablogConnect, /* xConnect */
vtablogBestIndex, /* xBestIndex */
@@ -483,17 +597,17 @@ static sqlite3_module vtablogModule = {
vtablogColumn, /* xColumn - read data */
vtablogRowid, /* xRowid - read data */
vtablogUpdate, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
vtablogBegin, /* xBegin */
vtablogSync, /* xSync */
vtablogCommit, /* xCommit */
vtablogRollback, /* xRollback */
vtablogFindMethod, /* xFindMethod */
vtablogRename, /* xRename */
vtablogSavepoint, /* xSavepoint */
vtablogRelease, /* xRelease */
vtablogRollbackTo, /* xRollbackTo */
vtablogShadowName, /* xShadowName */
vtablogIntegrity /* xIntegrity */
};
#ifdef _WIN32
+74 -26
View File
@@ -88,6 +88,15 @@ typedef unsigned int u32;
typedef struct DbdataTable DbdataTable;
typedef struct DbdataCursor DbdataCursor;
typedef struct DbdataBuffer DbdataBuffer;
/*
** Buffer type.
*/
struct DbdataBuffer {
u8 *aBuf;
sqlite3_int64 nBuf;
};
/* Cursor object */
struct DbdataCursor {
@@ -104,7 +113,7 @@ struct DbdataCursor {
sqlite3_int64 iRowid;
/* Only for the sqlite_dbdata table */
u8 *pRec; /* Buffer containing current record */
DbdataBuffer rec;
sqlite3_int64 nRec; /* Size of pRec[] in bytes */
sqlite3_int64 nHdr; /* Size of header in bytes */
int iField; /* Current field number */
@@ -149,6 +158,31 @@ struct DbdataTable {
" schema TEXT HIDDEN" \
")"
/*
** Ensure the buffer passed as the first argument is at least nMin bytes
** in size. If an error occurs while attempting to resize the buffer,
** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
*/
static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
if( nMin>pBuf->nBuf ){
sqlite3_int64 nNew = nMin+16384;
u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
if( aNew==0 ) return SQLITE_NOMEM;
pBuf->aBuf = aNew;
pBuf->nBuf = nNew;
}
return SQLITE_OK;
}
/*
** Release the allocation managed by buffer pBuf.
*/
static void dbdataBufferFree(DbdataBuffer *pBuf){
sqlite3_free(pBuf->aBuf);
memset(pBuf, 0, sizeof(*pBuf));
}
/*
** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
** table.
@@ -289,8 +323,7 @@ static void dbdataResetCursor(DbdataCursor *pCsr){
pCsr->iField = 0;
pCsr->bOnePage = 0;
sqlite3_free(pCsr->aPage);
sqlite3_free(pCsr->pRec);
pCsr->pRec = 0;
dbdataBufferFree(&pCsr->rec);
pCsr->aPage = 0;
}
@@ -494,6 +527,15 @@ static void dbdataValue(
}
}
/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
** a page-size, it returns the maximum number of cells that may be present
** on the page. */
#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
/* Maximum number of fields that may appear in a single record. This is
** the "hard-limit", according to comments in sqliteLimit.h. */
#define DBDATA_MX_FIELD 32676
/*
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
*/
@@ -522,6 +564,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
assert( iOff+3+2<=pCsr->nPage );
pCsr->iCell = pTab->bPtr ? -2 : 0;
pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
}
}
if( pTab->bPtr ){
@@ -539,7 +584,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
}
}else{
/* If there is no record loaded, load it now. */
if( pCsr->pRec==0 ){
if( pCsr->nRec==0 ){
int bHasRowid = 0;
int nPointer = 0;
sqlite3_int64 nPayload = 0;
@@ -566,23 +611,24 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
if( pCsr->iCell>=pCsr->nCell ){
bNextPage = 1;
}else{
int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
iOff += 8 + nPointer + pCsr->iCell*2;
if( iOff>pCsr->nPage ){
if( iCellPtr>pCsr->nPage ){
bNextPage = 1;
}else{
iOff = get_uint16(&pCsr->aPage[iOff]);
iOff = get_uint16(&pCsr->aPage[iCellPtr]);
}
/* For an interior node cell, skip past the child-page number */
iOff += nPointer;
/* Load the "byte of payload including overflow" field */
if( bNextPage || iOff>pCsr->nPage ){
if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
bNextPage = 1;
}else{
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
if( nPayload==0 ) nPayload = 1;
}
/* If this is a leaf intkey cell, load the rowid */
@@ -617,13 +663,13 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
/* Allocate space for payload. And a bit more to catch small buffer
** overruns caused by attempting to read a varint or similar from
** near the end of a corrupt record. */
pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
if( pCsr->pRec==0 ) return SQLITE_NOMEM;
memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
if( rc!=SQLITE_OK ) return rc;
assert( nPayload!=0 );
pCsr->nRec = nPayload;
/* Load the nLocal bytes of payload */
memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
iOff += nLocal;
/* Load content from overflow pages */
@@ -641,19 +687,21 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
nCopy = U-4;
if( nCopy>nRem ) nCopy = nRem;
memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
nRem -= nCopy;
pgnoOvfl = get_uint32(aOvfl);
sqlite3_free(aOvfl);
}
nPayload -= nRem;
}
memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
if( nHdr>nPayload ) nHdr = 0;
pCsr->nHdr = nHdr;
pCsr->pHdrPtr = &pCsr->pRec[iHdr];
pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
pCsr->iField = (bHasRowid ? -1 : 0);
}
}
@@ -661,14 +709,16 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
pCsr->iField++;
if( pCsr->iField>0 ){
sqlite3_int64 iType;
if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec]
|| pCsr->iField>=DBDATA_MX_FIELD
){
bNextPage = 1;
}else{
int szField = 0;
pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
szField = dbdataValueBytes(iType);
if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
}else{
pCsr->pPtr += szField;
}
@@ -678,20 +728,18 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
if( bNextPage ){
sqlite3_free(pCsr->aPage);
sqlite3_free(pCsr->pRec);
pCsr->aPage = 0;
pCsr->pRec = 0;
pCsr->nRec = 0;
if( pCsr->bOnePage ) return SQLITE_OK;
pCsr->iPgno++;
}else{
if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
return SQLITE_OK;
}
/* Advance to the next cell. The next iteration of the loop will load
** the record and so on. */
sqlite3_free(pCsr->pRec);
pCsr->pRec = 0;
pCsr->nRec = 0;
pCsr->iCell++;
}
}
@@ -881,12 +929,12 @@ static int dbdataColumn(
case DBDATA_COLUMN_VALUE: {
if( pCsr->iField<0 ){
sqlite3_result_int64(ctx, pCsr->iIntkey);
}else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
}else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
sqlite3_int64 iType;
dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
dbdataValue(
ctx, pCsr->enc, iType, pCsr->pPtr,
&pCsr->pRec[pCsr->nRec] - pCsr->pPtr
&pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
);
}
break;
+28
View File
@@ -524,5 +524,33 @@ do_test 7.1 {
list [catch { $R finish } msg] $msg
} {1 {file is not a database}}
reset_db
breakpoint
do_test 8.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 8192 pagesize 4096 filename db.sqlite
| page 1 offset 0
| 0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00 ...vte format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
| 96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00 ..v.............
| 4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19 ...........3....
| 4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61 ..CtableTable0Ta
| 4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c ble0.CREATE TABL
| 4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29 E Table0 (Col0 )
| page 2 offset 4096
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
| end db.sqlite
}]} {}
do_test 8.1 {
set R [sqlite3_recover_init db main test.db2]
catch { $R run }
list [catch { $R finish } msg] $msg
} {0 {}}
finish_test
+549
View File
@@ -0,0 +1,549 @@
# 2024 May 1
#
# 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]] recover_common.tcl]
set testprefix recovercorrupt3
#| 0: d5 d5 9b d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 ................
#| 16: 04 00 00 00 1d 00 00 00 00 00 00 00 5f 5f 5f 5f ............____
#| 32: 5f 5f 5f 5f 5f 5f 5f 5f 71 5f 5f 5f 02 02 02 02 ________q___....
#| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
#| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
#| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
#| 96: 02 02 02 02
#-------------------------------------------------------------------------
reset_db
do_test 1.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 3821 pagesize 1024 filename clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
| 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 01 00 00 00 02 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
| 96: 00 2e 7a 70 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 a0 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 29 29 ..............))
| 464: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 480: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 496: 29 29 29 dd dd dd dd dd dd dd dd dd dd dd dd dd ))).............
| 512: dd dd dd dd dd dd dd dd dd 6e 69 d2 e9 e9 e9 d2 .........ni.....
| 528: d2 d2 d2 d2 dd dd dd dd dd dd dd dd dd dd dd dd ................
| 544: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 560: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 576: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 592: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 608: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 624: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 640: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 656: dd dd dd dd dd dd dd da dd dd dd dd dd dd dd dd ................
| 672: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 688: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 704: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 720: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 736: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 752: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 768: dd dd dd dd dd dd dd dd dd dd dd dd dd 29 29 29 .............)))
| 784: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 800: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 816: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 832: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 848: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 864: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 880: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 896: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 912: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 928: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 944: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 960: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 976: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 992: 29 29 29 29 29 29 29 29 29 29 dd dd dd dd dd dd ))))))))))......
| 1008: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| page 2 offset 1024
| 0: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 16: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 32: dd dd 6e 69 d2 e9 e9 e9 d2 d2 d2 d2 d2 dd dd dd ..ni............
| 48: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 64: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 80: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 96: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 112: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 128: dd dd dd dd dd dd 29 29 29 29 29 29 29 29 29 29 ......))))))))))
| 144: 29 29 29 29 29 29 29 29 29 ad a5 29 29 29 29 00 )))))))))..)))).
| 160: 75 9c 11 00 5b e5 64 28 7c ca 09 69 28 2d 69 00 u...[.d(|..i(-i.
| 176: 85 88 6c 81 48 83 a0 93 c0 c0 82 8b 81 84 85 f9 ..l.H...........
| 192: 88 7a 00 7f 00 96 40 7b 12 4b 84 75 a0 00 99 a0 .z....@..K.u....
| 208: df a0 7e 81 c6 90 8f 7f 84 85 cc 84 82 90 88 60 ..~............`
| 224: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 240: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 256: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 272: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 288: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 832: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 848: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 864: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 880: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 896: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 912: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 928: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 944: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 960: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| page 3 offset 2048
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 832: 02 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 848: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 864: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 880: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 896: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 912: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 928: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 944: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 960: 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| page 4 offset 3072
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 736: 5f 5f 5f 5f 5f 5f 5f 00 d5 fe fe fe 08 00 00 00 _______.........
| end clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
}]} {}
sqlite3_dbdata_init db
do_execsql_test 1.1 {
PRAGMA writable_schema = 1;
}
do_test 1.2 {
set R [sqlite3_recover_init db main test.db2]
$R run
$R finish
} {}
#-------------------------------------------------------------------------
reset_db
do_test 2.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 3821 pagesize 1024 filename clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
| 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: 04 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
| 96: 00 2e 7a 70 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 a0 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 29 29 ..............))
| 464: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 480: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 496: 29 29 29 dd dd dd dd dd dd dd dd dd dd dd dd dd ))).............
| 512: dd dd dd dd dd dd dd dd dd 6e 69 d2 e9 e9 e9 d2 .........ni.....
| 528: d2 d2 d2 d2 dd dd dd dd dd dd dd dd dd dd dd dd ................
| 544: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 560: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 576: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 592: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 608: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 624: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 640: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 656: dd dd dd dd dd dd dd da dd dd dd dd dd dd dd dd ................
| 672: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 688: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 704: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 720: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 736: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 752: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 768: dd dd dd dd dd dd dd dd dd dd dd dd dd 29 29 29 .............)))
| 784: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 800: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 816: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 832: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 848: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 864: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 880: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 896: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 912: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 928: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 944: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 960: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 976: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 ))))))))))))))))
| 992: 29 29 29 29 29 29 29 29 29 29 dd dd dd dd dd dd ))))))))))......
| 1008: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| page 2 offset 1024
| 0: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 16: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 32: dd dd 6e 69 d2 e9 e9 e9 d2 d2 d2 d2 d2 dd dd dd ..ni............
| 48: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 64: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 80: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 96: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 112: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ................
| 128: dd dd dd dd dd dd 29 29 29 29 29 29 29 29 29 29 ......))))))))))
| 144: 29 29 29 29 29 29 29 29 29 ad a5 29 29 29 29 00 )))))))))..)))).
| 160: 75 9c 11 00 5b e5 64 28 7c ca 09 69 28 2d 69 00 u...[.d(|..i(-i.
| 176: 85 88 6c 81 48 83 a0 93 c0 c0 82 8b 81 84 85 f9 ..l.H...........
| 192: 88 7a 00 7f 00 96 40 7b 12 4b 84 75 a0 00 99 a0 .z....@..K.u....
| 208: df a0 7e 81 c6 90 8f 7f 84 85 cc 84 82 90 88 60 ..~............`
| 224: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 240: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 256: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 272: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 288: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 832: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 848: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 864: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 880: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 896: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 912: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 928: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 944: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 960: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| page 3 offset 2048
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 832: 02 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 848: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 864: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 880: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 896: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 912: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 928: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 944: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 960: 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| page 4 offset 3072
| 0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 736: 5f 5f 5f 5f 5f 5f 5f 00 d5 fe fe fe 08 00 00 00 _______.........
| end clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
}]} {}
sqlite3_dbdata_init db
do_execsql_test 2.1 {
PRAGMA writable_schema = 1;
}
do_test 2.2 {
set R [sqlite3_recover_init db main test.db2]
$R run
$R finish
} {}
finish_test
+1 -1
View File
@@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
if( bTable && !bVirtual ){
if( SQLITE_ROW==sqlite3_step(pTblname) ){
const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
recoverAddTable(p, zTbl, iRoot);
if( zTbl ) recoverAddTable(p, zTbl, iRoot);
}
recoverReset(p, pTblname);
}
+75
View File
@@ -0,0 +1,75 @@
# 2011 March 07
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionconflict
sqlite3_shutdown
test_sqlite3_log log
proc log {code msg} { puts "LOG $code $msg" }
sqlite3 db test.db
forcedelete test.db2
sqlite3 db2 test.db2
do_test 1.0 {
do_common_sql {
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 2, 2);
INSERT INTO t1 VALUES(3, 3, 3);
}
} {}
do_execsql_test -db db2 1.1 {
INSERT INTO t1 VALUES(6, 6, 6);
}
proc xConflict {args} {
return "ABORT"
}
do_test 1.2 {
set chng [changeset_from_sql {
UPDATE t1 SET b=10, c=10 WHERE a=1;
UPDATE t1 SET b=444 WHERE a=2;
INSERT INTO t1 VALUES(4, 4, 4);
INSERT INTO t1 VALUES(5, 5, 5);
INSERT INTO t1 VALUES(6, 6, 6);
}]
execsql BEGIN db2
set res [list [catch { sqlite3changeset_apply db2 $chng xConflict } msg] $msg]
execsql ROLLBACK db2
set res
} {1 SQLITE_ABORT}
do_execsql_test -db db2 1.3 {
SELECT * FROM t1;
} {
1 1 1
2 2 2
3 3 3
6 6 6
}
finish_test
+14 -1
View File
@@ -289,6 +289,12 @@ endif
# embedding in the JS files and in building the distribution zip file.
# It must NOT be in $(dir.tmp) because we need it to survive the
# cleanup process for the dist build to work properly.
#
# Slight caveat: this uses the version info from the in-tree
# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
# end result is that the generated JS files may have static version
# info from $(bin.version-info) which differ from their runtime-emited
# version info (e.g. from sqlite3_libversion()).
bin.version-info := $(dir.top)/version-info
.NOTPARALLEL: $(bin.version-info)
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
@@ -335,19 +341,26 @@ DISTCLEAN_FILES += $(bin.stripccomments)
#
# 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.
#
# -D... flags which should be included in all invocations should be
# appended to $(C-PP.FILTER.global).
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) \
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
-DSQLITE_TEMP_STORE=3
C-PP.FILTER.global ?=
ifeq (1,$(SQLITE_C_IS_SEE))
C-PP.FILTER.global += -Denable-see
endif
define C-PP.FILTER
# Create $2 from $1 using $(bin.c-pp)
# $1 = Input file: c-pp -f $(1).js
# $2 = Output file: c-pp -o $(2).js
# $3 = optional c-pp -D... flags
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
$$(bin.c-pp) -f $(1) -o $$@ $(3)
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global)
CLEAN_FILES += $(2)
endef
# /end C-PP.FILTER
+15 -4
View File
@@ -329,7 +329,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
}
if(wasm.exports.sqlite3_activate_see instanceof Function){
//#if enable-see
if(wasm.exports.sqlite3_key_v2 instanceof Function){
/**
This code is capable of using an SEE build but note that an SEE
WASM build is generally incompatible with SEE's license
@@ -346,6 +347,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_activate_see", undefined, "string"]
);
}
//#endif enable-see
/**
Functions which require BigInt (int64) support are separated from
the others because we need to conditionally bind them or apply
@@ -624,10 +627,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.bindingSignatures.wasmInternal = [
["sqlite3__wasm_db_reset", "int", "sqlite3*"],
["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
["sqlite3__wasm_vfs_create_file", "int",
"sqlite3_vfs*","string","*", "int"],
[/* DO NOT USE. This is deprecated since 2023-08-11 because it can
trigger assert() in debug builds when used with file sizes
which are not sizes to a multiple of a valid db page size. */
"sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
],
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
];
/**
@@ -1547,6 +1554,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
case capi.SQLITE_CONFIG_SQLLOG: // 21 /* xSqllog, void* */
case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23 /* int nByte */
default:
/* maintenance note: we specifically do not include
SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
it's only for legacy support and no apps written with
this API require that. */
return capi.SQLITE_NOTFOUND;
}
};
+222 -50
View File
@@ -87,6 +87,104 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/
const __vfsPostOpenSql = Object.create(null);
//#if enable-see
/**
Converts ArrayBuffer or Uint8Array ba into a string of hex
digits.
*/
const byteArrayToHex = function(ba){
if( ba instanceof ArrayBuffer ){
ba = new Uint8Array(ba);
}
const li = [];
const digits = "0123456789abcdef";
for( const d of ba ){
li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] );
}
return li.join('');
};
/**
Internal helper to apply an SEE key to a just-opened
database. Requires that db be-a DB object which has just been
opened, opt be the options object processed by its ctor, and opt
must have either the key, hexkey, or textkey properties, either
as a string, an ArrayBuffer, or a Uint8Array.
This is a no-op in non-SEE builds. It throws on error and returns
without side effects if none of the key/textkey/hexkey options
are set. It throws if more than one is set or if any are set to
values of an invalid type.
Returns true if it applies the key, else an unspecified falsy value.
*/
const dbCtorApplySEEKey = function(db,opt){
if( !capi.sqlite3_key_v2 ) return;
let keytype;
let key;
const check = (opt.key ? 1 : 0) + (opt.hexkey ? 1 : 0) + (opt.textkey ? 1 : 0);
if( !check ) return;
else if( check>1 ){
toss3(capi.SQLITE_MISUSE,
"Only ONE of (key, hexkey, textkey) may be provided.");
}
if( opt.key ){
/* It is not legal to bind an argument to PRAGMA key=?, so we
convert it to a hexkey... */
keytype = 'key';
key = opt.key;
if('string'===typeof key){
key = new TextEncoder('utf-8').encode(key);
}
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
key = byteArrayToHex(key);
keytype = 'hexkey';
}else{
toss3(capi.SQLITE_MISUSE,
"Invalid value for the 'key' option. Expecting a string,",
"ArrayBuffer, or Uint8Array.");
return;
}
}else if( opt.textkey ){
/* For textkey we need it to be in string form, so convert it to
a string if it's a byte array... */
keytype = 'textkey';
key = opt.textkey;
if(key instanceof ArrayBuffer){
key = new Uint8Array(key);
}
if(key instanceof Uint8Array){
key = new TextDecoder('utf-8').decode(key);
}else if('string'!==typeof key){
toss3(capi.SQLITE_MISUSE,
"Invalid value for the 'textkey' option. Expecting a string,",
"ArrayBuffer, or Uint8Array.");
}
}else if( opt.hexkey ){
keytype = 'hexkey';
key = opt.hexkey;
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
key = byteArrayToHex(key);
}else if('string'!==typeof key){
toss3(capi.SQLITE_MISUSE,
"Invalid value for the 'hexkey' option. Expecting a string,",
"ArrayBuffer, or Uint8Array.");
}
/* else assume it's valid hex codes */
}else{
return;
}
let stmt;
try{
stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1));
stmt.step();
}finally{
if(stmt) stmt.finalize();
}
return true;
};
//#endif enable-see
/**
A proxy for DB class constructors. It must be called with the
being-construct DB object as its "this". See the DB constructor
@@ -175,16 +273,28 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
__ptrMap.set(this, pDb);
__stmtMap.set(this, Object.create(null));
try{
//#if enable-see
dbCtorApplySEEKey(this,opt);
//#endif
// Check for per-VFS post-open SQL/callback...
const pVfs = capi.sqlite3_js_db_vfs(pDb);
if(!pVfs) toss3("Internal error: cannot get VFS for new db handle.");
const pVfs = capi.sqlite3_js_db_vfs(pDb)
|| toss3("Internal error: cannot get VFS for new db handle.");
const postInitSql = __vfsPostOpenSql[pVfs];
if(postInitSql instanceof Function){
postInitSql(this, sqlite3);
}else if(postInitSql){
checkSqlite3Rc(
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
);
if(postInitSql){
/**
Reminder: if this db is encrypted and the client did _not_ pass
in the key, any init code will fail, causing the ctor to throw.
We don't actually know whether the db is encrypted, so we cannot
sensibly apply any heuristics which skip the init code only for
encrypted databases for which no key has yet been supplied.
*/
if(postInitSql instanceof Function){
postInitSql(this, sqlite3);
}else{
checkSqlite3Rc(
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
);
}
}
}catch(e){
this.close();
@@ -280,6 +390,36 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- `flags`: open-mode flags
- `vfs`: the VFS fname
//#if enable-see
SEE-capable builds optionally support ONE of the following
additional options:
- `key`, `hexkey`, or `textkey`: encryption key as a string,
ArrayBuffer, or Uint8Array. These flags function as documented
for the SEE pragmas of the same names. Using a byte array for
`hexkey` is equivalent to the same series of hex codes in
string form, so `'666f6f'` is equivalent to
`Uint8Array([0x66,0x6f,0x6f])`. A `textkey` byte array is
assumed to be UTF-8. A `key` string is transformed into a UTF-8
byte array, and a `key` byte array is transformed into a
`hexkey` with the same bytes.
In non-SEE builds, these options are ignored. In SEE builds,
`PRAGMA key/textkey/hexkey=X` is executed immediately after
opening the db. If more than one of the options is provided,
or any option has an invalid argument type, an exception is
thrown.
Note that some DB subclasses may run post-initialization SQL
code, e.g. to set a busy-handler timeout or tweak the page cache
size. Such code is run _after_ the SEE key is applied. If no key
is supplied and the database is encrypted, execution of the
post-initialization SQL will fail, causing the constructor to
throw.
//#endif enable-see
The `filename` and `vfs` arguments may be either JS strings or
C-strings allocated via WASM. `flags` is required to be a JS
string (because it's specific to this API, which is specific
@@ -288,7 +428,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
For purposes of passing a DB instance to C-style sqlite3
functions, the DB object's read-only `pointer` property holds its
`sqlite3*` pointer value. That property can also be used to check
whether this DB instance is still open.
whether this DB instance is still open: it will evaluate to
`undefined` after the DB object's close() method is called.
In the main window thread, the filenames `":localStorage:"` and
`":sessionStorage:"` are special: they cause the db to use either
@@ -433,40 +574,56 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
out.returnVal = ()=>opt.resultRows;
}
if(opt.callback || opt.resultRows){
switch((undefined===opt.rowMode)
? 'array' : opt.rowMode) {
case 'object': out.cbArg = (stmt)=>stmt.get(Object.create(null)); break;
case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
case 'stmt':
if(Array.isArray(opt.resultRows)){
toss3("exec(): invalid rowMode for a resultRows array: must",
"be one of 'array', 'object',",
"a result column number, or column name reference.");
}
out.cbArg = (stmt)=>stmt;
switch((undefined===opt.rowMode) ? 'array' : opt.rowMode) {
case 'object':
out.cbArg = (stmt,cache)=>{
if( !cache.columnNames ) cache.columnNames = stmt.getColumnNames([]);
/* https://sqlite.org/forum/forumpost/3632183d2470617d:
conversion of rows to objects (key/val pairs) is
somewhat expensive for large data sets because of the
native-to-JS conversion of the column names. If we
instead cache the names and build objects from that
list of strings, it can run twice as fast. The
difference is not noticeable for small data sets but
becomes human-perceivable when enough rows are
involved. */
const row = stmt.get([]);
const rv = Object.create(null);
for( const i in cache.columnNames ) rv[cache.columnNames[i]] = row[i];
return rv;
};
break;
case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
case 'stmt':
if(Array.isArray(opt.resultRows)){
toss3("exec(): invalid rowMode for a resultRows array: must",
"be one of 'array', 'object',",
"a result column number, or column name reference.");
}
out.cbArg = (stmt)=>stmt;
break;
default:
if(util.isInt32(opt.rowMode)){
out.cbArg = (stmt)=>stmt.get(opt.rowMode);
break;
default:
if(util.isInt32(opt.rowMode)){
out.cbArg = (stmt)=>stmt.get(opt.rowMode);
break;
}else if('string'===typeof opt.rowMode
&& opt.rowMode.length>1
&& '$'===opt.rowMode[0]){
/* "$X": fetch column named "X" (case-sensitive!). Prior
to 2022-12-14 ":X" and "@X" were also permitted, but
having so many options is unnecessary and likely to
cause confusion. */
const $colName = opt.rowMode.substr(1);
out.cbArg = (stmt)=>{
const rc = stmt.get(Object.create(null))[$colName];
return (undefined===rc)
? toss3(capi.SQLITE_NOTFOUND,
"exec(): unknown result column:",$colName)
: rc;
};
break;
}
toss3("Invalid rowMode:",opt.rowMode);
}else if('string'===typeof opt.rowMode
&& opt.rowMode.length>1
&& '$'===opt.rowMode[0]){
/* "$X": fetch column named "X" (case-sensitive!). Prior
to 2022-12-14 ":X" and "@X" were also permitted, but
having so many options is unnecessary and likely to
cause confusion. */
const $colName = opt.rowMode.substr(1);
out.cbArg = (stmt)=>{
const rc = stmt.get(Object.create(null))[$colName];
return (undefined===rc)
? toss3(capi.SQLITE_NOTFOUND,
"exec(): unknown result column:",$colName)
: rc;
};
break;
}
toss3("Invalid rowMode:",opt.rowMode);
}
}
return out;
@@ -884,10 +1041,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
and names. */) ? 0 : 1;
evalFirstResult = false;
if(arg.cbArg || resultRows){
const cbArgCache = Object.create(null)
/* 2nd arg for arg.cbArg, used by (at least) row-to-object
converter */;
for(; stmt.step(); stmt._lockedByExec = false){
if(0===gotColNames++) stmt.getColumnNames(opt.columnNames);
if(0===gotColNames++){
stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || []));
}
stmt._lockedByExec = true;
const row = arg.cbArg(stmt);
const row = arg.cbArg(stmt,cbArgCache);
if(resultRows) resultRows.push(row);
if(callback && false === callback.call(opt, row, stmt)){
break;
@@ -1522,7 +1684,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
they are larger than 32 bits, else double or int32, depending
on whether they have a fractional part. Booleans are bound as
integer 0 or 1. It is not expected the distinction of binding
doubles which have no fractional parts is integers is
doubles which have no fractional parts and integers is
significant for the majority of clients due to sqlite3's data
typing model. If [BigInt] support is enabled then this
routine will bind BigInt values as 64-bit integers if they'll
@@ -1906,16 +2068,26 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Functionally equivalent to DB(storageName,'c','kvvfs') except
that it throws if the given storage name is not one of 'local'
or 'session'.
As of version 3.46, the argument may optionally be an options
object in the form:
{
filename: 'session'|'local',
... etc. (all options supported by the DB ctor)
}
noting that the 'vfs' option supported by main DB
constructor is ignored here: the vfs is always 'kvvfs'.
*/
sqlite3.oo1.JsStorageDb = function(storageName='session'){
const opt = dbCtorHelper.normalizeArgs(...arguments);
storageName = opt.filename;
if('session'!==storageName && 'local'!==storageName){
toss3("JsStorageDb db name must be one of 'session' or 'local'.");
}
dbCtorHelper.call(this, {
filename: storageName,
flags: 'c',
vfs: "kvvfs"
});
opt.vfs = 'kvvfs';
dbCtorHelper.call(this, opt);
};
const jdb = sqlite3.oo1.JsStorageDb;
jdb.prototype = Object.create(DB.prototype);
+1 -1
View File
@@ -245,7 +245,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
The exception's message is created by concatenating its
arguments with a space between each, except for the
two-args-with-an-objec form and that the first argument will
two-args-with-an-object form and that the first argument will
get coerced to a string, as described above, if it's an
integer.
+1 -34
View File
@@ -459,11 +459,6 @@ sqlite3.initWorker1API = function(){
return wState.dbList[0] && getDbId(wState.dbList[0]);
};
const guessVfs = function(filename){
const m = /^file:.+(vfs=(\w+))/.exec(filename);
return sqlite3.capi.sqlite3_vfs_find(m ? m[2] : 0);
};
const isSpecialDbFilename = (n)=>{
return ""===n || ':'===n[0];
};
@@ -485,36 +480,8 @@ sqlite3.initWorker1API = function(){
toss("Throwing because of simulateError flag.");
}
const rc = Object.create(null);
let byteArray, pVfs;
oargs.vfs = args.vfs;
if(isSpecialDbFilename(args.filename)){
oargs.filename = args.filename || "";
}else{
oargs.filename = args.filename;
byteArray = args.byteArray;
if(byteArray) pVfs = guessVfs(args.filename);
}
if(pVfs){
/* 2022-11-02: this feature is as-yet untested except that
sqlite3__wasm_vfs_create_file() has been tested from the
browser dev console. */
let pMem;
try{
pMem = sqlite3.wasm.allocFromTypedArray(byteArray);
const rc = util.sqlite3__wasm_vfs_create_file(
pVfs, oargs.filename, pMem, byteArray.byteLength
);
if(rc) sqlite3.SQLite3Error.toss(rc);
}catch(e){
throw new sqlite3.SQLite3Error(
e.name+' creating '+args.filename+": "+e.message, {
cause: e
}
);
}finally{
if(pMem) sqlite3.wasm.dealloc(pMem);
}
}
oargs.filename = args.filename || "";
const db = wState.open(oargs);
rc.filename = db.filename;
rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs");
@@ -1272,7 +1272,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return poolUtil;
}).catch(async (e)=>{
await thePool.removeVfs().catch(()=>{});
return e;
throw e;
});
}).catch((err)=>{
//error("rejecting promise:",err);
+16 -23
View File
@@ -545,6 +545,10 @@ const char * sqlite3__wasm_enum_json(void){
DefInt(SQLITE_CONFIG_SMALL_MALLOC);
DefInt(SQLITE_CONFIG_SORTERREF_SIZE);
DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE);
/* maintenance note: we specifically do not include
SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
it's only for legacy support and no apps written with
this API require that. */
} _DefGroup;
DefGroup(dataTypes) {
@@ -1674,35 +1678,24 @@ int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){
return sqlite3_config(op, arg);
}
#if 0
// Pending removal after verification of a workaround discussed in the
// forum post linked to below.
/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Returns a pointer to sqlite3_free(). In compliant browsers the
** return value, when passed to sqlite3.wasm.exports.functionEntry(),
** must resolve to the same function as
** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where
** sqlite3 is exported globally, the following must be true:
**
** ```
** sqlite3.wasm.functionEntry(
** sqlite3.wasm.exports.sqlite3__wasm_ptr_to_sqlite3_free()
** ) === sqlite3.wasm.exports.sqlite3_free
** ```
**
** Using a function to return this pointer, as opposed to exporting it
** via sqlite3__wasm_enum_json(), is an attempt to work around a
** Safari-specific quirk covered at
** https://sqlite.org/forum/info/e5b20e1feb37a19a.
**/
** If z is not NULL, returns the result of passing z to
** sqlite3_mprintf()'s %Q modifier (if addQuotes is true) or %q (if
** addQuotes is 0). Returns NULL if z is NULL or on OOM.
*/
SQLITE_WASM_EXPORT
void * sqlite3__wasm_ptr_to_sqlite3_free(void){
return (void*)sqlite3_free;
char * sqlite3__wasm_qfmt_token(char *z, int addQuotes){
char * rc = 0;
if( z ){
rc = addQuotes
? sqlite3_mprintf("%Q", z)
: sqlite3_mprintf("%q", z);
}
return rc;
}
#endif
#if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
#include <emscripten/wasmfs.h>
@@ -285,7 +285,7 @@ globalThis.sqlite3Worker1Promiser.defaultConfig = {
}/*defaultConfig*/;
/**
sqlite3Worker1Promiser.v2() works identically to
sqlite3Worker1Promiser.v2(), added in 3.46, works identically to
sqlite3Worker1Promiser() except that it returns a Promise instead
of relying an an onready callback in the config object. The Promise
resolves to the same factory function which
+34 -12
View File
@@ -1382,15 +1382,19 @@ globalThis.WhWasmUtilInstaller = function(target){
conversion of argument or return types, but see xWrap() and
xCallWrapped() for variants which do.
If the first argument is a function is is assumed to be
a WASM-bound function and is used as-is instead of looking up
the function via xGet().
As a special case, if passed only 1 argument after the name and
that argument in an Array, that array's entries become the
function arguments. (This is not an ambiguous case because it's
not legal to pass an Array object to a WASM function.)
*/
target.xCall = function(fname, ...args){
const f = target.xGet(fname);
const f = (fname instanceof Function) ? fname : target.xGet(fname);
if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function.");
if(f.length!==args.length) __argcMismatch(fname,f.length)
if(f.length!==args.length) __argcMismatch(((f===fname) ? f.name : fname),f.length)
/* This is arguably over-pedantic but we want to help clients keep
from shooting themselves in the foot when calling C APIs. */;
return (2===arguments.length && Array.isArray(arguments[1]))
@@ -1537,7 +1541,7 @@ globalThis.WhWasmUtilInstaller = function(target){
jsFuncToWasm().
- bindScope (string): one of ('transient', 'context',
'singleton'). Bind scopes are:
'singleton', 'permanent'). Bind scopes are:
- 'transient': it will convert JS functions to WASM only for
the duration of the xWrap()'d function call, using
@@ -1787,11 +1791,29 @@ globalThis.WhWasmUtilInstaller = function(target){
const __xResultAdapterCheck =
(t)=>xResult.get(t) || toss("Result adapter not found:",t);
/**
Fetches the xWrap() argument adapter mapped to t, calls it,
passing in all remaining arguments, and returns the result.
Throws if t is not mapped to an argument converter.
*/
cache.xWrap.convertArg = (t,...args)=>__xArgAdapterCheck(t)(...args);
/**
Identical to convertArg() except that it does not perform
an is-defined check on the mapping to t before invoking it.
*/
cache.xWrap.convertArgNoCheck = (t,...args)=>xArg.get(t)(...args);
/**
Fetches the xWrap() result adapter mapped to t, calls it, passing
it v, and returns the result. Throws if t is not mapped to an
argument converter.
*/
cache.xWrap.convertResult =
(t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined));
/**
Identical to convertResult() except that it does not perform an
is-defined check on the mapping to t before invoking it.
*/
cache.xWrap.convertResultNoCheck =
(t,v)=>(null===t ? v : (t ? xResult.get(t)(v) : undefined));
@@ -1903,15 +1925,15 @@ globalThis.WhWasmUtilInstaller = function(target){
const C-string, encoded as UTF-8, copies it to a JS string,
and returns that JS string.
- `string:dealloc` or `utf8:dealloc) (results): treats the result value
as a non-const UTF-8 C-string, ownership of which has just been
transfered to the caller. It copies the C-string to a JS
string, frees the C-string, and returns the JS string. If such
a result value is NULL, the JS result is `null`. Achtung: when
using an API which returns results from a specific allocator,
e.g. `my_malloc()`, this conversion _is not legal_. Instead, an
equivalent conversion which uses the appropriate deallocator is
required. For example:
- `string:dealloc` or `utf8:dealloc` (results): treats the result
value as a non-const UTF-8 C-string, ownership of which has
just been transfered to the caller. It copies the C-string to a
JS string, frees the C-string, and returns the JS string. If
such a result value is NULL, the JS result is `null`. Achtung:
when using an API which returns results from a specific
allocator, e.g. `my_malloc()`, this conversion _is not
legal_. Instead, an equivalent conversion which uses the
appropriate deallocator is required. For example:
```js
target.xWrap.resultAdapter('string:my_free',(i)=>{
+8 -3
View File
@@ -19,10 +19,15 @@ MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))
# built, and won't be built until we expand the dependencies. Thus we
# have to use a temporary name for the archive until we can get
# that binary built.
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
dist-name-prefix := sqlite-wasm
ifeq (1,$(SQLITE_C_IS_SEE))
dist-name-extra := -see
else
dist-name-prefix := sqlite-wasm-snapshot-$(shell /usr/bin/date +%Y%m%d)
dist-name-extra :=
endif
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
dist-name-prefix := sqlite-wasm$(dist-name-extra)
else
dist-name-prefix := sqlite-wasm$(dist-name-extra)-snapshot-$(shell /usr/bin/date +%Y%m%d)
endif
dist-name := $(dist-name-prefix)-TEMP
+56 -2
View File
@@ -1482,7 +1482,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
/*step() skipped intentionally*/.reset(true);
} finally {
T.assert(0===st.finalize())
.assert(undefined===st.finalize());
.assert(undefined===st.finalize());
}
try {
@@ -2587,7 +2587,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const pVfs = capi.sqlite3_vfs_find('kvvfs');
T.assert(pVfs);
const JDb = this.JDb = sqlite3.oo1.JsStorageDb;
const unlink = this.kvvfsUnlink = ()=>{JDb.clearStorage(filename)};
const unlink = this.kvvfsUnlink = ()=>JDb.clearStorage(this.kvvfsDbFile);
unlink();
let db = new JDb(filename);
try {
@@ -2605,6 +2605,60 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
}
}
}/*kvvfs sanity checks*/)
//#if enable-see
.t({
name: 'kvvfs with SEE encryption',
predicate: ()=>(isUIThread()
|| "Only available in main thread."),
test: function(sqlite3){
this.kvvfsUnlink();
let db;
const encOpt1 = 1
? {textkey: 'foo'}
: {key: 'foo'};
const encOpt2 = encOpt1.textkey
? encOpt1
: {hexkey: new Uint8Array([0x66,0x6f,0x6f]/*==>"foo"*/)}
try{
db = new this.JDb({
filename: this.kvvfsDbFile,
...encOpt1
});
db.exec([
"create table t(a,b);",
"insert into t(a,b) values(1,2),(3,4)"
]);
db.close();
let err;
try{
db = new this.JDb({
filename: this.kvvfsDbFile,
flags: 'ct'
});
T.assert(db) /* opening is fine, but... */;
db.exec("select 1 from sqlite_schema");
console.warn("sessionStorage =",sessionStorage);
}catch(e){
err = e;
}finally{
db.close();
}
T.assert(err,"Expecting an exception")
.assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
"Expecting NOTADB");
db = new sqlite3.oo1.DB({
filename: this.kvvfsDbFile,
vfs: 'kvvfs',
...encOpt2
});
T.assert( 4===db.selectValue('select sum(a) from t') );
}finally{
if( db ) db.close();
this.kvvfsUnlink();
}
}
})/*kvvfs with SEE*/
//#endif enable-see
;/* end kvvfs tests */
////////////////////////////////////////////////////////////////////////
+89 -82
View File
@@ -1,5 +1,5 @@
C Fix\sa\stypo\sin\sa\scomment.
D 2024-03-20T10:40:25.308
C Add\sa\stest\scase\sto\sthe\sfix\sto\sPRAGMA\sintegrity_check\sin\sthe\sprevious\scheck-in.
D 2024-05-02T12:00:36.739
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -74,7 +74,7 @@ F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c e19807ce0ae31c1c6e9898e89ecc93183d7ec224ea101af039722a4f49e5f2b8
F ext/fts3/fts3_snippet.c 4d6523e3eddeb7b46e7a82b3476a0a86a0c04821e0e2b8dd40f45ee28057cb13
F ext/fts3/fts3_snippet.c 610328fe128c047c6b0eba77768982ccf3933daae095d497949a75c9dfd47409
F ext/fts3/fts3_term.c 845f0e2456b1be42f7f1bec1da1dfc05bc347531eff90775ffc6698902c281de
F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
F ext/fts3/fts3_tokenize_vtab.c 7fd9ef364f257b97218b9c331f2378e307375c592f70fd541f714e747d944962
@@ -92,7 +92,7 @@ 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 bc3a0ca78be7d3df08e7602c00ca48021ebae40682d75eb001bfdf6e54ffb44e
F ext/fts5/fts5.h ecba24fed7b359b3a53016bb07e411b3b4c9cdf163aa141006536423a63b611e
F ext/fts5/fts5.h 8856e11a5f0269cd346754cea0765efe8089635b80cad3222e8bfdb08cd5348a
F ext/fts5/fts5Int.h defa43c0932265138ee910ca416e6baccf8b774e0f3d610e74be1ab2880e9834
F ext/fts5/fts5_aux.c 4584e88878e54828bf7d4d0d83deedd232ec60628b7731be02bad6adb62304b1
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
@@ -248,7 +248,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl 3eba8e9bee4221ed165f3304b51b2a74a705f4ec5df3d044573a2be539534af8
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/icu.c 3add8197e0a86c1761771a39500ebae749438bcf1836160b407a56b4eaa8721c
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/intck/intck1.test f3a3cba14b6aeff145ffa5515546dd22f7510dad91512e519f43b92b56514012
F ext/intck/intck2.test d2457c7e5e5b688046d15ebe08a1e1427cc5e7a6dc8d6af215f42e8bcaf67304
@@ -411,7 +411,7 @@ F ext/misc/regexp.c 4bdd0045912f81c84908bd535ec5ad3b1c8540b4287c70ab840709636240
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F ext/misc/series.c 384f93a8a09cf45e1aa6575660cb580ed61d372c590aad05cdcd4a84fbd8f6ab
F ext/misc/series.c d96e5aac21658c6b5d54f918ac140460ec7197734c1a4fba806950831a7b1e7a
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
F ext/misc/shathree.c 543af7ce71d391cd3a9ab6924a6a1124efc63211fd0f2e240dc4b56077ba88ac
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
@@ -426,7 +426,7 @@ F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808d269d
F ext/misc/vtablog.c f2c9d41afe00b51b2c8307b79f508eb0c2dcd57bae074807944e73376fcf15b7
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
F ext/misc/zipfile.c 64cb3d98b6316586e6056d182051aa9d28fdedfbf4b908e6b7a7d70209b1db11
@@ -478,13 +478,14 @@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69
F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949
F ext/recover/dbdata.c 520636e61eddfa22fe13b0324c0e7b67b699464ff63aeaf4c26ff00b7ba0844c
F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
F ext/recover/recovercorrupt2.test b9b974f006340a1300b5a7e687bd6097c5238498181c6f92d87406a77ece430b
F ext/recover/recovercorrupt2.test 1418f1710debc24ff38276cedfcea234beb37a34205708e7e3e6d76cc4a979db
F ext/recover/recovercorrupt3.test 2e7b9a1b528ca23ed382cec6f64e3fcbbd0f8e852add7562397fd8df83f335d5
F ext/recover/recoverfault.test 9d9f88eeb222615a25e7514f234c950d46bee20d24cd8db49d8fff8d650dcfe1
F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539ccabf63623e7bb7e09
F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
@@ -492,7 +493,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc
F ext/recover/sqlite3recover.c 65ef0f56301a16c0536c9839fb7e23540c9c4f75da0afe3b7b4d163c8f624404
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -566,6 +567,7 @@ F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8
F ext/session/sessionalter.test 460bdac2832a550519f6bc32e5db2c0cee94f335870aaf25a3a403a81ab20e17
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
F ext/session/sessionconflict.test 28890457bb90457be772d3067cdb5f78db9b51d997e4f3d09f22cddc9be80a38
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
F ext/session/sessionfault.test 573bf027fb870d57bd4e7cf50822a3e4b17b2b923407438747aaa918dec57a09
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
@@ -587,7 +589,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 4bb4cf70a8153dd5b5fee17d724075c54174da630b424bbcf48c744633396f62
F ext/wasm/GNUmakefile 21f015f342e4ed9b7ff632c10750512259d26c836a34f4f535673fae9a7c9fcc
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -605,18 +607,18 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
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 587dc6db2d69329a5f4cb9635c377f516cf4a8e30f443f33380e5044889ec71b
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
F ext/wasm/api/sqlite3-api-glue.js 114085f4dceb28e06d20d3fb597b2501a4aa69f4b6cd29234f7cc1cf81d5b92d
F ext/wasm/api/sqlite3-api-oo1.js 40f6834314b60e636f0046a9c49b8566a992dcf04be9ea593e680c23f6984b2b
F ext/wasm/api/sqlite3-api-prologue.js 34457b25dcf0005c81d76f011f207026ec164f6ff0f69f024b608025ca808ea9
F ext/wasm/api/sqlite3-api-worker1.js 9704b77b5eb9d0d498ceeaf3e7a837021b14c52ac15d6556c7f97e278ec725c3
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 196ad83d36ca794e564044788c9d21b964679d63cad865f604da37c4afc9a285
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 5a430874906ff3f4a6ca69aadf0c2aaedc1bb45489b8365bff7e955a83a8d42a
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 8433ee332d5f5e39fb19427fccb7bad7f44aa99b5504daad3343fc128c311e78
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309
F ext/wasm/api/sqlite3-wasm.c d33a16495ca871781e78812d3a18fed78b797468fffee657b8d7199b277ff359
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bd89edfe42a4d7122a6d6d405c5423cf00aabba1f76f6ea8e2dba9c628ddd91a
F ext/wasm/api/sqlite3-wasm.c 9267174b9b0591b4f71193542ab57adf95bb9415f7d3453acf4a8ca8052f5e6c
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 5bffc94b0ba45c658f7a70c683c536642cd95f4d6fc71d20785864111c396740
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
@@ -626,7 +628,7 @@ F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
F ext/wasm/common/whwasmutil.js 4c64594eecc7af4ae64259e95a71ba2a7edf118881aaff0bba86d0c7164e78e4
F ext/wasm/common/whwasmutil.js e474e0fac695abf88e5385581e26d53e5706cd268cab9d92a56eab2873c08daa
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32e7be5bf
@@ -636,7 +638,7 @@ F ext/wasm/demo-worker1-promiser.c-pp.html 635cf90685805e21772a5f7a35d1ace80f98a
F ext/wasm/demo-worker1-promiser.c-pp.js fcc628cb42fcfaf07d250477801de1e6deb1e319d003976612a0db8d76b9fccc
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
F ext/wasm/dist.make f2ce42305268fe33d4b50f6e4bb3daf4a60302a90736eee382f1b8af9ff32ec1
F ext/wasm/dist.make 653e212c1e84aa3be168d62a10616ccea45ee9585b0192745d2706707a5248ce
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
F ext/wasm/fiddle.make 3c2eace29255d6ddd219f5d8cc2728cb28b9fe717ea80b6062c2a6178947a16b
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
@@ -662,7 +664,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js 18331ec28d7e63c8e262a9872a8da3964d37b7ac22eabe0016af93f3c6f74cc4
F ext/wasm/tester1.c-pp.js 6d0a9aa44a97b4aadd582e0999ce45a2671b854a12ea3205d1c908da6bd4bdef
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -682,25 +684,25 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc
F src/alter.c e1b6782b85dd758f89e5c588e4e3eb82638c2dafc0c857b79a43bb8ec1746fca
F src/analyze.c a3df28274e2565ba5656577d7e3fd262169a213e6eb0bd47890e0f0729a4031c
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 285b493d843e7ba8ef78b6ae7d31238e904901dbc0c484f7904de4cf18fd8802
F src/btree.c 71b80e77b255144db47180fda8138740608e382a44231942464029b1a45fc036
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
F src/build.c fff536730a6d83120ae38d960f812b548394e8af6907249effb1764d69178106
F src/build.c 11ec7014a3c468e7b3ccc8dda8d9111cd5a29a358df18818788601e0600aaabd
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
F src/expr.c d7cfe9b9fe7ab47b254706589467d2e65fec3536b936d6f4eb28b84da6726ecc
F src/expr.c 005bf7a088a2fb12a50752a2a1d40d423b8942e1920e93c3a1ba76da0bfbe52b
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
F src/func.c 283d4f3b2751a1d9339fd93a8a013d1948fd5f4474a3cab0955eb4fafd445d0f
@@ -709,7 +711,7 @@ 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 06ce505713e86172612f9e01febefd2d3331d1f70461b4ada0eae5a76bb6349f
F src/insert.c 4bd7c7e54a1062dcd0214b7a6296f7194eb10fb14d3ddca1ed20b01c2a86a18c
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
@@ -734,28 +736,28 @@ 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 8d7533b3b4d0d2d6ddd34d1ebc92f50a91f04e722a3a9295a000bc3c25128e2f
F src/os_unix.c 6227cbc4ac93046f121436886cf3712da6f4e2082af6314f976eeae1d86b794a
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
F src/pager.c 9beb80f6e330dd63c5d8ba0f7a7f3a55fff22067a68d424949c389bfc6fa0c56
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
F src/parse.y 5bcef16094213efcc365a9d4dc4e3131f09251dc8838dce4a9e5f9764bff5b82
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
F src/pragma.c e8221d6310c9923c80f6fa6d09b7ea7c5263a671f53db8d0894df23efcdb617b
F src/pragma.c d357a25276d222adfd4637c48880409ec4539f30844b74001c6ba5c7d1a1f0f7
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
F src/printf.c 87b67bba3662a0523f39ae6b084a3907109702f717c654d6cecb838af5cd57f1
F src/printf.c 8b250972305e14b365561be5117ed0fd364e4fd58968776df1ce64c6280b90f9
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c eb1860b134fb044fd819c4347105c148d5aac7c6498032be2829e5cc95619b28
F src/resolve.c 647edf93729ba124c0a6048982af56c2fa4f841e69d626e4f3caa620f082bb15
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c a83532bae45185f271b59babf715a31a831ac17e2b4bc061f52ee53825c688f1
F src/select.c 04178566d0188be7de471064ced8cec1d407920726cb49b609486282d78faf56
F src/shell.c.in 0354ca51eee5fbf6af394a7ef9f5ef6823ef45b743db65431f6777e4d5be2199
F src/sqlite.h.in 41c5febd217b1e475aae022895c60f57fbe39ff6136450110662cfad67002d43
F src/sqlite.h.in 32389e0d584551b300d0157881336162c14315a424cbf385c0d65eb7c2e31f7b
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h f8928f0397d797046396dd9d360a6af8ce6dcb48bd72ea290165b07c8c518744
F src/sqliteInt.h 4ca38e206befb3738d8cca97b6c6ee56c10f1c5bdb379ac5442d0f1a71b9fefa
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -771,7 +773,7 @@ F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c f6af1e41cb7901edafb065a8198e4a0192dd42432b642d038965be5e628dec12
F src/test_bestindex.c 1ee3d64b49ca06a9cb8195fab04f1a0585cafc90d25a2a817caa14e7caab22e7
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 5fa77ee6064ba546e144c4fea870c5ede2c54314616f81485c6a9c4192100c75
@@ -813,32 +815,32 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 3f703cacdab728d7741e5a6ac242006d74fe1c2754d4f03ed889d7253259bd68
F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
F src/trigger.c 0905b96b04bb6658509f711a8207287f1315cdbc3df1a1b13ba6483c8e341c81
F src/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
F src/treeview.c 4f9ba6c1c7c9893fc046fdb0bc1f6bdec7660122b1ae37e51fb9b64c286caafd
F src/trigger.c 0858f75818ed1580332db274f1032bcc5effe567cb132df5c5be8b1d800ca97f
F src/update.c 732404a04d1737ef14bb6ec6b84f74edf28b3c102a92ae46b4855438a710efe7
F src/upsert.c 2e60567a0e9e8520c18671b30712a88dc73534474304af94f32bb5f3ef65ac65
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
F src/util.c 4d6d7ebfe6772a1b950c97bbb1d1a72ad4874617ec498ab8aa73b7f5a43e44bb
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c da8407be6055f5751bf85681542d130a320b4fd1f4d8719bf83a464743d9aae4
F src/vdbe.c 3b1793c5d2235ae89b01ef051a33d7d2ad3704c71799653b112686735ad401ff
F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
F src/vdbeaux.c 6385727adf51a649e4993098870a62c3945fe21dbc0e0fd9013772aff930b8fb
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
F src/vdbemem.c 213bf303826c0ef702e3a2a69dab2309d84b8381b822c6787885859fd7cd4c4e
F src/vdbemem.c 385c8b89da3b5ef9a468d77a466958aa72ee1212d5cb005f23ec63df1d413054
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
F src/vtab.c 38fcf63832f7e606755fa47b028c2eb6d6cd5facb40e280d66fbda4ed9a52188
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 4c475fb672a6fe57830561e614dbee21a9a24a6f616d1cfcbe85f356a09f14ad
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 5e9a5d642cceb666152c59091a3dbb645a9dda209b4e65a2f9215ee9298d26cf
F src/where.c 0ef9638651b900d64d7e1e877af37cd7900159ff875547ec29b918a1497e5c9c
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
F src/whereexpr.c 7b64295f1d82ad0928df435925dd7bbd5997b44a026153113eace0d9e71ff435
F src/wherecode.c 1f6940349e92a6e056aecd70163b00f331554c815c362b4cc80906c48151d73d
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -867,7 +869,7 @@ F test/altermalloc3.test 8040e486368403f2fdd6fc3998258b499bd4cc2f3ddbb5f8f874cd4
F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba
F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
F test/altertab3.test e167ce3b8e243b52306c1e40b13eb868f402a969513c063998593862cc643b44
F test/altertab3.test b331ae34e69594e19605e3297805202d6156fcc8f75379dfd972a2e51cae8721
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
@@ -931,10 +933,11 @@ F test/bestindex4.test 3039894f2dad50f3a68443dffad1b44c9b067ac03870102df1ce3d9a4
F test/bestindex5.test a0c90b2dad7836e80a01379e200e5f8ec9476d49b349af02c0dbff2fb75dc98d
F test/bestindex6.test 16942535b551273f3ad9df8d7cc4b7f22b1fcd8882714358859eb049a6f99dd4
F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c414b71e
F test/bestindex8.test 333ad8c6a554b885a49b68c019166eda92b05f493a92b36b0acdf7f766d04dad
F test/bestindex8.test b63a4f171a2c83d481bb14c431a8b72e85d27b2ffdaa0435a95d58ca941678f9
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
F test/bestindexC.test c14a8c8639b6825b0efa1ae693f34ec04f41a46e3056e7063d6e0f46bf4ff692
F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -1019,10 +1022,10 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test 9d8cbf6214e492abe9e822e759b9751ae336cec0a6fe3ff3b37bfbd8ff9c22ca
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test 504d90502d9993440226edc355d2275524b89064ea3df5ee5c27f7028ec59d07
F test/corruptL.test 652fc8ac0763a6fd3eb28b951d481924167b2d9936083bcc68253b2274a0c8fe
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/corruptN.test 7c099d153a554001b4fb829c799b01f2ea6276cbc32479131e0db0da4efd9cc4
F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
F test/cost.test cc434a026b1e9d0d98137a147e24e5daf1b1ad09e9ff7da63b34c83ddd136d92
F test/count.test cd4bd531066e8d77ef8fe1e3fc8253d042072e117ccab214b290cf83f1602249
F test/countofview.test 4088e461a10ee33e69803c177a69aa1d7bba81a9ffc2df66d76465a22ca7fdfc
F test/coveridxscan.test f35c7208dedc4f98e471c569df64c0f95a49f6e072d8dc7c8f99bdee2697de1b
@@ -1057,7 +1060,7 @@ F test/dbpagefault.test 35f06cfb2ef100a9b19d25754e8141b9cba9b7daabd4c60fa5af93fc
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
F test/decimal.test ef731887b43ee32ef86e1c8fddb61a40789f988332c029c601dcf2c319277e9e
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
@@ -1100,7 +1103,8 @@ F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a
F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
F test/enc3.test 55ef64416d72975c66167310a51dc9fc544ba3ae4858b8d5ab22f4cb6500b087
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test f3f7548d2f3df03e2f23ecaf35c7c2cc7b89848bd7c3606d94a010521b7ea4f6
F test/eqp.test 3302598f611220a6c61e29d9b7bb62fd4a43504509b978dbabdb0b3e56ae3bc0
F test/eqp2.test 6e8996148de88f0e7670491e92e712a2920a369b4406f21a27c3c9b6a46b68dd
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test 73969a2d43a511bf44080c44485a8c4d796b6a4f038d19e491867081155692c0
F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747
@@ -1199,7 +1203,7 @@ F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
F test/fts3snippet2.test e79afeb1f673713f96d7fc5655726081975399d11e659d15553207be43301dc4
F test/fts3snippet2.test 03f6738ab3897bea2ba6be424a0613872e167acbf37a66200d655d737b470f65
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
@@ -1230,7 +1234,7 @@ F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401b
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test b56905748ce0567c01d60005f3e6ad1af19453d224ba4730ee687d048fd09ef9
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func2.test 69f6ae3751b4ec765bdc3b803c0a255aa0f693f28f44805bef03e6b4a3fd242f
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
F test/func4.test a3f9062487dbd826776f54f4e0e9517fe8c3cf689af92735308965774d51fac5
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
@@ -1245,7 +1249,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 e6a40f53ac5624aa5b7c4f31c385f09ba088d524cecc4512fd3057caeed8f530
F test/fuzzcheck.c dc159967609d00b0cfe619e735cbbf8482570aca85711397034b0662b6c18fc7
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1257,7 +1261,7 @@ F test/fuzzdata8.db 4a53b6d077c6a5c23b609d8d3ac66996fa55ba3f8d02f9b6efdd0214a767
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
F test/fuzzinvariants.c 4355043e98cd8555c62462fcbba91c17c6492b0b017bbbe68656d5f2208f6444
F test/fuzzinvariants.c 0729b9d8ed77ad0f8c5c7601168a707d5803087d2da030ede9057c51c809cc6c
F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d
F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -1266,14 +1270,14 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test 18cae9140fa7f9a6f346e892a3fe3e31b2ca0be1494cd01b918adb74281016a6
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
@@ -1337,7 +1341,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test d5054173442fdf98260eeb6bb9751daa733b0ae6842fe50dcbd5469945b86985
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
@@ -1432,7 +1436,7 @@ F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db
F test/misc5.test 027cf0ac10314ea534173f335a33bb4059907ddabbac2c16786766d6f26c8923
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
@@ -1467,7 +1471,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/optfuzz-db01.c 9f2fa80b8f84ebbf1f2e8b13421a4e0477fe300f6686fbd76cac1d2db66e0fdc
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
F test/optfuzz.c 690430a0bf0ad047d5a168bf52b05b2ee97aedaad8c14337e9eb5050faa64994
F test/orderby1.test 02cfd870127a7342170b829175c5c53e9e7405744451ac1aeb2f7e2b0c18ca76
F test/orderby1.test 7d0e4ee692a3e808c1026b3c483594ad1e468b68b50dcefa0d678a8c05274ceb
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
@@ -1497,10 +1501,10 @@ F test/pendingrace.test 6aa33756b950c4529f79c4f3817a9a1e4025bd0d9961571a05c0279b
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 8bb6d3992c1c31ff6d5553d1e0693d642f7e19015648c6ae7034cb497d26bbd4
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
F test/pragma4.test 9559cf5173864bf47c0431873d158fbeb72f920a59905b1f46069d8543eccdab
F test/pragma4.test 22834a228e59b80f5c15b519b710474859d91535002670ddb7cd13ac44b54e9a
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
@@ -1509,7 +1513,7 @@ F test/printf.test 685fec5a0c5af2490ab0632775a301554361d674211d690f5bee0a97b0533
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/pushdown.test 1495a09837a1cedfc0adf07ba42dc6b83be05a2c15de331b67c39a0e22078238
F test/pushdown.test 3330746a897ea271b1021bc1e7e57c6f8d49bcb8ca7d58a823d01aa64a303cc7
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quickcheck.test a4b7e878cd97e46108291c409b0bf8214f29e18fddd68a42bc5c1375ad1fb80a
@@ -1521,13 +1525,14 @@ F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/readonly.test c1985f0b4ab55041f2ba629dadc6578a3ff0f0e5b0ec7912e85c51f49c3e82fe
F test/recover.test 6463509a7404e0c35431dd9b4a1c3b4a29d7a6af8a08462b31670c8a5a616d3a
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test 3ead782eddf51f573cdd43bcbb10d1b485ac095a19a76d16c43fd159ea9b7466
F test/returning1.test 2ebfe6e56f3de9b194295620f46a747c26cebdab937defb9afd84b96dd202ccb
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
@@ -1535,7 +1540,7 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190cfd4
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test aaa2572271edf58f8f88ac4d39f69e57ee5ae7a858332cdce9106e7cff8b7963
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
F test/rowvalue.test baf4fa3ec1a8c1c920c3faa5fd25959cb454bbd99ac8960397c34549d9fc4abe
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 1347e25ca11c547c5a6ff0cc5626f95aa9740e9275bfaec096029f57cb2130ce
@@ -1558,7 +1563,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
F test/scanstatus.test b249328caf4d317e71058006872b8012598a5fa045b30bf24a81eeff650ab49e
F test/scanstatus2.test 317670daf7f3eef48a9598cb7800ba8eccab51949cf52bca3f7da3b83a0c1c8c
F test/scanstatus2.test 688adc0c3ab1ffadead218cbce6446b10aa892004a8ea5e3640d59257fb836f2
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
@@ -1578,7 +1583,7 @@ F test/select6.test 9b2fb4ffedf52e1b5703cfcae1212e7a4a063f014c0458d78d29aca3db76
F test/select7.test f659f231489349e8c5734e610803d7654207318f
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812
F test/selectA.test 6aef8b2136a4ac7a3e2e4161d2b8ca7bc6ebe2779de084f9bb66ca9e2323a937
F test/selectA.test 1da8ce3884c326e11d2855baffb76436b0d7e044404af8a2a70d1399a4ff7e29
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test 38c530b0cc5728b793c3c11f52b52c70290d39822224acd39011c89c1853bd31
F test/selectD.test 6d1909b49970bf92f45ce657505befcef5fc7cbc13544e18103a316d32189bfb
@@ -1588,7 +1593,7 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b7871aac
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
F test/sessionfuzz.c 666b47e177c7b25f01ba645d41fb9131d2d54ae673f0d81c08f5af2b3e6ecbda
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
@@ -1659,7 +1664,7 @@ F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b3594
F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
F test/subquery.test 312c5d26304b0e93a56ba2cb9d4480b8a1c8217e3b2b8f8be2bfb0b2458ac3a7
F test/subquery.test 903abf41049f8404256f7be24b3151328304a5b25162e17ab0079460237382fc
F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
@@ -1675,7 +1680,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test 54f27eacd054aa528a8b6e3331192c484104f30aaee351ad035f2b39a00f87c4
F test/tabfunc01.test f150d206294471d20f50029e6b46b76b87a7a010b16dc57eb44245c76dd02802
F test/table.test 7862a00b58b5541511a26757ea9c5c7c3f8298766e98aa099deec703d9c0a8e0
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1688,8 +1693,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf
F test/testrunner.tcl 01bc3b5bc900dc73b076180727eb2869dc61426b1ab95ac2f42def5d1f3d407e
F test/testrunner_data.tcl 7032a64e4757db0bf83c6874cab2ccbb14a8708b4d68c1ddc8b359e204139cb7
F test/testrunner.tcl 1386667c04207d0a540ce1a9bc5ee0b734f7a3ba856c14a03943fb4f32de55bb
F test/testrunner_data.tcl 3d36660cfd55ea5e20e661e8f94c0520feebcb437848f9b98b33c483cc479c0c
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1904,7 +1909,7 @@ F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af623
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb25d3
F test/upsert1.test beba4316fbd4b7b9d76784313f6129a548cfe7abea04d46db33e2efce1ab0ac2
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
@@ -1914,7 +1919,7 @@ F test/uri.test c1abaaaa28e9422d61e5f3f9cbc8ef993ec49fe802f581520731708561d49384
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
F test/vacuum-into.test 35dc6f79b563f91c61822f61797363e97fed1bf28f1f722688b98d43f1980d76
F test/vacuum-into.test 77845cee98770c416dae9b0da6bb3229753861f2da65c11b4f9715d081712d8a
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
@@ -1922,11 +1927,11 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
F test/values.test e7c156f92d32ed645908fbad0a1144f0f31650376cdcb212fde701978c89d3b1
F test/values.test 52102ad9e5068b449429e40a976486a52246041f7cd79d086a2b170e77dec925
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
F test/view.test 3c23d7a068e9e4a0c4e6907498042772adea725f0630c3d9638ffd4e5a08b92b
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
F test/vt02.c 5b44ac67b1a283fedecf2d6e2ceda61e7a157f01d44dcb4490dcb1e87d057060
@@ -1949,6 +1954,7 @@ F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtabJ.test a6aef49d558af90fae10565b29501f82a95781cb4f797f2d13e2d19f9b6bc77b
F test/vtabK.test 13293177528fada1235c0112db0d187d754af1355c5a39371abd365104e3afbf
F test/vtabL.test 49ec7342e8bfcb0d6c3d2443c619f430c609c042d5d7e6ddf52def65d6d1812f
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
@@ -2014,6 +2020,7 @@ F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08a
F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
F test/whereL.test 438a397fa883b77bb6361c08a8befa41b52e9cfbe15a2a43715d122f8cfa8649
F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250
F test/whereN.test 63a3584b71acfb6963416de82f26c6b1644abc5ca6080c76546b9246734c8803
F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
@@ -2100,7 +2107,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl a16682eae5f01f85e5861b2aa215ca0d46b4230658ee25977e02b4508566fb75 x
F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
@@ -2180,8 +2187,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1ad1ca498296493c8e89cda911cc153baa51c90ae6c19961841e6b4e37302a23
R 881bc9317ed9df88acd3db1968866969
P b04e7a23478f1012e501a810f3e09cca81a66e802f5f72cae80c81120174e2cb
R 0ac28bb5468fe4b54198e9b7f938f439
U drh
Z 3ac48e6dcd121003681750f4a6450153
Z 39f04eb486031705b188423b1deb4083
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
54680d0fbec1f0575ac4be6dca866971795dab2c42b02a492d5cd485f46d153f
39a57b596d309d9e2d4c59409fe5d36e0665781ce0307d157ff8b6e883161bbb
+5
View File
@@ -2262,7 +2262,12 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
}else{
char aff = pTab->aCol[i].affinity;
if( aff==SQLITE_AFF_REAL ){
pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
}
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
pTab->aCol[i].affinity = aff;
}
nField++;
}
+27 -14
View File
@@ -5143,6 +5143,12 @@ static int accessPayload(
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
}else{
/* Sanity check the validity of the overflow page cache */
assert( pCur->aOverflow[0]==nextPage
|| pCur->aOverflow[0]==0
|| CORRUPT_DB );
assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
@@ -5624,6 +5630,23 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
return rc;
}
#ifdef SQLITE_DEBUG
/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
** this flags are true for a consistent database.
**
** This routine is is called from within assert() statements only.
** It is an internal verification routine and does not appear in production
** builds.
*/
static int cursorIsAtLastEntry(BtCursor *pCur){
int ii;
for(ii=0; ii<pCur->iPage; ii++){
if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
}
return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
}
#endif
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
@@ -5652,18 +5675,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
testcase( pCur->ix!=pCur->pPage->nCell-1 );
/* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = 0;
return SQLITE_OK;
}
@@ -5716,6 +5728,7 @@ int sqlite3BtreeTableMoveto(
}
if( pCur->info.nKey<intKey ){
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = -1;
return SQLITE_OK;
}
@@ -9521,7 +9534,7 @@ int sqlite3BtreeInsert(
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->ix;
pCur->curFlags &= ~BTCF_ValidNKey;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}else{
assert( pPage->leaf );
}
@@ -9551,7 +9564,7 @@ int sqlite3BtreeInsert(
*/
if( pPage->nOverflow ){
assert( rc==SQLITE_OK );
pCur->curFlags &= ~(BTCF_ValidNKey);
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
+6 -9
View File
@@ -2828,20 +2828,20 @@ void sqlite3EndTable(
int regRowid; /* Rowid of the next row to insert */
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
int iCsr; /* Write cursor on the new table */
if( IN_SPECIAL_PARSE ){
pParse->rc = SQLITE_ERROR;
pParse->nErr++;
return;
}
iCsr = pParse->nTab++;
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
assert(pParse->nTab==1);
sqlite3MayAbort(pParse);
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
pParse->nTab = 2;
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
if( pParse->nErr ) return;
@@ -2862,11 +2862,11 @@ void sqlite3EndTable(
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
sqlite3TableAffinity(v, p, 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid);
sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid);
sqlite3VdbeGoto(v, addrInsLoop);
sqlite3VdbeJumpHere(v, addrInsLoop);
sqlite3VdbeAddOp1(v, OP_Close, 1);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
}
/* Compute the complete text of the CREATE statement */
@@ -2927,9 +2927,6 @@ void sqlite3EndTable(
sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
}
sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)",
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
}
/* Add the table to the in-memory representation of the database.
+3
View File
@@ -65,6 +65,9 @@ static const char * const sqlite3azCompileOpt[] = {
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
# endif
#endif
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
"ALLOW_ROWID_IN_VIEW",
#endif
#ifdef SQLITE_ALLOW_URI_AUTHORITY
"ALLOW_URI_AUTHORITY",
#endif
+64 -20
View File
@@ -1873,15 +1873,16 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
pNewItem->regResult = pOldItem->regResult;
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}else if( pNewItem->fg.isTabFunc ){
pNewItem->u1.pFuncArg =
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
}else{
pNewItem->u1.nRow = pOldItem->u1.nRow;
}
pNewItem->u2 = pOldItem->u2;
if( pNewItem->fg.isCte ){
pNewItem->u2.pCteUse->nUse++;
}
if( pNewItem->fg.isTabFunc ){
pNewItem->u1.pFuncArg =
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
}
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
pTab->nTabRef++;
@@ -2392,7 +2393,7 @@ static SQLITE_NOINLINE int exprNodeIsConstantFunction(
pWalker->eCode = 0;
return WRC_Abort;
}
return WRC_Continue;
return WRC_Prune;
}
@@ -2473,9 +2474,11 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
case TK_IF_NULL_ROW:
case TK_REGISTER:
case TK_DOT:
case TK_RAISE:
testcase( pExpr->op==TK_REGISTER );
testcase( pExpr->op==TK_IF_NULL_ROW );
testcase( pExpr->op==TK_DOT );
testcase( pExpr->op==TK_RAISE );
pWalker->eCode = 0;
return WRC_Abort;
case TK_VARIABLE:
@@ -2497,7 +2500,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
}
static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
Walker w;
w.eCode = initFlag;
w.pParse = pParse;
@@ -2506,7 +2509,6 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
@@ -2526,7 +2528,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){
** function and on its parameters.
*/
int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 1, 0);
return exprIsConst(pParse, p, 1);
}
/*
@@ -2543,7 +2545,23 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
*/
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 2, 0);
return exprIsConst(pParse, p, 2);
}
/*
** This routine examines sub-SELECT statements as an expression is being
** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
** constant as long as they are uncorrelated - meaning that they do not
** contain any terms from outer contexts.
*/
static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
assert( pSelect!=0 );
assert( pWalker->eCode==3 || pWalker->eCode==0 );
if( (pSelect->selFlags & SF_Correlated)!=0 ){
pWalker->eCode = 0;
return WRC_Abort;
}
return WRC_Prune;
}
/*
@@ -2551,9 +2569,26 @@ static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
**
** Consider uncorrelated subqueries to be constants if the bAllowSubq
** parameter is true.
*/
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(0, p, 3, iCur);
static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
Walker w;
w.eCode = 3;
w.pParse = 0;
w.xExprCallback = exprNodeIsConstant;
if( bAllowSubq ){
w.xSelectCallback = exprSelectWalkTableConstant;
}else{
w.xSelectCallback = sqlite3SelectWalkFail;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
}
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
/*
@@ -2571,7 +2606,10 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2) pExpr cannot use subqueries or non-deterministic functions.
** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
** true and the subquery is non-correlated
**
** (2b) pExpr cannot use non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
@@ -2600,7 +2638,8 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
int sqlite3ExprIsSingleTableConstraint(
Expr *pExpr, /* The constraint */
const SrcList *pSrcList, /* Complete FROM clause */
int iSrc /* Which element of pSrcList to use */
int iSrc, /* Which element of pSrcList to use */
int bAllowSubq /* Allow non-correlated subqueries */
){
const SrcItem *pSrc = &pSrcList->a[iSrc];
if( pSrc->fg.jointype & JT_LTORJ ){
@@ -2625,7 +2664,8 @@ int sqlite3ExprIsSingleTableConstraint(
}
}
}
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
/* Rules (1), (2a), and (2b) handled by the following: */
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
}
@@ -2710,7 +2750,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
*/
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
assert( isInit==0 || isInit==1 );
return exprIsConst(0, p, 4+isInit, 0);
return exprIsConst(0, p, 4+isInit);
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -2800,9 +2840,12 @@ int sqlite3ExprCanBeNull(const Expr *p){
return 0;
case TK_COLUMN:
assert( ExprUseYTab(p) );
return ExprHasProperty(p, EP_CanBeNull) ||
NEVER(p->y.pTab==0) || /* Reference to column of index on expr */
(p->iColumn>=0
return ExprHasProperty(p, EP_CanBeNull)
|| NEVER(p->y.pTab==0) /* Reference to column of index on expr */
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|| (p->iColumn==XN_ROWID && IsView(p->y.pTab))
#endif
|| (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);
@@ -5025,8 +5068,9 @@ expr_code_doover:
if( !ExprHasProperty(pExpr, EP_Collate) ){
/* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
** "SOFT-COLLATE" that is added to constraints that are pushed down
** from outer queries into sub-queries by the push-down optimization.
** Clear subtypes as subtypes may not cross a subquery boundary.
** from outer queries into sub-queries by the WHERE-clause push-down
** optimization. Clear subtypes as subtypes may not cross a subquery
** boundary.
*/
assert( pExpr->pLeft );
sqlite3ExprCode(pParse, pExpr->pLeft, target);
+8 -3
View File
@@ -610,8 +610,10 @@ static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
int ii;
if( exprListIsConstant(pParse,pRow)==0 ) return 0;
for(ii=0; ii<pRow->nExpr; ii++){
assert( pRow->a[ii].pExpr->affExpr==0 );
if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0;
Expr *pExpr = pRow->a[ii].pExpr;
assert( pExpr->op!=TK_RAISE );
assert( pExpr->affExpr==0 );
if( 0!=sqlite3ExprAffinity(pExpr) ) return 0;
}
return 1;
@@ -3180,7 +3182,10 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
if( pDest->pCheck
&& (db->mDbFlags & DBFLAG_Vacuum)==0
&& sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
+8 -1
View File
@@ -6398,12 +6398,19 @@ static int unixOpen(
rc = SQLITE_READONLY_DIRECTORY;
}else if( errno!=EISDIR && isReadWrite ){
/* Failed to open the file for read/write access. Try read-only. */
UnixUnusedFd *pReadonly = 0;
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
fd = robust_open(zName, openFlags, openMode);
pReadonly = findReusableFd(zName, flags);
if( pReadonly ){
fd = pReadonly->fd;
sqlite3_free(pReadonly);
}else{
fd = robust_open(zName, openFlags, openMode);
}
}
}
if( fd<0 ){
+1 -1
View File
@@ -7087,7 +7087,7 @@ sqlite3_file *sqlite3PagerFile(Pager *pPager){
** This will be either the rollback journal or the WAL file.
*/
sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
#if SQLITE_OMIT_WAL
#ifdef SQLITE_OMIT_WAL
return pPager->jfd;
#else
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
+8 -7
View File
@@ -1703,7 +1703,7 @@ void sqlite3Pragma(
/* Set the maximum error count */
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
if( zRight ){
if( sqlite3GetInt32(zRight, &mxErr) ){
if( sqlite3GetInt32(pValue->z, &mxErr) ){
if( mxErr<=0 ){
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
@@ -2870,9 +2870,9 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
seen[0] = 0;
seen[1] = 0;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->iColumn < pTab->iHidden ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT;
j = pConstraint->iColumn - pTab->iHidden;
assert( j < 2 );
seen[j] = i+1;
@@ -2885,12 +2885,13 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
j = seen[0]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
pIdxInfo->aConstraintUsage[j].omit = 1;
if( seen[1]==0 ) return SQLITE_OK;
pIdxInfo->estimatedCost = (double)20;
pIdxInfo->estimatedRows = 20;
j = seen[1]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
pIdxInfo->aConstraintUsage[j].omit = 1;
if( seen[1] ){
j = seen[1]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
pIdxInfo->aConstraintUsage[j].omit = 1;
}
return SQLITE_OK;
}
+1 -1
View File
@@ -857,7 +857,7 @@ void sqlite3_str_vappendf(
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else{
Select *pSel = pItem->pSelect;
assert( pSel!=0 );
assert( pSel!=0 ); /* Because of tag-20240424-1 */
if( pSel->selFlags & SF_NestedFrom ){
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
}else if( pSel->selFlags & SF_MultiValue ){
+8
View File
@@ -632,6 +632,11 @@ static int lookupName(
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
){
cnt = cntTab;
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
eNewExprOp = TK_NULL;
}
#endif
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
@@ -1349,6 +1354,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
assert( pExpr->x.pSelect );
if( pNC->ncFlags & NC_SelfRef ){
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
}else{
@@ -1357,6 +1363,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
pExpr->x.pSelect->selFlags |= SF_Correlated;
}
pNC->ncFlags |= NC_Subquery;
}
@@ -1882,6 +1889,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
+54 -14
View File
@@ -1673,9 +1673,16 @@ static void generateSortTail(
int addrExplain; /* Address of OP_Explain instruction */
#endif
ExplainQueryPlan2(addrExplain, (pParse, 0,
"USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"")
);
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->nOBSat==0 || nKey==1 ){
ExplainQueryPlan2(addrExplain, (pParse, 0,
"USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":""
));
}else{
ExplainQueryPlan2(addrExplain, (pParse, 0,
"USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey
));
}
sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd);
sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush);
@@ -1713,7 +1720,6 @@ static void generateSortTail(
regRow = sqlite3GetTempRange(pParse, nColumn);
}
}
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->sortFlags & SORTFLAG_UseSorter ){
int regSortOut = ++pParse->nMem;
iSortTab = pParse->nTab++;
@@ -2330,17 +2336,22 @@ void sqlite3SubqueryColumnTypes(
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
i64 n;
int m = 0;
Select *pS2 = pSelect;
pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
/* pCol->szEst = ... // Column size est for SELECT tables never used */
pCol->affinity = sqlite3ExprAffinity(p);
while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
pS2 = pS2->pNext;
pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr);
}
if( pCol->affinity<=SQLITE_AFF_NONE ){
pCol->affinity = aff;
}
if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
int m = 0;
Select *pS2;
for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){
for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
}
if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
@@ -5054,6 +5065,18 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
** The hope is that the terms added to the inner query will make it more
** efficient.
**
** NAME AMBIGUITY
**
** This optimization is called the "WHERE-clause push-down optimization".
**
** Do not confuse this optimization with another unrelated optimization
** with a similar name: The "MySQL push-down optimization" causes WHERE
** clause terms that can be evaluated using only the index and without
** reference to the table are run first, so that if they are false,
** unnecessary table seeks are avoided.
**
** RULES
**
** Do not attempt this optimization if:
**
** (1) (** This restriction was removed on 2017-09-29. We used to
@@ -5119,15 +5142,19 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
** clause and the subquery.
**
** Without this restriction, the push-down optimization might move
** the ON/USING filter expression from the left side of a RIGHT JOIN
** over to the right side, which leads to incorrect answers. See
** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
** Without this restriction, the WHERE-clause push-down optimization
** might move the ON/USING filter expression from the left side of a
** RIGHT JOIN over to the right side, which leads to incorrect answers.
** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
**
** (10) The inner query is not the right-hand table of a RIGHT JOIN.
**
** (11) The subquery is not a VALUES clause
**
** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This
** case only comes up if SQLite is compiled using
** SQLITE_ALLOW_ROWID_IN_VIEW.
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
@@ -5238,7 +5265,19 @@ static int pushDownWhereTerms(
}
#endif
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){
Expr *pLeft = pWhere->pLeft;
if( ALWAYS(pLeft)
&& pLeft->op==TK_COLUMN
&& pLeft->iColumn < 0
){
return 0; /* Restriction (12) */
}
}
#endif
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
nChng++;
pSubq->selFlags |= SF_PushDown;
while( pSubq ){
@@ -5865,6 +5904,7 @@ int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->eTabType = TABTYP_VIEW;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
/* The usual case - do not allow ROWID on a subquery */
@@ -7666,7 +7706,7 @@ int sqlite3Select(
#endif
assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
}
/* Convert unused result columns of the subquery into simple NULL
+9 -3
View File
@@ -3305,8 +3305,8 @@ int sqlite3_set_authorizer(
#define SQLITE_RECURSIVE 33 /* NULL NULL */
/*
** CAPI3REF: Tracing And Profiling Functions
** METHOD: sqlite3
** CAPI3REF: Deprecated Tracing And Profiling Functions
** DEPRECATED
**
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
** instead of the routines described here.
@@ -6887,6 +6887,12 @@ int sqlite3_autovacuum_pages(
** The exceptions defined in this paragraph might change in a future
** release of SQLite.
**
** Whether the update hook is invoked before or after the
** corresponding change is currently unspecified and may differ
** depending on the type of change. Do not rely on the order of the
** hook call with regards to the final result of the operation which
** triggers the hook.
**
** The update hook implementation must not do anything that will modify
** the database connection that invoked the update hook. Any actions
** to modify the database connection must be deferred until after the
@@ -8357,7 +8363,7 @@ int sqlite3_test_control(int op, ...);
** The sqlite3_keyword_count() interface returns the number of distinct
** keywords understood by SQLite.
**
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
** makes *Z point to that keyword expressed as UTF8 and writes the number
** of bytes in the keyword into *L. The string that *Z points to is not
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
+5 -5
View File
@@ -1156,7 +1156,7 @@ extern u32 sqlite3WhereTrace;
** 0x00000010 Display sqlite3_index_info xBestIndex calls
** 0x00000020 Range an equality scan metrics
** 0x00000040 IN operator decisions
** 0x00000080 WhereLoop cost adjustements
** 0x00000080 WhereLoop cost adjustments
** 0x00000100
** 0x00000200 Covering index decisions
** 0x00000400 OR optimization
@@ -1906,7 +1906,7 @@ struct sqlite3 {
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
@@ -3580,11 +3580,12 @@ struct Select {
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated 0x20000000 /* True if references the outer context */
/* True if S exists and has SF_NestedFrom */
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
@@ -5081,8 +5082,7 @@ int sqlite3ExprTruthValue(const Expr*);
int sqlite3ExprIsConstant(Parse*,Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
int sqlite3ExprIsTableConstant(Expr*,int);
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
int sqlite3ExprContainsSubquery(Expr*);
#endif
+1 -1
View File
@@ -226,7 +226,7 @@ static int tclConnect(
}
sqlite3_free(zCmd);
*ppVtab = &pTab->base;
*ppVtab = pTab ? &pTab->base : 0;
return rc;
}
+3 -1
View File
@@ -235,12 +235,14 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
}
if( pItem->pSelect ){
sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
if( pItem->pTab ){
Table *pTab = pItem->pTab;
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
}
assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
sqlite3TreeViewPop(&pView);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
@@ -344,7 +346,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
if( p->pLimit->pRight ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewItem(pView, "OFFSET", 0);
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
sqlite3TreeViewPop(&pView);
}
+68
View File
@@ -951,6 +951,72 @@ static ExprList *sqlite3ExpandReturning(
return pNew;
}
/* If the Expr node is a subquery or an EXISTS operator or an IN operator that
** uses a subquery, and if the subquery is SF_Correlated, then mark the
** expression as EP_VarSelect.
*/
static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){
UNUSED_PARAMETER(NotUsed);
if( ExprUseXSelect(pExpr)
&& (pExpr->x.pSelect->selFlags & SF_Correlated)!=0
){
testcase( ExprHasProperty(pExpr, EP_VarSelect) );
ExprSetProperty(pExpr, EP_VarSelect);
}
return WRC_Continue;
}
/*
** If the SELECT references the table pWalker->u.pTab, then do two things:
**
** (1) Mark the SELECT as as SF_Correlated.
** (2) Set pWalker->eCode to non-zero so that the caller will know
** that (1) has happened.
*/
static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
int i;
SrcList *pSrc;
assert( pSelect!=0 );
pSrc = pSelect->pSrc;
assert( pSrc!=0 );
for(i=0; i<pSrc->nSrc; i++){
if( pSrc->a[i].pTab==pWalker->u.pTab ){
testcase( pSelect->selFlags & SF_Correlated );
pSelect->selFlags |= SF_Correlated;
pWalker->eCode = 1;
break;
}
}
return WRC_Continue;
}
/*
** Scan the expression list that is the argument to RETURNING looking
** for subqueries that depend on the table which is being modified in the
** statement that is hosting the RETURNING clause (pTab). Mark all such
** subqueries as SF_Correlated. If the subqueries are part of an
** expression, mark the expression as EP_VarSelect.
**
** https://sqlite.org/forum/forumpost/2c83569ce8945d39
*/
static void sqlite3ProcessReturningSubqueries(
ExprList *pEList,
Table *pTab
){
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3ExprWalkNoop;
w.xSelectCallback = sqlite3ReturningSubqueryCorrelated;
w.u.pTab = pTab;
sqlite3WalkExprList(&w, pEList);
if( w.eCode ){
w.xExprCallback = sqlite3ReturningSubqueryVarSelect;
w.xSelectCallback = sqlite3SelectWalkNoop;
sqlite3WalkExprList(&w, pEList);
}
}
/*
** Generate code for the RETURNING trigger. Unlike other triggers
** that invoke a subprogram in the bytecode, the code for RETURNING
@@ -987,6 +1053,7 @@ static void codeReturningTrigger(
sSelect.pSrc = &sFrom;
sFrom.nSrc = 1;
sFrom.a[0].pTab = pTab;
sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
sFrom.a[0].iCursor = -1;
sqlite3SelectPrep(pParse, &sSelect, 0);
if( pParse->nErr==0 ){
@@ -1013,6 +1080,7 @@ static void codeReturningTrigger(
int i;
int nCol = pNew->nExpr;
int reg = pParse->nMem+1;
sqlite3ProcessReturningSubqueries(pNew, pTab);
pParse->nMem += nCol+2;
pReturning->iRetReg = reg;
for(i=0; i<nCol; i++){
+3
View File
@@ -921,6 +921,9 @@ void sqlite3Update(
}
}
if( chngRowid==0 && pPk==0 ){
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
#endif
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
}
}
+10 -6
View File
@@ -1152,7 +1152,9 @@ jump_to_p2:
**
** The instruction at the address in register P1 is a Yield.
** Jump to the P2 parameter of that Yield.
** After the jump, register P1 becomes undefined.
** After the jump, the value register P1 is left with a value
** such that subsequent OP_Yields go back to the this same
** OP_EndCoroutine instruction.
**
** See also: InitCoroutine
*/
@@ -1164,8 +1166,8 @@ case OP_EndCoroutine: { /* in1 */
pCaller = &aOp[pIn1->u.i];
assert( pCaller->opcode==OP_Yield );
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
pIn1->u.i = (int)(pOp - p->aOp) - 1;
pOp = &aOp[pCaller->p2 - 1];
pIn1->flags = MEM_Undefined;
break;
}
@@ -4582,7 +4584,8 @@ case OP_SequenceTest: {
** is the only cursor opcode that works with a pseudo-table.
**
** P3 is the number of fields in the records that will be stored by
** the pseudo-table.
** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
** will return NULL for every column.
*/
case OP_OpenPseudo: {
VdbeCursor *pCx;
@@ -6192,7 +6195,8 @@ case OP_Last: { /* jump0, ncycle */
**
** Let N be the approximate number of rows in the table or index
** with cursor P1 and let X be 10*log2(N) if N is positive or -1
** if N is zero. Thus X will be within the range of -1 to 640, inclusive
** if N is zero.
**
** Jump to P2 if X is in between P3 and P4, inclusive.
*/
case OP_IfSizeBetween: { /* jump */
@@ -6203,8 +6207,8 @@ case OP_IfSizeBetween: { /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_INT32 );
assert( pOp->p3>=-1 && pOp->p3<=640 );
assert( pOp->p4.i>=-1 && pOp->p4.i<=640 );
assert( pOp->p3>=-1 && pOp->p3<=640*2 );
assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->uc.pCursor;
+2 -1
View File
@@ -2404,7 +2404,6 @@ int sqlite3_stmt_scanstatus_v2(
}
if( flags & SQLITE_SCANSTAT_COMPLEX ){
idx = iScan;
pScan = &p->aScan[idx];
}else{
/* If the COMPLEX flag is clear, then this function must ignore any
** ScanStatus structures with ScanStatus.addrLoop set to 0. */
@@ -2417,6 +2416,8 @@ int sqlite3_stmt_scanstatus_v2(
}
}
if( idx>=p->nScan ) return 1;
assert( pScan==0 || pScan==&p->aScan[idx] );
pScan = &p->aScan[idx];
switch( iScanStatusOp ){
case SQLITE_SCANSTAT_NLOOP: {
+4 -4
View File
@@ -1949,10 +1949,10 @@ int sqlite3Stat4Column(
sqlite3_value **ppVal /* OUT: Extracted value */
){
u32 t = 0; /* a column type code */
int nHdr; /* Size of the header in the record */
int iHdr; /* Next unread header byte */
int iField; /* Next unread data byte */
int szField = 0; /* Size of the current data field */
u32 nHdr; /* Size of the header in the record */
u32 iHdr; /* Next unread header byte */
i64 iField; /* Next unread data byte */
u32 szField = 0; /* Size of the current data field */
int i; /* Column index */
u8 *a = (u8*)pRec; /* Typecast byte array */
Mem *pMem = *ppVal; /* Write result into this Mem object */
+2 -2
View File
@@ -286,10 +286,10 @@ static int bytecodevtabColumn(
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
case 9: /* nexec */
sqlite3_result_int(ctx, pOp->nExec);
sqlite3_result_int64(ctx, pOp->nExec);
break;
case 10: /* ncycle */
sqlite3_result_int(ctx, pOp->nCycle);
sqlite3_result_int64(ctx, pOp->nCycle);
break;
#else
case 9: /* nexec */
+20 -5
View File
@@ -813,12 +813,27 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Table *pTab;
Parse sParse;
int initBusy;
int i;
const unsigned char *z;
static const u8 aKeyword[] = { TK_CREATE, TK_TABLE, 0 };
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
/* Verify that the first two keywords in the CREATE TABLE statement
** really are "CREATE" and "TABLE". If this is not the case, then
** sqlite3_declare_vtab() is being misused.
*/
z = (const unsigned char*)zCreateTable;
for(i=0; aKeyword[i]; i++){
int tokenType = 0;
do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
if( tokenType!=aKeyword[i] ) return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
pCtx = db->pVtabCtx;
if( !pCtx || pCtx->bDeclared ){
@@ -826,6 +841,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE_BKPT;
}
pTab = pCtx->pTab;
assert( IsVirtual(pTab) );
@@ -839,11 +855,10 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
initBusy = db->init.busy;
db->init.busy = 0;
sParse.nQueryLoop = 1;
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable)
&& ALWAYS(sParse.pNewTable!=0)
&& ALWAYS(!db->mallocFailed)
&& IsOrdinaryTable(sParse.pNewTable)
){
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) ){
assert( sParse.pNewTable!=0 );
assert( !db->mallocFailed );
assert( IsOrdinaryTable(sParse.pNewTable) );
assert( sParse.zErrMsg==0 );
if( !pTab->aCol ){
Table *pNew = sParse.pNewTable;
+198 -34
View File
@@ -302,6 +302,42 @@ static Expr *whereRightSubexprIsColumn(Expr *p){
return 0;
}
/*
** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
** This function checks to see if the term is compatible with an index
** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
** or "NOCASE") used by the comparison in pTerm. If it is not compatible
** with affinity idxaff, NULL is returned.
*/
static SQLITE_NOINLINE const char *indexInAffinityOk(
Parse *pParse,
WhereTerm *pTerm,
u8 idxaff
){
Expr *pX = pTerm->pExpr;
Expr inexpr;
assert( pTerm->eOperator & WO_IN );
if( sqlite3ExprIsVector(pX->pLeft) ){
int iField = pTerm->u.x.iField - 1;
inexpr.flags = 0;
inexpr.op = TK_EQ;
inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
assert( ExprUseXSelect(pX) );
inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
pX = &inexpr;
}
if( sqlite3IndexAffinityOk(pX, idxaff) ){
CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
return pRet ? pRet->zName : sqlite3StrBINARY;
}
return 0;
}
/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
@@ -352,16 +388,24 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
if( (pTerm->eOperator & pScan->opMask)!=0 ){
/* Verify the affinity and collating sequence match */
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
CollSeq *pColl;
const char *zCollName;
Parse *pParse = pWC->pWInfo->pParse;
pX = pTerm->pExpr;
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
continue;
if( (pTerm->eOperator & WO_IN) ){
zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
if( !zCollName ) continue;
}else{
CollSeq *pColl;
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
continue;
}
assert(pX->pLeft);
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
}
assert(pX->pLeft);
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
if( sqlite3StrICmp(zCollName, pScan->zCollName) ){
continue;
}
}
@@ -713,9 +757,13 @@ static void translateColumnToCopy(
** are no-ops.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
static void whereTraceIndexInfoInputs(
sqlite3_index_info *p, /* The IndexInfo object */
Table *pTab /* The TABLE that is the virtual table */
){
int i;
if( (sqlite3WhereTrace & 0x10)==0 ) return;
sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName);
for(i=0; i<p->nConstraint; i++){
sqlite3DebugPrintf(
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
@@ -733,9 +781,13 @@ static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
p->aOrderBy[i].desc);
}
}
static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
static void whereTraceIndexInfoOutputs(
sqlite3_index_info *p, /* The IndexInfo object */
Table *pTab /* The TABLE that is the virtual table */
){
int i;
if( (sqlite3WhereTrace & 0x10)==0 ) return;
sqlite3DebugPrintf("sqlite3_index_info outputs for %s:\n", pTab->zName);
for(i=0; i<p->nConstraint; i++){
sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
i,
@@ -749,8 +801,8 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
}
#else
#define whereTraceIndexInfoInputs(A)
#define whereTraceIndexInfoOutputs(A)
#define whereTraceIndexInfoInputs(A,B)
#define whereTraceIndexInfoOutputs(A,B)
#endif
/*
@@ -934,7 +986,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
){
pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0));
@@ -976,7 +1028,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
** if they go out of sync.
*/
if( IsView(pTable) ){
extraCols = ALLBITS;
extraCols = ALLBITS & ~idxCols;
}else{
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
}
@@ -1203,7 +1255,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0)
){
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
}
@@ -1493,11 +1545,11 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int rc;
whereTraceIndexInfoInputs(p);
whereTraceIndexInfoInputs(p, pTab);
pParse->db->nSchemaLock++;
rc = pVtab->pModule->xBestIndex(pVtab, p);
pParse->db->nSchemaLock--;
whereTraceIndexInfoOutputs(p);
whereTraceIndexInfoOutputs(p, pTab);
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
if( rc==SQLITE_NOMEM ){
@@ -3244,10 +3296,13 @@ static int whereLoopAddBtreeIndex(
}
}
/* Set rCostIdx to the cost of visiting selected rows in index. Add
** it to pNew->rRun, which is currently set to the cost of the index
** seek only. Then, if this is a non-covering index, add the cost of
** visiting the rows in the main table. */
/* Set rCostIdx to the estimated cost of visiting selected rows in the
** index. The estimate is the sum of two values:
** 1. The cost of doing one search-by-key to find the first matching
** entry
** 2. Stepping forward in the index pNew->nOut times to find all
** additional matching entries.
*/
assert( pSrc->pTab->szTabRow>0 );
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
/* The pProbe->szIdxRow is low for an IPK table since the interior
@@ -3258,7 +3313,15 @@ static int whereLoopAddBtreeIndex(
}else{
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
}
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
/* Estimate the cost of running the loop. If all data is coming
** from the index, then this is just the cost of doing the index
** lookup and scan. But if some data is coming out of the main table,
** we also have to add in the cost of doing pNew->nOut searches to
** locate the row in the main table that corresponds to the index entry.
*/
pNew->rRun = rCostIdx;
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
}
@@ -3994,6 +4057,21 @@ static int isLimitTerm(WhereTerm *pTerm){
&& pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
}
/*
** Return true if the first nCons constraints in the pUsage array are
** marked as in-use (have argvIndex>0). False otherwise.
*/
static int allConstraintsUsed(
struct sqlite3_index_constraint_usage *aUsage,
int nCons
){
int ii;
for(ii=0; ii<nCons; ii++){
if( aUsage[ii].argvIndex<=0 ) return 0;
}
return 1;
}
/*
** Argument pIdxInfo is already populated with all constraints that may
** be used by the virtual table identified by pBuilder->pNew->iTab. This
@@ -4134,13 +4212,20 @@ static int whereLoopAddVirtualOne(
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
/* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET
** terms. And if there are any, they should follow all other terms. */
assert( pbRetryLimit || !isLimitTerm(pTerm) );
if( isLimitTerm(pTerm) && *pbIn ){
assert( !isLimitTerm(pTerm) || i>=nConstraint-2 );
assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) );
if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){
/* If there is an IN(...) term handled as an == (separate call to
** xFilter for each value on the RHS of the IN) and a LIMIT or
** OFFSET term handled as well, the plan is unusable. Set output
** variable *pbRetryLimit to true to tell the caller to retry with
** LIMIT and OFFSET disabled. */
** OFFSET term handled as well, the plan is unusable. Similarly,
** if there is a LIMIT/OFFSET and there are other unused terms,
** the plan cannot be used. In these cases set variable *pbRetryLimit
** to true to tell the caller to retry with LIMIT and OFFSET
** disabled. */
if( pIdxInfo->needToFreeIdxStr ){
sqlite3_free(pIdxInfo->idxStr);
pIdxInfo->idxStr = 0;
@@ -5511,7 +5596,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}
}
pWInfo->nRowOut = pFrom->nRow;
/* Free temporary memory and return success */
@@ -5519,6 +5603,83 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
return SQLITE_OK;
}
/*
** This routine implements a heuristic designed to improve query planning.
** This routine is called in between the first and second call to
** wherePathSolver(). Hence the name "Interstage" "Heuristic".
**
** The first call to wherePathSolver() (hereafter just "solver()") computes
** the best path without regard to the order of the outputs. The second call
** to the solver() builds upon the first call to try to find an alternative
** path that satisfies the ORDER BY clause.
**
** This routine looks at the results of the first solver() run, and for
** every FROM clause term in the resulting query plan that uses an equality
** constraint against an index, disable other WhereLoops for that same
** FROM clause term that would try to do a full-table scan. This prevents
** an index search from being converted into a full-table scan in order to
** satisfy an ORDER BY clause, since even though we might get slightly better
** performance using the full-scan without sorting if the output size
** estimates are very precise, we might also get severe performance
** degradation using the full-scan if the output size estimate is too large.
** It is better to err on the side of caution.
**
** Except, if the first solver() call generated a full-table scan in an outer
** loop then stop this analysis at the first full-scan, since the second
** solver() run might try to swap that full-scan for another in order to
** get the output into the correct order. In other words, we allow a
** rewrite like this:
**
** First Solver() Second Solver()
** |-- SCAN t1 |-- SCAN t2
** |-- SEARCH t2 `-- SEARCH t1
** `-- SORT USING B-TREE
**
** The purpose of this routine is to disallow rewrites such as:
**
** First Solver() Second Solver()
** |-- SEARCH t1 |-- SCAN t2 <--- bad!
** |-- SEARCH t2 `-- SEARCH t1
** `-- SORT USING B-TREE
**
** See test cases in test/whereN.test for the real-world query that
** originally provoked this heuristic.
*/
static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){
int i;
#ifdef WHERETRACE_ENABLED
int once = 0;
#endif
for(i=0; i<pWInfo->nLevel; i++){
WhereLoop *p = pWInfo->a[i].pWLoop;
if( p==0 ) break;
if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;
if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
u8 iTab = p->iTab;
WhereLoop *pLoop;
for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
if( pLoop->iTab!=iTab ) continue;
if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
/* Auto-index and index-constrained loops allowed to remain */
continue;
}
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x80 ){
if( once==0 ){
sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n");
once = 1;
}
sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC);
}
#endif /* WHERETRACE_ENABLED */
pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */
}
}else{
break;
}
}
}
/*
** Most queries use only a single table (they are not joins) and have
** simple == constraints against indexed fields. This routine attempts
@@ -5853,16 +6014,10 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
for(i=0; i<pIdx->nColumn; i++){
Expr *pExpr;
int j = pIdx->aiColumn[i];
int bMaybeNullRow;
if( j==XN_EXPR ){
pExpr = pIdx->aColExpr->a[i].pExpr;
testcase( pTabItem->fg.jointype & JT_LEFT );
testcase( pTabItem->fg.jointype & JT_RIGHT );
testcase( pTabItem->fg.jointype & JT_LTORJ );
bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
bMaybeNullRow = 0;
}else{
continue;
}
@@ -5894,7 +6049,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
p->iDataCur = pTabItem->iCursor;
p->iIdxCur = iIdxCur;
p->iIdxCol = i;
p->bMaybeNullRow = bMaybeNullRow;
p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
p->aff = pIdx->zColAff[i];
}
@@ -6301,6 +6456,7 @@ WhereInfo *sqlite3WhereBegin(
wherePathSolver(pWInfo, 0);
if( db->mallocFailed ) goto whereBeginError;
if( pWInfo->pOrderBy ){
whereInterstageHeuristic(pWInfo);
wherePathSolver(pWInfo, pWInfo->nRowOut+1);
if( db->mallocFailed ) goto whereBeginError;
}
@@ -6850,7 +7006,15 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
if( (ws & WHERE_IDX_ONLY)==0 ){
assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
SrcItem *pSrc = &pTabList->a[pLevel->iFrom];
assert( pLevel->iTabCur==pSrc->iCursor );
if( pSrc->fg.viaCoroutine ){
int m, n;
n = pSrc->regResult;
assert( pSrc->pTab!=0 );
m = pSrc->pTab->nCol;
sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
}
if( (ws & WHERE_INDEXED)
+15
View File
@@ -2474,6 +2474,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** iLoop==3: Code all remaining expressions.
**
** An effort is made to skip unnecessary iterations of the loop.
**
** This optimization of causing simple query restrictions to occur before
** more complex one is call the "push-down" optimization in MySQL. Here
** in SQLite, the name is "MySQL push-down", since there is also another
** totally unrelated optimization called "WHERE-clause push-down".
** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
*/
iLoop = (pIdx ? 1 : 2);
do{
@@ -2724,7 +2730,16 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
pRJ->regReturn);
for(k=0; k<iLevel; k++){
int iIdxCur;
SrcItem *pRight;
assert( pWInfo->a[k].pWLoop->iTab == pWInfo->a[k].iFrom );
pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
mAll |= pWInfo->a[k].pWLoop->maskSelf;
if( pRight->fg.viaCoroutine ){
sqlite3VdbeAddOp3(
v, OP_Null, 0, pRight->regResult,
pRight->regResult + pRight->pSelect->pEList->nExpr-1
);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
iIdxCur = pWInfo->a[k].iIdxCur;
if( iIdxCur ){
+6 -3
View File
@@ -1638,6 +1638,7 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
continue;
}
if( pWC->a[ii].leftCursor!=iCsr ) return;
if( pWC->a[ii].prereqRight!=0 ) return;
}
/* Check condition (5). Return early if it is not met. */
@@ -1652,12 +1653,14 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
/* All conditions are met. Add the terms to the where-clause object. */
assert( p->pLimit->op==TK_LIMIT );
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
if( p->iOffset>0 ){
if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){
whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
}
if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
}
}
}
+23
View File
@@ -763,4 +763,27 @@ do_execsql_test 30.2 {
)}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 31.0 {
CREATE TABLE t1(ii INTEGER PRIMARY KEY, tt INTEGER, rr REAL);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
)
INSERT INTO t1 SELECT NULL, i, 5.0 FROM s;
}
do_test 31.1 {
set pg [db one {PRAGMA page_count}]
execsql {
ALTER TABLE t1 DROP COLUMN tt;
}
set pg2 [db one {PRAGMA page_count}]
expr $pg==$pg2
} {1}
do_execsql_test 31.2 {
SELECT rr FROM t1 LIMIT 1
} {5.0}
finish_test
+1 -1
View File
@@ -158,7 +158,7 @@ do_test 2.2 {
set ::lFilterArgs [list]
execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 }
set ::lFilterArgs
} {{5 50}}
} {{50 5}}
do_test 2.3 {
set ::lFilterArgs [list]
+178
View File
@@ -0,0 +1,178 @@
# 2024-04-26
#
# 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.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix bestindexC
ifcapable !vtab {
finish_test
return
}
register_tcl_module db
proc vtab_command {lVal method args} {
switch -- $method {
xConnect {
return "CREATE TABLE t1(a)"
}
xBestIndex {
set hdl [lindex $args 0]
set clist [$hdl constraints]
set orderby [$hdl orderby]
set idxstr [list]
set res [list]
set idx 0
foreach c $clist {
array set a $c
if {$a(usable)==0} continue
if {$a(op)=="limit" && ![info exists ::do_not_use_limit]} {
lappend idxstr limit
lappend res omit $idx
}
if {$a(op)=="offset" && ![info exists ::do_not_use_offset]} {
lappend idxstr offset
lappend res omit $idx
}
incr idx
}
return "cost 1000000 rows 1000000 idxnum 0 idxstr {$idxstr} $res"
}
xFilter {
set idxstr [lindex $args 1]
set LIMIT ""
foreach a $idxstr b [lindex $args 2] {
set x($a) $b
}
if {![info exists x(limit)]} { set x(limit) -1 }
if {![info exists x(offset)]} { set x(offset) -1 }
set LIMIT " LIMIT $x(limit) OFFSET $x(offset)"
set idx 1
foreach v $lVal {
lappend lRow "($idx, '$v')"
incr idx
}
return [list sql "
SELECT * FROM ( VALUES [join $lRow ,]) $LIMIT
"]
}
}
return {}
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f");
CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "A B C D E F a b");
} {}
do_execsql_test 1.1 {
CREATE TEMP TABLE t_unionall AS
SELECT * FROM x1 UNION ALL SELECT * FROM x2;
CREATE TEMP TABLE t_intersect AS
SELECT * FROM x1 INTERSECT SELECT * FROM x2;
CREATE TEMP TABLE t_union AS
SELECT * FROM x1 UNION SELECT * FROM x2;
CREATE TEMP TABLE t_except AS
SELECT * FROM x1 EXCEPT SELECT * FROM x2;
}
foreach {tn limit} {
1 "LIMIT 8"
2 "LIMIT 4"
3 "LIMIT 4 OFFSET 2"
4 "LIMIT 8 OFFSET 4"
} {
foreach {op tbl} {
"UNION ALL" t_unionall
"UNION" t_union
"INTERSECT" t_intersect
"EXCEPT" t_except
} {
set expect [execsql "SELECT * FROM $tbl $limit"]
do_execsql_test 1.2.$tbl.$tn "SELECT * FROM (
SELECT * FROM x1 $op SELECT * FROM x2
) $limit" $expect
}
}
#-------------------------------------------------------------------------
reset_db
register_tcl_module db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f");
CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "a b e f");
} {}
do_execsql_test 2.1 {
SELECT * FROM x1
EXCEPT
SELECT * FROM x2
LIMIT 3
} {c d}
#-------------------------------------------------------------------------
reset_db
register_tcl_module db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "1 2 3 4 5 6 7 8 9 10");
} {}
do_execsql_test 3.1 {
SELECT * FROM y1 WHERE a = COALESCE('8', a) LIMIT 3
} {8}
do_execsql_test 3.2 {
SELECT * FROM y1 WHERE a = '2' LIMIT 3
} {2}
load_static_extension db series
do_execsql_test 3.3 {
SELECT * FROM generate_series(1, 5) WHERE value = (value & 14) LIMIT 3
} {2 4}
do_execsql_test 3.4 {
SELECT value FROM generate_series(1,10) WHERE value>2 LIMIT 4 OFFSET 1;
} {4 5 6 7}
set ::do_not_use_limit 1
do_execsql_test 3.5 {
SELECT * FROM y1 LIMIT 5 OFFSET 3
} {4 5 6 7 8}
unset ::do_not_use_limit
set ::do_not_use_offset 1
do_execsql_test 3.6 {
SELECT * FROM y1 LIMIT 5 OFFSET 3
} {4 5 6 7 8}
unset ::do_not_use_offset
finish_test
+85
View File
@@ -1505,4 +1505,89 @@ do_catchsql_test 19.4 {
PRAGMA integrity_check;
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 18.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 20480 pagesize 4096 filename crash-a4150b729051e4.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 04 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 64: 00 00 00 00 00 00 00 00 00 00 ff f0 00 00 00 00 ................
| 96: 00 00 00 00 0d 00 00 00 04 0e e5 00 0f c2 0f 75 ...............u
| 112: 0f 19 0e e5 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 3808: 00 00 00 00 00 32 04 06 17 17 11 01 4b 69 6e 64 .....2......Kind
| 3824: 65 78 74 31 61 62 63 74 31 05 43 52 45 41 54 45 ext1abct1.CREATE
| 3840: 20 49 4e 44 45 58 20 74 31 61 62 63 20 4f 4e 20 INDEX t1abc ON
| 3856: 74 31 28 61 2c 62 2c 63 29 5a 03 06 17 25 25 01 t1(a,b,c)Z...%%.
| 3872: 79 74 61 62 6c 65 73 71 6c 69 74 65 5f 73 74 61 ytablesqlite_sta
| 3888: 74 34 73 71 6c 69 74 65 5f 73 74 61 74 34 04 43 t4sqlite_stat4.C
| 3904: 52 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c 69 REATE TABLE sqli
| 3920: 74 65 5f 73 74 61 74 34 28 74 62 6c 2c 69 64 78 te_stat4(tbl,idx
| 3936: 2c 6e 65 71 2c 6e 6c 74 2c 6e 64 6c 74 2c 73 61 ,neq,nlt,ndlt,sa
| 3952: 6d 70 6c 65 29 4b 02 06 17 25 25 01 5b 74 61 62 mple)K...%%.[tab
| 3968: 6c 65 73 71 6c 69 74 65 5f 73 74 61 74 31 73 71 lesqlite_stat1sq
| 3984: 6c 69 74 65 5f 73 74 61 74 31 03 43 52 45 41 54 lite_stat1.CREAT
| 4000: 45 20 54 41 42 4c 45 20 73 71 6c 69 74 65 5f 73 E TABLE sqlite_s
| 4016: 74 61 74 31 28 74 62 6c 2c 69 64 78 2c 73 74 61 tat1(tbl,idx,sta
| 4032: 74 29 3c 01 06 17 11 11 01 65 74 61 62 6c 65 74 t)<......etablet
| 4048: 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 1t1.CREATE TABLE
| 4064: 20 74 31 28 61 20 54 45 58 54 2c 20 62 20 49 4e t1(a TEXT, b IN
| 4080: 54 2c 20 63 20 49 4e 54 2c 20 64 20 49 4e 54 29 T, c INT, d INT)
| page 2 offset 4096
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4000: 0b 07 05 13 01 01 01 62 63 64 64 06 0b 0c 06 05 .......bcdd.....
| 4016: 13 02 01 01 64 65 66 01 59 09 0a 0c 05 05 13 03 ....def.Y.......
| 4032: 01 01 64 65 66 02 6f 08 09 0c 04 05 13 02 01 01 ..def.o.........
| 4048: 61 62 63 01 59 07 08 0c 03 05 13 02 01 01 87 62 abc.Y..........b
| 4064: 63 00 ea 06 07 0c 02 05 13 02 01 01 61 62 63 00 c...........abc.
| 4080: ea 06 06 0b 01 05 13 01 01 01 61 62 63 7b 04 04 ..........abc...
| page 3 offset 8192
| 0: 0d 00 00 00 01 0f e0 00 0f e1 00 00 00 00 00 00 ................
| 4064: 00 1d 01 04 11 17 31 74 31 74 31 61 62 63 31 30 ......1t1t1abc10
| 4080: 30 30 30 20 35 30 30 30 20 32 30 30 30 20 31 30 000 5000 2000 10
| page 4 offset 12288
| 0: 0d 00 00 00 07 0e ac 00 0f d1 0f a0 0f 6f 0f 3e .............o.>
| 16: 0f 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3744: 00 00 00 00 00 00 00 00 00 00 00 00 2f 07 07 11 ............/...
| 3760: 17 1b 1b 1b 24 74 31 74 31 61 62 63 32 20 31 20 ....$t1t1abc2 1
| 3776: 31 20 31 35 20 36 20 36 20 36 32 20 35 20 36 20 1 15 6 6 62 5 6
| 3792: 36 05 13 02 01 01 64 65 66 02 37 08 05 2f 06 07 6.....def.7../..
| 3808: 11 17 1b 1b 1b 24 74 41 74 31 61 62 63 32 20 31 .....$tAt1abc2 1
| 3824: 20 31 20 31 35 20 35 20 55 20 35 32 20 34 20 35 1 15 5 U 52 4 5
| 3840: 20 35 05 13 02 01 01 64 65 66 01 59 09 06 2e 05 5.....def.Y....
| 3856: 07 11 17 1b 1b 1b 22 74 31 74 31 61 62 63 31 20 .......t1t1abc1
| 3872: 31 20 31 20 31 34 20 34 20 34 20 34 31 20 33 20 1 1 14 4 4 41 3
| 3888: 34 20 34 08 b3 cd f0 f1 62 63 64 64 06 07 2f 05 4 4.....bcdd../.
| 3904: 07 11 17 1b 1b 1b 24 74 37 74 31 61 62 63 34 20 ......$t7t1abc4
| 3920: 31 20 31 20 31 30 20 33 20 33 20 33 30 20 32 20 1 1 10 3 3 30 2
| 3936: 33 20 33 05 13 02 01 01 61 62 63 01 59 07 04 2f 3 3.....abc.Y../
| 3952: 03 07 11 17 1b 1b 1b 24 74 31 74 31 61 62 63 34 .......$t1t1abc4
| 3968: 20 32 20 31 20 31 30 20 31 20 32 20 32 30 20 31 2 1 10 1 2 20 1
| 3984: 20 32 20 32 05 13 02 01 01 61 62 63 00 ea 06 03 2 2.....abc....
| 4000: 2f 02 07 11 17 1b 1b 1b 24 74 31 74 31 61 62 63 /.......$t1t1abc
| 4016: 34 20 32 20 31 20 31 30 20 31 20 31 20 31 30 20 4 2 1 10 1 1 10
| 4032: 31 20 31 20 31 05 13 02 01 01 61 62 63 00 ea 05 1 1 1.....abc...
| 4048: 02 2d 01 07 11 17 1b 1b 1b 20 74 31 74 31 61 62 .-....... t1t1ab
| 4064: 63 34 20 31 20 31 20 31 30 20 30 20 30 1f 30 30 c4 1 1 10 0 0.00
| 4080: 20 30 20 30 20 30 05 13 01 01 09 61 62 63 7b 04 0 0 0.....abc..
| page 5 offset 16384
| 0: 0a 00 00 00 07 0f a8 00 0f f5 00 00 00 00 00 00 ................
| 4000: 00 00 00 00 00 00 00 00 0c 05 13 02 01 01 64 65 ..............de
| 4016: 66 02 37 08 05 0c 05 13 02 01 01 64 65 66 01 59 f.7........def.Y
| 4032: 09 06 0b 05 12 01 01 01 62 63 64 64 06 07 0c 05 ........bcdd....
| 4048: 13 02 01 01 61 62 63 01 59 07 01 2c 05 13 02 01 ....abc.Y..,....
| 4064: 01 61 62 63 00 ea 06 03 0c 05 13 02 01 01 61 62 .abc..........ab
| 4080: 63 00 ea 05 00 00 00 00 00 00 00 00 00 00 00 00 c...............
| end crash-a4150b729051e4.db
}]} {}
do_catchsql_test 18.1 {
SELECT a FROM t1 WHERE b GLOB b AND b GLOB '0^x]␅6␚xz]';
} {1 {database disk image is malformed}}
finish_test
+1 -1
View File
@@ -103,7 +103,7 @@ do_eqp_test 5.2 {
} {
QUERY PLAN
|--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--USE TEMP B-TREE FOR LAST TERM OF ORDER BY
}
do_eqp_test 5.3 {
+5 -1
View File
@@ -135,6 +135,10 @@ reset_db
do_catchsql_test default-5.1 {
CREATE TABLE t1 (a,b DEFAULT(random() NOTNULL IN (RAISE(IGNORE),2,3)));
INSERT INTO t1(a) VALUES(1);
} {1 {RAISE() may only be used within a trigger-program}}
} {1 {default value of column [b] is not constant}}
do_catchsql_test default-5.2 {
CREATE TABLE Table0 (Col0 DEFAULT (RAISE(IGNORE) ) ) ;
INSERT INTO Table0 DEFAULT VALUES ;
} {1 {default value of column [Col0] is not constant}}
finish_test
+3 -3
View File
@@ -413,7 +413,7 @@ do_eqp_test 4.2.3 {
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
|--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY
}
do_eqp_test 4.2.4 {
SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1
@@ -425,7 +425,7 @@ do_eqp_test 4.2.4 {
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
|--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY
}
do_eqp_test 4.2.5 {
SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1
@@ -437,7 +437,7 @@ do_eqp_test 4.2.5 {
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
|--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY
}
do_eqp_test 4.3.1 {
+49
View File
@@ -0,0 +1,49 @@
# 2024 March 20
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix eqp2
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c, d);
CREATE INDEX i1 ON t1(a, b, c);
}
do_eqp_test 1.1 {
SELECT * FROM t1 ORDER BY a, b, c
} {
QUERY PLAN
`--SCAN t1 USING INDEX i1
}
do_eqp_test 1.2 {
SELECT * FROM t1 ORDER BY a, b, +c
} {
QUERY PLAN
|--SCAN t1 USING INDEX i1
`--USE TEMP B-TREE FOR LAST TERM OF ORDER BY
}
do_eqp_test 1.3 {
SELECT * FROM t1 ORDER BY a, +b, +c
} {
QUERY PLAN
|--SCAN t1 USING INDEX i1
`--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY
}
finish_test
+11
View File
@@ -55,5 +55,16 @@ do_execsql_test 2.2 {
'(def AND (one NEAR abc)) OR one'
} {<b>one</b>}
#-------------------------------------------------------------------------
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE f USING fts3(a,b);
INSERT INTO f VALUES (101,x'056522650565056505650d051e056505650565286505650565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056f05650565056505650565056505650565050565056505640565056505650565056505651e05650565056505650565056505650505656565056505650565056505651e0565056505650565056505650565052265056505650569056505650565056505650565056505650565056505650500406505650565056505650565056505000101e5c501014b010101c501c5c501010101f5010201010101014101017373737373737373737373737373737373737373737373737373737330737373737373737373737373737365056505650d051e05650565056528056505650d05650505656505650565650565056505650565056505e505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565286505c705650565050565059494949494949494949494949494949494949494949494949494949494949494949494650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650505650565056505650565056505650565056500000000000000000000000000000000000000000000000000000000000000000565056505656505650565056505650d056500000000000000000000000000000000000000000000000000000000000000000100000000000000ed0000000000ffffffffffffffffffffff0007ffffff0001c5c50001c5c50001c5c50001c5c50001c5c50001c5c50001e5c50001c5c50001c5c50001c5c50001c5c50001c5c5000100000014720000000000000016dac5c50001c5c50001c5c50001c5c50001c5c50001c5c50d0505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800465056505650565056505651e650565056505650565056505650d05650505656505650565050565650584058005650565056505650565056505650565056522650565056505650d051e056505650561286505c70565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef650565058405056505650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650565226505737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373733a73737373737373737373737373737373737373737373737373737373737373737373737373737373737c7373737365056505650d051e05650565056528650565056505650505650565056505650565056505650565056505e505650565056505656505650565056505650d05650505656505650565ef65056505');
}
do_execsql_test 3.1 {
SELECT length(snippet(f)) FROM f WHERE b MATCH x'0565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056505650565056505650565056505650565050565056505640565056505650565056505651e05650565056522650565056505650d051e056505650565286505650565056505056505650565056505650565056505650565056505650565056505656505650565056505650d05650505656505650565ef65056505844c746e65650565056505650565056505650565056505650565058405800565056505650565056505651e650565056505650565056505650d056505056565056505650565056505840580056505650565056f05650565056505650565056505650565050565056505640565056505650565056505651e05650565056505650565056505650505656565056505650565056505651e0565056505650565056505650565052265056505650569056505650565056505650565056505650565056505650500406505650565056505650565056505000101e5c501014b010101c501c5c501010101f50102010101010141010141010001017bf15905000000000017';
} {192}
set sqlite_fts3_enable_parentheses 0
finish_test
+23
View File
@@ -508,4 +508,27 @@ do_test func2-3.9.2 {
bin_to_hex [lindex $blob 0]
} "12"
#-------------------------------------------------------------------------
# At one point this was extremely slow to compile.
#
do_test func2-3.10 {
set tm [time {
execsql {
SELECT '' IN (zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(
zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(zerobloB(1)
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
}
}]
set tm [lindex $tm 0]
expr $tm<2000000
} {1}
finish_test
+11 -5
View File
@@ -979,7 +979,8 @@ extern int fuzz_invariant(
int iRow, /* The row number for pStmt */
int nRow, /* Total number of output rows */
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
int eVerbosity /* How much debugging output */
int eVerbosity, /* How much debugging output */
unsigned int dbOpt /* Default optimization flags */
);
/* Implementation of sqlite_dbdata and sqlite_dbptr */
@@ -1031,7 +1032,12 @@ static int recoverDatabase(sqlite3 *db){
/*
** Run the SQL text
*/
static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
static int runDbSql(
sqlite3 *db, /* Run SQL on this database connection */
const char *zSql, /* The SQL to be run */
unsigned int *pBtsFlags,
unsigned int dbOpt /* Default optimization flags */
){
int rc;
sqlite3_stmt *pStmt;
int bCorrupt = 0;
@@ -1107,7 +1113,7 @@ static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
iRow++;
for(iCnt=0; iCnt<99999; iCnt++){
rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow,
&bCorrupt, eVerbosity);
&bCorrupt, eVerbosity, dbOpt);
if( rc==SQLITE_DONE ) break;
if( rc!=SQLITE_ERROR ) g.nInvariant++;
if( eVerbosity>0 ){
@@ -1330,7 +1336,7 @@ int runCombinedDbSqlInput(
char cSaved = zSql[i+1];
zSql[i+1] = 0;
if( sqlite3_complete(zSql+j) ){
rc = runDbSql(cx.db, zSql+j, &btsFlags);
rc = runDbSql(cx.db, zSql+j, &btsFlags, dbOpt);
j = i+1;
}
zSql[i+1] = cSaved;
@@ -1340,7 +1346,7 @@ int runCombinedDbSqlInput(
}
}
if( j<i ){
runDbSql(cx.db, zSql+j, &btsFlags);
runDbSql(cx.db, zSql+j, &btsFlags, dbOpt);
}
}
testrun_finished:
+24 -15
View File
@@ -30,7 +30,13 @@
/* Forward references */
static char *fuzz_invariant_sql(sqlite3_stmt*, int);
static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int,sqlite3_stmt*);
static void reportInvariantFailed(sqlite3_stmt*,sqlite3_stmt*,int);
static void reportInvariantFailed(
sqlite3_stmt *pOrig, /* The original query */
sqlite3_stmt *pTest, /* The alternative test query with a missing row */
int iRow, /* Row number in pOrig */
unsigned int dbOpt, /* Optimization flags on pOrig */
int noOpt /* True if opt flags inverted for pTest */
);
/*
** Do an invariant check on pStmt. iCnt determines which invariant check to
@@ -68,7 +74,8 @@ int fuzz_invariant(
int iRow, /* Current row number */
int nRow, /* Number of output rows from pStmt */
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
int eVerbosity /* How much debugging output */
int eVerbosity, /* How much debugging output */
unsigned int dbOpt /* Default optimization flags */
){
char *zTest;
sqlite3_stmt *pTestStmt = 0;
@@ -76,13 +83,20 @@ int fuzz_invariant(
int i;
int nCol;
int nParam;
int noOpt = (iCnt%3)==0;
if( *pbCorrupt ) return SQLITE_DONE;
nParam = sqlite3_bind_parameter_count(pStmt);
if( nParam>100 ) return SQLITE_DONE;
zTest = fuzz_invariant_sql(pStmt, iCnt);
if( zTest==0 ) return SQLITE_DONE;
if( noOpt ){
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, ~dbOpt);
}
rc = sqlite3_prepare_v2(db, zTest, -1, &pTestStmt, 0);
if( noOpt ){
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, dbOpt);
}
if( rc ){
if( eVerbosity ){
printf("invariant compile failed: %s\n%s\n",
@@ -212,7 +226,7 @@ int fuzz_invariant(
}
sqlite3_finalize(pCk);
if( rc==SQLITE_DONE ){
reportInvariantFailed(pStmt, pTestStmt, iRow);
reportInvariantFailed(pStmt, pTestStmt, iRow, dbOpt, noOpt);
return SQLITE_INTERNAL;
}else if( eVerbosity>0 ){
printf("invariant-error ignored due to the use of virtual tables\n");
@@ -223,7 +237,6 @@ not_a_fault:
return SQLITE_OK;
}
/*
** Generate SQL used to test a statement invariant.
**
@@ -296,14 +309,6 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
** WHERE clause. */
continue;
}
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( sqlite3_strlike("%rowid%",zColName,0)==0
|| sqlite3_strlike("%oid%",zColName,0)==0
){
/* ROWID values are unreliable if SQLITE_ALLOW_ROWID_IN_VIEW is used */
continue;
}
#endif
for(j=0; j<i; j++){
const char *zPrior = sqlite3_column_name(pBase, j);
if( sqlite3_stricmp(zPrior, zColName)==0 ) break;
@@ -497,13 +502,17 @@ static void printRow(sqlite3_stmt *pStmt, int iRow){
static void reportInvariantFailed(
sqlite3_stmt *pOrig, /* The original query */
sqlite3_stmt *pTest, /* The alternative test query with a missing row */
int iRow /* Row number in pOrig */
int iRow, /* Row number in pOrig */
unsigned int dbOpt, /* Optimization flags on pOrig */
int noOpt /* True if opt flags inverted for pTest */
){
int iTestRow = 0;
printf("Invariant check failed on row %d.\n", iRow);
printf("Original query --------------------------------------------------\n");
printf("Original query (opt-flags: 0x%08x) --------------------------\n",
dbOpt);
printf("%s\n", sqlite3_expanded_sql(pOrig));
printf("Alternative query -----------------------------------------------\n");
printf("Alternative query (opt-flags: 0x%08x) -----------------------\n",
noOpt ? ~dbOpt : dbOpt);
printf("%s\n", sqlite3_expanded_sql(pTest));
printf("Result row that is missing from the alternative -----------------\n");
printRow(pOrig, iRow);
+17 -1
View File
@@ -149,7 +149,7 @@ ifcapable icu {
# 2020-03-19
# The ESCAPE clause on LIKE takes precedence over wildcards
#
do_execsql_test idu-6.0 {
do_execsql_test icu-6.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT);
INSERT INTO t1 VALUES
@@ -164,4 +164,20 @@ do_execsql_test icu-6.1 {
SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_';
} {2}
# 2024-04-02
# Optional 3rd argument to icu_load_collation() that specifies
# the "strength" of comparison.
#
reset_db
do_catchsql_test icu-7.1 {
SELECT icu_load_collation('en_US','error','xyzzy');
} {1 {unknown collation strength "xyzzy" - should be one of: PRIMARY SECONDARY TERTIARY DEFAULT QUARTERNARY IDENTICAL}}
do_execsql_test icu-7.2 {
SELECT icu_load_collation('en_US','prim','PRIMARY'),
icu_load_collation('en_US','dflt','DEFAULT');
} {{} {}}
do_execsql_test icu-7.3 {
SELECT char(0x100)=='a', char(0x100)=='a' COLLATE dflt, char(0x100)=='a' COLLATE prim;
} {0 0 1}
finish_test
+22
View File
@@ -266,4 +266,26 @@ do_execsql_test 9.2 {
SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500');
} {1e500}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 10.0 {
CREATE TABLE t1(a, b TEXT COLLATE NOCASE);
INSERT INTO t1 VALUES('abc', 'def');
INSERT INTO t1 VALUES('ghi', 'jkl');
}
do_execsql_test 10.1 {
SELECT rowid FROM t1 WHERE (a, b) IN ( VALUES('abc', 'def'), ('ghi', 'JKL') );
} {1 2}
do_execsql_test 10.2 {
CREATE INDEX i1 ON t1(a, b COLLATE BINARY);
}
do_execsql_test 10.3 {
SELECT rowid FROM t1 WHERE (a, b) IN ( VALUES('abc', 'def'), ('ghi', 'JKL') );
} {1 2}
finish_test
+32
View File
@@ -309,4 +309,36 @@ do_execsql_test 12.3 {
SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1;
}
#-------------------------------------------------------------------------
# 2024-04-05 dbsqlfuzz b9e65e2f110df998f1306571fae7af6c01e4d92b
reset_db
do_execsql_test 13.1 {
CREATE TABLE t1(a INT AS (b), b INT);
INSERT INTO t1(b) VALUES(123);
CREATE TABLE t2(a INT, c INT);
SELECT a FROM t2 NATURAL RIGHT JOIN t1;
} {123}
do_execsql_test 13.2 {
CREATE INDEX t1a ON t1(a);
SELECT a FROM t2 NATURAL RIGHT JOIN t1;
} {123}
# Further tests of the same logic (indexes on expressions
# used by RIGHT JOIN) from check-in ffe23af73fcb324d and
# forum post https://sqlite.org/forum/forumpost/9b491e1debf0b67a.
db null NULL
do_execsql_test 13.3 {
CREATE TABLE t3(a INT, b INT);
CREATE UNIQUE INDEX t3x ON t3(a, a+b);
INSERT INTO t3(a,b) VALUES(1,2),(4,8),(16,32),(4,80),(1,-300);
CREATE TABLE t4(x INT, y INT);
INSERT INTO t4(x,y) SELECT a, b FROM t3;
INSERT INTO t4(x,y) VALUES(99,99);
SELECT a1.a, sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t4 ON a=x
GROUP BY a1.a ORDER BY 1;
} {NULL NULL 1 -592 4 192 16 48}
do_execsql_test 13.4 {
SELECT sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t3 ON true
GROUP BY a1.a ORDER BY 1;
} {-1480 240 480}
finish_test
+6 -1
View File
@@ -100,6 +100,11 @@ do_execsql_test misc8-2.1 {
# 2016-02-26: An assertion fault found by the libFuzzer project
#
ifcapable allow_rowid_in_view {
set nosuch "1 {ambiguous column name: rowid}"
} else {
set nosuch "1 {no such column: rowid}"
}
do_catchsql_test misc8-3.0 {
SELECT *
FROM
@@ -110,7 +115,7 @@ do_catchsql_test misc8-3.0 {
(SELECT 6 AS j UNION ALL SELECT 7) AS x4
WHERE i<rowid
ORDER BY 1;
} {1 {no such column: rowid}}
} $nosuch
# The SQLITE_DBCONFIG_MAINDBNAME interface
#
+1 -1
View File
@@ -520,7 +520,7 @@ do_eqp_test 8.1 {
} {
QUERY PLAN
|--SCAN t1 USING INDEX i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--USE TEMP B-TREE FOR LAST TERM OF ORDER BY
}
do_execsql_test 8.2 {
+3
View File
@@ -387,6 +387,9 @@ ifcapable attach {
PRAGMA integrity_check=4
}
} {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
do_catchsql_test pragma-3.5.2 {
PRAGMA integrity_check='4'
} {1 {no such table: 4}}
do_catchsql_test pragma-3.6 {
PRAGMA integrity_check=xyz
} {1 {no such table: xyz}}
+19 -1
View File
@@ -83,7 +83,7 @@ foreach {tn sql} {
# Verify that that P4_INTARRAY argument to OP_IntegrityCk is rendered
# correctly.
#
db close
catch {db close}
forcedelete test.db
sqlite3 db test.db
do_test pragma4-2.100 {
@@ -264,5 +264,23 @@ do_execsql_test 5.0 {
0 a {} 0 'abc' 0 1 b {} 0 -1 0 2 c {} 0 +4.0 0
}
# 2024-03-24 https://sqlite.org/forum/forumpost/85b6a8b6705fb77a
#
catch {db2 close}
catch {db3 close}
ifcapable vtab {
reset_db
do_execsql_test 6.0 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(a INT PRIMARY KEY, b INT);
CREATE TABLE t2(c INT PRIMARY KEY, d INT REFERENCES t1);
SELECT t.name, f."table", f."from", i.name, i.pk
FROM pragma_table_list() AS t
JOIN pragma_foreign_key_list(t.name, t.schema) AS f
JOIN pragma_table_info(f."table", t.schema) AS i
WHERE i.pk;
} {t2 t1 d a 1}
}
finish_test
+109 -4
View File
@@ -1,4 +1,4 @@
# 2017 April 29
# 2017-04-29
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@@ -8,6 +8,26 @@
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test cases for the push-down optimizations.
#
#
# There are two different meanings for "push-down optimization".
#
# (1) "MySQL push-down" means that WHERE clause terms that can be
# evaluated using only the index and without reference to the
# table are run first, so that if they are false, unnecessary table
# seeks are avoided. See https://sqlite.org/src/info/d7bb79ed3a40419d
# from 2017-04-29.
#
# (2) "WHERE-clause pushdown" means to push WHERE clause terms in
# outer queries down into subqueries. See
# https://sqlite.org/src/info/6df18e949d367629 from 2015-06-02.
#
# This module started out as tests for MySQL push-down only. But because
# of naming ambiguity, it has picked up test cases for WHERE-clause push-down
# over the years.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -87,8 +107,8 @@ do_test 2.2 {
} {three}
# 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f
# Disable the push-down optimization for compound subqueries if any
# arm of the compound has an incompatible affinity.
# Disable the WHERE-clause push-down optimization for compound subqueries
# if any arm of the compound has an incompatible affinity.
#
reset_db
do_execsql_test 3.1 {
@@ -185,7 +205,7 @@ do_eqp_test 3.8 {
# SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)
# 2023-05-09 https://sqlite.org/forum/forumpost/a7d4be7fb6
# Restriction (9) on the push-down optimization.
# Restriction (9) on the WHERE-clause push-down optimization.
#
reset_db
db null -
@@ -227,4 +247,89 @@ do_execsql_test 5.0 {
WHERE e>0;
} {- - 3 4 5}
# 2024-04-05
# Allow push-down of operators of the form "expr IN table".
#
reset_db
do_execsql_test 6.0 {
CREATE TABLE t01(w,x,y,z);
CREATE TABLE t02(w,x,y,z);
CREATE VIEW t0(w,x,y,z) AS
SELECT w,x,y,z FROM t01 UNION ALL SELECT w,x,y,z FROM t02;
CREATE INDEX t01x ON t01(w,x,y);
CREATE INDEX t02x ON t02(w,x,y);
CREATE VIEW v1(k) AS VALUES(77),(88),(99);
CREATE TABLE k1(k);
INSERT INTO k1 SELECT * FROM v1;
}
do_eqp_test 6.1 {
WITH k(n) AS (VALUES(77),(88),(99))
SELECT max(z) FROM t0 WHERE w=123 AND x IN k AND y BETWEEN 44 AND 55;
} {
QUERY PLAN
|--CO-ROUTINE t0
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)
| | `--LIST SUBQUERY xxxxxx
| | |--MATERIALIZE k
| | | `--SCAN 3 CONSTANT ROWS
| | `--SCAN k
| `--UNION ALL
| |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)
| `--LIST SUBQUERY xxxxxx
| `--SCAN k
|--SEARCH t0
`--LIST SUBQUERY xxxxxx
`--SCAN k
}
# ^^^^--- The key feature above is that the SEARCH for each subquery
# uses all three fields of the index w, x, and y. Prior to the push-down
# of "expr IN table", only the w term of the index would be used. Similar
# for the following tests:
#
do_eqp_test 6.2 {
SELECT max(z) FROM t0 WHERE w=123 AND x IN v1 AND y BETWEEN 44 AND 55;
} {
QUERY PLAN
|--CO-ROUTINE t0
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)
| | `--LIST SUBQUERY xxxxxx
| | |--CO-ROUTINE v1
| | | `--SCAN 3 CONSTANT ROWS
| | `--SCAN v1
| `--UNION ALL
| |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)
| `--LIST SUBQUERY xxxxxx
| |--CO-ROUTINE v1
| | `--SCAN 3 CONSTANT ROWS
| `--SCAN v1
|--SEARCH t0
`--LIST SUBQUERY xxxxxx
|--CO-ROUTINE v1
| `--SCAN 3 CONSTANT ROWS
`--SCAN v1
}
do_eqp_test 6.3 {
SELECT max(z) FROM t0 WHERE w=123 AND x IN k1 AND y BETWEEN 44 AND 55;
} {
QUERY PLAN
|--CO-ROUTINE t0
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)
| | `--LIST SUBQUERY xxxxxx
| | `--SCAN k1
| `--UNION ALL
| |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)
| `--LIST SUBQUERY xxxxxx
| `--SCAN k1
|--SEARCH t0
`--LIST SUBQUERY xxxxxx
`--SCAN k1
}
finish_test
+55
View File
@@ -0,0 +1,55 @@
# 2024 March 21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for using databases in read-only mode on
# unix.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$tcl_platform(platform)=="windows"} finish_test
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
set ::testprefix readonly
do_execsql_test 1.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
}
db close
file attributes test.db -permissions r--r--r--
sqlite3 db test.db
do_catchsql_test 1.1 {
INSERT INTO t1 VALUES(7, 8);
} {1 {attempt to write a readonly database}}
do_execsql_test 1.2 {
BEGIN;
SELECT * FROM t1;
} {1 2 3 4 5 6}
# The following attempts to open a read/write fd on the database 20,000
# times. And each time instead opens a read-only fd. At one point this
# was failing to reuse cached fds, causing a "too many open file-descriptors"
# error.
do_test 1.3 {
for {set ii 0} {$ii < 20000} {incr ii} {
sqlite3 db2 test.db
db2 close
}
set {} {}
} {}
finish_test
+65 -5
View File
@@ -227,21 +227,21 @@ ifcapable !allow_rowid_in_view {
} else {
# Note: The values returned by the RETURNING clauses of the following
# two statements are the rowid columns of views. These values are not
# well defined, so the INSERT returns -1, and the UPDATE returns 1, 2
# and 3. These match the values used for new.rowid expressions, but
# not much else.
# well defined, so the INSERT returns -1, and the UPDATE returns NULL.
# These match the values used for new.rowid expressions, but not much
# else.
do_catchsql_test 10.3a {
INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid;
} {0 -1}
do_catchsql_test 10.3b {
UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid;
} {0 {1 2 3}}
} {0 {{} {} {}}}
do_execsql_test 10.4 {
SELECT * FROM log;
} {
insert -1 1234 5678 update 1 z y update 2 z y update 3 z y
insert -1 1234 5678 update {} z y update {} z y update {} z y
}
}
@@ -460,4 +460,64 @@ do_catchsql_test 19.1 {
END;
} {0 {}}
# 2024-04-24
# https://sqlite.org/forum/forumpost/2c83569ce8945d39
#
# If the RETURNING clause includes subqueries that reference the
# table being modified, make sure that the subqueries are identified
# as correlated so that the results are recomputed after each step
# instead of being computed once and reused.
#
reset_db
db null N
do_execsql_test 20.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
INSERT INTO t1 VALUES(1,10),(2,20),(3,30),(4,40),(6,60),(8,80);
BEGIN;
DELETE FROM t1 WHERE a<>3
RETURNING a,
(SELECT min(a) FROM t1),
(SELECT max(a) FROM t1),
(SELECT round(avg(a),2) FROM t1);
ROLLBACK;
} {
1 2 8 4.6
2 3 8 5.25
4 3 8 5.67
6 3 8 5.5
8 3 3 3.0
}
do_execsql_test 20.2 {
BEGIN;
DELETE FROM t1
RETURNING a,
(SELECT min(a) FROM t1),
(SELECT max(a) FROM t1),
(SELECT round(avg(a),2) FROM t1);
ROLLBACK;
} {
1 2 8 4.6
2 3 8 5.25
3 4 8 6.0
4 6 8 7.0
6 8 8 8.0
8 N N N
}
do_execsql_test 20.3 {
BEGIN;
DELETE FROM t1
RETURNING a,
(SELECT min(t2.a)+t1.a*100 FROM t1 AS t2),
(SELECT max(t2.a)+t1.a*100 FROM t1 AS t2),
(SELECT round(avg(t2.a),2)+t1.a*100 FROM t1 AS t2);
ROLLBACK;
} {
1 102 108 104.6
2 203 208 205.25
3 304 308 306.0
4 406 408 407.0
6 608 608 608.0
8 N N N
}
finish_test
+1 -1
View File
@@ -804,7 +804,7 @@ do_execsql_test 16.0 {
}
ifcapable allow_rowid_in_view {
set nosuch "1 {no such column: rowid}"
set nosuch "1 {ambiguous column name: rowid}"
do_execsql_test 16.1 { SELECT rowid FROM t1, t2; } {1}
do_catchsql_test 16.2 { SELECT rowid FROM t1, v1; } $nosuch
do_catchsql_test 16.3 { SELECT rowid FROM t3, v1; } $nosuch
+11
View File
@@ -328,6 +328,17 @@ QUERY (nCycle=nnn)
--SCAN xy2 (nCycle=nnn)
}
#-------------------------------------------------------------------------
reset_db
# Check that an OOB parameter (45) does not cause asan or valgrind errors.
#
do_test 7.0 {
db eval {SELECT * FROM sqlite_schema}
set stmt [db version -last-stmt-ptr]
sqlite3_stmt_scanstatus -flags complex $stmt 1000000
} {}
#explain_i { SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1 }
#puts_debug_info { SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1 }
+2 -2
View File
@@ -1340,10 +1340,10 @@ do_eqp_test 4.1.2 {
`--MERGE (UNION ALL)
|--LEFT
| |--SCAN t5 USING INDEX i2
| `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
| `--USE TEMP B-TREE FOR LAST TERM OF ORDER BY
`--RIGHT
|--SCAN t4 USING INDEX i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--USE TEMP B-TREE FOR LAST TERM OF ORDER BY
}
do_execsql_test 4.1.3 {
+1
View File
@@ -60,6 +60,7 @@
#define SQLITE_DEBUG 1
#define SQLITE_THREADSAFE 0
#undef SQLITE_OMIT_LOAD_EXTENSION
#define SQLITE_OMIT_LOAD_EXTENSION 0
#define SQLITE_ENABLE_SESSION 1
#define SQLITE_ENABLE_PREUPDATE_HOOK 1
+59
View File
@@ -651,5 +651,64 @@ do_eqp_test subquery-10.2 {
# `--SEARCH t1 USING INDEX x12 (aa=?)
#
#-----------------------------------------------------------------------------
# 2024-04-25 Column affinities for columns of compound subqueries
#
reset_db
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
do_execsql_test subquery-11.1 {
CREATE TABLE t1(ix INT, rx REAL, bx BLOB, tx TEXT, ax);
INSERT INTO t1 VALUES(1,1.0,x'31','x',NULL);
WITH c(a) AS (SELECT 'y' UNION SELECT tx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT tx FROM t1 UNION SELECT 'y') SELECT affinity(a) FROM c;
} {text text text text}
do_execsql_test subquery-11.2 {
WITH c(a) AS (SELECT 2 UNION SELECT tx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT tx FROM t1 UNION SELECT 2) SELECT affinity(a) FROM c;
} {blob blob blob blob}
do_execsql_test subquery-11.3 {
WITH c(a) AS (SELECT 2.0 UNION SELECT tx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT tx FROM t1 UNION SELECT 2.0) SELECT affinity(a) FROM c;
} {blob blob blob blob}
do_execsql_test subquery-11.4 {
WITH c(a) AS (SELECT null UNION SELECT tx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT tx FROM t1 UNION SELECT null) SELECT affinity(a) FROM c;
} {text text text text}
do_execsql_test subquery-11.5 {
WITH c(a) AS (SELECT x'32' UNION SELECT tx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT tx FROM t1 UNION SELECT x'32') SELECT affinity(a) FROM c;
} {text text text text}
do_execsql_test subquery-11.6 {
WITH c(a) AS (SELECT 3 UNION SELECT ix FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT ix FROM t1 UNION SELECT 3) SELECT affinity(a) FROM c;
} {integer integer integer integer}
do_execsql_test subquery-11.7 {
WITH c(a) AS (SELECT 3.0 UNION SELECT ix FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT ix FROM t1 UNION SELECT 3.0) SELECT affinity(a) FROM c;
} {integer integer integer integer}
do_execsql_test subquery-11.8 {
WITH c(a) AS (SELECT '3' UNION SELECT ix FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT ix FROM t1 UNION SELECT '3') SELECT affinity(a) FROM c;
} {blob blob blob blob}
do_execsql_test subquery-11.10 {
WITH c(a) AS (SELECT x'32' UNION SELECT ix FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT ix FROM t1 UNION SELECT x'32') SELECT affinity(a) FROM c;
} {integer integer integer integer}
do_execsql_test subquery-11.11 {
WITH c(a) AS (SELECT 4 UNION SELECT rx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT rx FROM t1 UNION SELECT 4) SELECT affinity(a) FROM c;
} {real real real real}
do_execsql_test subquery-11.12 {
WITH c(a) AS (SELECT '4' UNION SELECT rx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT rx FROM t1 UNION SELECT '4') SELECT affinity(a) FROM c;
} {blob blob blob blob}
do_execsql_test subquery-11.13 {
WITH c(a) AS (SELECT null UNION SELECT rx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT rx FROM t1 UNION SELECT null) SELECT affinity(a) FROM c;
} {real real real real}
do_execsql_test subquery-11.14 {
WITH c(a) AS (SELECT x'b4' UNION SELECT rx FROM t1) SELECT affinity(a) FROM c;
WITH c(a) AS (SELECT rx FROM t1 UNION SELECT x'b4') SELECT affinity(a) FROM c;
} {real real real real}
finish_test
+26
View File
@@ -322,6 +322,32 @@ ifcapable altertable {
} {1 {table pragma_compile_options may not be altered}}
}
#-----------------------------------------------------------------------------
# 2024-04-26 LIMIT and OFFSET passed into virtual tables
# https://sqlite.org/forum/forumpost/c243b8f856
#
do_execsql_test tabfunc01-900 {
SELECT * FROM (
SELECT * FROM generate_series(1,10)
UNION ALL
SELECT * FROM generate_series(101,104)
) LIMIT 10 OFFSET 5;
} {6 7 8 9 10 101 102 103 104}
do_execsql_test tabfunc01-910 {
SELECT * FROM (
SELECT * FROM generate_series(1,10)
UNION ALL
SELECT * FROM generate_series(101,104)
) LIMIT -1 OFFSET 5;
} {6 7 8 9 10 101 102 103 104}
do_execsql_test tabfunc01-920 {
SELECT * FROM (
SELECT * FROM generate_series(1,10)
UNION ALL
SELECT * FROM generate_series(101,104)
) LIMIT -1 OFFSET 0;
} {1 2 3 4 5 6 7 8 9 10 101 102 103 104}
# Free up memory allocations
intarray_addr
+34 -11
View File
@@ -60,13 +60,15 @@ Usage:
$a0 status
where SWITCHES are:
--buildonly
--dryrun
--explain
--jobs NUMBER-OF-JOBS
--stop-on-coredump
--stop-on-error
--zipvfs ZIPVFS-SOURCE-DIR
--buildonly Build test exes but do not run tests
--config CONFIGS Only use configs on comma-separate list CONFIGS
--dryrun Write what would have happened to testrunner.log
--explain Write summary to stdout
--jobs NUM Run tests using NUM separate processes
--omit CONFIGS Omit configs on comma-separated list CONFIGS
--stop-on-coredump Stop running if any test segfaults
--stop-on-error Stop running after any reported error
--zipvfs ZIPVFSDIR ZIPVFS source directory
Special values for PERMUTATION that work with plain tclsh:
@@ -172,6 +174,8 @@ set TRG(reporttime) 2000
set TRG(fuzztest) 0 ;# is the fuzztest option present.
set TRG(zipvfs) "" ;# -zipvfs option, if any
set TRG(buildonly) 0 ;# True if --buildonly option
set TRG(config) {} ;# Only build the named configurations
set TRG(omitconfig) {} ;# Do not build these configurations
set TRG(dryrun) 0 ;# True if --dryrun option
set TRG(explain) 0 ;# True for the --explain option
set TRG(stopOnError) 0 ;# Stop running at first failure
@@ -266,7 +270,7 @@ set TRG(schema) {
/* Fields updated as jobs run */
starttime INTEGER,
endtime INTEGER,
state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ),
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
output TEXT
);
@@ -443,6 +447,10 @@ if {[llength $argv]==1
} job {
display_job [array get job]
}
set nOmit [db one {SELECT count(*) FROM jobs WHERE state='omit'}]
if {$nOmit} {
puts "$nOmit jobs omitted due to failures"
}
}
mydb close
@@ -468,10 +476,16 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} {
if {$isLast} { usage }
} elseif {($n>2 && [string match "$a*" --buildonly]) || $a=="-b"} {
set TRG(buildonly) 1
} elseif {($n>2 && [string match "$a*" --config]) || $a=="-c"} {
incr ii
set TRG(config) [lindex $argv $ii]
} elseif {($n>2 && [string match "$a*" --dryrun]) || $a=="-d"} {
set TRG(dryrun) 1
} elseif {($n>2 && [string match "$a*" --explain]) || $a=="-e"} {
set TRG(explain) 1
} elseif {($n>2 && [string match "$a*" --omit]) || $a=="-c"} {
incr ii
set TRG(omitconfig) [lindex $argv $ii]
} elseif {[string match "$a*" --stop-on-error]} {
set TRG(stopOnError) 1
} elseif {[string match "$a*" --stop-on-coredump]} {
@@ -485,8 +499,6 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} {
}
set argv [list]
# This script runs individual tests - tcl scripts or [make xyz] commands -
# in directories named "testdir$N", where $N is an integer. This variable
# contains a list of integers indicating the directories in use.
@@ -911,6 +923,8 @@ proc add_jobs_from_cmdline {patternlist} {
release {
set patternlist [lrange $patternlist 1 end]
foreach b [trd_builds $TRG(platform)] {
if {$TRG(config)!="" && ![regexp "\\y$b\\y" $TRG(config)]} continue
if {[regexp "\\y$b\\y" $TRG(omitconfig)]} continue
set bld [add_build_job $b $TRG(testfixture)]
foreach c [trd_configs $TRG(platform) $b] {
add_tcl_jobs $bld $c $patternlist
@@ -965,11 +979,16 @@ proc make_new_testset {} {
proc mark_job_as_finished {jobid output state endtm} {
r_write_db {
if {$state=="failed"} {
set childstate omit
} else {
set childstate ready
}
trdb eval {
UPDATE jobs
SET output=$output, state=$state, endtime=$endtm
WHERE jobid=$jobid;
UPDATE jobs SET state='ready' WHERE depid=$jobid;
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
}
}
}
@@ -1192,6 +1211,10 @@ proc run_testset {} {
puts "FAILED: $displayname"
}
}
set nOmit [trdb one {SELECT count(*) FROM jobs WHERE state='omit'}]
if {$nOmit>0} {
puts "$nOmit jobs skipped due to prior failures"
}
}
puts "\nTest database is $TRG(dbname)"
+36
View File
@@ -23,6 +23,7 @@ namespace eval trd {
set tcltest(linux.No-lookaside) veryquick
set tcltest(linux.Devkit) veryquick
set tcltest(linux.Apple) veryquick
set tcltest(linux.Android) veryquick
set tcltest(linux.Sanitize) veryquick
set tcltest(linux.Device-One) all
set tcltest(linux.Default) all_plus_autovacuum_crash
@@ -53,6 +54,7 @@ namespace eval trd {
set extra(linux.Device-Two) {fuzztest sourcetest threadtest}
set extra(linux.No-lookaside) {fuzztest sourcetest}
set extra(linux.Devkit) {fuzztest sourcetest}
set extra(linux.Android) {fuzztest sourcetest}
set extra(linux.Apple) {fuzztest sourcetest}
set extra(linux.Sanitize) {fuzztest sourcetest}
set extra(linux.Default) {fuzztest sourcetest threadtest}
@@ -246,6 +248,40 @@ namespace eval trd {
-O2
-DSQLITE_ENABLE_LOCKING_STYLE=1
}
set build(Android) {
-Os
-DHAVE_USLEEP=1
-DSQLITE_HAVE_ISNAN
-DSQLITE_POWERSAFE_OVERWRITE=1
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_DEFAULT_AUTOVACUUM=1
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
-DSQLITE_ENABLE_FTS3
-DSQLITE_ENABLE_FTS3_BACKWARDS
-DSQLITE_ENABLE_FTS4
-DSQLITE_SECURE_DELETE
-DSQLITE_ENABLE_BATCH_ATOMIC_WRITE
-DBIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
-DSQLITE_ALLOW_ROWID_IN_VIEW
-DSQLITE_ENABLE_BYTECODE_VTAB
-Wno-unused-parameter
-Werror
-DUSE_PREAD64
-Dfdatasync=fdatasync
-DHAVE_MALLOC_H=1
-DHAVE_MALLOC_USABLE_SIZE
-DSQLITE_ENABLE_DBSTAT_VTAB
}
# Compile-options used by Android but omitted from these
# tests:
# -DNDEBUG=1
# -DSQLITE_DEFAULT_LEGACY_ALTER_TABLE
# -DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576
# -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600
# -DSQLITE_OMIT_BUILTIN_TEST
# -DSQLITE_OMIT_LOAD_EXTENSION
# -DSQLITE_OMIT_COMPILEOPTION_DIAGS
#
set build(Apple) {
-Os
-DHAVE_GMTIME_R=1
+24
View File
@@ -268,4 +268,28 @@ do_catchsql_test upsert1-1210 {
INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(b+?1) DO NOTHING;
} {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
# 2024-04-11 https://sqlite.org/forum/forumpost/284955a3cd454a15
# Incorrect value passed into a trigger that fires as the result of
# an upsert.
#
reset_db
do_execsql_test upsert1-1300 {
CREATE TABLE t1(x INT, y TEXT);
INSERT INTO t1 VALUES
(11, printf('%.9000c','a')),
(11, printf('%.9000c','a')),
(33, printf('%.9000c','b')),
(33, printf('%.9000c','b'));
CREATE TABLE t2(x INT UNIQUE, y TEXT);
CREATE TRIGGER r1 BEFORE UPDATE ON t2 BEGIN
SELECT raise(ABORT,'Incorrect old.y value passed to trigger!')
WHERE old.y != new.y;
/* ^^^ This trigger will fire and cause the ABORT if the problem has
** not been fixed, or if there is a regression. */
END;
INSERT INTO t2(x, y) SELECT x, y FROM t1
WHERE true
ON CONFLICT (x) DO UPDATE SET y = excluded.y;
} {}
finish_test
+34 -1
View File
@@ -26,13 +26,36 @@ ifcapable {!vacuum} {
forcedelete out.db
do_execsql_test vacuum-into-100 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b ANY,
c INT AS (b+1), --- See "2024-04-09" block
CHECK( typeof(b)!='integer' OR b>a-5 ) --- comment below
);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b) SELECT x, randomblob(600) FROM c;
CREATE INDEX t1b ON t1(b);
DELETE FROM t1 WHERE a%2;
SELECT count(*), sum(a), sum(length(b)) FROM t1;
} {50 2550 30000}
# Update 2024-04-09 for forum post eec177d68fe7fa2c.
#
# VACUUM INTO is sensitive to tables holding both generated columns
# and CHECK constraints.
#
# CHECK constraints are ignored for read-only databases in order to save
# memory (see check-in 34ddf02d3d21151b on 2014-05-21). But the xfer
# optimization normally only works if CHECK constraints match between the
# source and destination tables. So the xfer optimization was not
# working for VACUUM INTO when the source was a read-only database and the
# table held CHECK constraints. But if the table has generated columns,
# then the xfer optimization is required or else VACUUM will raise an
# error.
#
# Fix this by ignoring CHECK constraints when determining whether or not
# the xfer optimization can run while doing VACUUM.
do_execsql_test vacuum-into-110 {
VACUUM main INTO 'out.db';
} {}
@@ -88,11 +111,21 @@ do_catchsql_test vacuum-into-420 {
# The ability to VACUUM INTO a read-only database
db close
if {$tcl_platform(platform)=="windows"} {
file attributes test.db -readonly 1
} else {
file attributes test.db -permissions 292 ;# 292 == 0444
}
sqlite3 db test.db -readonly 1
forcedelete test.db2
do_execsql_test vacuum-into-500 {
VACUUM INTO 'test.db2';
}
if {$tcl_platform(platform)=="windows"} {
file attributes test.db -readonly 0
} else {
file attributes test.db -permissions 420 ;# 420 = 0644
}
sqlite3 db2 test.db2
do_test vacuum-into-510 {
db2 eval {SELECT name FROM sqlite_master ORDER BY 1}
+132
View File
@@ -580,4 +580,136 @@ do_eqp_test 16.7 {
`--SCAN 4-ROW VALUES CLAUSE
}
#--------------------------------------------------------------------------
# 2024-03-23 dbsqlfuzz crash-c2c5e7e08b7e489d270a26d895077a03f678c33b
#
do_execsql_test 17.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 AS SELECT * FROM (VALUES(1,2), (3,4 IN (1,2,3)));
}
do_execsql_test 17.2 {
SELECT * FROM t1
} {1 2 3 0}
# 2024-03-25 dbsqlfuzz crash-74cf7c9904360322a6c917e4934b127543d1cd51
#
do_catchsql_test 18.1 {
DROP TABLE t1;
CREATE TABLE t1(x INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES(RAISE(IGNORE)),(0);
} {1 {RAISE() may only be used within a trigger-program}}
do_catchsql_test 18.2 {
DROP TABLE t1;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
INSERT INTO t1(y) VALUES(RAISE(IGNORE)),(0);
END;
INSERT INTO t1 VALUES(1,2,3);
SELECT * FROM t1;
} {0 {1 2 3}}
do_catchsql_test 18.3.1 {
DROP TABLE t1;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
INSERT INTO t1(y) VALUES(RAISE(ABORT,'error 18.3')),(0);
END;
INSERT INTO t1 VALUES(1,2,3);
} {1 {error 18.3}}
do_execsql_test 18.3.2 {
SELECT * FROM t1;
} {}
do_catchsql_test 18.4.1 {
DROP TABLE t1;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
INSERT INTO t1(y) VALUES(1),(RAISE(ABORT,'error 18.4')),(0);
END;
INSERT INTO t1 VALUES(1,2,3);
} {1 {error 18.4}}
do_execsql_test 18.4.2 {
SELECT * FROM t1;
} {}
do_catchsql_test 18.5.1 {
DROP TABLE t1;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
INSERT INTO t1(y) VALUES(1),
(CASE WHEN new.z>7 THEN RAISE(ABORT,'error 18.5') ELSE 2 END);
END;
INSERT INTO t1 VALUES(1,2,3);
SELECT * FROM t1;
} {0 {1 2 3 2 1 {} 3 2 {}}}
do_catchsql_test 18.5.2 {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,13);
} {1 {error 18.5}}
do_catchsql_test 18.5.3 {
SELECT * FROM t1;
} {0 {}}
# 2024-04-18 dbsqlfuzz crash-bde3bf80aedf25afa56e2997a0545a314765d3f8
# Verify that the VALUES expressions used as an argument to an outer
# join work correctly.
#
reset_db
db null NULL
do_execsql_test 19.1 {
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES(11,22);
SELECT * FROM t1 LEFT JOIN (VALUES(33,44),(55,66)) AS t2 ON a=b;
} {11 22 NULL NULL}
do_execsql_test 19.2 {
SELECT * FROM (VALUES(33,44),(55,66)) AS t2 RIGHT JOIN t1 ON a=b;
} {NULL NULL 11 22}
do_execsql_test 19.3 {
SELECT *, '|' FROM t1 FULL JOIN (VALUES(33,44),(55,66)) AS t2 ON a=b
ORDER BY +column1
} {11 22 NULL NULL | NULL NULL 33 44 | NULL NULL 55 66 |}
do_execsql_test 19.4 {
SELECT *, '|' FROM (VALUES(33,44),(55,66)) AS t2 FULL JOIN t1 ON a=b
ORDER BY +column1
} {NULL NULL 11 22 | 33 44 NULL NULL | 55 66 NULL NULL |}
# 2024-04-21 dbsqlfuzz 6fd1ff3a64bef4a6c092e8d757548e95698b0df5
# A continuation of the 2024-04-18 problem above. We have to create
# Pseudo-cursor that is always NULL on the viaCoroutine loop in case
# there are OP_Columns generated against it by the sub-WHERE clause.
#
db null N
do_execsql_test 19.5 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
DROP TABLE IF EXISTS t3;
CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2);
CREATE TABLE t2(column1,column2); INSERT INTO t2 VALUES(11,22),(33,44);
CREATE TABLE t3(d,e); INSERT INTO t3 VALUES(3,4);
}
do_execsql_test 19.6 {
-- output verify using PG 14.2
SELECT *
FROM t1 CROSS JOIN t2 FULL JOIN t3 ON a=d
ORDER BY +d, +column1;
} {1 2 11 22 N N
1 2 33 44 N N
N N N N 3 4}
do_execsql_test 19.7 {
SELECT *
FROM t1 CROSS JOIN (VALUES(11,22),(33,44)) FULL JOIN t3 ON a=d
ORDER BY +d, +column1;
} {1 2 11 22 N N
1 2 33 44 N N
N N N N 3 4}
do_execsql_test 19.8 {
-- output verified using PG 14.2
SELECT *
FROM t1 CROSS JOIN t2 FULL JOIN t3 ON a=d
WHERE column1 IS NULL;
} {N N N N 3 4}
do_execsql_test 19.9 {
SELECT *
FROM t1 CROSS JOIN (VALUES(11,22),(33,44)) FULL JOIN t3 ON a=d
WHERE column1 IS NULL;
} {N N N N 3 4}
finish_test
+23
View File
@@ -801,4 +801,27 @@ ifcapable schema_pragmas {
} { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 }
}
#-----------------------------------------------------------------------
# 2024-04-25 Trying to make type information on compound subqueries
# more predictable and rational.
#
reset_db
do_execsql_test view-31.1 {
CREATE TABLE x2(b TEXT);
CREATE TABLE x1(a TEXT);
INSERT INTO x1 VALUES('123');
-- Two queries get the same result even though the order of terms
-- in the CTE is reversed
WITH c(x) AS ( SELECT b FROM x2 UNION SELECT 123 )
SELECT count(*) FROM x1 WHERE a IN c;
WITH c(x) AS ( SELECT 123 UNION SELECT b FROM x2 )
SELECT count(*) FROM x1 WHERE a IN c;
} {0 0}
do_execsql_test view-31.2 {
CREATE TABLE t3(a INTEGER, b TEXT);
INSERT INTO t3 VALUES(123, 123);
WITH s AS ( VALUES(123), (456) ) SELECT * FROM t3 WHERE b IN s;
} {123 123}
finish_test
+68
View File
@@ -0,0 +1,68 @@
# 2024-03-26
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vtabL
ifcapable !vtab {
finish_test
return
}
register_tcl_module db
proc vtab_command {method args} {
switch -- $method {
xConnect {
return $::create_table_sql
}
}
return {}
}
breakpoint
foreach {tn cts} {
1 {SELECT 123}
2 {SELECT 123, 456}
3 {INSERT INTO t1 VALUES(5, 6)}
4 {CREATE INDEX i1 ON t1(a)}
5 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END;}
6 {DROP TABLE nosuchtable}
7 {DROP TABLE x1}
8 {DROP TABLE t1}
9 {CREATE TABLE xyz AS SELECT * FROM sqlite_schema}
10 {CREATE TABLE xyz AS SELECT 1 AS 'col'}
} {
set ::create_table_sql $cts
do_catchsql_test 1.$tn {
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
} {1 {vtable constructor failed: x1}}
}
foreach {tn cts} {
1 {CREATE TABLE IF NOT EXISTS t1(a, b)}
2 {CREATE TABLE ""(a, b PRIMARY KEY) WITHOUT ROWID}
} {
set ::create_table_sql $cts
execsql { DROP TABLE IF EXISTS x1 }
do_execsql_test 2.$tn.1 {
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
}
do_execsql_test 2.$tn.2 {
SELECT a, b FROM x1
}
}
finish_test
+103
View File
@@ -0,0 +1,103 @@
# 2024-04-02
#
# 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 the whereInterstageHeuristic() routine in the query planner.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix whereN
# The following is a simplified and "sanitized" version of the original
# real-world query that brought the problem to light.
#
# The issue is a slow query. The answer is correct, but it was taking too
# much time, because it was doing a full table scan rather than an indexed
# lookup.
#
# The problem was that the query planner was overestimating the number of
# output rows. The estimated number of output rows is accurate if the
# DSNAME parameter is "ds-one". In that case, a large fraction of the rows
# in "violation" end up being output. The query planner correctly deduces
# that it is faster to do a full table scan of the large "violation" table
# to avoid the after-query sort that implements the ORDER BY clause. However,
# if the DSNAME is "ds-two", then only a few rows (about 6) are generated,
# and it is much much faster to do an indexed lookup of "violation" followed
# by a sort operation to implement ORDER BY
#
# The problem, of course, is that the query planner has no way of knowing
# in advance how many rows will be generated. The query planner tries to
# estimate a worst case, which is a large number of output rows, and it picks
# the best plan for that case. However, the plan choosen is very inefficient
# when the number of output rows is small.
#
# The whereInterstageHeuristic() routine in the query planner attempts to
# correct this by adjusting the query plan such that it avoids the very bad
# query plan for a small number of rows, at the expense of a slightly less
# efficient plan for a large number of rows. The large number of rows case
# is perhaps 5% slower with the revised plan, but the small number of
# rows case is around 100 times faster. That seems like a good tradeoff.
#
do_execsql_test 1.0 {
CREATE TABLE datasource(dsid INT, name TEXT);
INSERT INTO datasource VALUES(1,'ds-one'),(2,'ds-two'),(3,'ds-three');
CREATE INDEX ds1 ON datasource(name, dsid);
CREATE TABLE rule(rid INT, team_id INT, dsid INT);
WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<9)
INSERT INTO rule(rid,team_id,dsid) SELECT n, 1, 1 FROM c;
WITH RECURSIVE c(n) AS (VALUES(10) UNION ALL SELECT n+1 FROM c WHERE n<24)
INSERT INTO rule(rid,team_id,dsid) SELECT n, 2, 2 FROM c;
CREATE INDEX rule2 ON rule(dsid, rid);
CREATE TABLE violation(vid INT, rid INT, vx BLOB);
/*** Uncomment to insert actual data
WITH src(rid, cnt) AS (VALUES(1,3586),(2,1343),(3,6505),(5,76230),
(6,740),(7,287794),(8,457),(12,1),
(14,1),(16,1),(17,1),(18,1),(19,1))
INSERT INTO violation(vid, rid, vx)
SELECT rid*1000000+value, rid, randomblob(15)
FROM src, generate_series(1,cnt);
***/
CREATE INDEX v1 ON violation(rid, vid);
CREATE INDEX v2 ON violation(vid);
ANALYZE;
DELETE FROM sqlite_stat1;
DROP TABLE IF EXISTS sqlite_stat4;
INSERT INTO sqlite_stat1 VALUES
('violation','v2','376661 1'),
('violation','v1','376661 28974 1'),
('rule','rule2','24 12 1'),
('datasource','ds1','3 1 1');
ANALYZE sqlite_schema;
}
set DSNAME ds-two ;# Only a few rows. Change to "ds-one" for many rows.
do_eqp_test 1.1 {
SELECT count(*), length(group_concat(vx)) FROM (
SELECT V.*
FROM datasource DS, rule R, violation V
WHERE V.rid=R.rid
AND R.dsid=DS.dsid
AND DS.name=$DSNAME
ORDER BY V.vid desc
);
} {
QUERY PLAN
|--CO-ROUTINE (subquery-xxxxxx)
| |--SEARCH DS USING COVERING INDEX ds1 (name=?)
| |--SEARCH R USING COVERING INDEX rule2 (dsid=?)
| |--SEARCH V USING INDEX v1 (rid=?)
| `--USE TEMP B-TREE FOR ORDER BY
`--SCAN (subquery-xxxxxx)
}
# ^^^^---- We want to see three SEARCH terms. No SCAN terms.
# The ORDER BY is implemented by a separate sorter pass.
finish_test
+1
View File
@@ -105,6 +105,7 @@ set boolean_defnnz_options {
set boolean_defnil_options {
SQLITE_32BIT_ROWID
SQLITE_4_BYTE_ALIGNED_MALLOC
SQLITE_ALLOW_ROWID_IN_VIEW
SQLITE_ALLOW_URI_AUTHORITY
SQLITE_BUG_COMPATIBLE_20160819
SQLITE_CASE_SENSITIVE_LIKE