Compare commits

..

799 Commits

Author SHA1 Message Date
mistachkin 192514559d Updates to the 'vtshim' extension.
FossilOrigin-Name: 163c6cdf93451cb4ae7655266654d4aec2b94c4ceb0a6fc68859ecc73bf393a9
2022-07-22 20:48:04 +00:00
mistachkin 58fb401664 Add experimental 'xShadowName2' method for virtual table modules.
FossilOrigin-Name: 57beb700c081b20758d52ad4d395be34ef53f71a231f3dd27613030ac232bca8
2022-07-22 20:24:38 +00:00
drh 825fa17b1f Omit the EP_MemToken flag that was made obsolete by [e1f1cfe7f4387b60], for
a size reduction and performance increase.

FossilOrigin-Name: 28934a9d92d5e5ac862a0dc7169f071f39047f98dc79441db697cf353a4b9433
2022-07-22 19:28:04 +00:00
drh 034d111807 In a TK_BLOB Expr node, the Expr.zToken might not be a well-formed
BLOB literal if there has been a prior OOM.
dbsqlfuzz 23871e5805d6c45b392f9b7aa1e8a2b98f3c27cd.

FossilOrigin-Name: c538d075350927222ab0a6598b844f7b15153c5dc008d71b921a2b73c4f4a7a4
2022-07-22 18:25:04 +00:00
drh d00505dc97 Update the documentation for SQLITE_OPEN_NOFOLLOW to state more clearly that
nothing in the database path is allowed to be a symbolic link.

FossilOrigin-Name: de9222697b2ca8cae2cc7aa9082cca3910038ebbab1e8ee15270b06711711a0b
2022-07-22 14:52:29 +00:00
mistachkin e50998859d Fix harmless compiler warning seen with MSVC.
FossilOrigin-Name: 648172de20d70532ed0fb9713b76161dd481e09bbd973c03dffb51fb61b731cc
2022-07-21 18:37:50 +00:00
drh 9553016377 Make use of the sqlite3ExprDeferredDelete() interface in the previous
check-in, and in another place where it might be helpful.

FossilOrigin-Name: 22f90e9683d5cd6619ccdb06a02e9dde9f4b7457391c0dbb4c3216c22fc0db47
2022-07-20 20:36:26 +00:00
drh 3245f3be67 Simplify the logic that converts the "1" expression in "ORDER BY 1" into a
copy of the expression that defines the first output column.

FossilOrigin-Name: e1f1cfe7f4387b60443bd31742e2f49db1a2d0443200318a898ba0da216619be
2022-07-20 16:42:40 +00:00
larrybr a5cc692422 Improve accuracy of julian day milliseconds calculation.
FossilOrigin-Name: e5e9311863544ef30dccd3bd0b3a048a864a650e69cdf9aab13dbe32a4777b51
2022-07-19 21:12:54 +00:00
dan cf2ad7ae36 Remove a few unsuitable scripts from the "veryquick" test suite. Also have every second testrunner.tcl process favour running test scripts that contain text like "testrunner: slow" before any others.
FossilOrigin-Name: 22d280a5cd395abbedcfffbac3d3b3a614c327be25763ca380c1338a2a7bd33a
2022-07-18 19:32:30 +00:00
drh 2a7b27f1c6 Add the "testrunner" makefile target.
FossilOrigin-Name: 954c6593152f8c7372ed1233b32cce153d0ce4804869cf4ec5504d106a4920a2
2022-07-18 18:13:02 +00:00
drh 077e17b59a Increase the size of loop variables in the printf() implementation to avoid
harmless compiler warnings.

FossilOrigin-Name: aab790a16e1bdff78759f9c9ae87a2559ba82dd34ef3dedfb66035a0db7067a7
2022-07-18 15:02:00 +00:00
drh 449b473ee6 Enhance the REGEXP extension so that it will accept the start-of-input
mark ("^") in the middle of parentheses.
[forum:/forumpost/0d6a9160f81ef1a8|Forum post 0d6a9160f81ef1a8].

FossilOrigin-Name: ed8a8ebd62a319b5dabbdf67ee27141153b9899d7c8f08eeb4bdf35271015c71
2022-07-18 13:55:21 +00:00
drh 18934137dd Fix a problem in the REGEXP extension for the {M,N} construct where M is zero.
See [forum:/forumpost/8694e55a2c29963c|forum post 8694e55a2c29963c] for more
information.

FossilOrigin-Name: af15bb75306a4b94593b8431a34768b3de3d6689293e85ca02db16bf3e9f39e2
2022-07-18 13:10:53 +00:00
drh 67a0bf383f Enhance the ext/misc/regexp.c code so that when it is compiled with
SQLITE_DEBUG, a new function named regexp_bytecode() is available that
prints out the compiled NFA as human-readable text, for debugging purposes.

FossilOrigin-Name: cb5c08978fe8f074e6ae16953575213709e98b8bbae4359e0d2e6de67a7ea9e5
2022-07-18 11:44:16 +00:00
dan b496eef690 Fixes for the generated "mallocs.tcl" and "leaks.tcl" scripts generated by running tcl tests with the --malloctrace=1 option.
FossilOrigin-Name: 449799e2d5902464540e8fda53ab429e0518278dab3b17c86911759114cddea0
2022-07-16 18:08:48 +00:00
drh 02cb3ff004 In the query planner, restore the former aggressiveness in reordering of
FROM clause terms that existed prior to version 3.39.0 for queries that
contain no RIGHT or FULL JOINs.

FossilOrigin-Name: 92d60b64ebfc2d1f0a9cabaa88e7bf0d11737ed01a77b627af10dd1b96a5321c
2022-07-15 20:39:39 +00:00
dan 40e3fa3035 Fix a memory leak in fts3 that could occur when processing a corrupt database.
FossilOrigin-Name: d74f6f6d5136995b8bf900eb671e4b15ca81e03cc1ab5b7a1aa43dc4f3617760
2022-07-15 15:08:48 +00:00
drh b3623e0af7 Fix the whereKeyStats() routine (part of STAT4 processing only) so that it
is able to cope with row-value comparisons against the primary key index
of a WITHOUT ROWID table.
[forum:/forumpost/3607259d3c|Forum post 3607259d3c].

FossilOrigin-Name: 0620e419a927a3da6ebe921aaa3471686f0fdc2e485f4c2d5c88f32092228724
2022-07-15 12:16:11 +00:00
dan b1c034b2f1 Update some faulty assert() statements in fts3.
FossilOrigin-Name: b072851be1a5e49441469dbfa4580e132ebb1d8bc2de98fe1aa67bb9c7cf13a3
2022-07-15 11:34:23 +00:00
dan de353fb5c2 Ensure all testrunner.tcl processes use the same pending-byte value when
accessing testrunner.db. Otherwise locking doesn't work and the db is corrupted.

FossilOrigin-Name: b65225653e4e5c20cc43f4dfdde6c110f6d14b87bff02a65fd61beabe50ec8db
2022-07-14 21:17:22 +00:00
dan ca0720a9d8 Update testrunner.tcl so that it can run the test suites defined in permutation.test.
FossilOrigin-Name: 15ce937ef42491c503cb91f5bb3ce4dc5cdb3a927ff2f2b873fb6bf96808f3aa
2022-07-14 18:09:56 +00:00
drh e834484d89 When applying the omit-ORDER-BY optimization, defer deleting the AST of
the deleted ORDER BY clause until after code generation ends.

FossilOrigin-Name: f22f95b838873f1d2a320afe3d0f4e4847948fcd343097b93a9f684a6f66d6ba
2022-07-14 01:48:27 +00:00
dan 615aeceaff Fix testrunner.tcl so that it can detect the number of logical cores on osx.
FossilOrigin-Name: 14918f28221a3124b78a490fbb483279551ccc5a0032ea854ff0ac365684cc60
2022-07-13 21:28:19 +00:00
dan 4f28ee9d76 Minor change to help message in testrunner.tcl.
FossilOrigin-Name: e4f9cb01d790c27394cc021e7d4a16f4d5feda2d2493abd82e9660d7e6e9fec0
2022-07-13 21:10:11 +00:00
dan 2bb2d53bca Add new script test/testrunner.tcl. For running a set of test scripts using
multiple processes.

FossilOrigin-Name: 0122e93dc19c228546908b9ef5c58f88d27d79233523e2d09a4bbd56b0c492f9
2022-07-13 21:02:07 +00:00
dan cda165ff9a Fix a problem preventing "testrunnter.tcl all" from working.
FossilOrigin-Name: 0ed1e83c6fc12acd06ecf7210a869bebaf5e5e75762e5f16bf1834ecab717d59
2022-07-13 20:26:37 +00:00
dan 95cc6a5e11 Update testrunner.tcl to allow the user to specify which tests to run on the command line.
FossilOrigin-Name: 900febcf362fa5f592c640d16177f33c13aab11ce31a61c7e18ff1be6e70bf9b
2022-07-13 19:57:35 +00:00
dan e9a7ebe19f Fix testrunner.tcl so that it checks for memory leaks.
FossilOrigin-Name: 106f6724d54ccec3edf8c9a0422b89c4f227adb26021ed6f0fc91392ef4b3fc5
2022-07-13 17:46:42 +00:00
drh b88bf865c3 The query flattener should not run if the subquery is a compound that contains
a RIGHT JOIN in any arm and the subquery is not the first element of the
outer query.  Otherwise, prior elements of the outer query will not have
the JT_LTORJ flag set.  Fix for the problem reported in
[forum:/forumpost/174afeae5734d42d|forum post 174afeae5734d42d].

FossilOrigin-Name: 274e244c85935084b2f0f85176283f018bf9b74e7703f985bd5a2f6f8bdcff5d
2022-07-13 15:52:15 +00:00
dan 0505851451 Add test/testrunner.tcl, an experimental script for distributing the work of veryquick.test between multiple processes.
FossilOrigin-Name: ef229cbb7ffbeb8c8877dff70e9d6d43050d2297dee582a37df3a0caaebd2a41
2022-07-12 20:31:16 +00:00
stephan 4413ec7255 Renamed the SQLITE_SHELL_WASM_WEB_MODE to SQLITE_SHELL_FIDDLE, which seems to be more in line with project convensions and indicates that that flag is only intended for /fiddle mode, as opposed to arbitrary wasm-on-the-web use.
FossilOrigin-Name: d1d019bfa2f62b0dc39bba42e17786ca2e4362b6d11d206e5445a051a0f93ae0
2022-07-12 15:53:02 +00:00
dan 03437f7886 Fix another test case error message similar to those fixed in [b3d6b3c3].
FossilOrigin-Name: 6d0f677291d2b5ec68c86292da240c5557422aae1290c0844223974449ce539b
2022-07-12 15:17:50 +00:00
dan 8d48e30b39 Update makefiles to fix building the non-amalgamation testfixture with SQLITE_DEBUG.
FossilOrigin-Name: d9c4a9d09b6b22d7d95420b495dc7d7a42a0638be5824f6af6630539fe787cd4
2022-07-12 15:10:16 +00:00
drh f0af3db770 Fix a bug in wapptest.tcl introduced by [51255bad4c1fb607].
FossilOrigin-Name: b26d097e099b18ff434467adafe83fc55429488dbb8ce9c879bb03d8c5b7d3eb
2022-07-12 10:46:02 +00:00
stephan ea1e3b4251 Renamed SQLITE_SHELL_WASM_MODE to SQLITE_SHELL_WASM_WEB_MODE and no longer automatically enable it if __EMSCRIPTEN__ is defined, in order to facilitate using Emscripten to build the shell for CLI-based WASM runtimes (which cannot make use of the web-specific user input changes). The fiddle build now explicitly passes the new flag on at compile-time.
FossilOrigin-Name: ee059ad5a811a1511e37158f041a7bf9070529d530410d2f1c4395cdd25c6d33
2022-07-12 09:40:27 +00:00
drh b2d7137154 Back out the pager performance enhancement at [a1c090e08139f99d3], because it
turns out we should never allow a zero key into the pcache interface according
to the design specs, even if that page is immediately released without ever
being used.

FossilOrigin-Name: ec96293ead83603ebe5d7f250d6fdc11f22172f05a9513f175331437c3eaa4c8
2022-07-12 07:13:38 +00:00
drh ebdf4c0240 Add the --config option to wapptest.tcl. The argument is a glob pattern. All
configurations must match the glob pattern in order to run.  The default value
is "*".

FossilOrigin-Name: 51255bad4c1fb6074f602586fabad675ae310b9c37f4b80ecf60e2959fb0db12
2022-07-11 22:20:39 +00:00
dan f703b42dc4 Update the expected error messages in some OOM test cases to account for [44d77a7f807].
FossilOrigin-Name: b3d6b3c3fc68dca7e20418eefa35ce3b583322b884b88a11c6773419f027a7a4
2022-07-11 21:40:34 +00:00
drh 90120b9f4a Use 64-bit memory allocation APIs in the sqlite_stmt virtual table, to avoid
harmless compiler warnings.

FossilOrigin-Name: afb9e60ee3b194f33664a6722356e5d3c69ce1d4da1a0affd92b8e6aaf4dd2da
2022-07-11 19:47:57 +00:00
drh d5c2e08449 In the sqlite_stmt extension, store the result of strlen() in a 64-bit
integer to avoid a compiler warning, even though we know that the length
will always fit comfortably in 32 bits.

FossilOrigin-Name: 3fe19452499afc8e6b38905e1ce7e9153adbfebf10dccf39da4b7f1b0cd24f05
2022-07-11 19:12:47 +00:00
drh f1ab642cde Fix harmless compiler warnings about unused debugging functions in treeview.c.
FossilOrigin-Name: 4d6f907712e35eddf6af36eb823c3ccdfcdff1c63b2c224b3bcf34ffec95d511
2022-07-11 18:26:14 +00:00
drh fc7f8f81da Back out the optimization at [1a8c2e54375ee2cf7] because there are some
cases where it does not work.

FossilOrigin-Name: fe39c8d5fd813308fb27a05ce257ff003d3c09c0372f500e8def5a528a2558b7
2022-07-11 18:11:51 +00:00
drh cd9e863079 Ensure that the Parse.nErr flag is set following an SQLITE_TOOBIG error on
a nested parse.  Fix for the problem identified by
[forum/forumpost/d5a82ba9eedee30c | forum post d5a82ba9eedee30c].
Also, remove unnecessary clearing of the Parse.zErrMsg field
following a nested parse.

FossilOrigin-Name: 44d77a7f807f5dc3e94e6cd88a27bea79257f0f2ccf332891bdaa4668d0bb987
2022-07-11 14:36:03 +00:00
dan 3dfab26028 Fix a problem in fts3 to do with deferred tokens and OR expressions.
FossilOrigin-Name: d0bfe5c574dbc467ba97d96306d78a62a55b78dbbbe4d25aa962db6aa40406f6
2022-07-11 14:26:38 +00:00
drh 25bb72a7a8 When an OOM occurs and sets the Parse.nErr value, also set the Parse.nErr
value for all outer Parse objects.
dbsqlfuzz d33f60aaa67733aa700cd69dacf8e0e23a327a29

FossilOrigin-Name: 9a494d25944f4f640026e7a7ae2948e555d7af31487c55ed2ec2818a0789b887
2022-07-10 21:12:54 +00:00
drh 74879e137d Performance optimizations in the WHERE clause processing of the query planner.
FossilOrigin-Name: 50c8e8de52a6ba328bc9eb38e1a67033b643ddf41ff507d2240e97e0072b6db3
2022-07-08 20:03:41 +00:00
drh 5f289e8400 Omit an unnecessary structure initialization in whereLoopAddAll(), replacing
it with an assert() to show that the initialization has already occurred, for
a small performance increase and size reduction.

FossilOrigin-Name: 27be9e963459ca0b20c339264125e175550debf50fdbec7d78412768a6326b42
2022-07-08 18:23:04 +00:00
drh 4efa360f89 Size reduction and performance optimization in whereLoopAddBtreeIndex().
FossilOrigin-Name: 64d2312c121e3dabbc1f86effe9dfc57915395466ea2c3746821848f743b8d8f
2022-07-08 17:57:10 +00:00
drh 72f38795b4 In wherePathSolver(), defer initializing variables until they are actually
needed, in case they are not needed.  This gives a small performance increase.

FossilOrigin-Name: 6f28a9652a3f1e5354afb76314db8f33f92f5e888e336d025f34881c0a8d64ae
2022-07-08 16:56:47 +00:00
dan 43bb445f77 Upgrade the TEA build system used to build the Tcl package.
FossilOrigin-Name: ace65da8fa947926566037762ee9ff1b7686173eb7a50c7b55c4204171228b08
2022-07-08 15:06:07 +00:00
dan 2337e97949 Fix typo in autoconf/tea/win/makefile.vc.
FossilOrigin-Name: 094b2aadd55b0bd93cab5e3172e3a3c1bea83cd312920ffc79088d4a30d2689a
2022-07-08 13:57:45 +00:00
drh 0e400f4e7d Remove an obsolete statement from a comment. No changes to code.
FossilOrigin-Name: 99afb3f41b923f06211d655d46c902da13c8f7aadf2421d6e93c048f5b49e660
2022-07-08 11:55:54 +00:00
dan 554cb87d96 Update options in the TEA package msvc makefile to match other builds.
FossilOrigin-Name: d72e12b99dd1f8abdd855130adc27dbfc8794cfe9550a8495f68c4498a89d07e
2022-07-08 11:21:30 +00:00
dan 5ca48c0b35 Update the build options used for the TEA package to match those used to build the binaries at download.html.
FossilOrigin-Name: 9d6d9dba6680b62c24f5671109f3c28b6829645bffc5ed4e92d016fd2ad02a3e
2022-07-08 11:14:19 +00:00
drh e6aec72312 Very small size reduction and performance increase in btree.c.
FossilOrigin-Name: 9a7c031a822246ee36bc440c7492e9c8ebeec6bc7066e56f114756b1881b2eb8
2022-07-07 22:59:35 +00:00
drh f15b77b7cf Size reduction and performance increase in defragementPage() of btree.c.
FossilOrigin-Name: 1b03f197b5572084177012a58990f8dba7ff10382ff5657fda62867a4d0b1af9
2022-07-07 21:04:03 +00:00
dan c59b7b1fb0 Upgrade the TEA build system in autoconf/tea/. To match tclconfig commit 20fe9e6f59 and Tcl Sample Extension be47fb0446.
FossilOrigin-Name: 1531f7391890d7d3cd091c2d1284230f128e5282bf676967ebcb212210e51e71
2022-07-07 20:49:22 +00:00
drh ebaa9477d7 Size reduction and performance increase in the pageFindSlot() routine of
btree.c.

FossilOrigin-Name: 5d247e38560b97975568e8a48324acaca1002ec2ef7fa3efc9c8aa7d83412aad
2022-07-07 20:29:49 +00:00
drh dce232a298 Size reduction and performance increase in the freeSpace() routine of btree.c.
FossilOrigin-Name: 7d7aed053f600659c63d8bac6d5da77879936c3fc57bfd058a4943b3bc530575
2022-07-07 20:11:35 +00:00
mistachkin 07fae32db0 Fix harmless compiler warnings seen with MSVC.
FossilOrigin-Name: 61e2094afbbcbd5fdf5c3ec06b96134fafb7b854dc9bfa7d0619bed6d35efbe4
2022-07-06 23:50:01 +00:00
dan e7ebe0aa81 Avoid ignoring the last line of a csv file if the final field is empty and
there is no trailing CFLS. Also have the csv extension treat the last line of a
file in the same way as any other line if it is short fields.

FossilOrigin-Name: 587795d47fcaf5142526fabbcc4d5a632f561f258414c2846e8932a49b5b2e6b
2022-07-06 15:44:57 +00:00
dan e36281fc31 Avoid dropping error codes in the xBegin() method of virtual table sqlite_dbpage.
FossilOrigin-Name: 570e2bce595d3a48977dca0bb573dd3fe745a0d13b7122b3ad8ab4745c0700d0
2022-07-06 13:59:45 +00:00
dan f53487a42d Fix for builds with both SQLITE_DEBUG and SQLITE_OMIT_WINDOWFUNC defined.
FossilOrigin-Name: 77916947ce3f0828e1c50bcb8a6438c951ab9e74d83ec4324e82e90e100b9a98
2022-07-05 19:53:59 +00:00
dan c578e4f0eb Fix a problem in the csv extension that was triggered when the very first field in the csv file is zero bytes in size.
FossilOrigin-Name: b12ddabf07b5e06bcee8dda3f990af3a131ab52b8fa969ba061b26d38458f31d
2022-07-05 17:49:04 +00:00
drh 48cae1320b Fix an assert() in btree to be more precise, as the previous form of that
asser might fail due to recent performance optimizations.

FossilOrigin-Name: 4774938134d0105423720bdc1b4e82164a1e28d993c5cd81c1b03f1f0878427e
2022-07-05 10:40:30 +00:00
drh 3325a5c497 Size reduction and performance optimization in sqlite3WalFindFrame().
FossilOrigin-Name: 1a8c2e54375ee2cf73773b798fed0ae07b42f5e068fddc513c093de5c1f46615
2022-07-04 15:14:25 +00:00
drh 16316f1b68 In the getNormalPage() routine of pager.c, consolidate pgno error checking
into a single spot for small size reduction and performance increase.

FossilOrigin-Name: a1c090e08139f99d30aa89db0756dc59fe8990ce15b3db4d4b726cc6acdab46f
2022-07-04 09:41:44 +00:00
drh 0e4ab0db7e Enhance the REGEXP extension so that the end-of-input indicate ("$") is
allowed to occur on one branch of an OR ("|").
[forum:/forumpost/0107d5d40dd273e2|Forum post 0107d5d40dd273e2], second
issue.

FossilOrigin-Name: 3c04d21e6c632feb3bea8d1fa76bedcbfe254b0dc59865633d158a3f1bddefba
2022-07-03 18:12:43 +00:00
drh f28727f61e Fix the initial-prefix optimization for the REGEXP extension such that it
works even if the prefix contains characters that require a 3-byte UTF8
encoding.  This should fix the problem reported by
[forum:/forumpost/96692f8ba5|forum post 96692f8ba5].

FossilOrigin-Name: c94595a6e15490b432f099fefbe2429fa19287f7bdc86332cba0fd1e08f65bd6
2022-07-03 14:25:47 +00:00
drh a57ac0a827 Improved comment on sqlite3VdbeSwap(). No changes to code.
FossilOrigin-Name: 6a8e4fb72a9e3dea9e5752c3d54fddba8878b355bd43f3c879f042f247a6610f
2022-07-03 11:16:03 +00:00
drh 20e9cbe0ff Remove debugging code that has always been commented out. Cosmetic change.
FossilOrigin-Name: b54064170c51a2c905f98737c224e19c06dc728342ca2224e32ebeb47f803bcd
2022-07-03 11:12:59 +00:00
dan 2c1b1ddc55 Do not attempt the OP_Count optimization on queries with HAVING clauses.
FossilOrigin-Name: 566b7842ee286ed8620a87b06de65bc173ad0d208df4157292238fcb059cb484
2022-07-01 21:03:19 +00:00
drh 064390b2b1 Performance improvement in resolveP2Values(). Save over 1 million CPU
cycles by omitting the loop termination condition and exiting when the
OP_Init (always the first opcode in any VDBE program) is encountered.

FossilOrigin-Name: bb179140c8abfd9d05d62380daba027bdeabbbafc720b7e36b99a36af806017e
2022-07-01 19:42:12 +00:00
drh 2b294b543f Small performance improvement to sqlite3_finalize().
FossilOrigin-Name: 8a6913b66cc5af354497044ccb849eb80d00d0799362475f1537a6999196895e
2022-06-30 22:46:28 +00:00
dan d85e4ac347 Add missing "finish_test" command to the end of test script merge1.test.
FossilOrigin-Name: 13cb3f1e63ed1e906f820655645a4966f0cae140ac442177b6685637dcfd365a
2022-06-30 11:01:48 +00:00
dan e26f592ea5 Have the sqlite_stmt table buffer all data for the current scan within the xFilter method.
FossilOrigin-Name: 84a91c255e3d77728820561f16bdd9a87b7ff42b5430a9e13f404dfc3365c716
2022-06-29 15:16:48 +00:00
drh b0b734d145 Fix a missing dependency for json.lo in Makefile.in
FossilOrigin-Name: 65930a5c069e7274b945ce1aed0abb0edba3d4ab4e63916cc38c11cdef998926
2022-06-27 11:28:25 +00:00
drh 54f1fc4f94 Put an ALWAYS() on an unreachable branch.
FossilOrigin-Name: 58caa50a410b7eb0e68658ea1e606d75ea85cdae04e864270c932246ba990b5e
2022-06-25 20:32:29 +00:00
drh fe9833482f Allow flattening of a subquery that is the right operand of a LEFT JOIN
in an aggregate query as long as there is no GROUP BY clause.  (The GROUP BY
clause will interfere with the operation of the TK_IF_NULL_ROW expression
nodes.)

FossilOrigin-Name: 2cf373b10c9bc4cbc5fe63d0a6948011df7bbc2f40dc025c9349f875da782b88
2022-06-25 19:43:44 +00:00
drh 62f1b48638 Increase the version number to 3.40.0 so as to begin the next
development cycle.

FossilOrigin-Name: 4542e32302067f24bf71c77620e09663f47c3ddce703c21ffa82d09532ae1d51
2022-06-25 19:30:07 +00:00
drh 3691e56210 Fix documentation type. [forum:/forumpost/8d900996ed|forum post 8d900996ed].
FossilOrigin-Name: 869061f18d2f2f500451c87ab62d3ca71a5321d5246b2e2c7bf960e48c6b5250
2022-06-25 18:55:08 +00:00
drh 47d8c40ca5 Version 3.39.0
FossilOrigin-Name: 14e166f40dbfa6e055543f8301525f2ca2e96a02a57269818b9e69e162e98918
2022-06-25 14:57:57 +00:00
drh a36fedbda0 Change a harmless assert() into a testcase(). The actually test case code
is in TH3.  Fix for the problem described at
[forum:/info/ed29e196d5c4f3d5|forum post ed29e196d5c4f3d5].

FossilOrigin-Name: cd6254fcd32798f7be4e6d827597ddaa2e46ac6e2f0149cd3a3be0416fa18835
2022-06-25 02:39:29 +00:00
drh 86bc5e41bb Fix a harmless UBSAN warning associated with PRAGMA schema_version
found by OSSFuzz.

FossilOrigin-Name: e93fd170ce4ae91d572c46d03f68f55d00091d0188030517455017d90d212587
2022-06-24 12:56:48 +00:00
dan a5ec23a705 In sqlite3WhereBegin, do not proceed with coding the loop if an error is detected as part of WHERE expression analysis.
FossilOrigin-Name: db5266dec601a9513bc8dd09a9f8bb4aef55b780d22610946099e8edd4836587
2022-06-24 11:05:36 +00:00
drh 2a40a882f2 A minor fix to test/fuzzinvariants.c so that it works even with column names
that originally contain a ':' and that are disambiguated.

FossilOrigin-Name: 8d9b1fff9d87522c4464aaf3ff0a7b93db244c59b4010562e35a8f161da4859b
2022-06-24 11:02:42 +00:00
drh 521e0b6cb6 New test cases for query flattening with LEFT JOIN.
FossilOrigin-Name: 27f68e47320c751e3663507500c1c44f0b7f885f89c678fce6a35b1bc372dd64
2022-06-23 22:43:11 +00:00
drh 3a6e0c3f04 Reintroduce flattener constraint (3c), but this time make it apply only if
the outer query holds a GROUP BY, not if the outer query is an aggregate.

FossilOrigin-Name: 641dfb9182a6cbadb3c452f5420f896791b7844b794f693443bcd38dca14da35
2022-06-23 20:56:45 +00:00
drh d198183465 Add back the ability to flatten a LEFT JOIN subquery - previously removed
due to ticket [cad1ab4cb7b0fc344].

FossilOrigin-Name: f8fe936ad4f7678f9b26ba6fab41c5df9f4938634cdb3286b0f2dcd1357f919a
2022-06-23 15:15:03 +00:00
drh 9efc618607 Minor correction to a comment. No code changes.
FossilOrigin-Name: 5fa00959ebc3a46fe400564d5a30e8c44857cd4f0473fb25e84154019eff3f39
2022-06-23 12:36:56 +00:00
drh 2b0ea0204f Enhance the TCL scrip that generates sqlite3-all.c so that it outputs all
text in its original order.

FossilOrigin-Name: 83ff1a28e3e7a99fa90d5079897d76529c4256eed859bf7cb98b860fbedfdc5b
2022-06-22 18:51:47 +00:00
drh f221e4b5d6 Fix requirements marks that changed due to typo fixes in the documentation.
FossilOrigin-Name: 5247df05991df979024df5a30bb3473401add92d4c12b01c040a16dda6da39f5
2022-06-22 18:33:21 +00:00
drh cf5cab01cf More comment fixes. No changes to code.
FossilOrigin-Name: 5c9133ef431a031249760267ca851239d0857ffba633cac27d3865cf179c3274
2022-06-22 15:55:28 +00:00
drh 0751fc3b85 Allow more line with on the debugging output for SrcItem elements in the
parse tree.  This affects debugging builds only and is a no-op for production
builds.

FossilOrigin-Name: edbe24e7fc81ab6c26ab05f2231cb46d157d71a677ce8a2983e0c6e48122a2bd
2022-06-22 14:43:52 +00:00
drh 2591cfb673 Additional enhancements to comments. No changes to code.
FossilOrigin-Name: d9a320448f5693d906adf437800675cd4773701db065f3ed238b933fb80f6681
2022-06-22 14:25:12 +00:00
larrybr b885744709 Give dbtotxt an option to prepend .open --hexdb
FossilOrigin-Name: afeee6125d141ae281658a5f7b73e9b77bc252fa387678b2b5837488180bf108
2022-06-22 14:00:24 +00:00
drh 861ac67a9d Fix a typo in a comment. No changes to code.
FossilOrigin-Name: ef9de201b33678a80bb27c5be8f9dc973c8a4f14af9bfdd3ace36887c8a591ea
2022-06-22 12:54:25 +00:00
drh 8c44962aaf Disable the short-cut query planner if the NOT INDEXED modifier is used.
[forum:/forumpost/454d706296|Forum post 454d706296].

FossilOrigin-Name: bd87d107fe474ceeac8bacb01c80bc479edbc2ae4e30697bf54ab91a5a8d2a98
2022-06-21 18:38:18 +00:00
drh b9294de1e6 Allow a HAVING clause on any aggregate query, even if there is no GROUP BY
clause.  This brings SQLite into closer agreement with PostgreSQL and fixes
the concern raised by 
[forum:/forumpost/1a7fea4651|forum post 1a7fea4651].

FossilOrigin-Name: 9322a7c21f1c22ba00e9b889223e89bc1591db6e561ce05091e905e98c1bf2b3
2022-06-21 13:41:24 +00:00
drh 4af6462fb8 Add an ALWAYS() macro to an always-true branch.
FossilOrigin-Name: 364645d8fe22491cd566e868027e739464205e892753356016b1988ead207af4
2022-06-20 19:12:57 +00:00
drh 436c28a265 Do not allow FROM-clause terms on the left side of a RIGHT or FULL JOIN to
be reordered. [forum:/forumpost/6650cd40b5634f35|forum post 6650cd40b5634f35].
This is probably more strict that necessary to get correct behavior,
but for the first release that supports RIGHT/FULL JOIN it is perhaps better
to be correct than fast.  A less strict constraint might be to prohibit
FROM-clause terms that originate on the left side of a RIGHT JOIN from
crossing from the right side to the left side of a LEFT JOIN.  Revisit this
later.

FossilOrigin-Name: 238453ffab0ba1bdddb529be35da82d5e8fb312a9574003a5441f455e601a909
2022-06-20 18:26:14 +00:00
drh d7480403bc Do not allow an ON clause to references tables to its right if there is a
RIGHT or LEFT join anywhere in the query.  Other RDBMSes prohibit this always,
but SQLite must allow ON clauses to reference tables to their right for legacy
compatibility, unless there is a RIGHT or LEFT join someplace in the query,
in which case there is no legacy to support.

FossilOrigin-Name: e615dbe02ca949252d1526ed5c48f8ce08159773ea2008ce666484379d0d9854
2022-06-20 17:04:44 +00:00
drh ae8776e092 The fix at [cab9b4cccd13bf0a] was incomplete, as demonstrated by
[forum:/forumpost/57bdf2217d|forum post 57bdf2217d].  This check-in
should complete the fix.

FossilOrigin-Name: fb0a23b6789da8e934562ce9ebd9d58ea13a10fd10dee5cbfc7ac8f394e1aeec
2022-06-20 12:42:28 +00:00
drh 1d49768151 Follow-up to check-in [0057bbb508e7662b] - ensure that the database page
has been initialized prior to continuing with the optimization.  If the page
is not initialized, that indicates that the database is corrupt.
dbsqlfuzz 09ee46becd5e6d1b2a55c9f8ad767335a90aadb0.

FossilOrigin-Name: 11162446f12ae3af6e4a63bb5c374129b2505f6006f91d4028c7165f05fe9651
2022-06-19 16:55:07 +00:00
drh 13736999d9 Enable query invariant checking in fuzzcheck by default. There is no way
to turn it off.  Update the invariant checking logic to be consistant with
dbsqlfuzz.

FossilOrigin-Name: 66ca729bbbf37cb7ff8eb12f51429e0c0833bd5d3f0ef20a1eaeeb10820713c2
2022-06-18 20:20:30 +00:00
drh d0d21f5565 Abandon a query-invariant check in fuzzcheck if the call to
sqlite3_bind_value() returns anything other than SQLITE_OK or SQLITE_RANGE.

FossilOrigin-Name: d31e1cd2ab44c7cce20b8990dff17719c286dd2fb46ba6d4f581a9553cf31891
2022-06-18 14:50:43 +00:00
drh 8fa6206bc4 In the --query-invariants option of fuzzcheck, correctly deal with OOMs
causing the return value of sqlite3_column_name() to be NULL.

FossilOrigin-Name: eabbee4a51bc1a865bddee890004ff3a1c9cc6b797b21f73e908642e154cef50
2022-06-18 10:26:12 +00:00
drh 01156ec1c9 Fix the OP_Concat operator such that when concatenating a BLOB with an
odd number of bytes on a database that is UTF16, the size of the resulting
string is reduced to a multiple of two.

FossilOrigin-Name: 5eb2c23635320b76f5e1aea4d94375b847fe4b38cdb4e287fba188753f4773b1
2022-06-17 21:31:30 +00:00
drh c2beb0d8f6 Omit the --query-invariants processing in fuzzcheck for queries that contain
the implies_nonnull_row() test function.

FossilOrigin-Name: 0602a0844893465ac2fe53c0fa648a5cbcbc6452fff6181c42fab517f047b583
2022-06-17 17:11:51 +00:00
drh f26e45139e Do not run --query-invariants on statements that make use of
sqlite_offset().

FossilOrigin-Name: c5ac4cbfb173c613d633b2c76484d735073692d001a336576174201b8f9af7b1
2022-06-17 16:52:54 +00:00
drh b103c574fd Various fixes and improvements to the --query-invariants option of
fuzzcheck.

FossilOrigin-Name: 09aca89b7c26c1eb7f9df1d1cfdada18848d7c188fa7fbbcf95442dabce476ea
2022-06-17 16:39:55 +00:00
drh ea64cb31a5 Allow integers and floating point numbers to compare equal.
FossilOrigin-Name: 0fe2e465ba931d4bceaf171693d2ee7af45a5f96840e65e9d4ee4a2e60f155d8
2022-06-17 16:32:21 +00:00
drh 63880362ed Improve query-invariants to the point that it would have discovered the
[f23a429d4153518d] bug if that bug had not already been fixed.

FossilOrigin-Name: 2a7251ed9c4c959b6df75172159c6b4445e1c2212e357d2c49ab8fa19cb3ac11
2022-06-17 16:09:47 +00:00
drh c68fb84759 Only run query-invariant checks after the original query has run to completion,
so that we know it does not error-out on a subsequent row.

FossilOrigin-Name: d1fc857bb8dcd5914f5a9bbcc4efe5f4abe19a190e42e2c923b28327a95e4de6
2022-06-17 15:52:43 +00:00
drh 36f904f065 Fix the virtual table detection mechanism to avoid false-positives that were
blocking all failures.  Then fix a few of the additional problems that are
revealed by that fix.  More fixes are needed.

FossilOrigin-Name: 42b2e6676fed1508ea0ba17c292e83134825469735700da97817c45d45c54e66
2022-06-17 15:11:31 +00:00
drh 6efabd6cd3 Fix the new --query-invariants option on fuzzcheck so that it does not
use an unprotected sqlite3_value object as an argument to sqlite3_value_int64().

FossilOrigin-Name: d9f820151d74a690b5fa560597a5b3ace20165a112e1b58cb4a7c47b42745643
2022-06-17 12:25:33 +00:00
dan 2a7aff93ed Avoid omitting the rhs of FULL JOINs in cases where it is only correct to omit the rhs of a LEFT JOIN.
FossilOrigin-Name: f23a429d4153518d37387e121f22a30b22e2b31e126ad168e72049a96be86269
2022-06-17 11:39:24 +00:00
drh 3e245bcef3 Minor fix to the query invariant testing logic of fuzzcheck.
FossilOrigin-Name: 447e62a0946f5d77b7358adcabaeb23a7012cdfbfa1ef6082734cd9b45b2699d
2022-06-16 20:29:36 +00:00
drh 8f9261a8e9 Improvements to query invariants in fuzzcheck.
FossilOrigin-Name: 3a461f61b47e6ba6d5dcc2b7470ebde512b57bc68086f65050e07b06f42b7351
2022-06-15 20:18:44 +00:00
drh e3bf2c8e9b Improvements to query invariant checking in fuzzcheck.
FossilOrigin-Name: 56c60a35ea457f06db58ec3f694a1ae16fd03e6625da1d7879d63d72bbcb1c62
2022-06-15 16:26:37 +00:00
drh dba3a5ab87 When running an incremental vacuum, detect growth in the size of the database
file (which can only occur if the file is corrupt) and fail with SQLITE_CORRUPT.

FossilOrigin-Name: cd7a44124558ea6a43c89b1cba4402d7bf6a6ccb83be0eeb7dd01b56933bca73
2022-06-15 14:57:04 +00:00
drh 516c85026b Add the --query-invariants option to fuzzcheck. No changes to the SQLite core.
FossilOrigin-Name: fef282f9fbb10967102f9676d85b8c6a3b36aff7109f1becdaeaeddef0dff4f1
2022-06-15 12:50:51 +00:00
drh 10c5341c72 Dbsqlfuzz discovered a case where a bytecode branch is in fact taken, so change
the designator from VdbeCoverageNeverTaken() to VdbeCoverage().  Test case
in TH3.

FossilOrigin-Name: 988a2a759f2b9da0e287e65306039b7a3e2b5aac3d31fe15cbb30d30ea6caf71
2022-06-15 12:32:27 +00:00
drh 0c278c3d76 Add the --query-invariants flag to fuzzcheck. The query invariant checks are
only run if that flag is enabled.

FossilOrigin-Name: d13b4621291831ff33cc4a8d53653eaa3f59fecf2fbc5d404db17e33a914495d
2022-06-15 10:46:52 +00:00
drh a913f9b992 Improvements to query invariant testing. Almost working now.
FossilOrigin-Name: e039820418d64fb57cb1a8f9f21186284e6c76255a53445c5d7aef6cca89bfc4
2022-06-15 10:37:16 +00:00
drh 27a242c634 Fix the OP_NullRow opcode so that it works even if it applied to an
ephemeral cursor that has not yet been created.

FossilOrigin-Name: 0e925654c24774933c7738c68f704b229c68e18c8baa45f506b8d6f09164d0d8
2022-06-14 22:21:23 +00:00
dan bbf71138cf Add missing SQLITE_FCNTL_SIZE_HINT call to a path taken during transaction rollback.
FossilOrigin-Name: 6c3266c1b4fc446c7c3a40a8816caf4f9fe0cafe4f27cdafecac61425a17927e
2022-06-14 21:34:13 +00:00
drh a1f79dae98 Attempt to enhance fuzzcheck to do some simple invariant testing on queries.
This is an incremental check-in for a work-in-progress.

FossilOrigin-Name: ce2d780163b3a28486904860a1815acc4169c09b971cfd199bb58d1e9a57b000
2022-06-14 19:12:25 +00:00
drh 92d1afba9b Do not remove the EP_CanBeNull flag from expressions during a LEFT JOIN
strength reduction if the query also contains a RIGHT JOIN. Fix for
the problem identified by
[forum/forumpost/b40696f50145d21c|forum post b40696f50145d21c].

FossilOrigin-Name: b1be2259e2e08ec22a88bc9a18b3ab4d83246ad4c635c05cdf80d3eff84df06a
2022-06-13 12:42:24 +00:00
drh 1cc5c4ac84 The same restrictions on the use of WHERE clause terms to drive indexes
in the presence of RIGHT JOINs also apply to the use of WHERE clause terms
to manufacture automatic indexes.  This fixes a problem identified by
[forum:/forumpost/51e6959f61|forum post 51e6959f61].

FossilOrigin-Name: 342c501f532523347e6c339351e02043dd6ee9e11a291224b65ea72bd6c2ba40
2022-06-10 16:41:54 +00:00
stephan e45b87a9b7 fiddle: minor style tweaks, including using swapped colors for the input/output fields to help (hopefully) reduce the "which field is which?" dissonance.
FossilOrigin-Name: e25dad868f9ef2c7847319c9f6f106999ba8b0a3e09ed9edfbd25e8fc6f3c10e
2022-06-10 15:43:03 +00:00
drh 958fcd417c Do not allow constant propagation between WHERE-clause terms and ON-clause terms
as this can confuse RIGHT JOIN.  Fix for the problem reported by
[forum:/forumpost/8e4c352937e82929|forum post 8e4c352937e82929].

FossilOrigin-Name: cab9b4cccd13bf0ab2bc38dc9a9c04ddd34e29c65ab6aef07b6bb3c31a43bece
2022-06-10 11:28:52 +00:00
drh a27e350b6f Fix a faulty assert() statement identified by
[forum:/forumpost/0b91a75039|forum post 0b91a75039].

FossilOrigin-Name: 1f132bb03a22479ceeca0fd14940e2a1b29ce54b7784d5b0133450056813d877
2022-06-10 10:10:31 +00:00
stephan 0c2b00b0d6 fiddle: modernized the UI based on related code in fossil's /pikchrshow. Changed the color scheme to match sqlite.org.
FossilOrigin-Name: c4523ffcc076e9cddba62c3b832f9a04d4f3c5595a312ac74099927aae085a52
2022-06-10 09:31:12 +00:00
drh 65458dc146 Do not allow the subtype of a value to cross a subquery boundary. This
fixes the problem identified by
[forum:/forumpost/3d9caa45cbe38c78|forum post 3d9caa45cbe38c78].

FossilOrigin-Name: bbaf1f2eb1e1637b356ed7ab1d1cf5bbc8e1fe3bb2fb46a8f37de091726f38af
2022-06-09 20:26:06 +00:00
drh e5dea28482 Prevent subtype values from slipping across a subquery boundry when the
subquery is implemented as a co-routine.

FossilOrigin-Name: 9e51a6c0fbfb1899b2b01888430125fba6d4da9bad9eeaa3ad41e29fca54bbe5
2022-06-09 17:17:14 +00:00
drh 8878f8a8d3 The subtype of a value should not propagate across a subquery boundary.
Proposed fix for the problem reported by
[forum:/forumpost/3d9caa45cbe38c78|forum post 3d9caa45cbe38c78].
Additional works is needed as not all cases are covered.

FossilOrigin-Name: 08af1fe27ebd0edf6e0f1ac477deea033e7f7c813f1016b75196836daf02d2e4
2022-06-09 16:19:01 +00:00
drh 0483668007 Move an #ifdef in shell.c to avoid a harmless "unused function"
compiler warning.

FossilOrigin-Name: 5abb5ef500f52c52dac33e54d824cf89481fec1643c27943f34f0ca4560a7e00
2022-06-08 18:29:23 +00:00
dan 0a841a2b85 Avoid zeroing the value returned by sqlite3_changes() when a DML statement is automatically reprepared in sqlite3_step().
FossilOrigin-Name: 09c8f9f1970cd5b369d98a2b38f0b04d44ed095cb0bda80f7968bb6be4e0263b
2022-06-08 18:20:36 +00:00
drh 8a5469b6f5 Improved comments on the new query flattener restriction of the previous
check-in.  Also a NEVER() macro on an unreachable branch.

FossilOrigin-Name: 8c9e2d6315fde014bd6e25a7fa58ba054f5328c8a56e9d3d1c2d069c025a1b03
2022-06-08 17:48:14 +00:00
drh 40357f0d5d Fix the query flattener so that it refuses a flattening that might leave both
an inner-join and outer-join ON-clause constraint (or equivalent) on the same
term of the FROM clause.

FossilOrigin-Name: f6c4fb48b65c2e8659aa0a1119c330e8bad5e42b2db2030850bfc9c04afef5c8
2022-06-08 15:38:16 +00:00
drh 5c118e3946 Add restriction (29) to the query flattener - do not allow flattening that
would leave both EP_InnerON and EP_OuterON constraints on the same join term.

FossilOrigin-Name: c585d6a4678b04f4cedc08852d01c44cdf52ae2c8ccd1174c3d5a395088bf528
2022-06-08 15:30:39 +00:00
drh a341bae948 New test cases refute check-in [3f45007d544e5f78].
FossilOrigin-Name: 12d3c96c39d12f6b01b77456eb874fff445ebfc60f50aada51b06ed37af364ea
2022-06-08 13:13:12 +00:00
drh 093dd41e97 Do not allow a partial index scan on the left table of a RIGHT JOIN, because
since the index is partial, some rows will be omitted from the scan, and
those rows will subsequently be picked up by the no-match logic in the
right-join post-processing loop.
[forum:/forumpost/c4676c4956|forum post c4676c4956].

FossilOrigin-Name: 615c0026119f7870c3b6ef9dcb57ce4ecf5acedea3e2b5cfc25aa450eb8f17a0
2022-06-08 12:46:58 +00:00
drh f6bee94e22 Minor fix to test/index9.test so that it can be invoked with other
index tests using a wildcard.

FossilOrigin-Name: ccbd6e774903f9202f9311954979f6fcc3b13eba1f3402a549a7aee6ed1d55eb
2022-06-08 12:35:39 +00:00
drh 644817721e Update the routine that determines whether or not a partial index can be used
so that it is not specific to LEFT JOIN.

FossilOrigin-Name: 5a107fd7fa01554d73fefc0611e5797b8c23e782ce0df3aeba7e2f288675b2ce
2022-06-08 12:20:49 +00:00
drh 33b2cb9aec Fix the query flattener to deal with a RIGHT JOIN corner case described
by [forum:/forumpost/323f86cc30|forum post 323f86cc30].

FossilOrigin-Name: 3f45007d544e5f787d5837b4d9f484ba473d69cdba83c229228e9c2f6b972b75
2022-06-07 13:09:58 +00:00
drh bb1369037b Test cases for [forum:/forumpost/323f86cc30|forum post 323f86cc30] added
to join8.test, though commented out so that they do not (yet) run.

FossilOrigin-Name: 7f97cb67d01a11f1b7e5b5f05824f9adbc6e4689d1809d60ceda50a595ba6d4a
2022-06-07 11:02:43 +00:00
drh d580bea7d4 Preserve the database encoding on the CAST operator in the
sqlite3ValueFromExpr() routine.
[forum:/forumpost/800eecf5e6cdc3f4|Forum thread 800eecf5e6cdc3f4].
Test case in TH3.

FossilOrigin-Name: 3f6a442099b8264cc788e8aa2b12cc583439a5263c4fe433fd22b7af1be2458e
2022-06-07 10:14:22 +00:00
drh 6fdac75127 More precise determination of when a WHERE clause can be used to drive an
index on an outer join.

FossilOrigin-Name: 318543a91108c6fd0764d7ee7beee49838f54d44c54dae3dc9d4cb8336d52fe1
2022-06-06 23:22:06 +00:00
drh 16828c8c12 More precise determination of when a WHERE/ON clause term can be used as an
indexed join constraint.  Testcase macros added to ensure test coverage.

FossilOrigin-Name: f419e98c515e704efa11728192b2594e962cb0e6d2d1837f99a8caf65f4d93cb
2022-06-06 22:33:44 +00:00
dan 93c4087ffe Extra test cases for outer joins.
FossilOrigin-Name: c7505765280fb27ec2c8c4da6f87229a4078e3a4a27525226b6bf55864caa04b
2022-06-06 21:08:27 +00:00
drh c18fc6134e Do not allow a WHERE clause constraint to be used to drive an index for
the right operand of a RIGHT JOIN, since this can cause problem if the
constraint implies a not-NULL value for one of the columns for the left
operand of the same join.  See
[forum:/forumpost/206d99a16dd9212f|forum post 206d99a16dd9212f].

FossilOrigin-Name: 4a31b7942a15c9c4363477365784d6d4ac5b1bbe8ff8aeaf2dd3d6532bf8bc96
2022-06-06 15:27:42 +00:00
larrybr 8a4d2bc34f In CLI, drop .dbinfo command when build options prevent it from working.
FossilOrigin-Name: 4b50a55165f4603674a250df89cfc5ac1fef8aabaf433df8400df14d53bfbbe0
2022-06-06 15:22:11 +00:00
larrybr 0dbb3db431 Sync w/trunk, pickup fts3corrupt6.test change.
FossilOrigin-Name: 268072f636b25c24ec47e34f2a8356f466ec200b80487b1041e89e0ae909c8bd
2022-06-06 14:00:41 +00:00
stephan 8fca1c7044 fiddle: replaced the huge file selection widget with a smaller proxy button.
FossilOrigin-Name: f7c17449ea0685e322f50abe7a59b7afcde0f7e38e03645ec5b13753a6d0dcf3
2022-06-06 06:29:09 +00:00
dan fd80fa9b6d Fix a test case in fts3corrupt6.test. Was failing due to [f1dfbc4f].
FossilOrigin-Name: 04b2e47784238008ce9057e2761ded91d895dc16d3bc8a3a3508df98a4769602
2022-06-06 06:17:54 +00:00
stephan 626aa48c26 shell: in WASM mode, permit ATTACH because the filesystem is a virtual sandbox and ATTACH can be used to provide more import/export options. Minor doc updates in sqlite3-api.js.
FossilOrigin-Name: f28de5b726999b913b442fa51355d020ba1f1662d2f7978380623c16438eb238
2022-06-06 04:09:44 +00:00
larrybr f3d6e8fd6e In CLI, drop .dbinfo command when build options prevent it from working.
FossilOrigin-Name: 2512d2f68dfff4d74c881a4102b63ca528e690ad93ab2b4eb1f03ce1d9ac155c
2022-06-05 22:58:40 +00:00
larrybr b61c2424d7 Create new branch named "dbinfo-guard"
FossilOrigin-Name: 8d942ba72ea995d0e8d1f8694bb428e5f919fc75afd3e059a69547e27991d580
2022-06-05 22:40:49 +00:00
dan 93a4b411ef Fix to test case in fts3corrupt.test. No changes to source code.
FossilOrigin-Name: d18818afc6021a32989499c26ab38fa442e5a55e662e39bb06e5c0daa9c65e25
2022-06-03 14:08:40 +00:00
dan 181d75ef9e Fix a 1-byte overread in fts3 that could occur when processing corrupt records.
FossilOrigin-Name: f1dfbc4f7452154ca5190ac22e17fdabebb92833967b11f7dae21b8d3a5857bd
2022-06-03 13:52:53 +00:00
dan 410fac35d7 Fix a problem with flattening and window functions causing an "IS <column>" to be transformed to "IS TRUE" or "IS FALSE" when <column> is a view or sub-select expression that is the literal value "TRUE" or "FALSE".
FossilOrigin-Name: 2a952c7738d94e70024e06600fee8c3a49f317f2d02774468019bd7cf9488c8b
2022-06-02 16:26:21 +00:00
mistachkin bf154369e7 Avoid a direct use of abort() in debug builds to prevent a compilation issue for Windows CE.
FossilOrigin-Name: 8eb9a7dd07afc0aef0b7c67054d73e7e821138867d115407b71c985e90d44d59
2022-06-02 02:45:59 +00:00
drh 486191603f New test cases for row values and RIGHT JOIN.
FossilOrigin-Name: 5f0582b90fab9111e4a645c692549c35480e62635c596f8c7fa3466bd22f7235
2022-06-01 20:08:22 +00:00
drh f89f4efb28 Ensure that subqueries associated with row-values are invoked before being
used when processing a RIGHT JOIN.  Fix for the problem described by
[forum:/forumpost/087de2d9ec87305b|forum post 087de2d9ec87305b].

FossilOrigin-Name: 5a9465dcc0c23fc2c66cd4898bcdfd5086fe4c71ec19a95db7221fdf7c0bbbbd
2022-06-01 16:05:25 +00:00
stephan 4e5aeb54f2 fiddle: added another UI element to the list of those which are disabled during long-running activities. Added DB.close() binding to the Worker-based wasm binding.
FossilOrigin-Name: 5933163ed1a8f996e81023c7c5822655dc6411d30016f37fe8863f760530dc5b
2022-06-01 16:04:29 +00:00
drh a5d06a3d54 Ensure that all necessary row-value subqueries are invoked while running
the right-join post processing.

FossilOrigin-Name: e4e71b4cd4c026fc36f0da1703e6237e6ddd8ff2e08dc3c0011632b9e63098cd
2022-06-01 15:53:11 +00:00
stephan 23aa8ff4de Minor tweaks to, and consolidation of, the wasm-related build flags.
FossilOrigin-Name: f0ad6b1b324f9c0f4340f6cf9584884d1206b56fe1010db43bcbef324e713ea3
2022-06-01 14:52:23 +00:00
dan f74f4ed5b5 Fix a minor problem in the Tcl "incrblob" command. This does not affect the SQLite core.
FossilOrigin-Name: e96feccc21d9b858f076960e029b615809243d0cc3f95db75180feb01887451f
2022-06-01 14:32:05 +00:00
drh 0f4b534b60 Candidate fix for the problem with row-value WHERE clause constraints on
a RIGHT JOIN.

FossilOrigin-Name: fdd782a7bb217e2aceda97a588c0d7874ee19885abfcf0658472d6c3387da6ee
2022-06-01 13:32:47 +00:00
drh 6d013d890e Only include the code for sqlite_offset() if compiled with
-DSQLITE_ENABLE_OFFSET_SQL_FUNC.

FossilOrigin-Name: 382cd7e10b2df4216da8f25b55546bc74a963d9834af240f75ec8b8321ba106e
2022-06-01 13:32:05 +00:00
drh 1324b2830e Fix a typo in a comment in a test case. No changes to code.
FossilOrigin-Name: 570efa45dd4c6848dcbd550f78fcaa00b6d84dcffe0a2d12e65ea8ee4468c0e8
2022-06-01 13:01:57 +00:00
drh 0286cdbca6 Additional enhancements to the test cases.
FossilOrigin-Name: 55cfad74cace74e541b354228e3ad46e17028213a9f639edf2007c6a8f3ba8fc
2022-06-01 11:58:11 +00:00
drh 47b4969e2d Fix test cases in the previous check-in to make them postgres-compatible.
FossilOrigin-Name: f223ba72b6e02a7ccfd894b4b135f4609b1eb79f547ec279b1c52a6996cd5a73
2022-06-01 11:46:39 +00:00
drh 36c19f7799 Test case for [forum:/forumpost/087de2d9ec|forum post 087de2d9ec] showing
a problem when a row-value constraint is used with RIGHT JOIN.

FossilOrigin-Name: d1e3e0d26e302587a6cfcb7aa4fcdefe2b3891037732a0df0d0fe10a14454e00
2022-06-01 11:43:57 +00:00
stephan ea7a4e4fb3 The Worker-specific variants of the most significant DB-class JS bindings are implemented, most notably various uses of DB.exec().
FossilOrigin-Name: 371d6f7497016ca9bf82c8524b4d701ddf1e614b3fb4e69ff63935da0d51ed05
2022-06-01 11:20:07 +00:00
drh 645682a7c7 Move the sqlite_offset() function implementation to be an in-line function,
thereby avoiding special case code and freeing up a bit in the
FuncDef.flags field.

FossilOrigin-Name: 1c9812c458bd229c862efe5df1b64fae333da9871c8756b5ae4605a81bcda4b5
2022-06-01 11:05:59 +00:00
stephan 6ffa895884 Initial proof of concept code for a JavaScript binding which runs in the main window thread but acts on a db handle running in a Worker thread. Expanded the DB.exec() and DB() constructor to simplify certain use cases.
FossilOrigin-Name: d9efe3e92d1c95aee6f5ae37a8ba28d8cf4891d746744ce4aa2464f766821a0b
2022-06-01 08:09:06 +00:00
stephan bff17db433 Initial bits for a JS API variant in which the client operates in the main thread and sqlite3 in a Worker. This is far from complete.
FossilOrigin-Name: f6d6f969791f0d2367ae5418623b4794f6df657d9d7d9002fb5aec4206dcfd4c
2022-06-01 00:00:59 +00:00
drh c7fc08f69a New FULL JOIN test cases. No changes to code.
FossilOrigin-Name: 13e89ef6649475815d3f4e4aef73a4be1157dd388e55c7f856faeb4b7387774b
2022-05-31 18:18:09 +00:00
drh aa03c69591 More JOIN test cases inspired by the problem fixed in [3869fd9a2b9483cb].
FossilOrigin-Name: f2d224c5fa06de70f6f22e159a3b7065d4c6b004f9accc13004b9ac1f2fd5549
2022-05-31 17:24:56 +00:00
drh f51672a945 Fix an assert that is incorrect for a corrupt database.
FossilOrigin-Name: fe0a840805b435efd38a953a8aae60e29a35289f9d9955472a8bab2bce7051c8
2022-05-31 15:18:55 +00:00
drh d69820c42b Many new PG-confirmed test cases in joinD.test.
FossilOrigin-Name: 481e89c764ad8906cd21c8fbe58df57ae40bb3f261fa4892ea7ce7762786ad26
2022-05-31 14:19:04 +00:00
drh 9f67cc26c1 Restore an ON-clause test case (removed by [3869fd9a2b9483cb]) that turns out
to be necessary for correct operation.  Fix for
[forum:/forumpost/c2554d560bac97c5|forum post c2554d560bac97c5].

FossilOrigin-Name: f407ec678f5bf5bfd20b7ba596472c9a85e6f21383a4cde49af1dae542fff582
2022-05-31 11:22:30 +00:00
drh c9dfe2b808 Add back in a test case for ON-clauses that was removed yesterday by
[3869fd9a2b9483cbf] but which turned out to be necessary after all.

FossilOrigin-Name: aba52a90eef2a5d06e7c499fe84b2efcde7f01e67129058f8223a6a0272aacb9
2022-05-31 11:13:55 +00:00
drh b1f08bc690 Add test cases for
[forum:/forumpost/c2554d560bac97c5|forum post c2554d560bac97c5].

FossilOrigin-Name: e66d5ae86c09cbe581b8f4f1bff33376cc680bba3da24f85384dd6c3eb85ddcf
2022-05-31 10:48:02 +00:00
stephan 5fd9f03291 Updated the wasm builds to generate gzip'ed copies of relevant files to take advantage of althttpd's new capability of substituting gzip files in place of requested files. This cuts over-the-wire size of the fiddle app by more than half.
FossilOrigin-Name: 40925585f1dab25babac46a0f4b9d633315110b8d4ccb04cc6df115d167e5ab4
2022-05-31 02:03:29 +00:00
drh 404bf6bac6 For an outer join, then ON-clause constraints need to be evaluated at just
the right moment - not too early and not too late.  Fix for the problem
reported by [forum:/forumpost/3902c7b833|forum post 3902c7b833].

FossilOrigin-Name: 3869fd9a2b9483cbbf83d8f369c1744abc42f12e63abba402be35dd7e136161c
2022-05-30 17:33:22 +00:00
drh 1943005f62 Apply the UPDATE-FROM file from check-in [98b3816bbaf539ea] to
update-delete-limit builds.

FossilOrigin-Name: 7e87892c249f023ee9ed1d5f75a9ad8db10fb38f14dd9e6954b12b9b28400b07
2022-05-28 14:03:23 +00:00
stephan 1a66ff359f fiddle: changed the internal key of the session/local storage to avoid conflicts with the pikchr fiddle app (which is derived from this one) when running from the same HTTP origin as an instance of that app in a dev environment.
FossilOrigin-Name: fd668da5ccf037c2ad8e61e381dd1eb398a8deab42a00593e551c30bd176890d
2022-05-28 11:59:46 +00:00
stephan e9ab04a446 fiddle: corrected a piece of far-corner-case error handling and made the various checkbox config options persistent.
FossilOrigin-Name: 2ba429a4f8300b981b23d54c2bdb54bd4863522c1c18bf9a67a82e3dce845b10
2022-05-28 11:29:00 +00:00
drh 5af8a86d62 Mark an always-true conditional as ALWAYS().
FossilOrigin-Name: 3492fe8a212cbe02b9016866e2499b99c3b566a4b0bc91fba267e6e1fe1b8943
2022-05-27 18:06:49 +00:00
drh abe1ff38dd Minor simplification to ALTER TABLE logic.
FossilOrigin-Name: 01beb0365c529481605f1864b1b6760e2484fad08d56a72e00e34acff37e23f8
2022-05-27 17:36:21 +00:00
stephan 23b34bbc25 Corrected a broken HTML comment (was using a C-style comment closer).
FossilOrigin-Name: db742e3e7d1caeff8d9df1d86abf54fcb2f2263db7a433ffacf3cd3777e533c5
2022-05-27 17:13:56 +00:00
dan ca29bbce2f Fix another problem with ALTER TABLE and UPDATE...FROM in triggers.
FossilOrigin-Name: 33cf12235e6469ba17cfb72cef0e480dfd0dea81ed412fb1fb24b05dbeb8dc02
2022-05-27 15:33:51 +00:00
dan 4209d553e7 Fix further issues with ALTER TABLE and triggers that contain UPDATE..FROM statements.
FossilOrigin-Name: 53fbc269ddbabc4a97d297e881e5f9cd2bfbcd24af4af1b7cf9db412a3a51813
2022-05-27 15:04:43 +00:00
drh 8d2f661ab8 Omit an unnecessary branch.
FossilOrigin-Name: f56473f9cc1b476b3219fe5b70ba2e4b269b20c880b99ba34c744ed893042081
2022-05-27 14:41:48 +00:00
stephan cd69784646 fiddle: added an option to completely wipe/reset the db. The Options area can now be toggled on/off via tapping the label at its top. Running the input SQL is now limited to the selected area if any text is currently selected, per suggestion in the forum.
FossilOrigin-Name: d100283e378f2d8e353399848184a4ab8ccf6316218fffc28b90a656cf81c279
2022-05-27 03:27:10 +00:00
dan b8bbe3e2db Fix issues with ALTER TABLE and triggers containing "UPDATE...FROM" statements.
FossilOrigin-Name: 2fba0d41b781d226915fa2bf888a7bc640c046ce22670ceb53f62a09f3975259
2022-05-26 19:10:11 +00:00
drh 26c4df0fb0 Correct handling of outer joins in the FROM clause of an UPDATE statement
that occurs inside of a trigger.  Follow-on to [98b3816bbaf539ea].

FossilOrigin-Name: 664a49fa813144b6fa5a7ae3f65af5412f150dd5def261c4d581d706b39f7846
2022-05-26 17:33:42 +00:00
drh e91bde4655 Clarification of the meaning of the N parameter in sqlite3_db_name().
Documentation only.  No changes to code.

FossilOrigin-Name: f22f41d2c8a676b9a339e7f00c29c163bbb7079b1a4a76ee1a6a96aaf7de5f9e
2022-05-26 14:46:09 +00:00
stephan 78907bba3e Fixed a minor cut/paste mistake in the previous checkin. Affects only internal docs.
FossilOrigin-Name: 37e3764839b968456f576fad67d3d99007773f5c0689165ecbdc610fcabef1ca
2022-05-26 05:18:33 +00:00
stephan c121e087f3 Makefile.in: added explanations, intended for maintainers and hackers, of the various emcc flags used for building the wasm files. No code or build rule changes.
FossilOrigin-Name: 1a159159094d6357b3cadbb8e5499cec4de35ef382c03fcc45c11daee906c3d6
2022-05-26 05:08:25 +00:00
drh 724e298e9c Slight increase in the accuracy of log10().
FossilOrigin-Name: c48a735bd4a1dbd541aed5937c25fc0c606c4263d8ee94cae30a06b1a7b26d9a
2022-05-25 13:10:29 +00:00
drh 7bfbd2508c Do not allow the right operand of a RIGHT JOIN to be reordered with other
FROM clause terms that are even further to the right.  Fix for the issue
identified by [forum:/forumpost/5cfe08eed6|forum post 5cfe08eed6].

FossilOrigin-Name: 4be0c60e38edc5d5bfd72bb35a3c91c55240b4e6313a40614beb60f1ab9d9f4c
2022-05-25 12:49:59 +00:00
drh 361e0ede47 Add in a VdbeCoverage() macro accidentally omitted from [d64ae49a1f251317].
FossilOrigin-Name: 18b5cea0392a28f694b8931a80e93518f8d3d297d787fa44d1544e373f76838e
2022-05-25 11:17:13 +00:00
drh ddcdf0b0dd Fix the UPDATE-FROM logic so that it works the same as PostgreSQL when the
FROM clause contains an outer join.

FossilOrigin-Name: 98b3816bbaf539ea745456e1c0064e47d2903d33ee0ceb029bdb97d56fcde937
2022-05-25 11:09:07 +00:00
stephan 26542e722b Got the sqlite3-api JS bits wrapped up in deferred-load module. Whether that's going to be easier to use, in practice, remains to be seen. Consolidated two of the test-related JS files.
FossilOrigin-Name: dd83cc05f2522d221641807dd66b33df48ac9264f27e5b6f63f312084f109801
2022-05-25 08:51:07 +00:00
stephan e599cc427f Renamed EXPORTED_FUNCTIONS.sqlite3 to EXPORTED_FUNCTIONS.sqlite3-api to avoid any potential confusion about that file (not) being an sqlite3 database.
FossilOrigin-Name: 3d6245c6f9f2ef4ca6746639d300cc5795598b119034439dfed671de3da638fb
2022-05-25 04:38:35 +00:00
stephan 085c5c6b43 Add the ability to import/export db files into/from fiddle.
FossilOrigin-Name: e0c30438a4f1372afb93a0488bae17b3f85d535717b215f494a83ae909871d2c
2022-05-25 04:35:22 +00:00
stephan d0b22b81c8 Further minor cleanups and docs in the fiddle app and worker.
FossilOrigin-Name: 199e01799dfa48e3fddafb7f2ae5360604150a44186d5c5a977e158ad8e7e657
2022-05-25 04:20:08 +00:00
stephan 79669c25c4 fiddle: refactored so that it no longer exposes any global symbols. Doing so with the main sqlite3.api module will be much tricker.
FossilOrigin-Name: cd227be805d0cd4b6e3c72ed0992ad3aec3db9c366909d9d82c6d3a29009c6eb
2022-05-25 03:08:22 +00:00
drh fb98dac04f An attempt to get UPDATE FROM working when the FROM clause contains a
RIGHT or FULL JOIN.

FossilOrigin-Name: a124e4f96f883d8682ba7a253d33a9565ed0fc3580525225b95733bd3782a806
2022-05-25 02:32:11 +00:00
stephan 80bf86967f fiddle: added support for exporting (downloading) the current db file. To do this we had to fall back to named dbs, instead of defaulting to an in-memory one, but the virtual filesystem is an in-memory FS, so the end effect is the same.
FossilOrigin-Name: 7c7fd34c8a05832a3973aaffe696250cb4d2a0b1646c9bfbe83970daf33cd817
2022-05-24 22:16:12 +00:00
stephan de1e02ee52 fiddle: initial work on loading a client-side db file. Works but requires some cleanup. Export is not yet implemented.
FossilOrigin-Name: 0fa8378c006fcf2311772d36cf2e3c2cd8e8648f671de89ee9832e2e1a06ef49
2022-05-24 19:01:21 +00:00
drh 6af03b469e When an ON clause on an INNER JOIN references a table to the right of
of the join, just convert the ON clause to an ordinary WHERE clause term,
in order to be compatible with older versions of SQLite.  See
[forum:/forumpost/687b0bf563a1d4f1|forum thread 687b0bf563a1d4f1] for details.

FossilOrigin-Name: 2b6ebba26d936ae7b9acf7d4bd15e82cbfabda22e1044b3dd838c7b07095100e
2022-05-24 16:05:41 +00:00
stephan 73c6ad1920 MoUse re descriptive var names in ext/fiddle/Makefile.
FossilOrigin-Name: 2f9a42fb141d386f6edd03a37da3b0cef63dcc9fbfd076076b5330a8aa7d45a8
2022-05-24 14:45:16 +00:00
stephan 400ee2ecef fiddle: lots of generic refactoring, restructuring, and cleanup in the higher-level code. Added push-fiddle ext/fiddle/Makefile target to push the fiddle app to a remote server via rsync.
FossilOrigin-Name: ed19fef3459499abb0a4a010f368b4576d6e068d930c8480446ea677ac87c1c1
2022-05-24 14:36:45 +00:00
stephan 2f6a729d55 wasm/JS: minor doc updates, corrected bind()ing of the undefined value to behave as documented, removed some superfluous code.
FossilOrigin-Name: 526c8c728019b317624a93f6f07840ca524bca84e7c03ce5e86e38953146236f
2022-05-24 01:15:21 +00:00
stephan 64f0e9376b wasm/JS: documented DB.selectValue() and corrected the fetching of NULL columns via Stmt.get().
FossilOrigin-Name: 70f91fab825d365f505750acdb8d3ae532880c4cdb64d1e61bb21b24a115958b
2022-05-24 00:35:18 +00:00
stephan a240a24ad0 wasm/JS: added support for scalar UDFs. Fixed a deallocation problem with bind()ed strings/blobs.
FossilOrigin-Name: 325a9ee31ad7abae563c4da5cd8228e151b00aa9afcac7e9bca5efaa9d48e107
2022-05-24 00:22:10 +00:00
stephan e145136a4e wasm: minor refactoring and doc updates.
FossilOrigin-Name: 6044605b2a712da73600cabb967797a03ed1915dc0ab0b10edbd52525e548196
2022-05-23 19:38:57 +00:00
stephan 325b56b504 fiddle: cleaned up and documented the status-loading progress mechanism in prep for reusing it in the sqlite3-api worker.
FossilOrigin-Name: 107e3497869d757265f2a4235082bf324ba1220075d1096c2a82021a5d348a6c
2022-05-23 16:54:18 +00:00
stephan dc5888e04a wasm: added missing 'use strict' and fixed an undeclared var use caught by that.
FossilOrigin-Name: c16a7f4950d47c2f5177db7dc5d83f0f11eb0cafdce1ec688d6f1bd740d92733
2022-05-23 13:55:39 +00:00
stephan 192201d2ed wasm: corrected isSupportedBindType() to behave as documented.
FossilOrigin-Name: 7e2d2e807272e98e9a3c9c9ba492b796a603f36b7cc12b16923cd8a9e6579851
2022-05-23 13:52:36 +00:00
drh ea488b1258 New test cases to further demonstrate the difference in name matching rules
for LEFT JOIN versus RIGHT JOIN that protect legacy behavior.
[forum:/forumpost/e90a8e6e6fa652ac|Forum thread e90a8e6e6fa652ac].

FossilOrigin-Name: 2c586060a016f5481bad29bfb8f4ac4e1204075afdd0fa1851fbbcf2abda4893
2022-05-23 12:37:54 +00:00
drh 51e5d447ba Add an assert() to clear a harmless static-analyzer warning.
FossilOrigin-Name: 919ba2f0472e12c2d1e82364c1481e778b24ea406615b08992964a4eb80abee7
2022-05-23 11:51:10 +00:00
drh 43baa1de76 Do not run the subroutine that materializes a view or subquery until just
before the materialization is actually needed, so that if the materialization
turns out to never been needed, unnecessary work can be avoided.

FossilOrigin-Name: d64ae49a1f2513171d678259928c67741d79b2ae595078299525641a676cc46b
2022-05-23 10:57:20 +00:00
stephan 71eacead76 WASM: removed the in64-related bindings, as MDN says that calling a wasm function which has an int64 type in its signature will currently throw because JS has no 64-bit integer support. Those bindings now use doubles and simply hope that the user doesn't exceed their integer precision (2^53-1, approx 9 quadrillion).
FossilOrigin-Name: 392e84828275ec203bc713d3a5d4790852add57539add6b29b5f6de1da2dc97a
2022-05-23 01:11:49 +00:00
stephan c21c0e2af9 WASM: an arg handling fix for DB.exec({multi:true...}).
FossilOrigin-Name: 0d6332f706ec5c34cc6a9ff79878f4e10a9ad81b24cc7d743b52168586285811
2022-05-22 22:10:38 +00:00
stephan 744a65cf7d WASM: added exec(), execMulti(), and several getters. Various touchups and fixes.
FossilOrigin-Name: b790c91b85e9cf8eecce86ac1717e8ccd2c3b6b98a1ad6a5d64eefc94ee86f9d
2022-05-22 22:00:39 +00:00
stephan f6868562ce Implemented Stmt.get() and friends for WASM OO #1 wrapper. Added basic tests for prepare/step/get. Restructured module init output to introduce only 1 global-scope symbol instead of 2.
FossilOrigin-Name: 601dc3fa29c2ce2ede5a8320c79050305f3774b6d7bc759247c5021f3b74aaec
2022-05-22 19:09:59 +00:00
stephan 40b5b19a0f WASM: added bindings for sqlite3_compileoption_get/used(), moved OO #1 into sqlite3-api.js since it can only be used from the same thread as that API and separating them complicates client-side use. Started adding test utilities and tests for the OO1 API.
FossilOrigin-Name: f3bc0328c87cac7d50513b0f13576d8fe7b411396f19c08fbe7e7c657b33cfbf
2022-05-22 16:25:43 +00:00
stephan d60b7275c3 WASM OO wrapper #1: prepare() and bind() APIs are in place but are untested, pending fetch/get APIs.
FossilOrigin-Name: 84c8f63a1c446331a3afe52b0c8bdfa6980f24aa4cf600f576877fef5e650c39
2022-05-22 14:07:44 +00:00
stephan 166542cc98 Build refactoring for the fiddle/wasm bits. Set up wasm binding of a chunk of the core C API and added some infastructure for creating test pages for it.
FossilOrigin-Name: dea098b64eb95c395b346ebcae687afe42b7d21df48833527808c02226300a66
2022-05-22 00:27:19 +00:00
stephan 4ec29fc115 Minor fiddle-related build restructuring to support upcoming development of the C-style wasm sqlite3 interface, plus some commentary about the plans and goals for that.
FossilOrigin-Name: c7cfdd4c3682659352642461d3307bf8180703b121ec1802ba5881f8e1ef9809
2022-05-21 21:13:44 +00:00
drh 40822eb262 Defer materializing a view or subquery until the materialization is actually
needed, so that if it is not needed, not useless work is performed.

FossilOrigin-Name: 16bf350683fd6ac906dbd02b21fb8bf1b1014ed05594cacf108645acd383ae65
2022-05-21 18:03:33 +00:00
drh 660dfbdcfb Fix a typo in a comment.
FossilOrigin-Name: 34d7045b2cc8ef16fd4115499888703a376d2c3a289e7fdd117f8341ffa586c3
2022-05-21 15:54:45 +00:00
drh b800bd63aa Use the newer OP_BeginSubrtn opcode instead of OP_Integer to start the
subroutine used to matrialize a view.  This does not change execution but
does make the byte code a little easier to read.

FossilOrigin-Name: cebd4fd606f967de527cff79df8e80e16d06eec257939322f16d21303868fb4d
2022-05-21 15:12:41 +00:00
stephan 4257373f6d fiddle: refactor into main thread (UI) and worker thread (wasm module). Added bits needed to support triggering sqlite3_interrupt() but do not yet have a second SharedWorker to test it with.
FossilOrigin-Name: 5ff3326856bc190cee15a5fca5ded89aacc4bf931a8df98726a872b310e2a4fc
2022-05-21 14:19:05 +00:00
stephan 0592b20faf fiddle: add a selection list of example queries.
FossilOrigin-Name: 74abf03977e1ff8c6043defa38211cdfcfbba1979771b90ed9d3dbc99750fe9f
2022-05-21 00:45:46 +00:00
stephan 2eb454147a In the shell WASM build, call open_db() early so that we can get access to the global db handle from certain experimentation-only function without having to first run some SQL code.
FossilOrigin-Name: 31706ef851f7d55e2fe865933ec03f42dfa8b49e6d1f12b6c016b5c1d3460504
2022-05-21 00:01:45 +00:00
stephan 056b72a988 Added the standard sqlite license header to the the fiddle JS files. Minor internal renamings in those same files.
FossilOrigin-Name: 67e40d99ff84a6cb23c68bf0722a4f9dee29b8ad18d9e7aac7d1665e99901ba1
2022-05-20 13:50:04 +00:00
stephan e26d162402 #if'd out the '.nonce' and '.check' commends in WASM builds.
FossilOrigin-Name: 326f79ea54566a9302be99d920856f13b48f2c2ed265fa87d78ced367d4b1946
2022-05-19 22:04:23 +00:00
stephan 1c0dcec4c5 #if'd out the the '.cd' and '.clone' commands for WASM builds.
FossilOrigin-Name: fa391868dd626ffdb220bed6834d0a10c7336f0fc4ca56055147784de1a4f99d
2022-05-19 21:56:50 +00:00
stephan 2f72d711ac fiddle: consolidated two duplicate CSS rules. Internal doc typo fix.
FossilOrigin-Name: d3175a793fb2d1ac9ecfd7a7c3b1627fe583effcd37740206a11b115f099d521
2022-05-19 18:14:34 +00:00
stephan 091fb16e09 Added a disclaimer about fiddle's experimental and subject-to-change/removal nature.
FossilOrigin-Name: 75b4f574089c4969d2f2c3615a52029e98515e36390c530cdf63f15f4f687a1d
2022-05-19 17:47:17 +00:00
drh 9d023c227f Merge the changes to support the "fiddle" extension.
FossilOrigin-Name: 58585f01aa4747d3a09771fb462066bd037914f435ff04fa16ed9b0571e7912a
2022-05-19 16:59:46 +00:00
stephan d59ac28d4f When building fiddle from its own directory (e.g. from emacs instead of the normal build process), force -O0 the sake of compilation speed. The top-level build now defaults to -Oz, which is more appropriate for that case.
FossilOrigin-Name: 56b82ae806c61b95e62042ca70ed952ce01832b02da55c2b315f9201989514ab
2022-05-19 16:49:15 +00:00
drh 7db1289b0f Tweaks to the fiddle make target so that it builds with all of the same
extensions as the standard CLI.

FossilOrigin-Name: d46a6cb97406d90b9ad1da66369454e9b8f387ffbebcdf1c386c3c21f790c16f
2022-05-19 16:42:41 +00:00
stephan 2d0a85c5de Added a toggle to swap input/output field positions and simplified setup of checkboxes which toggle a CSS class on a given element.
FossilOrigin-Name: eae3ab10c813d6f051d497271be2df05f54005ec54b19a2a27d04d632bccbeac
2022-05-19 16:30:03 +00:00
stephan e9e0208561 Default to top/bottom layout with input on the bottom. Offer a toggle to swap input/output positions.
FossilOrigin-Name: 362d236aca31ca2004d1e81d8e306f7a12a6cb4eeb2bab432a9c2aae5206ddd7
2022-05-19 16:11:35 +00:00
stephan 38240592ad Numerous layout tweaks, the most significant being that the layout now adapts to the window size. Swapped positions of the input/output areas. This version supports, by uncommenting a few bits, a jquery.terminal-based view but alternatives to that 300kb dependency are still under investigation.
FossilOrigin-Name: 1aad3642c9fc14c25223628a309d84decc8d73a123e42d6efdc36d855b5b0666
2022-05-19 15:58:13 +00:00
stephan 6da6f31cca fiddle make target now accepts fiddle_cflags=... from the CLI to overrid -Ox and such for one-off builds.
FossilOrigin-Name: 4609a4f8626ae3d8179cae27e391bd06ffda18e9ef9e1b78745b36c7e8dd25db
2022-05-19 10:58:59 +00:00
stephan 403445be23 Ensure that the output area is cleared of any init-time messages which the emscripten bootstrapping process emits when downloading of the wasm module is slow.
FossilOrigin-Name: 1d8d0593573f9fc8e0990a292a4b3317d8a4c323d60514d0768543dd65c24d1e
2022-05-19 10:38:54 +00:00
stephan 618a375e9f #if'd out the '.log' command in WASM builds. Cleaned up the user-visible parts of the WASM module initialization.
FossilOrigin-Name: b5fa12f824690c1022e4d69b0f5c3949324b311557a7412810741731db7e2cce
2022-05-19 10:24:50 +00:00
stephan 0fb074ab61 Split the fiddle JS code into separate pre-/post-init files to simplify editing. emcc will combine these into the final fiddle.js, so the number of output deliverables does not change.
FossilOrigin-Name: d3d8ea011868bcfa11bb3fe2db78eea6e77ac1005534d9c091f9a81e03f0a7e6
2022-05-19 09:55:14 +00:00
stephan b8a2b20509 Added an option to auto-clear the output area before submitting the input. Experimentally inverted the colors in the input/output areas.
FossilOrigin-Name: 1a1e4e7fdbd0ec61218c3a311164086316d825181f3fc1c1ec235b63488746ef
2022-05-19 09:22:16 +00:00
stephan 9af6beb977 Replaced the toggle for the notes/caveats section of the fiddle UI with a button to remove that section.
FossilOrigin-Name: 6661d60527820417bbfd01c782d242c5190252ea703fc6f56376537d5c8f6a1e
2022-05-19 01:12:23 +00:00
stephan 29f2458aae #if'd out the '.import' command in WASM builds. Several minor cosmetic UI tweaks.
FossilOrigin-Name: e4f87eb7c3ed16b7e431f86b7d337bb4097246d20780207b43e28fffda3d8a61
2022-05-19 00:38:34 +00:00
stephan 348f7420b3 #if out the '.load' command in WASM builds. Several UI layout tweaks.
FossilOrigin-Name: 67d98297f01d4274c510f5c5cb2a219aeb36fcbb7ce78b8b9ed65639a4561c73
2022-05-18 23:40:27 +00:00
stephan 02520cc8f6 In wasm builds, ifdef out shell commands which require file I/O, pipes, or which trigger an exit() (.quit and .exit). Documented some of the quirks and limitations of the C/WASM crossover. Keep the JS code from calling into the C code after an exit() has been triggered.
FossilOrigin-Name: bee436e62a956e49b0df4a92abff2c89f2b44e21d8f593716df0331f8fc49814
2022-05-18 22:58:34 +00:00
stephan b0dae2b3c3 Improved handling/reporting of conditions which trigger an exit() from native code, e.g. calling the '.read' command. Added a Help button which simply submits the '.help' command. Added commented-out variants of various -Ox flags to simplify experimenting with them.
FossilOrigin-Name: bf06ddf4125d2726019fa16d312726c8551094be991509499b5688f6a68a7747
2022-05-18 21:18:21 +00:00
stephan 0076e49700 Code style fixes: s/char const/const char/.
FossilOrigin-Name: 9bf042b2eb2137239a59e421e89eb463e719b264eac3db2adae44e321b9a4ad3
2022-05-18 18:10:17 +00:00
stephan 8ae45e4c6b The fiddle input/output areas now stretch and shrink as needed to account for their available space.
FossilOrigin-Name: 4eec05457fabe8248b8fd48d6187e772b69429ed64e99f02d0ad6b1230b5835e
2022-05-18 17:40:19 +00:00
stephan 9f69b9411e Increased default size of the fiddle output area, changed the .nullvalue default in the input area, and minor CSS tweaks.
FossilOrigin-Name: 281aaae73167828bdf0bb2c07f83622475ab29b5755ac7fb8584c8e919c0a09b
2022-05-18 17:22:02 +00:00
stephan f8cd3d2b5c Initial version of an sqlfiddle-style application using a WASM build of the sqlite3 shell.
FossilOrigin-Name: af9c21c9e0caf05adac7a9fcde39a9164c89f1c78b767b6fdd74a1405a3d373f
2022-05-18 17:14:24 +00:00
drh b8b2d9c5e1 Fix harmless compiler warnings in the new unixFullPathname implementation.
FossilOrigin-Name: f7e1ceb5b59a876cfd04a8aac0ee2b322c970555b9c361b4953d711ef6596e37
2022-05-17 15:11:57 +00:00
dan 5348fbe332 Avoid treating constant expressions like "? IN ()" or "? NOT IN ()" as integers if they appear in a GROUP BY or ORDER BY clause.
FossilOrigin-Name: d8b249e8cdf0babe1427d0587dbdc27a52ec06a5ef3a20dfb05a0ea4adb85858
2022-05-17 15:01:01 +00:00
drh ff16267d7d Add the sqlite3_db_name() interface.
FossilOrigin-Name: 2ad152236c408cbb1f942b221de4bf3cbaa9c35313d7eb07a63f46b6040fc981
2022-05-17 14:59:05 +00:00
dan c7d7ebd755 Add memory barriers to multi-threaded code in test4.c.
FossilOrigin-Name: 9260f4e0fdc8066b4772999bacb5f4130ef714d4ac1967029ceacff618bc48ff
2022-05-16 16:55:22 +00:00
dan 07576c3fe8 Fix a problem in test file swarmvtab3.test causing occasional failures.
FossilOrigin-Name: f935c155ef205802c16b4ebea4a3fb01bf5689662b7b4f2af56f0f9021d6d4b1
2022-05-16 16:10:04 +00:00
drh 96d5549778 Do not allow an index scan on an index-on-expression for a RIGHT JOIN because
the index might not be positioned on the correct row when running the
the right-join no-match loop.
dbsqlfuzz 39ee60004ff027a9e2846cf76e02cd5ac0953739

FossilOrigin-Name: 2277f9ba7087dd993ac0f4007c523aa9cf74dba187f53af03d8c164886726fee
2022-05-14 19:05:13 +00:00
drh d83997ba7f Improved debugging comment generation for the OP_Column opcode.
FossilOrigin-Name: 3e073bfddfcd652dfae8656d8978a4de427d21847fdaccfce53b6b895ad33f01
2022-05-14 17:40:47 +00:00
drh c93bf1d462 Improvements to the decision of when to check ON constraints for an inner
join that is an operand to a RIGHT JOIN.  Fix for issue identify by
[forum:/forumpost/c06b10ad7e|forum post c06b10ad7e].

FossilOrigin-Name: 9d17233c7d98bf25c1a518d067e778708b3db6d6302edd8d7e376ba0ba4f1c30
2022-05-14 15:59:42 +00:00
drh 086b800fcd Change an unreachable branch into an assert().
FossilOrigin-Name: 778e57a558dc3f819ca57623bcb85f58c8fbeb28bc12a1e2edbdd1244e9107c5
2022-05-13 23:01:28 +00:00
drh 556527a154 Transitive equality constriants do not work on a RIGHT JOIN, since the
right-hand side might be a non-matched row.

FossilOrigin-Name: 0f96810b840dd6f209562635b21f55a7ed6210c01336fcfeb3b79e08a615a28d
2022-05-13 20:11:32 +00:00
drh f69dad8c53 Walk back the optimization from check-in [cc458317bd77046c] that tries to
reuse the same ephemeral cursor of a list subquery when that subquery is
reused, as it does not work in cases where the list subquery is used both
for lookups and for scans.

FossilOrigin-Name: 12ee29d632ae4b585ef6bc07d3289d00c121268945dffd5673b251d95874e3f8
2022-05-13 19:50:29 +00:00
drh 767bc8de8e Defer generating WHERE clause constraints for a RIGHT JOIN until after the
ON-clause processing for the RIGHT JOIN has done its own row elimination.
This fixes and incorrect output from some RIGHT JOINs that was identified
by [forum:/forumpost/41cc3851d864c5e6|forum post 41cc3851d864c5e6].

FossilOrigin-Name: 238d9c247cf69cc77fdb1af9d42ebe258610a533ac4204e2ddf8af17f24d18c4
2022-05-13 17:45:52 +00:00
drh a6e8ee12e2 Redefine the acccess rules for the Expr.w union so that the Expr.w.iJoin
member is accessible on either EP_OuterON or EP_InnerON.

FossilOrigin-Name: 6f741d6cfb8831a3ac966257ac4519bcc8156293447bf50323c2d9b170125974
2022-05-13 16:38:40 +00:00
drh f8d2745f99 Corrections to the header comment to the new joinE.test script. Add the
generator TCL as a comment at the bottom of the script.

FossilOrigin-Name: 2f4456f67f64f131fc852ad9a7420eb43b57b879a9bec7e4b295f1dc0d7bfa56
2022-05-13 15:36:47 +00:00
drh d383557960 New test cases for outer joins. Case joinE-32 currently gets an incorrect
answer.  See [forum:/forumpost/41cc3851d8|forum post 41cc3851d8] for the bug
report.

FossilOrigin-Name: 02b24863e6dc617c9260f79292a96b7c861d088268e77fd17204570515eb792c
2022-05-13 15:31:30 +00:00
drh 67a99dbee8 Improved names for flags on the Expr object: EP_FromJoin becames
EP_OuterON and EP_InnerJoin becomes EP_InnerON.

FossilOrigin-Name: 1ffea07ff98b894729c698b681cc7433df3bbfccd8a0529a706908602a636937
2022-05-13 14:52:04 +00:00
drh 8b0e5c3c7e Fix a harmless compiler warning in the CLI.
FossilOrigin-Name: 7a2ac303d1436a423a635db63d195097c88160ff46855194f6e630f9d3b3fa82
2022-05-12 17:09:33 +00:00
drh d631c6af80 Ensure that ON clauses are applied to the correct outer join.
FossilOrigin-Name: c7e3a13a3288c577209be99c630fbe924e19880e8af1aa8a83b517acaa8b43d7
2022-05-12 11:56:44 +00:00
drh 902e2602c2 Add IS NOT DISTINCT FROM and IS DISTINCT FROM binary operators which are
equivalent to IS and IS NOT, respectively, for compatability with PostgreSQL
and hence standard SQL.

FossilOrigin-Name: db27611e172102483eaede3981d473e3d5bf93d98bc68f480398b1573876349d
2022-05-12 11:45:20 +00:00
drh d59a388b61 Fix the ".echo" command of the CLI so that it shows the results of input
lines immediately, before invoking sqlite3_prepare().

FossilOrigin-Name: cf7fdabdba3a7600ea730263ca80ba80154645dfa15c31c037b780d6cb70e530
2022-05-12 11:01:41 +00:00
larrybr 175fdcb912 Zap stray --help output from intermediate version.
FossilOrigin-Name: deb7372b18cc8fb9d305085498fd24b3c2c17bd920ae2d03fa885af02ad47008
2022-05-11 20:29:32 +00:00
larrybr f4874818a4 Change .echo on effect so that SQL is echoed before prepare. This slightly alters echoed output when multiple SQL statements are submitted at once. Also sync with trunk.
FossilOrigin-Name: c1eff632c41809214edea2850a93852fff66da3ca0dc393e8fe55e0976d422fd
2022-05-11 19:59:31 +00:00
drh 6868bca6c5 The unix interface now resolves all symbolic links in filenames before
actually using those filenames.

FossilOrigin-Name: d55273e36e312336b8fc77dc771657d3b2c3437fbbd79f3be37701982560d634
2022-05-11 17:57:43 +00:00
drh b302c065d8 Use osReadlink() in os_unix.c, not readlink() directly.
FossilOrigin-Name: c3da4c1611cebd9f9d695892a3ffddc47d5f0db1a1ea8bd2b4f83ef7673b68de
2022-05-11 17:45:50 +00:00
drh e8346d0a88 For the unix VFS, rewrite the xFullPathname method so that it automatically
resolves all symbolic links, rendering a canonical pathname that contains
no symlinks.

FossilOrigin-Name: 40c9273d0e0e74e1df22e996a5d486e838f4320defd2121e2d95eeed8aea6235
2022-05-11 16:46:27 +00:00
larrybr d647819034 Fix .import leak in CLI and add shell leak testing to debug builds and the Tcl test suite.
FossilOrigin-Name: df842ebc796a2b0c913d19d873e88d048808dc5283465271369e302a680317e4
2022-05-11 03:42:38 +00:00
larrybr 51b011d8d5 Sync w/ trunk
FossilOrigin-Name: 1284225b0a8c7b630416be5348e99f7280f6443548ec97ffb1c85be23352b2bc
2022-05-11 03:29:52 +00:00
drh cc212e4450 Fix a bug in the sqlite3WhereMalloc() routines that were added by
chekc-in [f237e1d8cc41b937].  The bug was detected by dbsqlfuzz
test case 4c5e3e89bc251d28378be88233f531b84ec66901.

FossilOrigin-Name: 764b71267e0b31ff7eaf2a0def7526a1a02dce4d5b456dea060d97ed342efdd1
2022-05-10 23:28:12 +00:00
larrybr 73b7af0437 Make tester.tcl work on more Windows Tcl installations. And sync w/ trunk.
FossilOrigin-Name: d25fbdf8772f1c8283828424b208fc1758c82e9e28e0e52122c87db4af1c672d
2022-05-10 22:32:27 +00:00
drh 825ecf9c05 New requirement marks.
FossilOrigin-Name: e8479e56c615a6eb38b58e6d360bea8528ec14a9d7b0798b95d3eb513bd08f0f
2022-05-10 18:43:54 +00:00
drh 0338f53b05 Fix a stale requirement mark.
FossilOrigin-Name: fcda7fb1f184a31a67572aae15f3cdcd60f8aac199106a7b0f90aca251ca7017
2022-05-10 18:18:45 +00:00
drh d2b960cf41 Fix a stale requirement mark.
FossilOrigin-Name: 3eda4030f73384abf18b97cd8a4606e10b23e382d1b72dff7526aebfde23e0af
2022-05-10 17:42:55 +00:00
drh de695eab88 Fix a harmless UBSAN warning.
FossilOrigin-Name: 8f9355028bc7baeeb10ee9a5e29f093adac6c2f149596dec0be827be4ce491cb
2022-05-10 15:55:10 +00:00
larrybr 1607ac3357 Sync w/ trunk
FossilOrigin-Name: b7285f92bb9bfd8471e51ee5b6dbd7030b1f731683876e8ecca4a8c033688736
2022-05-10 14:57:38 +00:00
larrybr 527c39de80 For CLI, add ".echo sql" dot-command.
FossilOrigin-Name: 35cef458ca114649ee16e00714d817d57673b96c007454946cc411ae90fd06ce
2022-05-10 14:55:45 +00:00
larrybr be7777f4a5 Sync w/trunk
FossilOrigin-Name: 536691ed0f76ac37f3d86e4f5b1cff15ce4c011f84cd3452b5b45bafb6bf2522
2022-05-10 06:04:48 +00:00
larrybr f015a3d19f Cause most shell tests to be run under Tcl suite valgrind config.
FossilOrigin-Name: cd085b36ff777396ac2705c030c1518f8094a70a0b0ba4a628776429524d20f0
2022-05-10 01:11:51 +00:00
drh adef15986a Simplified "hidden" and "no-expand" handling in the *-expander.
FossilOrigin-Name: c6c3115f3a008cf9b0d7c5c812f17e38c8a75a904032c5f05f0bea03a7340527
2022-05-10 00:24:01 +00:00
larrybr 1a53219981 Create new branch named "echo-sql"
FossilOrigin-Name: 042f2935c9d07668eff6ad8a071c82aa12ccbf9a783dff7b74ddd6b4c82cf573
2022-05-09 18:33:14 +00:00
drh f71b8123df Minor STAT4 test case change due to the ANALYZE enhancement of
[eb59c46a5aed69bc|check-in eb59c46a5aed69bc].

FossilOrigin-Name: 8ce2fecb580da53fc01c53d8de10e2cc99499094215429ba925e777717e369b2
2022-05-09 17:55:34 +00:00
drh 4077b006ad Add ALWAYS() on two unreachable branches in the * expander.
FossilOrigin-Name: 387c852375bba62df040330944c9e979a6993f95ece3443597c5fc66e34263ca
2022-05-09 16:29:53 +00:00
drh 77874e782b Simplify a branch in the "*" expansion logic. New test case for an
INSTEAD OF trigger on a RIGHT and FULL outer join.

FossilOrigin-Name: d2717348f43b571c7bb58498e0c723331abf85de174189e66aca2c438ca26d5f
2022-05-09 12:59:16 +00:00
larrybr 2f5f674066 Simplify .import leak plug and arrange for CLI to be run under valgrind.
FossilOrigin-Name: 0d3e2380197aa3e725591266acaeb0d43a7e794ca9153e6c56253cdcf60720b1
2022-05-09 12:29:47 +00:00
larrybr fa5dfa8910 Stop a memory leak in .import, and add leak complaint to CLI debug builds.
FossilOrigin-Name: f5f09368b33b6af00f96e5b8f763e7ee2d00ba6af2aee0f2ca86bb58c03d0b71
2022-05-07 03:53:14 +00:00
larrybr 1e48d79f71 Create new branch named "import-leak-plug"
FossilOrigin-Name: 4a4cecab23ef2aab20b1db466d045d56921590eb67563ab5a31f7b0a0f75c533
2022-05-07 02:21:17 +00:00
drh 41724ebc5a Perserve the requested reserved-bytes size for the database file when
doing a VACUUM.

FossilOrigin-Name: dac6d87c71606f3ec7ce601be6d17357d323476ecb60dbb167030146783b62b2
2022-05-06 22:29:45 +00:00
drh 87b7ac0420 Prevent an infinite loop on SQLITE_ERROR_RETRY when trying to modify a
corrupt schema while PRAGMA writeable_schema=ON is active.
dbsqlfuzz ded83609f475cc989c7339d45efb5151c1495501

FossilOrigin-Name: 217b33234dc3dc36b5b6add50c170869421057a56a7576d1a61767956248d5c9
2022-05-06 00:43:06 +00:00
drh 744c17c482 Backout check-in [9fb20a21feb8f697] which was incorrect.
FossilOrigin-Name: 99225618a83b577efbd5d13c0d1ff73e9c5a71bb43c259d7c0f22cf3479c992f
2022-05-05 10:02:19 +00:00
drh c915b9c46f Improvements for name resolution for parenthsized joins.
FossilOrigin-Name: 006b2d9c52201c9e836b649018519acfb47f793f70b968722440f00084e9d846
2022-05-04 18:43:39 +00:00
drh 049d239a8c New test cases for RIGHT and FULL JOIN, focusing on cases that make use
of Bloom filters, and a bug fix related to when ON-clause constraints are
applied.

FossilOrigin-Name: 67510354e69bab98bd8095f5bedd34aae619fe2c7885975d7a6a00b7df5ece4e
2022-05-04 17:43:59 +00:00
drh 95cb5ccf92 Code EP_InnerJoin constraints at the same time that EP_FromJoin constraints
are coded.

FossilOrigin-Name: b57033d2af2196e2f7e5305f3504fc20da5cadeb66026d38b999fe909cab8ac5
2022-05-04 17:30:51 +00:00
drh b2cc3cf36e Merge ON-clause constraint usage fix from trunk into the joinD branch.
FossilOrigin-Name: 0a20d4a85964fb5f2060b9522356ad2711f41d0d526ba3d2e58fc51029878298
2022-05-04 14:46:08 +00:00
drh 11d63ebf2c Fix ON-clause constraint usage for FULL and RIGHT JOINs.
FossilOrigin-Name: 544268a723cafdf0460221f5f018e752836436bad0fac90852cec70e63d9dcde
2022-05-04 14:45:19 +00:00
drh 3b52f80237 New test cases using various join types and Bloom filters. Two cases
differ from PG and need to be resolved.

FossilOrigin-Name: befa8cbc0682bc3269f87e392a1f3d4baacf4db7c716ea84192bb9c13c99490b
2022-05-04 11:49:26 +00:00
larrybr b55776230d Fix CLI use of wrong allocator for free().
FossilOrigin-Name: 9fb20a21feb8f6979812f45691e06aa3e297d7370cf0d5820523e817a4e97863
2022-05-04 03:45:32 +00:00
drh 367c146b09 In the query planner, do not let tables commute across any outer join.
FossilOrigin-Name: 8cee5388232ade91ea627bb6857eb8937d7530b5ea519e0ae6da362c37c7ed35
2022-05-04 02:01:49 +00:00
larrybr bc33519de6 Typos cleared from README.md
FossilOrigin-Name: be3a1879c865cff85d8b1f0cc7b95295019c28cce67c687692a3210eeea6e314
2022-05-03 21:58:24 +00:00
drh eeada07457 Merge Bloom filter bug fix from trunk into the right-join branch.
FossilOrigin-Name: 72131ad1bda3d087e59cd4a51d87f10f65a55e658645397e1ede15f9fb1f5143
2022-05-03 16:26:50 +00:00
drh 00e5d3d59e Fix a typo in a comment.
FossilOrigin-Name: c19c3c48698bf2543d775411c62d01e629791e2f3c5317970fdbb830eacafac6
2022-05-03 16:18:25 +00:00
drh 8aa7f4d813 Fix the Bloom filter pull-down optimization so that it jumps to the correct
place if it encounters a NULL key.  Fix for the bug described by
[forum:/forumpost/2482b32700384a0f|forum thread 2482b32700384a0f].

FossilOrigin-Name: 6eda9b1a7784cf6d58c8876551f67ab98e78a08e726a0579d4def5ba881985bb
2022-05-03 14:01:48 +00:00
drh 207f626356 Add assert()s to show that jumps always land an an instruction that is between
1 and Vdbe.nOp-1.  Had these assert()s been in place before, they would have
caused an assertion fault for the byte-code error reported by
[forum:/forumpost/2482b32700|forum post 2482b32700].

FossilOrigin-Name: 8f8a58feb7047d19522ca32efbe42fd9ddf49aaf9064f7373eb56a88982406a2
2022-05-03 12:11:16 +00:00
drh d88fd53989 Organize the various flag bits of the ExprList_item object into a substructure
so that the whole lot can be copied all at once.  Faster and smaller code.

FossilOrigin-Name: 5341d4bbe9a943f9cdbbdea829e18f108e98972ebb706396c50fc62fcc6a6328
2022-05-02 20:49:30 +00:00
drh 689f1b9246 Merge trunk fixes into the right-join branch.
FossilOrigin-Name: e01f4c05c21e89dcc7985e00874f288d9ba5d5d932f7284f8d970bd3145ac0c2
2022-05-02 20:14:26 +00:00
drh 63879a2c99 Improved comments.
FossilOrigin-Name: 158b80bed61ade793ccfd979f26a5231fabc8c14697ca0141bba61bc13e3b2ba
2022-05-02 20:04:34 +00:00
drh 72d620bdb1 Name resolution and "*" wildcard expansion for parenthesized FROM clauses
seems to work the same as PG.  The code is chaos, however, and needs some
cleanup.

FossilOrigin-Name: 6f9c0b07aadc5189c65c3ee4e6938aac10fc0d98f1cb06980f5e5d7b0308f237
2022-05-02 19:59:03 +00:00
drh 56f38db700 Remove a testcase() macro taht was made obsolete by [a8da85c57e07721d].
FossilOrigin-Name: 053cf45ecaa7eac8cc64c7b2672807f736a45575a84b426263b2e1feb060b401
2022-05-02 15:47:57 +00:00
drh c35f02d676 Document (in comments) that the SQLITE_FlttnUnionAll bit has a specific value
needed by TH3.

FossilOrigin-Name: bcaa4a44749d157c5953c6f54c88b1ba29b4035f4b21fce986b7efbea372e109
2022-05-02 15:31:06 +00:00
drh 7a8809907f Fix a harmless compiler warning in sqlite3TreeViewWinFunc() (a routine that
does not even appear in release builds).

FossilOrigin-Name: daff6070039e45df7c47b323a8352e56d1264a7bfb065fe2d79c58454c95a262
2022-05-02 15:23:59 +00:00
drh 85f93850f7 Merge the latest trunk fixes and enhancements into the right-join branch.
FossilOrigin-Name: afbcf075c1e09ae064c7b16e63501cd1d374711812664aef76bd35d02d64a2b6
2022-05-02 15:10:38 +00:00
drh 3a45d30ea5 Improvement on check-in [a193749730d6cfba] so that the subroutine call to
the IN operator right-hand side generator from the RIGHT JOIN no-match logic
does not generate unreachable byte code.

FossilOrigin-Name: cc458317bd77046c4328715ae9e3409f3f4cd422a01162cb33405ef3a142b0a3
2022-05-02 14:32:56 +00:00
drh b94182bdc6 Bring the comments on sqlite3FindInIndex() into closer alignment with what
that routine actually does.

FossilOrigin-Name: 40f3274745b53bb72933c1052d0e85bc74be56d3a1068e9d54dc28763a2cfef9
2022-05-02 11:24:21 +00:00
drh bae50d6719 Defensive code in sqlite3TreeViewWindow() to fix a compiler warning.
FossilOrigin-Name: b250c218b4b6327a1cae3edbc037625ba998f89ee13a9bfbc2cefd1edfc4b768
2022-04-30 19:55:28 +00:00
drh 7497364749 Simplified fix to the problem with subroutine reuse in the RIGHT JOIN no-match
logic for a subquery on the right-hand side of an IN operator.  The code still
needs simplification.

FossilOrigin-Name: a193749730d6cfba617f2a64e7254c78f92bbf29b109c19055fc33f6cc643d4c
2022-04-30 18:40:22 +00:00
drh 2aa1086cab Preserve the COLLATE operator on an index on an expression when resolving
the use of that expression into a reference to the index.  See
[forum:/info/7efabf4b03328e57|forum thread 7efabf4b03328e57] for details.

FossilOrigin-Name: a8da85c57e07721dc1c918d67433d6c99ce48421e369123cc3194d855e55f7e8
2022-04-30 12:35:51 +00:00
drh a25bbaf74a Further improvements to codeEqualityTerm() for cases when an IN operator with
a right-hand side subquery is used as a constraint that needs to be processed
by the RIGHT JOIN non-matched logic.

FossilOrigin-Name: bb2798be3fb5737827eec505db2d4c8cb510d227d98fc26ce748bf2da7e8b382
2022-04-30 00:06:52 +00:00
drh c64f0e71c1 Enhance the TreeView debugging output for Expr with opcode TK_IN so as to
show the RHS table and the subroutine address.

FossilOrigin-Name: aec1e4cd59ae874b66335e4f87322fbe31fbb752429e68bf41338db316d0a9ed
2022-04-30 00:05:37 +00:00
drh 3d5665366f Enhance the codeEqualityTerm() routine inside the code generator so that it is
able to reuse an IN operator that has an invariant subquery on its right-hand
side while coding the non-matched loop of a RIGHT JOIN.
dbsqlfuzz 19f1102a70cf966ab249de56d944fc20dbebcfcf

FossilOrigin-Name: 56dd3065469e49320b13af039471b3f0b85e6f7368cfd97b1cdc0cf8fa8e1956
2022-04-29 19:00:11 +00:00
drh 8e8e9de87e With TreeView, only show the table columns for a SrcItem if the data source
is a subquery rather than a persistent table.

FossilOrigin-Name: 7b4a0d0fa1d8facaf5e550650d9b261eda7eb7a2a413627f2751f01c5477e1f3
2022-04-29 17:45:39 +00:00
drh 0c0d0526dc Multiple enhancements to the TreeView output for SrcItem, cherrypicked from
the right-join experimental branch.

FossilOrigin-Name: 293afa81112e824eec2557d004a27319d484276f796936e16d64243fe24f6b68
2022-04-29 17:13:52 +00:00
drh 08e1a6a29b Show the USING clause as part of the tree-view display of SrcItem.
FossilOrigin-Name: 9cba3ce577e442f83d7a2d6926e38ffe6bc45953c88ecdd384f3455890303cce
2022-04-29 17:03:25 +00:00
drh de7a820fd0 Minor typo fix in a comment, for the benefit of broken IDE syntax highlighters.
FossilOrigin-Name: 680ccecbc839373194ed2dcc1053e25512d9ea3f12f8c8963cb8fbd1a034d2f8
2022-04-29 12:09:43 +00:00
dan 07fd1bf323 Fix problem with SQLITE_OMIT_VIRTUALTABLE builds.
FossilOrigin-Name: a99ee612b9bd6d75b63e557ef5bdac2143425a558cf023a0480cc28c8300a9a8
2022-04-28 18:33:02 +00:00
drh a087eb8f6d In treeview.c, show the columns of the table associated with each SrcItem.
FossilOrigin-Name: 3aafccb5c3c780c29090ee5eb428a6c3153627ce8bf834bbd392e79a30e9389b
2022-04-28 18:17:51 +00:00
drh 4bea8c6b56 Tweaks to the name resolution on parenthesized joins. A small number of
tests fail now due to extra columns appearing in the expansion of "*".

FossilOrigin-Name: c86804917e3fffcf0c19bbf11875667f7968275210fc768e650826bd9c87a5d2
2022-04-28 17:35:58 +00:00
drh 09121b0523 Merge trunk enhancements into the right-join branch.
FossilOrigin-Name: 3fd9706bba4a71cb5c7ce1341c3be0a7727941445820a073e7b2f0f32512e8ef
2022-04-28 12:52:49 +00:00
drh 22b541b55a Fix a harmless typo in a comment.
FossilOrigin-Name: e1f4a115df34e45cf1bcf98961c699b582f564a58a979e95853b219bda06212c
2022-04-27 18:38:46 +00:00
drh 609959285b When computing STAT1 values using ANALYZE, if a ratio comes out to be between
1.0 and 1.1, then round it down to 1 rather than the using the default rounding
rule of changing it to 2.  The reduces the estimation error for the
case where a column value is very nearly, but not quite unique.

FossilOrigin-Name: eb59c46a5aed69bc6fd096997bf24c082e533c1085439f6ec1fbe5ff78e8b374
2022-04-27 16:41:56 +00:00
dan 9684d71081 Fix a test problem in rbubusy.test causing a crash under some circumstances.
FossilOrigin-Name: bc5bbd9fa636cc9ef0cbbc0600b8fc1404b9732670ac4e7a8b5a230fbce758d5
2022-04-27 13:33:48 +00:00
dan 5487cdcc0a Update corruptL.test so that it works with SQLITE_ENABLE_OVERSIZE_CELL_CHECK builds.
FossilOrigin-Name: b1bec72043f798f4d4d30e6b60a45ed4dc521115c8a9f97bb8228e3f089deefb
2022-04-26 19:16:11 +00:00
drh 3e4314b4f8 Fix a problem with automatic indexes introduced by
check-in [664b461bb5063d980] and reported by
[forum:/forumpost/0d3200f4f3bcd3a3|forum post 0d3200f4f3bcd3a3].

FossilOrigin-Name: 134cfb18ff930e4bccc1a7412a02be353bf67c6d5080bc0673afaac81afa889c
2022-04-25 20:56:55 +00:00
drh 0e464b5f51 Do not allow the push-down optimization on the right table of a RIGHT JOIN.
FossilOrigin-Name: 05917bfa02a7b6678c147d10fb53f55532ab15fd5d82d925ae921ae3759f0115
2022-04-25 20:47:58 +00:00
drh 5eb6e09795 The pushDownWhereTerms() routine should be using
sqlite3ExprIsTableConstraint(), not sqlite3ExprIsTableConstant().  This fixes
many problems, but still an error persists in join7.test.

FossilOrigin-Name: 10bf0e613809f71cc1a47ad40b517e2a66671212a6464e179c9d377e8b70d499
2022-04-25 20:38:42 +00:00
drh a9cdb90421 Fix a problem with automatic indexes introduced by
check-in [664b461bb5063d980] and reported by
[forum:/forumpost/0d3200f4f3bcd3a3|forum post 0d3200f4f3bcd3a3].

FossilOrigin-Name: 7ca3456c00998a429418ff29cf251b381586b330b88344c94a40c5df0b71da85
2022-04-25 19:40:33 +00:00
drh 95fe38f2fc Add a new optimizer disabling bit to disable just the UNION ALL branch of the
query flattener.

FossilOrigin-Name: c0f9ebab5455d8541a562122d3270b95ce571c3fd870b0048dda2b036c2b66c0
2022-04-25 14:59:59 +00:00
drh 7f417569f7 Avoid unintended side-effects on Parse.nSelect in the
sqlite3ViewGetColumnNames() routine.

FossilOrigin-Name: 59789fe1e745bb6f81898176e7e9c6064ac9f4bbefb4dc3c8f3e4c1379568f69
2022-04-25 14:49:48 +00:00
drh 1a6bac0d2f Remove NEVER() on branches formerly thought to unreachable
(see check-in [71272caff5874137]) in order to fix the first bug reported
by [forum:/forumpost/28821db852|forum post 28821db852].

FossilOrigin-Name: bd6811d8110d5f00596e2eff6d4b02af8b6d8557d41990e6f50518ead0fa01fb
2022-04-25 10:43:19 +00:00
drh 7980fadcef Merge enhancements and fixes from trunk into the right-join branch.
FossilOrigin-Name: 2fb165cf8bd1e43248612aa2922bd311df30dcbb3c2f1daee73c363e409c501f
2022-04-23 19:26:34 +00:00
drh ecb386b71f Prevent the ORDER BY LIMIT optimization from running if the innermost loop
is a right-join, as doing so will get an incorrect answer.

FossilOrigin-Name: 3aefc874d31885c64a5e02868edb2aa56a2b4429252d494e67e4088a9298ce5b
2022-04-23 19:21:47 +00:00
drh 30d2aab5fd In debug builds, add extra code to verify that there are no jumps that try to
escape from the right-join body subroutine.

FossilOrigin-Name: 45fe919266ba1843f3eeeb511ab43126069d4976c9fc64e57e0390c21f110b6e
2022-04-23 18:46:03 +00:00
drh 6c7e89b48a Fix false-positives in sqlite3VdbeNoJumpsOutsideSubrtn(). All tests pass now.
FossilOrigin-Name: 1300d978d5a072780e0f16722e42461dc983de9b4dfb2f5a7023c74c92ab9bc8
2022-04-23 18:34:55 +00:00
drh b77c312956 For debug builds, if the RIGHT JOIN body subroutine contains a jump that
escapes the subroutine, then abort the prepared statement with a descriptive
error and SQLITE_INTERNAL.  This extra sanity check causes many tests to
fail.

FossilOrigin-Name: 2c5bb2bff26cc70d8cac78ddd12d5ac37ab1472f5f88afbd975950a18ac2804d
2022-04-23 18:04:31 +00:00
drh d63c07e6c5 Fix an operator typo - This indicates that the branch needs further
investigation and verification.

FossilOrigin-Name: f6ab67965b718b0c6d7faf769c7e47384cfd2ddbb03df518e0c5d367f8583387
2022-04-23 14:30:22 +00:00
drh 0748e8bf9a Correctly resolve left and right USING columns of an outer join in a
parenthesized subjoin.

FossilOrigin-Name: ea91aba88c31a042f4e32d66dfa089f95d0f9d316ab26f298085eb34dbf73e86
2022-04-23 07:31:50 +00:00
drh ab843a51d3 Fix minor problems with the new join table name resolution logic.
FossilOrigin-Name: 3a6b0db4519072dbd41b1c105bf1a0c6b4dd90380e94a5662645d8d41483c707
2022-04-23 07:29:34 +00:00
drh 45e41b7371 Add the ability to access the USING columns of the right or left tables
of an OUTER JOIN even if the OUTER JOIN is in parentheses.  Prototype code
only.

FossilOrigin-Name: c3a427575fe71de3061495059e253c72c7213e2925ee2873e4f59fc73bfae103
2022-04-22 23:18:21 +00:00
drh f054c34372 Merge the latest enhancements and fixes from trunk onto the right-join branch.
FossilOrigin-Name: 7f8983345d1e3ac28d736fce9f90772aa0e4654670a1db3dd0ee45b55e92f2e4
2022-04-22 19:52:51 +00:00
drh d6bb6000ef Make use of the "%!S" format when running ExplainSubquery.
FossilOrigin-Name: 9425d79cb407dedc259655625369e023d22a04ef7db606ea3eefe7e4d662be1a
2022-04-22 18:07:38 +00:00
drh da653b897d Improve EXPLAIN QUERY PLAN output and comments on bytecode listings by
distinguishing between "subquery" and "join" and using consistent names
across EQP and bytecode.

FossilOrigin-Name: a2d3ee92420ec564e31eb0005367cf7ff3d00bfaed5a98ffdbe17c91c95d9d97
2022-04-22 17:36:10 +00:00
drh 67f70bea06 Honor the MATERIALIZED keyword on a common table expression by not flattening
the CTE into an outer query.

FossilOrigin-Name: 8d631a6b9eb06b54b10eda595a4c588ca38f909b4afa653b24d1f720b55d72f7
2022-04-22 16:15:48 +00:00
dan 9b843f0ce0 Add test cases to check the handling of SQLITE_BUSY in rbu.
FossilOrigin-Name: 6fccc733c6041a2946fb3d37e4737ae37defae5c110225dd746cdc038cc64957
2022-04-22 15:18:41 +00:00
drh 1ca14b74ed Simplification of data structures in the wildcard expander for
SF_NestedFrom queries.

FossilOrigin-Name: f7c18262347ff430879d5afc7a118d2b9b0050c845c6b1fe6c047062ea2ba8fe
2022-04-22 13:34:45 +00:00
drh 9c2d7aa7d0 Minor simplification to the result-set wildcard expander for SF_NestedFrom.
FossilOrigin-Name: d942530a6550a0cbe31790e462b0f0d57b9b4a896161878b7d45d11cbc1cb7a3
2022-04-22 12:46:46 +00:00
drh 8318b55d87 Merge the latest trunk fixes into the right-join branch.
FossilOrigin-Name: c74dc574c3b24a7d3533202f33b15341b043cfd89a80250563e6771ab6b6b8a7
2022-04-22 09:57:57 +00:00
drh 1c69bc912d Previous fix to join8.test needs a return.
FossilOrigin-Name: 7b4cd705a0339ddacad19564b07e50e4f68f54bf14dd2cd5d59b39314a4d2523
2022-04-21 23:34:35 +00:00
drh abb4e7598c Disable join8.test if the build lacks support for virtual tables.
FossilOrigin-Name: 94e1916a2f594e6b8a54734027deb99688244d05cefb3c78f23afab49af1e08f
2022-04-21 23:01:24 +00:00
drh 11140addbb Add support for RIGHT and FULL JOIN.
FossilOrigin-Name: f766dff012af0ea3c28a8ce4db850cd0205729a8283bce1e442992aded7c734b
2022-04-21 19:38:17 +00:00
drh 6dab33bf40 Fix harmless compiler warnings.
FossilOrigin-Name: 29255664127a975e5b0d5767cd4e56d93ff2ea1994702cdfbdca1b700952502e
2022-04-21 19:25:51 +00:00
drh a74b4c4d45 Fix a harmless uninitialized variable warning in MSVC.
FossilOrigin-Name: b870d2a2fa54ddab6ffc9b9d95f52420a5a6831aeb73dac75355ca1ab15a190e
2022-04-21 19:20:38 +00:00
drh 7e9a56f70f Fix harmless compiler warnings in the CLI.
FossilOrigin-Name: dfd2100bc4f316825fd199b347849d1a2b941837f9eedcf36f3c3d280692b991
2022-04-21 19:14:23 +00:00
drh 503ad9c72d Make sure the code generator knows to invoke row-value subroutines which
running the right-join post-processing loop.

FossilOrigin-Name: fd328e52aee1dace12b1c2f44b6f7e9d15d8f77c8e9d9e3d85840a129a4b1808
2022-04-21 14:48:40 +00:00
drh 825a6bffc4 Ensure correct fg.isNestedFrom values even on crazy parses.
FossilOrigin-Name: e611e8e62c948d28cd3f28452d3096bab06998a685ed9434061cc2054f5cac32
2022-04-21 14:08:29 +00:00
drh 18f8600fe6 Avoid materializing columns of SF_NestedFrom subqueries that are never used.
Other code improvements manually imported from the right-join-paren branch.

FossilOrigin-Name: cd8272fc2a34d1b245fd95208b9b601266ee7d2ff0f5ce52d03752f2c4e852a2
2022-04-21 13:11:26 +00:00
larrybr 6403e77d3b For CLI, fix how columnar mode fills in empty portions of wrapped row outputs.
FossilOrigin-Name: 77aed89192bdbad819ac17bf5d08728278a9b8cbbbef1d805df230caff79b417
2022-04-20 22:41:10 +00:00
drh 22b410d894 Small correction to the new bUsed logic of sqlite3ProcessJoin().
FossilOrigin-Name: ba04142e09bb1ccc86824760a2e11df47e070285a2d09c2f61b75255886597cd
2022-04-20 18:12:42 +00:00
drh e60ffa3350 Merge window function fix from trunk.
FossilOrigin-Name: b6b9e185f8c44b5f2f51111f7c5e4e2d77c8b853c5be271467ce138e8066340c
2022-04-20 16:54:47 +00:00
drh 910e57b9df Remove an unnecessary assignment operation.
FossilOrigin-Name: ed46527aca170ccbe9ed9ea4ae065db72c82dec17da7b99c928fae4495f05c2b
2022-04-20 16:53:23 +00:00
dan 41150bf35b Fix a problem with using multiple SQLITE_SUBTYPE function as window functions in a single query.
FossilOrigin-Name: 9430ead7ba433cbfce99f4f364a0c08499230e3a04f167326b0f131f098ffa09
2022-04-20 16:42:57 +00:00
drh bc656e220f Comment fixes and improvements in sqlite3ProcessJoin().
FossilOrigin-Name: 1118655f4d58da1273e83954c80d8bc17fa3bde7a39e81cb9947d59894d5ab93
2022-04-20 16:26:22 +00:00
drh 815b782e99 Improved tracking of nested SELECT objects used to implement
parenthensized FROM terms.

FossilOrigin-Name: 0da2232624571f4020c05d775ea518514d748fba8dacd4caba2e2e6ed1ae399f
2022-04-20 15:07:39 +00:00
drh b465a83353 Also show the ENAME_SPAN value in sqlite3TreeViewExprList(), if there is one.
FossilOrigin-Name: c1d42861778d65f7014c43fbaf09972a69ff0d81bfc2f4720160a989489cf2c8
2022-04-20 12:15:51 +00:00
drh d4e9caf987 Improved TreeView output for ExprList: Show the ENAME_TAB value, if there
is one.

FossilOrigin-Name: eb3f883b45f1bf3f388823360f4aec2d4b8776bfd96185b4fb44b7bc95c62318
2022-04-20 12:14:20 +00:00
drh 2627cbd4b5 Add a new comment to the body of lookupName(). No code changes.
FossilOrigin-Name: 22fa9b9b450fbbf7578597714eb1094f7d7433ac13497dc7d4a9affc4a2652ad
2022-04-20 12:02:52 +00:00
drh befbb40f44 Merge the ALTER TABLE fix from trunk.
FossilOrigin-Name: d5ceaef3fca8cb4791ead9cbfe00d0eafa1bdc2b0522c3599c68b40fe6a7efe2
2022-04-19 23:00:32 +00:00
dan cbde37d8e4 Fix a problem in ALTER TABLE with handling "table.*" expressions within SELECT statements in triggers.
FossilOrigin-Name: 24755fd0657252e49793bb1fe906973a2dd84a1bde03bea9a762de36cc96c2d2
2022-04-19 20:47:18 +00:00
drh 4d0d071a53 Improved comment on the JF_LTORJ constant definition.
FossilOrigin-Name: e0744da95fc010dc3a2e030ff491bcfa08a18691ee6ebc7d4e8aab3850f56eec
2022-04-19 19:51:51 +00:00
drh 3117b7b081 Fix a NULL-pointer dereference that can occur on an aggregate query that
uses FULL JOIN.  dbsqlfuzz 496a35dd4eefcd7935aaaeb0c69056bf49785d28.

FossilOrigin-Name: 63b8f8aec2a9ac3fbbd02715aa308eaf43c9ffde9d7c6db026d46edc575e7bdd
2022-04-19 18:23:01 +00:00
drh e32d6a0bbf Mark an unreachable "just-in-case" branch as unreachable.
FossilOrigin-Name: b966d52437f08a6759a83a45cafb0d706a8933a8e55dee38ae78166d1a5b3ba4
2022-04-19 15:56:03 +00:00
drh de75638b33 Add 512 new join test cases derived from PostgreSQL output.
FossilOrigin-Name: 78d58e461f99366d2749ccd6d02ab4cba0cab20bb80c097e7128da1e50303549
2022-04-19 15:01:57 +00:00
drh 2e61588931 Remove unnecessary cases for the resolver.
FossilOrigin-Name: 5bc9aa68e2f938f6a70dd4b08703fe52416d17efe461ec65d37332b57b827fdd
2022-04-19 09:39:39 +00:00
drh d737b16f92 Add the omitted "finish_test" to the end of joinA.test.
FossilOrigin-Name: 0907505cc9bb051280108fe5074211374b31836fae1ae6667a3de69f9d83fc01
2022-04-19 02:03:18 +00:00
drh 3b8c7545df New test cases for RIGHT and FULL JOIN.
FossilOrigin-Name: 5c2f670e0fb35648e1d6e1c48f4d8af815cd57d59eac6ba22e253511bb078870
2022-04-19 00:24:52 +00:00
drh 1c2bf41a12 Fix the query flattener so that it does not flatten a RIGHT or FULL JOIN into
any position of the outer query other than the first.

FossilOrigin-Name: 837322aa95b1c46201b7dd0c2e6c7b9915b4276d997949f1ecf961fb7f3514cf
2022-04-18 23:20:02 +00:00
drh ec39c96473 New test cases, including one that gets a different result than Postgres.
FossilOrigin-Name: 49ea11a4a5fd630db44f458304d4f45fa103529ed6b36d538c78074965e8d799
2022-04-18 22:51:24 +00:00
drh f80bb195b3 Disable the unused EU4_EXPR mode for the IdList object.
FossilOrigin-Name: 5bcf4aa3bf6b1b9f47142bc37683bb3bf0adeffd052d07449af7c9b415add052
2022-04-18 19:48:31 +00:00
drh 7466d5665a Even more test cases.
FossilOrigin-Name: 5f4310a104443ac3fc56f9d9cd2d428dd3e7a2a0285c8e74de6f499439fd6868
2022-04-18 19:34:41 +00:00
drh 23f240b325 New test cases for parenthesized NATURAL FULL JOINs.
FossilOrigin-Name: e34250efd34b526373bf072a43a7984ca19690836d7d2464dea8338066eaee8f
2022-04-18 19:28:08 +00:00
drh a20922cb20 New test case demonstrating the ability to invoke OP_NullRow on a cursor
that has never been opened.

FossilOrigin-Name: d173edc242f295f5812a58cad184695881d9b1b160cd5b25e303e22848e90ce1
2022-04-18 18:01:38 +00:00
drh 25f2ce6e71 Merge the btree bug-fix from trunk.
FossilOrigin-Name: a333c0b50c3af7cd818470a647d78c7c691ef15418ec7cffe80dd88405393069
2022-04-18 16:23:01 +00:00
drh 7348ca4e0b Ensure that left-hand side WITHOUT ROWID tables are set to OP_NullRow prior
to running the right-join loop.  This fixes a problem introduced by the
previous check-in.

FossilOrigin-Name: aab7665ce6c004df701a72aef1a5135f2c78f16c6ff728a00076afb66ba9d3a0
2022-04-18 16:20:59 +00:00
drh 2e1bcc9dd0 Fix problems with WHERE clauses that follow multiple FULL JOINs. This
introduces some new faults in the tests, probably due to something
unrelated.

FossilOrigin-Name: 95b242d4c2fed7c713299565ac1010f8a7534a5695589e87d5a0204c7bf5f3dc
2022-04-18 16:10:07 +00:00
dan 1942d1f236 Avoid an assert() failure in allocateSpace() triggered by a corrupt database. dbsqlfuzz f022eb0ce64d27808574d1dcde5cf7d002dabde8.
FossilOrigin-Name: 2de7f8cc7fe18f0828bb53f1fd11f5eb828faf4d6dfaf39693dff4f8926c1c7a
2022-04-18 15:56:58 +00:00
drh 41db500274 Merge the latest fixes from trunk.
FossilOrigin-Name: 1ba3b3ccf145d84fa75afabe2fa925f65e43f815b25b15bd60073a41aa97bf57
2022-04-18 14:41:24 +00:00
drh e98b71e65d Improved comment field in the bytecode generated for OP_Column and OP_Rowid.
FossilOrigin-Name: 1b2c5cef9560123344db391cd065090d1914724715ec6643d2d9b5fac2051a21
2022-04-18 14:15:07 +00:00
drh 088b615acd Improved comment field in the bytecode generated for OP_Column and OP_Rowid.
FossilOrigin-Name: 009bbf8026106c5a74cced06cced48badb870a4b6e6a2f8104a544d2a8d79e45
2022-04-18 13:57:57 +00:00
drh 01a6c16e0c New RIGHT JOIN test cases, one of which is currently failing.
FossilOrigin-Name: 9168cbbedd1c9d735279295a78212d830e24269f6d7e445e71faa2c06973223d
2022-04-18 13:08:17 +00:00
drh a1848a5d22 Change the row-value initialization subroutine call from within the
right-join body subroutine from an issue to an optimization opportunity.

FossilOrigin-Name: 829d49f27c041651ffeadc1397e4dd87a9994c9290e13b93542dbd2c514769cd
2022-04-18 11:22:46 +00:00
drh d875c7eefe Do not allow an empty table bypass to jump outside of a right-join body
subroutine.

FossilOrigin-Name: 1549dcd2353903b70abadd428eeef971ab940df04fb05a6b83b04ee30932db6d
2022-04-18 10:26:50 +00:00
drh d973268ccf Fix the sqlite3SrcListAppendList() routine so that it correctly adds
the JT_LTORJ attribute to the first SrcItem, if needed.

FossilOrigin-Name: 07ed0dca310d828f9fe152efa8ee2a89202771a8f661afa1dbeee34aaabef67a
2022-04-18 10:09:29 +00:00
drh abf86bd313 Leave sqlite3ProcessJoin() early if an OOM is encountered in the NATURAL
to USING converter.  This avoids NULL pointer dereferences further along in
the code.

FossilOrigin-Name: 0ccb224e13ad44c7e1a3aa186821a929faabc0075fe15799476c00d9a92e9d91
2022-04-18 09:59:33 +00:00
drh 79a25ee021 Fix to the coalesce() function generation in the resolver.
FossilOrigin-Name: 584bd55e20669d09b7efe3429ba847c42c32fb1eb960784c4e0dedcd96899313
2022-04-18 00:57:11 +00:00
drh d0453f7ec5 When converting a NATURAL JOIN into a JOIN USING, make sure to insert the
name correctly into the IdList even if it is a wierd quoted name.

FossilOrigin-Name: e62156b696f2496e2697cb3b46f136551b58644e2a5824aa3d759596694b2f4b
2022-04-18 00:04:15 +00:00
drh a3e2518bb3 Fix to the logic that computes coalesc() functions to resolve USING terms.
FossilOrigin-Name: 20388548d868511f8c8437718985d75fe9801835811fec716f1700727b9aa367
2022-04-17 23:46:18 +00:00
drh f68621fe83 Deal with OP_Return bypass in the RIGHT JOIN subroutine by adding extra
OP_Returns where needed.

FossilOrigin-Name: 71abe5641f599f27d1f0c800f6182e1168909f8aa99389b835b07d4b5f5483eb
2022-04-17 22:58:23 +00:00
drh 2bd9f44a18 Change OP_Return such that if P3 is 1, the Return is a no-op when the
P1 register contains a NULL.

FossilOrigin-Name: c90602328a4b26f06d76c5343d29ebb7a782186c86ea88f5965a41040cff5346
2022-04-17 20:30:52 +00:00
drh fe14699765 Further improvements to USING() processing for RIGHT and FULL JOINs. All
currently known issues are now resolved.  Performace is improved.

FossilOrigin-Name: 9fd3f22e2228dfba127f6ffe549109f3a4e910fa124adcc9c5483931bd6d5cd7
2022-04-17 18:46:17 +00:00
drh 6fda176ba6 New test cases, one of which is failing, indicating a bug that needs fixing.
FossilOrigin-Name: bd5fd68435ff068c18d7d46b33cf7591263a03c32a917a7df7c087b08c573cc8
2022-04-16 23:38:29 +00:00
drh 052953a4e6 Fix the USING to ON translation so that it works correctly for a sequence
of two or more joins where one of the joins to the right-hand side of the
list is a RIGHT or FULL JOIN.

FossilOrigin-Name: 9ffc2b231956cde1bc90519aa174b0e2dc30ef671ed745f4f3ffa9fbb7ffab4b
2022-04-16 22:57:41 +00:00
drh fdc621aece Since the query planner is unable to cope with a LEFT JOIN on the left-hand side
of a RIGHT JOIN, detect that situation early and raise a parsing error.
This is a temporary measure that needs to be fixed.

FossilOrigin-Name: 6d5d6e0403241c99ab4a47d7b6eedcd8ebc615a8ca8d66d7e81171f901b170d7
2022-04-16 19:13:16 +00:00
drh cebc8009ed Additional SELECT trace logic: Show the tree after result-set wildcard
expansion but before name resolution.

FossilOrigin-Name: a7babf75418adffa27dec7a9d382a60e1b9364fb51d72b0a10e2769b308b3c54
2022-04-16 18:33:22 +00:00
larrybr 2d27d36cba Make shell auto-column work with lots of columns when log() is missing.
FossilOrigin-Name: 82366436ef74838dae1f379f3e5b8ad187225a30ec58fb49f047ab7c08a263cf
2022-04-16 17:53:25 +00:00
dan b192970809 Fix a problem with "ON DELETE RESTRICT" and "ON UPDATE RESTRICT" foreign keys in attached databases scanning child tables in the wrong schema.
FossilOrigin-Name: 04d5b637f087520cd58211505f9b5c086ff96d864a1908f60464b6fe22c62b7d
2022-04-16 15:46:23 +00:00
drh 977eef6cdc New test cases. One of the new test cases shows a flaw in the base design
of RIGHT JOIN.

FossilOrigin-Name: 4c3ce6475a67b1e207a5b63d9e2d38ee5bc45c899ad00ee327f292bf59039b9c
2022-04-16 13:55:48 +00:00
drh bdbda1eb1f RIGHT JOIN USING now appears to work the same as PG-14. Legacy tests pass.
FossilOrigin-Name: 5bfb862419541de955dae35fc91f6e9fc70e2744bb786d49fa26bede80b9091d
2022-04-16 12:40:52 +00:00
drh be60896485 Revamp the USING clause processing so that it works (mostly) with RIGHT
and FULL JOIN.

FossilOrigin-Name: 719c8d920b435b0f234d47467a2abe2941ab7d55ecca886e211cfce577ae648c
2022-04-15 19:53:35 +00:00
drh e62d9149a6 Avoid deleting substructure of the Expr node in lookupName() until after
the error message is generated.

FossilOrigin-Name: b8e717663957dfd84e580bf21bc8e8881b33fdb94a2cc0c664a230e54d5e5076
2022-04-15 19:49:28 +00:00
drh bb3c62a758 Progress toward a working USING for FULL JOIN.
FossilOrigin-Name: fed2646adecb0a05dd674dc1cd2c0ae205078fe552ba93b8d68891c728c67637
2022-04-15 19:27:02 +00:00
drh 4ce7bf9156 When expanding "*" in the result set of a SELECT, do not attach a table name
to columns that are in subsequent USING clauses.

FossilOrigin-Name: 91530990e018580ec5322ace6f0c369a32a3529a0bfb4defb25ca20223a2a80f
2022-04-15 18:30:48 +00:00
drh 22c4bc8991 The sqlite3ProcessJoin() routine converts a NATURAL JOIN into a JOIN USING so
that henceforth the NATURAL keyword can be ignored.

FossilOrigin-Name: 8378e1e0d289627fb294ccd3f5865ef49df3a42b8a5aa211e21be1b42d9da753
2022-04-15 17:08:40 +00:00
drh a99e325468 Enhance the IdList object to exist in a single memory allocation (rather than
a separate allocate for the base object and the array of IDs).  Also permit
an IdList object to store an Expr pointer together with each name.

FossilOrigin-Name: 40f3c95871e6f40f287ef2756abafb8fc56dffdd0af69436e5c7d8e95022d94e
2022-04-15 15:47:14 +00:00
drh 358424aeff Add the "3" in the name of the sqlite3ProcessJoin() function.
FossilOrigin-Name: b925f72b6f679c61b0d6be16fabe64dc7605550b7bd86f35c586dcecd8217673
2022-04-15 15:15:01 +00:00
drh a51379ad78 Record the three known big issues with the current RIGHT JOIN design in
the join8 test module, with tests that deliberately fail in order to remind
us to fix the issues.

FossilOrigin-Name: 2c4ee723f4d0591d09776adfb82246bfa89153ab390b8b3f1878d1cdc43d68c8
2022-04-14 20:43:22 +00:00
drh b3ebf3043f Cherry pick subroutine indentation improvements and the hardening of
OP_Gosub from the right-join branch back into trunk.

FossilOrigin-Name: 12645f100d902690630a2925674aedbb01d41a53426a26a2f56de5b8fdec955f
2022-04-14 19:48:32 +00:00
drh 79f60034ee Another instance of indenting a subroutine.
FossilOrigin-Name: 73f4036b04798660b30e540cbab69420078df9fb62a6a39944e078c36272f905
2022-04-14 19:05:17 +00:00
drh d549a702b3 Check for interrupts and invoke the progress handler following a Gosub
opcode, to avoid and recover from infinite subroutine loops.

FossilOrigin-Name: 647211e044a5856ceb6bf3e7b78e650fe7d81f8b7bf34568b99b346405ba520c
2022-04-14 18:19:06 +00:00
drh 2c31c00bfa Rerun the subroutines that compute row-values if necessary from within
the RIGHT JOIN body subroutine.

FossilOrigin-Name: 9b9038bcd0ab5c4f01661456635526cef764f854ff24018a5e6e43825d07eb59
2022-04-14 16:34:07 +00:00
drh 37f5584a2f Adjust the output formatting of bytecode listings so that subroutines used
to implement subqueries are indented one level.

FossilOrigin-Name: 079b7b125206fb295720612f4853a5b786ec431ab595d35407195844779c149d
2022-04-14 15:55:34 +00:00
drh d345dcf39a Disable autoindexing for the RIGHT JOIN loop.
FossilOrigin-Name: 402a89e33e39b00352dc9fb3301d03c6f75d8bb5c2ad540cd22506bff10b4d85
2022-04-14 14:58:50 +00:00
drh 375f182b1d Adjust assert() statements to account for the new always-NULL cursor type
added by [4526c5d316508093].

FossilOrigin-Name: 7822faa48a058c0b0313b9241d290153fbe74ab84f58369a70014118a9085d1d
2022-04-14 14:40:29 +00:00
drh c504f677b6 Previous check-in accidentally inverted a test on an assert(). Fix that.
FossilOrigin-Name: 5ec4f806c569428851b6f0159451aa3ed66b3bc61a845fd7c543cffb694b882d
2022-04-14 14:19:23 +00:00
drh eab6c125bd Fix assert() statements associated with artifical null-value cursors
created by RIGHT JOIN.

FossilOrigin-Name: f5bce5f152259767497ae6826c558003822d976b3f35f4d74edee59a3490efb2
2022-04-14 12:59:25 +00:00
drh 95b1036e9a Fix a harmless (false-positive) unused variable compiler warning on MSVC.
FossilOrigin-Name: 63b04c63de680261a0d3eaf27154a1e8e77e3e166c3f2dbaea985603991c74f7
2022-04-13 19:00:57 +00:00
drh b60d1fbe8e Make the sqlite3TreeViewSrcList() routine a no-op if called with a
NULL SrcList object.

FossilOrigin-Name: 185d2720e7775e3060a1647353c10aada435244db53a0732ee786788a6ecae3f
2022-04-13 18:32:04 +00:00
drh 7c96039492 Fix an assert() in OP_Column so that it accounts for the new type of
pseudo-cursor that always returns NULL for any column.

FossilOrigin-Name: 371ddc97bef8e0d88ad965f00d27e010880174312ea36c4f1165dcf08441f40a
2022-04-13 18:20:23 +00:00
drh 3ac624344d If the OP_NullRow opcode is given a cursor that has not yet been opened,
then go automatically open it to a special pseudo-cursor that allows returns
NULL for every column.  Used by the new RIGHT JOIN implementation.

FossilOrigin-Name: 4526c5d316508093b7f3aeda1ce9d16ceb0be79842015a6d51f28c22b4473ca2
2022-04-13 17:41:03 +00:00
drh f7ecd956ce Move the explain comment for the RIGHT-JOIN post-processing loop to the
verify beginning of the loop - to make the start of the loop clearer to
human bytecode readers.

FossilOrigin-Name: 7ed2a271e6fcbb5e69a7f3a88d3f45fe6318819c0cc6a0dcc06c3dae5aa1503f
2022-04-13 16:46:35 +00:00
drh 94e615a6ac Add support for RIGHT and FULL OUTER JOINs.
FossilOrigin-Name: fa9d206f904280e3eafc6f4ba6c0c7325948364c62eeeb9f0fdc5825d622ec35
2022-04-13 12:34:54 +00:00
drh 12c35ec322 The rows of a RIGHT JOIN might come out in any arbitrary order. So disable
the ORDER-BY/GROUP-BY optimizations if a RIGHT JOIN is involved.

FossilOrigin-Name: d168f245ecf497368feea4697769930c00420ef47a584904dac85371b61fb78a
2022-04-13 12:12:01 +00:00
drh 3b79f7580a Fix an assert() in btree.c that might not be true for a corrupt database file.
FossilOrigin-Name: dbd8e2e46cfb2de0ebdbb62cda2fe669df3eda98f5d6112d541f581995b1361d
2022-04-13 10:49:50 +00:00
drh 146e64d2e4 Add missing VdbeCoverage() macros on new branch byte-code opcodes.
FossilOrigin-Name: 218c7167e562f5c327124f02a92de85079315320a221fb0508310d927596b14c
2022-04-13 01:52:32 +00:00
drh f7309bce10 Ensure that the JT_LTORJ bit in the SrcItem.fg.jointype is preserved during
query flattening.

FossilOrigin-Name: 61259050152321bc57dbdfdc3edcabb4f18c021b1ee0491c1e04ae24c7a59d89
2022-04-12 20:20:54 +00:00
drh 0879d5f9e0 For the bad join type error message "unknown or unsupported join type"
remove the "or unsupported" clause, because we now support all valid join
types.

FossilOrigin-Name: ab0a0562dd3594cf50ee56f6b3a5847fa5dcadf69146d560e3e7a95651b8f405
2022-04-12 18:40:14 +00:00
drh 949e2ab49a Factor out the RIGHT JOIN non-matched row loop from sqlite3WhereEnd(). This
reduces the register pressure on that routine and helps it to run faster
in the common case where there is no RIGHT JOIN.

FossilOrigin-Name: beeecf1604d4fb11e45058f48cb2289c6542e0bc218d63a245198113d8d5476b
2022-04-12 18:04:29 +00:00
drh 57d4b5bde1 Merge the latest enhancements from trunk into the right-join branch.
FossilOrigin-Name: b3e57ba120067c79e0398e39da9f00ecb11a5e18c36479da4c36a39e88a78a27
2022-04-12 17:43:30 +00:00
dan 6625d6d873 Earlier detection of corruption in balance_nonroot(). dbsqlfuzz 9191ade77ebd3b7a3356e074957aa85b0c669d14.
FossilOrigin-Name: bff4f083eb1c35544988493a5d73a42e646c4250b841f5aae38c2183f0867a0e
2022-04-12 17:02:27 +00:00
drh 61dac44eb9 The multi-index OR optimization does not work for RIGHT join, so disallow it.
FossilOrigin-Name: 34c2f7b237fa4e0e1cd94fb9c44ebe194b86b88dc575055cc46c7f3695d02756
2022-04-12 14:23:45 +00:00
drh a70782407d Always explicitly set each table cursor to NullRow before doing the RIGHT-JOIN
unmatched row pass.  This is a cheap opcode, and it adds an extra layer of
defense against incorrect results.

FossilOrigin-Name: a3d14e61ca22167296fee125a3e9aa63413408955e03bb3f9d85fa9f22df1b79
2022-04-12 13:46:21 +00:00
dan f7413d9acf Modify utility function sqlite3SetString() so that it may be used safely on Parse.zErrMsg. Fuzzer test case "crash-1604e5d76c92574e21e437049dab9b672e06b767.txt".
FossilOrigin-Name: 09c5a4ec13b02efd6207e26dab7beaf184f0d8ccea0bd0dfe94fc803fe5636ce
2022-04-12 11:02:06 +00:00
drh b087de063b Fix RIGHT JOIN for virtual tables.
FossilOrigin-Name: 75a9116e98b9ac5c1a4c62a01143a016d9ba6a0b495ff7af7468c11947a3e888
2022-04-11 21:00:38 +00:00
drh c133bab72a The query flattener must add TK_IF_NULL_ROW opcodes on substituted values
that land on the left operand of a RIGHT JOIN, just as it already does for
the right operand of a LEFT JOIN.

FossilOrigin-Name: 8e02cdf5b1128f5e5b82d93903063415ec312694e5ccdd19e99fa35433f1b68a
2022-04-11 20:15:52 +00:00
drh ec27077c4f New test cases added.
FossilOrigin-Name: bdd1499c0fa4f8aadf4857a0ccc0d839c250369f29766ebef80330964905e63b
2022-04-11 18:54:23 +00:00
drh 6134b2dff2 Fix handling of "continue" and "break" from inside the loop for the right
operand of a RIGHT JOIN.

FossilOrigin-Name: b6e773a26c2c6ee76ea61acb059b4e676d07ea62f6db9c513638f8986557cf04
2022-04-11 17:27:38 +00:00
drh ff02ac7f07 Do not attempt the LEFT JOIN strength reduction optimization on a FULL JOIN.
FossilOrigin-Name: 7ef3e99a73d70405a185d5d31f2d97d3bd99568fd6f10941e75d6c0baa27dc4f
2022-04-11 14:43:11 +00:00
drh c583719b65 Show LEFT and RIGHT JOIN processing in the EXPLAIN QUERY PLAN output.
FossilOrigin-Name: d91faeffea5cf0585fb71e5311fdcc6b8be85c7e9c732050b4448e617c970101
2022-04-11 14:26:37 +00:00
drh 37259f4e6b New test cases.
FossilOrigin-Name: d5f6791b86f946b348f5ddc9cedc0df4a86b17854a97554140799caf74c602f3
2022-04-11 13:13:57 +00:00
drh 3a6e4c59c4 Make a distinction between (1) WHERE clause constraints, (2) ON/USING
constraints on outer joins, and (3) ON/USING clause constraints on inner
joins.  Formerly, there was no distinctionb between 1 and 3, but RIGHT JOIN
needs to know the difference.  Make RIGHT JOIN aware of this difference and
add test cases.

FossilOrigin-Name: 0f6f61c3664cc87209c2a6f9b6df3a750d1510723fcde209c33db8feaf48bcf3
2022-04-11 12:38:06 +00:00
drh b77c07a715 Fix some comments that refer to LEFT JOIN that should refer to OUTER JOIN.
No changes to code.

FossilOrigin-Name: 5be5ede5cca1cd5ef863fe0feb2b4a990f4a42865281a6c2e4eb816f48847dc6
2022-04-11 11:59:25 +00:00
drh 189c065942 Merge the Expr.w.iJoin name change from trunk into the right-join branch.
FossilOrigin-Name: 29927926eb32acd963e2c496ad67d55177615ec4150fd218afaf2f9a730cabec
2022-04-11 11:48:17 +00:00
drh d198526289 Rename the Expr.w.iRightJoinTable to just Expr.w.iJoin, so that the words
"RightJoin" in the former name do not lead readers to believe that this has
something to do with RIGHT JOINs in particular.

FossilOrigin-Name: e8c00442d2daedec079748d13147bf73b0ec3c3cf432bce2cdccb706bdff2853
2022-04-11 11:25:28 +00:00
drh 79d2658671 Ensure that the JT_LTORJ flag is preserved when flattening a subquery that
is on the left side of a RIGHT JOIN.

FossilOrigin-Name: ccb61fb1f30e2741b19c1a0cbd2951715224852c86234a3c6a4bbd2e1187634a
2022-04-11 10:38:28 +00:00
drh 8a28ce7bc2 Show the JT_LTORJ flag in TreeView debugging output.
FossilOrigin-Name: 21eb44919f38abad30b75181ca8aec38b453b94dba2815caf7e946e07faa40d7
2022-04-11 00:54:30 +00:00
drh 41798d5bbc Do not allow query flattening nor the push-down optimization on the
right operand of a RIGHT JOIN.

FossilOrigin-Name: 5aa0c9ea9cf53c13bf266278b479b2e7af3aa5c6b144bd49ff155a4eb3c23c96
2022-04-11 00:21:53 +00:00
drh 529394e5c1 Cannot use an automatic index on the right table of a RIGHT JOIN because
automatic indexes must be WHERE_IDX_ONLY, but the RIGHT JOIN post-processing
does not know how to work with an index-only scan.

FossilOrigin-Name: beb4401dc09fb68e85ddcf3f99598527691535d0eb7693168f440e5a5a076e3f
2022-04-10 23:48:47 +00:00
drh 9debb58e48 Revisit [f84b2beca7197589]: disallow co-routine implementations of tables
that are to the left of a RIGHT JOIN, to avoid other complications.

FossilOrigin-Name: cf00ebfc4b77f45ec466b0d57d7c22c7f48acab19e4e55b168eb4b53f390d887
2022-04-10 23:01:20 +00:00
drh 62ed36bb5d Minor improvements to the sqlite3SrcListShiftJoinType() routine. This started
out to be an effort to convert RIGHT JOIN to LEFT JOIN if the join was on
the first pair of relations, but that messes up the "*" expansion and so won't
work.

FossilOrigin-Name: a48902c71ed30c83de7dbd26d1c7956136c35dc53b1076bc8b1ebcba568a3fd3
2022-04-10 20:28:41 +00:00
drh fcde633f7c When the left-most table of a RIGHT JOIN is implemented as a co-routine,
make sure all its columns are flushed to NULL when it finishes so that
they appear to be NULL during the RIGHT JOIN post-processing.

FossilOrigin-Name: f84b2beca719758979d7a5a63c3d16d5121a7518b3fbe5039af474a83dd569c2
2022-04-10 19:51:22 +00:00
drh e21e36dd2c More test cases and bug fixes.
FossilOrigin-Name: 140e97fde94fdc3babdd456ce1b22900ead0e40e2afe63d89d21ccdbf141b607
2022-04-10 17:14:48 +00:00
drh a20c71e9e8 More RIGHT JOIN test cases and a bug fix.
FossilOrigin-Name: 19e8ad690a140ca40838bf31a377c19010fcbbc2554a4f1746737543043e334b
2022-04-10 16:13:37 +00:00
drh ac8c438a79 Add a simple test case. (It is not difficult to create additional test
cases that assert, at this point.)

FossilOrigin-Name: f2201d5dcfc552bdddd0780b3f466bdaa886e557f147335c085395bfc001f6b0
2022-04-09 20:11:05 +00:00
larrybr 039132be20 Fix .import bug reported at https://sqlite.org/forum/forumpost/14db09d7e765b819 . zAutoColumn made to deliver characters, not bytes.
FossilOrigin-Name: 21e96600d90c1cda84777abe22a11058eba46c9faefeb05f8c31bc0e7fa84b19
2022-04-09 18:51:49 +00:00
drh de24dd706e Bug fixes. A basic FULL OUTER JOIN now works.
FossilOrigin-Name: 34bbeeb77bd530b2b1f0390e9e552f65ae35f09a74d80a09dd327e64f9be51a1
2022-04-09 18:48:11 +00:00
drh 86c1beb402 Add byte-code that computes unmatched rows on the right table of a RIGHT JOIN.
Compiles, and the code looks semi-reasonable, but still does not run.
Incremental check-in.

FossilOrigin-Name: 2db5a498e74241dd19ef51c601f1a2b3b687faed3e1be2d1e3ada737406ac8e9
2022-04-09 14:48:35 +00:00
drh 7c1734b09e The interior of the RIGHT JOIN loop is now a subroutine.
FossilOrigin-Name: 549f5a7ee639de80f049445002f58e93c805f9a3d3db1987ec9d139ccef4805e
2022-04-09 12:27:20 +00:00
drh c2308ad2a0 A few bits and bobs of code generation toward getting RIGHT JOIN to work.
Much more remains to do.

FossilOrigin-Name: 55b4543122646997d928598343bc467c993f971e86e9037c85430cc948750576
2022-04-09 03:16:26 +00:00
drh c187163090 Merge the sqlite3WhereMalloc() routine from trunk into the right-join branch.
FossilOrigin-Name: b1b3845aa38f469a27f07c8f6e8a98334f7967b19661ee4cf155d6997afd9d4c
2022-04-09 03:12:52 +00:00
drh f8bdcfa3f1 The sqlite3WhereMalloc() routine allocates memory that is automatically
deleted when the corresponding WhereInfo object is destroyed.

FossilOrigin-Name: f237e1d8cc41b937f34288daebfacf5f7b0990a807a805e0cb6b45bc730192d6
2022-04-09 03:06:01 +00:00
drh a76ac88af8 Preliminary code to support RIGHT JOIN. Everything seems to work, except that
the code to compute the unmatched rows for the RIGHT JOIN has not yet been
added, so the result of a RIGHT JOIN is currently the same as an INNER JOIN.

FossilOrigin-Name: 415abd6731b8e8a605adabfa6066c8a852a8531c300df41325d5f7e75cae5a70
2022-04-08 19:20:12 +00:00
drh 7d0ae00361 Enhance the sqlite_dbpage fix at [/info/642a0b4752743216|check-in 642a0b4752743]
from about a month ago such that it still takes a transaction on all attached
databases, but it only starts a read transaction for read-only operations,
rather than starting a write transaction for everything.

FossilOrigin-Name: 8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18
2022-04-08 17:01:29 +00:00
drh 81a23623d8 Improved explanation and commentary on the sqlite3JoinType() routine. One
of the error messages changes slightly, but besides that everything works
the same.

FossilOrigin-Name: 48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec
2022-04-08 15:11:10 +00:00
drh ce5dd9e8d6 Fix two unreachable branches introduced by the recent
sqlite3TriggersExist() optimization.

FossilOrigin-Name: 1b5475d212cf9de0bff69eee8c607b4fcd8e04bf4df72171429e7609c4153951
2022-04-07 20:45:38 +00:00
drh e603ab00ee Enhance the EXPLAIN output formatting in the CLI so that the subroutine that
implements the loop body for the multi-index OR optimization is indented.

FossilOrigin-Name: c2965fea9df7076b235d3eadaf84f0a36242476d0329030b0e57557b66e2540c
2022-04-07 19:06:31 +00:00
drh da4c7ccc07 The ".testctrl optimizations 0x400000" command disables the generation of
OP_ReleaseReg opcodes.  OP_ReleaseReg opcodes are usually only generated for
SQLITE_DEBUG builds and are used to verify that registers are descoped
propertly.  But they can get in the way of code understanding when studying
bytecode dumps.  So this new optimization setting is provided to
temporarily turn OP_ReleaseReg opcodes off.

FossilOrigin-Name: fa5276725f246cef9d58b27c1e617ee3f873f7a9b88284a4e8fc453ebda338bc
2022-04-07 18:17:56 +00:00
drh db08a6d13c Fix the parsing of C-style comments in Lemon, as reported by
[forum:/forumpost/b6edc69548|forum post b6edc69548].  This has no affect
on SQLite itself.

FossilOrigin-Name: 201569e09b000919ccb463bd581fb2ecd5320e7f584fdb1bc2aaba111061d5c3
2022-04-07 14:13:32 +00:00
drh a744167956 Optimization to sqlite3TriggersExist() saves over 700K CPU cycles.
FossilOrigin-Name: 5043a3507e0781878e0e1bea5095a33273958820baead4af8fc2929e9d7c07ee
2022-04-07 14:03:07 +00:00
drh 4cd8296f39 Avoid compiler warnings about the new sqlite3Show() debugging routines
begin "defined but not used".

FossilOrigin-Name: 47ddc26974fbad8233c953d435e79d4f5dd5e09fbd684ea5f4ad32f4cae6cae6
2022-04-07 13:48:34 +00:00
drh 9c949b1c46 Omit an unnecessary initialization in tokenExpr().
FossilOrigin-Name: 8f6ae686019c61a03fe70eb78d2b529b1cf126215b45513a97cfdf7086f82f54
2022-04-07 12:10:00 +00:00
drh c381056e6d Fix harmless compiler warnings.
FossilOrigin-Name: 61095b5bcb5c30d29f03efa5b4809e3a0b780ed57e35227c292aab9dd1cfe3f6
2022-04-07 10:11:35 +00:00
drh d44f8b2385 Improved technique for parsing the ON and USING clauses of a join is faster
and uses less memory.

FossilOrigin-Name: 158156a3e3d50042cafc75dea3aaaa68b1f2efb9c3d178518ea6e68e32e0d21c
2022-04-07 01:11:13 +00:00
drh 200adc9e75 Faster parsing of the FROM clause in joins for the common case where there
is no INDEXED BY clause.

FossilOrigin-Name: 848b7a0ea99ddc52091b78313f018c07d00a0e28aa6da8c1cae709c1d03468fe
2022-04-06 19:46:20 +00:00
drh c2d0df95ba Improvements to the display of AST for DML statements.
FossilOrigin-Name: 84c239a071cfaf8af107646f01ef269e2915fd2384e95927d484f2e408ba6bbf
2022-04-06 18:30:17 +00:00
drh 2a7dcbfbb0 Attempt to show triggers in the TreeView output from DELETE, INSERT, and
UPDATE statements.

FossilOrigin-Name: b0939d6f4d94b45dce53ace6295508a67d574cc72bd6977623bf77065b3c4e64
2022-04-06 15:41:53 +00:00
drh c16a5686fe Corrections and updates to the header comment describing the
TriggerStep object.  No changes to code.

FossilOrigin-Name: abb34c0830a49d4f4e277ddd17e710529e87cba7061f3546079dbba2f82b020e
2022-04-06 12:54:41 +00:00
drh 8f1eb6f5e4 Add the sqlite3Show() family of debugging interfaces under SQLITE_DEBUG.
No changes to deliverable builds.  Rename SQLITE_ENABLE_SELECTTRACE to
SQLITE_ENABLE_TREETRACE in ctime.c.

FossilOrigin-Name: bc33168cf1f48caf848c2dc5c3ae15e4efff8c0378f944eb5398a245139a2b35
2022-04-06 12:25:04 +00:00
drh 5e431bead8 Rename debugging defines and variables from SELECTTRACE to TREETRACE (and
similar) since the functionality has how expanded to include data structures
beyond SELECT statements.  Should not affect deliverable builds.

FossilOrigin-Name: 393fa32e188a017f431372b54037cb31e885030542f00d0bfd59da9d9db5c014
2022-04-06 11:08:38 +00:00
drh f8ef2dbd7b Add additional tree display routines for DELETE and UPDATE. No changes
to deliverable code.

FossilOrigin-Name: fbd288ff3d4ea47cd324b5952e7754a465901844f2d950f0860d4488d5b6eb9f
2022-04-06 10:37:44 +00:00
drh 7d2c1d24b0 Add new diagnostic "sqlite3TreeView" routines for IdList, Upsert, and for
INSERT statements.  This is all debugging code.  There are no changes to
release builds.

FossilOrigin-Name: f3084122039bcb30c8617f5f432009a49be8b488235850a1f10ef862c91560b2
2022-04-06 00:29:21 +00:00
drh ec534e6a23 Small performance and size improvement to OP_Found.
FossilOrigin-Name: 81587a18b7c0516628453000172a0c58e74ee173c15f655d035799d84d4e2d81
2022-04-04 20:20:22 +00:00
drh 50f22d17a8 Tag an always-taken branch using ALWAYS().
FossilOrigin-Name: ad8bc3d7443ff57ce5a8756428e717ac42ec0295191a9b4d7ae44846d8fa03a2
2022-04-04 19:58:55 +00:00
drh b834e0de59 Optimizations to the OP_Found opcode save about 600K cycles in speedtest1.
FossilOrigin-Name: 5c3357ad62843fe982b9c2d31dbf02018f2948ceab2c85dac917cd9ce1e97dd6
2022-04-04 19:43:57 +00:00
drh 36d2d09023 Use unpacked keys for OP_Found in foreign key processing.
FossilOrigin-Name: 328dc76657eb5317f0201859d2b3abe6918103b894f7beaed0aca3058a9f2b64
2022-04-04 18:17:59 +00:00
drh 0de10ac11c When constructing the JSON Path for the "fullpath" column of the
json_tree() and json_each() table-valued functions, be sure to quote
object labels where necessary.

FossilOrigin-Name: 0fbbe7881cadf0b3c211653c7a0797e0a90c7c24da78ecc8a27140c05f89f2ed
2022-04-04 15:15:45 +00:00
drh b07fb4f1c2 Fix the JSON Path parser so that it will accept zero-length object labels.
[forum/forumpost/c082aeab43|Forum thread c082aeab43].

FossilOrigin-Name: 84fe95d2a5b4d232d657e3b8110027a698a9bcd597f205cc535cfa97bc299f21
2022-04-04 14:24:14 +00:00
drh a81a9f78fd Performance optimization and stronger assert()s in the comparison opcodes.
FossilOrigin-Name: e0305e640b9078c7eed9ab0bcc14f4515b54e7cd9ade3306bc2d1660f05b2725
2022-04-04 11:38:49 +00:00
drh 1c8486301f Only invoke sqlite3VdbeClearObject() from a single location, so that the
compiler is more likely to in-line the code.  Performance increase and
size reduction.

FossilOrigin-Name: c6947a96e61f71aa61ca3d70d9e2612d784ab04d60fa88852b03cfce86b1bf2b
2022-04-04 01:12:11 +00:00
drh 8703edd3e9 Performance optimization in the sqlite3VdbeHalt() routine.
FossilOrigin-Name: 9564d72a0820dbcb38f905fcd42ed4c858ea8fb5f648b189ceb65380a14a785b
2022-04-03 22:35:13 +00:00
drh 8bb93daca0 Performance optimization and size reduction in the OP_Halt opcode.
FossilOrigin-Name: 21948e6e1ccd2ce128742415d21759604ecb8902226ec4707dbd75585450f208
2022-04-03 20:39:48 +00:00
drh 18bcfb999a Omit the Vdbe.runOnlyOnce flag (simplifying the prepared statement
implementation) and accomplish the same result by adding an "OP_Expire 1 1"
opcode to prepared statements that would normally have runOnlyOnce set.

FossilOrigin-Name: 6e20e1c46d17ac6aba21e02b57649af51cfa415d83d0c001b30677d2fd1f1dc1
2022-04-03 19:13:40 +00:00
drh 8ee75f7c3a Performance optimization and slight size reduction in the OP_Transaction
opcode.

FossilOrigin-Name: 7bee8c195f3fc27aaab13e493ad446a4f19201de3ac064ed6d8a3cbda7c69ee1
2022-04-03 10:42:06 +00:00
drh c2808f39d1 Expand the getVarint32() macro in a few places, as the C-compiler seems to
be able to optimize better when that macro is expanded manually.

FossilOrigin-Name: cd4fe34b98bf5ce26f3596c717edb73932f3b46ad6e9b4934d06b7b3c176a0d6
2022-04-02 22:47:47 +00:00
drh 1f416db292 Fix harmless compiler warnings.
FossilOrigin-Name: 8a3a3486358d076c34e515ac92663a04f0c7ff10f405094cb5b6ada0d5f05cdc
2022-04-02 20:08:48 +00:00
drh d13527daed Ensure that a zero-blob does not cause in invocation of memcpy() with a
zero length and a NULL source pointer.

FossilOrigin-Name: 35441eb5e1447e01f2031837a4ede705bce34f87be27912278cc730abce6cf05
2022-04-02 19:21:58 +00:00
drh 2c144b0f63 Minor loop optimization in OP_MakeRecord.
FossilOrigin-Name: 4350983b37879d3280432d90fef04f5cc4be1b3110b5435123d897e31b34db8a
2022-04-02 15:19:02 +00:00
drh d859dc2b25 In-line the sqlite3VdbeSerialPut() routine into the OP_MakeRecord opcode.
This allows some duplicate comparisons to be omitted, resulting in a size
reduction and performance increase.

FossilOrigin-Name: 6f4d6f212a3558c27be6e9dcf71cec43c424d445e5889c6e91dde84a19c5a2c1
2022-04-02 14:30:58 +00:00
drh b47b1f67dc The putVarint32() macro does not optimize well. So expand it into in-line
code in places were performance is an issue.

FossilOrigin-Name: 390c239e53cf936a97b268dce8171f0b17050542ae64735ca8ef375fec2c9544
2022-04-01 21:01:37 +00:00
drh 759e507ce5 Loop optimization in the OP_MakeRecord opcode.
FossilOrigin-Name: 47a61fbd63928021098fbe492283f1afda7c293b3b2706c001192ae4ff1b2cbe
2022-04-01 20:39:40 +00:00
drh 3b8b5be3b7 It is not necessary to de-ephermeralize the output registers in the
OP_ResultRow opcode.  Omit that step for a size reduction and performance
increase.

FossilOrigin-Name: 8a07745aed1d0a4eead55d43f1923597b12371f307ecf5bc19c5a1db9a107a50
2022-04-01 20:19:36 +00:00
drh 35e9e350ca There is no need for sqlite3_step() to check for an OOM condition prior
to starting up.

FossilOrigin-Name: 44be7f46ba89289683ed0e123169ca9adb1018de03071d66de480c910a23d074
2022-04-01 19:13:39 +00:00
drh a24832b7b2 Omit the Vdbe.doingRerun field for a slight size reduction and performance gain.
FossilOrigin-Name: e93297a9d775688e6274c54ba75b19fc1fe8b29b73b9b5e7f94f3f2ca37f045f
2022-04-01 19:04:13 +00:00
drh cf6e3fd787 New macro ROUND8P() which works like ROUND8() but assumes that the input is
already a multiple of the size of a pointer.  It becomes a no-op for
64-bit machines, giving a small size reduction and speed boost.

FossilOrigin-Name: d126f304cde66ebfe21a4967c22dcba0bac27cbce56318b14bd50051e49c978c
2022-04-01 18:45:11 +00:00
drh 473571b083 Provide and use a version of sqlite3VdbeFreeCursor() that guarantees the
cursor pointer is not NULL.  This saves a few bytes of code space and a
few CPU cycles.

FossilOrigin-Name: cb5e6f8e265c91221227e5f15b95798c688773262407dd138d414103184702f6
2022-04-01 18:19:04 +00:00
drh 2fb448f2c8 Remove an unnecessary branch from sqlite3VdbeReset().
FossilOrigin-Name: a7d79560a0efd6221ba59ce84bcb4fa94024a901ac4a45e192ddecc6e1b5c78c
2022-04-01 17:23:17 +00:00
drh 17c4865b83 Refactor the Vdbe.iVdbeMagic field into Vdbe.eVdbeState. Split the RUNNING
state into separate RUNNING and READY.  This gives a size reduction and
performance increase.

FossilOrigin-Name: 5a50a42fde9477868fad31099f5fe976437825fac44f8b3a4cf6c739c7667bbb
2022-04-01 17:01:57 +00:00
drh 00946d7953 Avoid a harmless uninitialized variable warning in PRAGMA incremental_vacuum.
FossilOrigin-Name: 6d976f90dfe4886c3f4c062151af5c5ca7454d34b71172401b8c67acd2d663a0
2022-04-01 16:22:41 +00:00
drh 659fdb4da8 Have the sqlite3_context object carry the encoding for the prepared statement
that it represents, so that sqlite3_result() and similar can set the encoding
according to the prepared statement, even if the database encoding has
changed.
dbsqlfuzz c409b10d0a6bccf78ab00f47e1d29d42ee5b3565

FossilOrigin-Name: d4e19314f564126e180e091f9135c7bc55a10442edb46fbd3a4cfad21201dfa6
2022-04-01 15:31:58 +00:00
drh 99a218282c Split out the RUN state into separate READY and RUN states.
FossilOrigin-Name: d698826b08b88e227eb83f84b3cdb19f17306b532eccfa162090abccdf3c63d8
2022-03-31 21:15:09 +00:00
drh 66181ce2b8 Rename Vdbe.iVdbeMagic to eVdbeState. Remove unnecessary states. This is
a preliminary step toward splitting RUN_STATE out into several other states.

FossilOrigin-Name: ff91191d232305d44ae6c0fbca2542a749422dc716fa1fd5d54f58c7d6052c14
2022-03-31 20:04:49 +00:00
drh c4c0ff8664 Fix harmless compiler warnings.
FossilOrigin-Name: b916087aacba53530d2bd19eef2a4fd7a253bf7fa87b49e0df17f7987d7164ae
2022-03-31 16:09:13 +00:00
drh 89cf958c00 Refinement to [3f9887d4a58cbfdb]: The SQLITE_CONSTRAINT error should only
be returned if the prepared statement came from sqlite3_prepare_v2().  The
legacy sqlite3_prepare() is documented to return only SQLITE_ERROR.

FossilOrigin-Name: f2d9262e4427ab37ba26c004fc7a4790c86c1856d695a6b4ec3e72732ea54c09
2022-03-31 11:12:56 +00:00
drh 7e62146b13 Faster and slightly smaller implementation of sqlite3Step().
FossilOrigin-Name: c6901a8c78838228f8135c9346b214e638b72086fd85367b9ff482273e62ece6
2022-03-30 17:56:27 +00:00
drh 66f58bf38d Small size reduction and performance increase in sqlite3FinishCoding().
FossilOrigin-Name: 9248ce50f57fb9c4ba67949fdf9c9567c3e626cd9dd1b41b71c602d29c77c43e
2022-03-30 17:36:40 +00:00
drh c55b62d4cb In setResultStrOrError(), if the input string pointer is NULL and hence the
value gets set to an SQL NULL, then the Mem.enc field is uninitialized.  So
do not read it.  This is a harmless OSSFuzz/ASAN found problem.

FossilOrigin-Name: 47d0b1c4cfc3d2d8f57a02079276bb70a205ffd0f18007dd39c92f813d4c87f5
2022-03-29 22:57:00 +00:00
drh 4cb32b70ed Ensure that sqlite3VdbeMemSetStr() always leaves the value in a consistent
state even if there is an error.

FossilOrigin-Name: c86ab289ec31ce9ae0abaf103a829b8d1e5ed632f493456f1f40607aeb91b41c
2022-03-29 20:50:20 +00:00
drh 555db979f6 Reverse the order of two tests to stop a harmless initialized value
warning from MSAN - reported by OSSFuzz.

FossilOrigin-Name: 800b8fdad73b67105e416b4b5c6a5c5ded7d6a43b4eacd6b67d690cab7584b0b
2022-03-29 19:19:23 +00:00
drh de9484858e Avoid unnecessary calls to balance() from sqlite3BtreeDelete().
FossilOrigin-Name: d0966d1bdd474e27cb048884d340184f0e81a4fab65eb6b74682b20630caddf8
2022-03-29 13:16:32 +00:00
drh fb92e07186 Fix the sqlite3_result_xxxxx() routines so that they all check for and
perform any necessary text encoding conversions and check for oversize
strings and BLOBs.  Thus those checks can be done where they are most
efficient and avoided in cases like OP_Function where they are more
expensive.

FossilOrigin-Name: d50b162b2f2e320af0889b931351f9443580465a933f6657fa98f437b6579277
2022-03-29 01:43:09 +00:00
drh bcedbb2781 Further size and performance optimizations for sqlite3VdbeMemSetStr().
FossilOrigin-Name: 310a3e102d8eedf92ee63ffffb48621abfb1e2736b96bd2a676d63cca0f40598
2022-03-28 18:34:40 +00:00
drh f4dd18ea36 Slightly smaller and faster sqlite3VdbeMemSetStr().
FossilOrigin-Name: 06928e745c7bcb26ec46a17989f30efe3536fd48a74c8a1cd423cc9ff6feccb5
2022-03-28 17:34:46 +00:00
drh 60a512d923 Performance increase in the loop that frees an opcode array.
FossilOrigin-Name: 4ccebb86aae178dbce905d782f04d98211f8fce9aacd71c12b8694c92a4f5c40
2022-03-28 15:06:36 +00:00
drh cea170ec96 Another small performance gain by using sqlite3DbFreeNN().
FossilOrigin-Name: daa924af987253345bdb1c71b13378681bd252521e94d01f5d4629601232c352
2022-03-28 14:56:47 +00:00
drh da3ec15f3c Use sqlite3DbFreeNN() instead of sqlite3DbFree() in a few hot spots for
better performance.

FossilOrigin-Name: b12de0ecc78a4f654c8e7b2b17cc2201688808a4f516908e9563a216677e655c
2022-03-28 14:18:03 +00:00
drh f5a8386c32 Performance optimization in the memsys5 memory allocator.
FossilOrigin-Name: 949133231f8f751aa86518d0d3f6f03d7827fec085bfef3929fa3d57369d0216
2022-03-28 13:22:54 +00:00
drh be341502db Fix the Bloom-filter optimization so that it does not use IS NULL or
IS NOT NULL constraints from the WHERE clause when operating on a LEFT JOIN.
[forum:/forumpost/031e262a89b6a9d2|Forum thread 031e262a89b6a9d2].

FossilOrigin-Name: 1a6328f2a5b4973094e5f85787145d652119822c86ec01a61f3f985c9d2903f2
2022-03-25 01:23:37 +00:00
drh 5705b41fb8 The "PRAGMA writable_schema=ON" flag should not allow OOM errors to pass
while parsing the schema.
dbsqlfuzz 9cc49e1a53e1cef8e3a1496a88c683aa20483163.

FossilOrigin-Name: a7abb725c7c783331e73837597917e25e5ff692aac8ec97a0a8c0e30db62d68b
2022-03-24 14:01:55 +00:00
drh 8ad3c43257 Use trickery to code the UTF-8 BOM for the --bom option on .output, .once,
and .excel in the CLI, to work around a warning in some Microsoft compilers.
[https://fossil-scm.org/forum/forumpost/bd0844268f0fab71|Fossil forum post bd0844268f0fab71].

FossilOrigin-Name: 43143ad131f17734fd2eff849e0a1bc2e26daf6a28c7e07d697d38732e6af5fc
2022-03-23 10:04:52 +00:00
drh 500d7e542c Ensure that database corruption does not cause the cursor passed into
sqlite3BtreeDelete() to be invalid.
dbsqlfuzz 209bf3de9ee11ae440848ab9bc9c13858f9be2e4.

FossilOrigin-Name: a85126f96614c53b030c6e6c43ff239eae458048597a10e9a0361fcec8628ecf
2022-03-22 23:33:20 +00:00
drh 56d88aad29 Harden the xShmLock method of both the unix and Windows VFSes so that they
are robust against being invoked when the SHM file is not open.

FossilOrigin-Name: 67d8b434f628d44c4a90ce8ff5ab2e381f500bb42bdbfab9a17d21925a2ec6cd
2022-03-22 19:41:55 +00:00
drh 6fad5776c0 Make the sqlite3_serialize() and sqlite3_deserialize() interfaces accessible
to loadable extensions.

FossilOrigin-Name: 81f8746bc65828fb91e170393f22f1f4e9c587a8938e8c11b72315fcd6131403
2022-03-22 11:22:55 +00:00
larrybr b5bb769c27 expose sqlite3_{deserialize,serialize}() in sqlite3ext.h
FossilOrigin-Name: da874180d35aacdeb9c06f5b425e8909d833e2765179c4337854d56b8a624fd5
2022-03-22 03:03:13 +00:00
larrybr cb0854a380 Create new branch named "extapi-serializing"
FossilOrigin-Name: a1220a2170a09075a42d1d6c4b502ffa7cc92856779b9eb2ecb9e05c09ccedac
2022-03-22 02:53:34 +00:00
drh a753a3a2be Do not allow an #ifdef inside of an assert(), as gcc tells us that is
not portable.

FossilOrigin-Name: c7a2047e93df36c172be0be773f9a04150dafe7ba1773269d74016418d262fc4
2022-03-21 20:08:13 +00:00
drh c63e40956b Some branches are no longer reachable after the previous change. Mark them
accordingly.  Also improve comments.

FossilOrigin-Name: 88d69f60cceb22bde42cfe43c23259c7bad47b8e06f918a79bd089a77b480d46
2022-03-21 18:48:31 +00:00
drh bd5fb3a888 Strengthen the defenses against corrupt databases in the
sqlite3BtreeInsert() function of the btree module.
[forum:/forumpost/c7ec29905f|Forum post c7ec29905f].

FossilOrigin-Name: 4df301c8610c4c36b4eb360d49ccaef873c63ea719ccb14b357754ff0b3ea5ef
2022-03-21 18:17:09 +00:00
drh 67aa2318c1 The previous assert() fix was not correct when building with
-DSQLITE_ENABLE_OFFSET_SQL_FUNC.  This is the fix.

FossilOrigin-Name: c0a4767fef27cfe4fdc1d8a29342998095894769a63d84e37ec47ced7ce4e5f7
2022-03-21 15:42:42 +00:00
drh 75c493f767 Fix the assert() that attempts to verify that the table-reference to
index-reference translator finds all required translations.
[forum:/forumpost/929168fdd6|Forum post 929168fdd6].

FossilOrigin-Name: fa9bd1fce47e8db1cfc4cd8efd2c09f8711ea917ce7d116dc7226c575cb9a6d4
2022-03-21 13:47:15 +00:00
drh ef07f96faf Fix an assert() in sqlite3TableAffinity() that might have been false if there
was a prior syntax error in the query.

FossilOrigin-Name: 23fdb169ca1622369cd44fd641946c37fef09071625838b3b9c86c31244ed205
2022-03-21 11:32:45 +00:00
drh 9198f5afac In the CLI, disable the zipfile and sqlar extensions in --safe mode.
FossilOrigin-Name: d8b65a2dab97392ff81bcc33ff707b4e626a10d84a258c6452e45f90cd2c7f45
2022-03-19 15:19:35 +00:00
drh d5c35f6d69 Fix the zipfile extension so that it knows that a zero-length BLOB returns
a NULL pointer.
[forum:/forumpost/ae86934905|Forum post ae86934905].

FossilOrigin-Name: 5f6d56737caefa78e542a7af2f95646e3a818e0ecdd8e838f3c2978500ce960c
2022-03-19 12:48:14 +00:00
drh 389e056bfe Change a conditional into an assert() due to the change in
[387ab17b8a0a4b87].

FossilOrigin-Name: 13b584869f40ea6aa2190dbac64709695ee8d72b27bc5afb8b39ab3763b9c46a
2022-03-17 23:49:58 +00:00
drh b45e1d674a Add a 4th output code (value 3) from the sqlite3_vtab_distinct() interface
that indicates that SQLite wants distinct results that are sorted.

FossilOrigin-Name: 135d8b97b01f9b5204f486f828c274c2d779c17723e79171ca61f738746adf8e
2022-03-17 22:09:17 +00:00
drh d6df8550b2 Updates a comment and an assert().
FossilOrigin-Name: 0c5be14aac07222b9cd2404ae485b6587f8cb2899e776bc45f1f1117bdd7e9b7
2022-03-17 18:03:08 +00:00
drh 494317ad57 Another fix for a corner-case in sqlite_offset() - this one having to
do with computed virtual columns in a WITHOUT ROWID table.

FossilOrigin-Name: 84ddd19bcec99f04b43b1a823477457758a2d93ea9beda43598e1234ea07776c
2022-03-17 11:23:13 +00:00
dan 247d09462e Add extra test cases.
FossilOrigin-Name: 0a922d141749cf3ef672f56449001e03f1a7e31822b66dcaf8550bb6e1b88cd3
2022-03-16 19:28:18 +00:00
drh 2f3e34624a Update the sqlite3_vtab_distinct() documentation.
FossilOrigin-Name: 88929d85e2ae81c51634ddb65ebec439958b63581016f9ccb4f5388715b3fe3f
2022-03-16 14:51:35 +00:00
dan ece092e728 Experimental change to have sqlite3_vtab_distinct() return 3 to indicate that results should sorted and duplicates may be removed.
FossilOrigin-Name: 11f4508895c0a46d8623ca2f4f37b4f1b54b6d9022765f6124a9d42132f7d633
2022-03-16 12:06:00 +00:00
larrybr c6e2f2e64d Make CLI complain about incomplete input at EOF. Fix for regression reported at https://sqlite.org/forum/forumpost/718f489a43be3197
FossilOrigin-Name: 72029cf7cdb266703cc8716102dbba8e6f2666e1f47409f42c39528795757b73
2022-03-15 17:57:42 +00:00
drh 836652952f Calling sqlite3_value_dup() on a pointer value results in an ordinary
NULL.  [forum:/forumpost/ae8592cc73|Forum post ae8592cc73].  Test cases
in TH3.

FossilOrigin-Name: fff1243b594c190d15f14b7ca4e60d23519cd15134f275991c685966fcc24145
2022-03-14 23:50:38 +00:00
drh d024eca323 Fix an assert() statement in the covering index optimization for the corner
case of dealing with an sqlite_offset() SQL function call.

FossilOrigin-Name: 3950b7d006add571579158c751247a9435801e53eafd84b43dd3046e01da8ee6
2022-03-14 22:58:04 +00:00
drh 1a25be1a9a Disable trigger coding while running sqlite3_declare_vtab().
dbsqlfuzz 97e1865771b4226f29e6e482411c1cae14133f50

FossilOrigin-Name: 387ab17b8a0a4b87903aab52abc7da79098b882aff2ab687a554d5794e9d183e
2022-03-14 20:31:57 +00:00
drh 90402d4d54 Foreign key constraint failures should return SQLITE_CONSTRAINT_FOREIGNKEY
even if there is a RETURNING clause.  See
[forum:/forumpost/e6be6e82c86aa59b|forum thread e6be6e82c86aa59b].

FossilOrigin-Name: 3f9887d4a58cbfdbabf2a37e975c81ba660f373414058920b379f3a81e6e1c2c
2022-03-14 16:54:05 +00:00
drh 5a1f761218 Add a comment linking a part of the UPDATE constraint checking code to
one of the corresponding TH3 test cases.

FossilOrigin-Name: 0606e8e93edb5de4d154f377dbf91f15295d25ca9013c0f1612ae6d63a0139ea
2022-03-11 15:42:05 +00:00
drh 27e456458e Fix a harmless compiler warning.
FossilOrigin-Name: 5d739aff96c47146dba72fd76fed62d4e43ded09b32246fdde13d5467f713135
2022-03-11 15:16:50 +00:00
drh 605137aae6 Fix a harmless compiler warning and restore performance in the
sqlite3BtreeIndexMoveto() last-page optimization.

FossilOrigin-Name: 8b032293b384c3728c27b0658ee634c028c0d231d067de8b747d2e9e4ae704a7
2022-03-11 14:20:06 +00:00
dan 7ef4d75bd2 Fix a case in fts5 where a corrupt database could cause a crash.
FossilOrigin-Name: 5e95df261cce275adb5b2226e9584f4c389bb0d53c3b4feafd5a14be8d02ce63
2022-03-11 12:02:18 +00:00
drh 3946561a7f Another corruption detection case in the sqlite3BtreeIndexMoveto()
last page optimization.

FossilOrigin-Name: 531e6ad0389c6c820bb8c64db5049fb6b0bffd30bd394fd8ee7412959b1752e2
2022-03-10 23:37:58 +00:00
drh 463edb6275 In the sqlite3BtreeIndexMoveto() last-page optimization, make sure to return
SQLITE_CORRUPT if corruption is detected.

FossilOrigin-Name: 4ef19ba9b5cbda435c0bb9f2faddf8f7fac5d51399ff69bd049571c2ca3d9357
2022-03-10 22:54:32 +00:00
drh fde3043200 Stronger defenses against corrupt schemas in the ALTER TABLE logic.
FossilOrigin-Name: 13fbde28173332522a7ad307c1aad2b83c9aa1fe737583afa2b29f6da4de6370
2022-03-10 21:04:49 +00:00
larrybr 551b650236 Amend sqlite3_column_*() doc table. (no code change)
FossilOrigin-Name: 1f473099776249f774a285fa117316636e00c3ff030ba0f22ed5bd05641c1bc9
2022-03-10 19:44:04 +00:00
drh 5e121a50b3 Prevent a NULL-pointer dereference when trying to parse a illegal
schema entry that contains a window function while doing a RENAME COLUMN.
[forum:/forumpost/ec2a2e0deb|Forum post ec2a2e0deb].

FossilOrigin-Name: 58de3c2b1a773a71b2d6a5d9a4dc0f839185d78d64519e7d267ad133b9830120
2022-03-10 16:26:00 +00:00
drh 105dcaa503 Refactor Window.pFunc into Window.pWFunc to disambiguate from other uses of
the variable or field named "pFunc".

FossilOrigin-Name: d9475ebcde169272ad7b1d3a82b2326df55dafc68217bfecd9fcd1f2b89efbd9
2022-03-10 16:01:14 +00:00
drh 7931f0a3d8 Only run atof1.test on x86_64 machines.
FossilOrigin-Name: 4173819cd285a1c133645eda27b9f6dc5a2247eaa0c834bdc60058ef3109b102
2022-03-10 11:48:16 +00:00
larrybr a1d60e6c8c Mention that sqlite3_column_text16() returns have native endianness
FossilOrigin-Name: 25b7f88fcb2bb1908abde109c1167c462efbb156b4a8a8f94d36202bd93ea433
2022-03-10 02:23:43 +00:00
drh 6a51e70c5f Check-in [642a0b4752743216] fixing sqlite_dbpage is not exactly correct.
This patch should fix it.

FossilOrigin-Name: 6ba36714ca5e5457bc424273129f2814b62b7fae38926aa6eeeeec81020d7f70
2022-03-10 01:10:28 +00:00
drh 6563d0c11a Further refinements to the sqlite_offset() fix from [6029514b08b88e3f].
FossilOrigin-Name: 6f838305e2c848a43b210bd1b7b962fb9e3c41de34de778675e6578fcd99f397
2022-03-09 18:29:19 +00:00
drh 46dc631a32 Fix the sqlite_dbpage virtual table so that it starts a write transaction
on all attached schemas.

FossilOrigin-Name: 642a0b4752743216271e4f855a465515ef7f6a985f280251e18d67e3d5fb694b
2022-03-09 14:22:28 +00:00
drh b528a5a04e Do not use va_arg() as an l-value, because
[forum:/forumpost/45e39c1311|AIX does not allow that], from what we are
told.

FossilOrigin-Name: 46d1a6de620f26fef9d0e2de6e9ea032790016441e4e6228a2f8cb30e20c9a51
2022-03-09 13:22:53 +00:00
drh 577f0a1e45 Improve the defenses against bad pathnames input into the findCreateFileMode()
function of os_unix.c in order to quiet static-analyzer warnings.  There
are no demonstrated problems in the prior code, but this change makes the code
easier to prove correct and more robust against future changes.

FossilOrigin-Name: a9cda38997a692e25d2fe994a9a3fb9472c00ba04323c82e706fdb1112d4244e
2022-03-09 12:20:40 +00:00
drh 32135d7e0a Fix a minor typo in a comment.
FossilOrigin-Name: cf61419f8816377f40ea032e1e3fb8b765ff7eb5b3a5ece8f7b59acffc5d3f05
2022-03-08 15:49:17 +00:00
drh e684ac6f12 Fix compiler warnings.
FossilOrigin-Name: 5e30c6ea707f9d381127e8b2bb59e0b39bc00997da2c14d32a0e302d0121203b
2022-03-08 13:59:46 +00:00
drh ec9b622fbf Disable an assert in moveToRoot() when the database is corrupt.
[forum:/forumpost/e9a176b7bd|Forum post e9a176b7bd].

FossilOrigin-Name: ae464a18d74bf44fc95bc335e75e6a57dc974f6d6a3d603133594039fb589af2
2022-03-07 18:32:08 +00:00
drh 42bb09c412 In the stay-on-last-page optimization for sqlite3BtreeIndexMoveto()
(check-in [0057bbb508e7662b] about 16 hours ago), be sure
to clear the BTCF_ValidOvfl flag, since the overflow cache is invalidated
by the search on the last page.  OSSFuzz issue 45329.

FossilOrigin-Name: 0021bebc162e001b788786703ce634e7b8fcd3976f7047a5956e82140791e765
2022-03-07 17:19:40 +00:00
drh 4c460bbffd Do not allocate new Trigger objects in the parser following a syntax error,
to avoid violating invariants associated with Expr nodes.  See
[forum:/forumpost/2024e94071ef1531|forum thread 2024e94071ef1531] for more
information.

FossilOrigin-Name: 5e0ed49b3d739d292f5df3e498449ae8f4357cbb83394181fb34f98ed8372707
2022-03-07 16:22:31 +00:00
drh 6d6ea42a25 Fix the code generated for vector IN operator constraints on virtual tables
so that they work even if the "omit" field in the sqlite3_index_info object
is off.  This has apparently never worked correctly before.  Presumably, nobody
has ever before written a virtual table that can use vector IN operator
constraints and that relies on bytecode to double-check the constraints.
Test cases in TH3.  Problem discovered by
dbsqlfuzz cab8e26194a40147627094f3c6849c0a7b1e0310.

FossilOrigin-Name: 21b656572d066b640ff5774205a4f0db13e1b08a35d0fd484da9130e759b0c26
2022-03-07 14:51:29 +00:00
drh c5a55db75d Optimizations to sqlite3BtreeIndexMoveto() avoid unnecessary comparisons if
the cursor is already near the end of the table and is not moving far.  This
case is more common that you would expect.  The optimization saves almost
4 million CPU cycles.

FossilOrigin-Name: 0057bbb508e7662b0da19e981c07ef10236cb616bda952745de3aa2d1c286289
2022-03-07 01:29:36 +00:00
larrybr 41f46703b8 Disentangle variable use in last checkin
FossilOrigin-Name: 4c3a02600f10926da1f88ddbd457bb1486e6e02dee366b5cfc89e498a10daa6f
2022-03-07 00:14:52 +00:00
larrybr 53e1186da9 For CLI .import, revert to importing into temp or main when given table is found there and no -schema option used. And plug an obscure leak.
FossilOrigin-Name: bf9d1278846dce9255f9a11ddfc5dfac1acea2eadcb20816a19d59f7bccaec0f
2022-03-06 23:41:21 +00:00
drh eab1064f04 Fix obsolete but harmless comments in btree. No changes to code.
FossilOrigin-Name: 4838b888e431f794b8a5ee65e797b3bf0616c03261de4e1fc9499287eb3e1265
2022-03-06 20:22:24 +00:00
drh 97a985e0c5 The sqlite_offset() function should be non-deterministic.
dbsqlfuzz 3df8230bb940870db87ffca2c0fc759c1e7fa356.

FossilOrigin-Name: e1a185e60afd32d3b25278dee42049920759ccd8fe709161007f5daa4a048693
2022-03-06 11:43:06 +00:00
drh dc9513601e Remove a NEVER() associated with sqlite_offset()>
FossilOrigin-Name: e29dffcdba6f68af5cb76ca250e06a42183d9db92b60a16b2337b0d43c68bf2e
2022-03-05 23:52:05 +00:00
drh ea840117af Fix the 'localtime' modifier in date/time functions so that it preserves
fractional seconds.
[forum:/forumpost/2ffbaa2c3fd7fb82|Forum post 2ffbaa2c3fd7fb82].

FossilOrigin-Name: 1c875b0764ab00e95c92f0ee329659e88041763e125c2891201d80f68c41f717
2022-03-05 20:12:53 +00:00
drh 8f32d92786 Further improvements to the sqlite_offset() function.
FossilOrigin-Name: 4230e2f5e068f2151fa33be25bb06123d41273dbe497a5ebc7173f8d7f81d160
2022-03-05 19:36:29 +00:00
drh a275e76696 Fix the sqlite_offset() function so that it gives the correct answer even
if the argument is a virtual column in an index-only query.  Test cases
in TH3.

FossilOrigin-Name: 6029514b08b88e3fb3c0163813af38358490a6b6070b90f69975a324481394e5
2022-03-05 14:44:12 +00:00
drh 768ab1f296 Update obsolete text in the ICU README.txt file talking about SQLite's
robustness (or lack thereof) in the face of corrupt database files.

FossilOrigin-Name: dc88fc62f096bcf4df91406f565197f335333388121f860ba4424d9c881b0117
2022-03-05 11:57:28 +00:00
drh ff55da360d Do try to evaluate the Bloom filter on a LEFT JOIN early, as doing so
essentially converts it into an INNER JOIN.  See
[forum:/forumpost/544af7eee2|forum thread 544af7eee2].

FossilOrigin-Name: d46d0e67c96bd49add4f71194496804a31209f2027a2e48eaf36dde26c1ca7df
2022-03-04 20:54:09 +00:00
drh 6f9d68817c When setting an sqlite3_value object to a pointer value, make sure any prior
memory allocations associated with that object have been cleared first.
dbsqlfuzz 33f842d1a09afaad5f078c3e1162a54b78e5f2ab.

FossilOrigin-Name: 31e1bde4b20bec4242b4101adad29bfa85648ea703d6e8c5c75e8c49b54a3a0f
2022-03-04 16:28:24 +00:00
drh 07559b2716 Restore the ability to push-down OR subterms of the WHERE clause when
processing a multi-index OR.

FossilOrigin-Name: d71fb6fdc32d2fce73059b6ab86d7d7bbc812c637469755dd45b6794aadc3a80
2022-03-03 19:40:21 +00:00
drh 4f12271780 Make sure the xParseCell and xCellSize methods of the MemPage object are
initialized consistently even if the page is detected as being corrupt.
dbsqlfuzz fd21f341f3b4f582401d2feb2a1c0c4cc2c26caa.

FossilOrigin-Name: 725a06434b886c96bb816340ef236530672a4593f0ceb3230ce69c8367beb997
2022-03-03 16:48:35 +00:00
drh c9bcc5aab7 Fix for the problem identified in
[forum:/forumpost/0cd8e058bf|forum post 0cd8e058bf]:
When evaluating an multi-index OR, do not push down auxiliary WHERE clause
terms that involve subqueries into the OR-subqueries.  Otherwise, the
covering-index optimizer might convert table-references into index-references
for the particular OR index that is active for the branch in which the
subquery subroutine is coded, and those index-references
will not work if the subquery subroutine is invoked from a different OR branch
that uses a different index.

FossilOrigin-Name: 61a1c6dbd089979cbeb8b0c0c5ee1ab1abcb466be1d21a3a851be73c27e67a6c
2022-03-03 15:59:22 +00:00
drh 1902516d16 Add the new OP_BeginSubrtn opcode (which is really an alias for OP_Integer)
and make other changes so that the span of a subroutine that implements
a subquery is more readily apparent in bytecode listings.

FossilOrigin-Name: b8226748709de37cfc86414714c20567254e5b320b380e767c322dba69a79d49
2022-03-03 15:00:44 +00:00
drh 5694569591 Bloom filter pull-down optimization is incompatible with Skip-Scan.
Make sure the query planner does not try to to both.
[forum:/info/50a1bbe08ce4c29c|Forum post 50a1bbe08ce4c29c].

FossilOrigin-Name: ad3ffa1a75a5a032ebb64d8e014ee0a85c5e44b732e4b11bd67f31a59e729b94
2022-03-02 21:04:10 +00:00
drh fc854505b4 Faster version of sqlite3VdbeMemRelease().
FossilOrigin-Name: 86c5fa2f301e4bdb538099f654b70b6ba0e214778cba2c53c53844e5d7ca129f
2022-03-02 17:50:59 +00:00
drh 5308d3931e Reinstate the releaseMemArray() performance optimization of
[bb520293d8c11518] with corrections.

FossilOrigin-Name: 1291080d118c678072289a2e57a56b73657e9256ae47eafa7853716c8d47392f
2022-03-02 13:45:22 +00:00
drh e3994f2975 The optimization at [ece326db50201937] is not quite right, so back it out
for now.

FossilOrigin-Name: b218a4b9fe44ffc5cb8d2a2491a5aad217d37b26ccc6b04caf8f28b71bcfe809
2022-03-02 11:39:11 +00:00
drh ceff761521 Fix a harmless compiler warning.
FossilOrigin-Name: 6497997aa80419688890ed5dbbb7d6acc26bf3732305ff4a728cba1fe4d1626b
2022-03-02 01:02:16 +00:00
drh 86af59830f The performance optimizations at [bb520293d8c11518] is not quite right,
so it has to be backed out.

FossilOrigin-Name: 15f73b121cacf77ada02bfe434f9caa1175ac482d007156cfb0864e4221490d1
2022-03-02 00:50:06 +00:00
drh a055abb8c4 The MemPage.aDataEnd field should point to the end of the data buffer for
the page, not just the end of the usable portion of that buffer.  The purpose
aDataEnd is to detect cells that overflow the page, and that won't work on a
page with reserved bytes and a cell that starts in the reserved region, unless
the boundary is at the very end of the page. Chromium issue 1276294.

FossilOrigin-Name: f839c0bc8388a31f6db5081906b66b9e129855ba27a13cf13bd995b083f7386e
2022-03-01 20:15:04 +00:00
drh 3b4cb719c0 Fix a minor typo in a comment.
FossilOrigin-Name: 86ba06aa4c55d3aefe030b19b2b5c08baf46bbb2218b04ac1228ab76682a929b
2022-03-01 19:19:20 +00:00
drh 3703429cdb Fix two assert() statements in btree.c which were not true in the case of
a corrupt database file.
[forum:/forumpost/14819f2063|Forum post 14819f2063].

FossilOrigin-Name: 3b36ed79d82fae47a08a7d27f4fcefb7978fdf0e7f8c0f4a82f59501f201b32b
2022-03-01 16:22:54 +00:00
drh e7fae604a0 Fix slightly-incorrect assert() statements.
[forum:/forumpost/f1e83b77b5ff37db|Forum post f1e83b77b5ff37db]

FossilOrigin-Name: 3c9f5c9defd7d36684132ae4ade9db2e2148dad4bd91bfe9374620ecafc35348
2022-03-01 15:48:16 +00:00
drh 90368c5dcb Increase the max_page_count on ROLLBACK, if necessary, so that it is sufficient
to cover the entire database.  Fix for the problem identified by
[forum:/forumpost/3b9e894312|forum post 3b9e894312].

FossilOrigin-Name: 12c012162ce110a7a7fbbe853f422e23cb4ae10b45237727328c8f3315b70842
2022-03-01 14:13:32 +00:00
drh 935c37229c Fix the Xfer-optimization on the INSERT statement so that it is omitted if
there is a RETURNING clause, since that optimization is not able to deal
with RETURNING.  See [forum:/forumpost/595e132f71|forum thread 595e132f71]
for details.

FossilOrigin-Name: 1d3760a517b8bd2a6be82d2d5788945f49397cdc539fe28fd23e2c0c62a1dbe2
2022-02-28 16:44:58 +00:00
drh 8552b10c45 Reorganize the bits in Mem.flags. Free up one bit for reuse.
FossilOrigin-Name: fe454291d959c299d6608dfc165c9e05fb53e431b0fc7aed1cb4a557cd61d8ab
2022-02-28 14:26:33 +00:00
drh 74a12dd6fd Expand the comment on the definition of the Mem object to better explain the
meanings of the various flag bits.

FossilOrigin-Name: f2f0426035d4e0334be000a3eb62bbd7d61fdab7c2ef9ba13cfdf6482396dd13
2022-02-28 13:38:28 +00:00
drh 0150c81cd3 Performance optimization in initMemArray() saves about 750K cycles with only
a 4-byte increase in code size.

FossilOrigin-Name: c3e9cd5e7430be0653a96a2097a695447549980e08cc8bd8d8097a50c954908e
2022-02-28 12:16:51 +00:00
drh 4296357c90 The performance increase in the previous check-in of this branch was due to
the revised loop in initMemArray() and reordering fields of Mem - not the
call the memcpy().  Changing the code to avoid memcpy() results in an even
better gain, and code that is far less dodgy.

FossilOrigin-Name: d74aa979530d4236f5900d2ef998b27065d352d7c18bcd822e5c8f1041a1a81c
2022-02-28 12:08:09 +00:00
drh c9373e86e8 An optimization to initMemArray() saves almost 500K cycles. But it seems a
little dodgy.  I want to think about this more before merging to trunk.
Perhaps there is a cleaner way to accomplish the same.

FossilOrigin-Name: 7fefd8676110a53e6c98a697e2dbf820740fe602a1e83b6caa8d099c41a15d80
2022-02-28 03:25:13 +00:00
drh b3d981c3b7 Avoid unnecessary deinitialization of the Mem.flags field.
FossilOrigin-Name: bb520293d8c11518ba153b986662f081ebfd781d38eb624c509605fa9148f6e9
2022-02-28 02:35:48 +00:00
drh f357cafaf5 Cache values of UnpackedRecord.aMem[0] into new fields of UnpackedRecord.
This avoids extra indirections and saves about 750K cycles.

FossilOrigin-Name: 7cf2d1f0396362aae7b93da75c2036d52ba86acba1cc90abca560bcf0314a22f
2022-02-27 21:10:49 +00:00
drh a1e951fa48 Bypass a single branch in vdbeRecordCompareString() in the common case, for
a performance increase of over 600K CPU cycles.

FossilOrigin-Name: 36f0f07e505dfb38c61d3b4d5b947013c8793e6796fe690e53864479b9276abb
2022-02-27 18:54:33 +00:00
drh a0318fd7b4 Remove an unnecessary local variable for a small performance increase and size
reduction.

FossilOrigin-Name: 9bda611f0d182a62ac1b68610313143c2e28868c16c7d4362a8f5945c27dd88e
2022-02-26 23:01:25 +00:00
drh 9090df6f73 Allow the OP_Column opcode to read rows that are larger than
SQLITE_LIMIT_LENGTH as long as the specific field being read out is
less than or equal to SQLITE_LIMIT_LENGTH.

FossilOrigin-Name: 1bf4848995ab094ad84ef4aa1563bce641d5acf7335fb4630c892b16cf7d7edd
2022-02-26 14:39:08 +00:00
drh fc56950337 Revise the initialization processing for OP_Column to make it about
1.8 million cycles faster.

FossilOrigin-Name: 3b7259ebd5b9b1f75577521c4d0d96f5503d302a513b20a0b17dbe8c3823dd33
2022-02-25 20:11:59 +00:00
drh a10be3da20 Fix the OP_NullRow documentation so that it accurately describes what it
actually does for a pseudo-cursor.

FossilOrigin-Name: 4e269902094e8f9d852e5fc852e473167048fdeb9034f1fb1436f6df205de926
2022-02-25 18:51:09 +00:00
drh 7fd6a7761f Improved comment on the codeDeferredSeek() routine. No code changes.
FossilOrigin-Name: 54f49f65ac943263a1622b1efe519c8a61f30f23694fd4fec89ad2bf0e17b473
2022-02-25 13:29:56 +00:00
drh d1f0a86c12 Fix unimportant typos in comment text.
FossilOrigin-Name: 393460132994d6ca133e52af57374e43a2795a9e7fc7781bd9dea752a2b52c6a
2022-02-25 11:30:29 +00:00
drh 9606a13432 Invoking SQLITE_TESTCTRL_INTERNAL_FUNCTIONS causes the flags field of the
PRAGMA function_list to show all bits, including internal-use-only bits,
rather than just the bits that are part of the API.

FossilOrigin-Name: ad1be34828726bfef0dbc0ce16090400cf3530e7b5077849af96774d7428387b
2022-02-25 01:23:17 +00:00
drh c45924ebc2 Remove unused P4 types on the Opcode object. Saves a few bytes of code
space and simplifies the code.

FossilOrigin-Name: aca538435939e6146f9a42e72e3a65030bbc5f646a0bbc7684e43688a0339888
2022-02-25 01:10:57 +00:00
drh a7c9dd546b Change the OP_Next and OP_Prev opcodes so that they invoke
sqlite3BtreeNext() and sqlite3BtreePrevious() directly rather than through
a function pointer, for improved performance and a decrease in code size.

FossilOrigin-Name: 9d13cbbef3cf64f281d3e100f23f1b2ed6e8d65920c7517a84e1e4f964ceff2e
2022-02-24 14:44:23 +00:00
larrybr b2d594a19b Spell fix, no code change
FossilOrigin-Name: f2597fae3c2b8f77f98a3ba9420b309f649b4008f9530d3cfaeeba1e2bf5d8a3
2022-02-24 11:09:08 +00:00
drh cdc59c82ad Fix an assert() so that it is still valid following OOM with the latest
enhancements.

FossilOrigin-Name: ecf832f71fbaee36ee10f6da5bde19a8af9f90adbba06e8c5706d18b768bae1f
2022-02-24 01:41:14 +00:00
drh fc4fe5a837 Update the version number of version 3.39.0 for the next development cycle.
FossilOrigin-Name: 9542e9bebbd25b20228fa2366b76d55845a40f12fdc4bbd077d1cb48e32b8cf2
2022-02-24 01:08:53 +00:00
drh 19ae01be13 Add a new subclass for MemPage.xCellSize specifically for the case of a leaf
page in a B+Tree, that is optimized for that cases.  This gains a half million
cycles or more at the cost of less than 200 bytes of code space.

FossilOrigin-Name: 7ad829224adbec5d74ff9e5ab040eb2ad3e17fe45da7a2cf0cca770a0731401a
2022-02-23 22:56:10 +00:00
drh 009a48e0ad Optimize calls to get2byte() in btree.c for almost a one-million cycle
performance gain and a few bytes less code.

FossilOrigin-Name: 41061f29969dc546c2702f7f412127070a4dd54593827692df93a83c939dfb61
2022-02-23 18:23:15 +00:00
drh eac750e9a6 Defer the check for error check Pgno zero until after the page fetch misses,
to gain a few CPU cycles and a small size reduction.

FossilOrigin-Name: ece326db50201937eb688809df39edc7fb97413b4614d2e2e783418192f7b02a
2022-02-23 17:16:30 +00:00
drh 584bfcaeb6 Store the page number for the PENDING_BYTE page in the Pager object, rather
than computing the page number every time it is needed, because it turns out
that number is needed quite frequently.  This saves a few hundred thousand
CPU cycles and a few bytes of code space.

FossilOrigin-Name: 5aa9c3eb45514d5eb7b32696d25a9aeb7dad485e1ea5adb833fac6d1f2105f1a
2022-02-23 17:00:44 +00:00
drh f2a777fa5d For the "PRAGMA database_list" statement, do not check to see if the schema
is up-to-date and do not try to reload the schema.

FossilOrigin-Name: 710de6a2137c872812effa43ea888aa77d339362ca0b6c8990d4426c8fb20689
2022-02-22 20:29:31 +00:00
drh 98095e3949 Version 3.38.0
FossilOrigin-Name: 40fa792d359f84c3b9e9d6623743e1a59826274e221df1bde8f47086968a1bab
2022-02-22 18:58:40 +00:00
drh 60f3657b4a Fix an undersized memory allocation in the test harness for RTREE. This
error was in test logic only, not in the SQLite library itself.
[forum:/forumpost/35470a0a72a005e1|forum post 35470a0a72a005e1]

FossilOrigin-Name: 7e3c9594390ac8defaf9825e14b4c19ef8c123b747971dd3d4df16110f443d3b
2022-02-22 15:47:55 +00:00
drh 16f56e8416 Fix compiler warnings for older compilers (ex: gcc 4.0.1 powerpc-apple-darwin).
FossilOrigin-Name: 5c188243d769681c68938c8e432155c8ec838d9e32fe8d1b12286ebc9d0e87f1
2022-02-21 14:30:59 +00:00
drh a12500005f Remove stray tab characters from auxiliary source code files.
FossilOrigin-Name: e25e33582b69289a2c3a6bc403e3911de22a3b529db1a565efb9f1af01b9e382
2022-02-21 13:44:51 +00:00
drh 91260dcf83 Add SQLITE_OMIT_JSON to the compile-time option test sequence.
FossilOrigin-Name: f36325a6e21c4d3b6ab48ebfb2efabda089281344d1e61949d1c9290e88395b1
2022-02-21 13:02:23 +00:00
drh d01a1bd94a Do not allow error messages from sqlite3NestedParse() to leak up into the
main parse.

FossilOrigin-Name: 9c4e21abdca664d6b7bcf0043fe9ec05ef8b2949ba6ee7208abaaec1ff4ed679
2022-02-21 00:23:49 +00:00
larrybr a7919add6a Improve .backup and .save help text
FossilOrigin-Name: 741651fd4b1b776b4dea156cdc987f426f7c668ece203bda6654b2c7117c8933
2022-02-19 21:25:48 +00:00
drh 1ff855b22e Add a NEVER() to a branch that is unreachable for STAT4.
FossilOrigin-Name: e4e97505af4016c48465009686bfeffe9627e225a5b2082a5bf4baeee40db5c9
2022-02-19 15:57:28 +00:00
drh b15a3940d1 Enhance the documentation on sqlite3_stmt_readonly() to explain that
EXPLAIN and EXPLAIN QUERY PLAN do not affect the return value.  Add test
cases to verify this.  Add new test cases and requirements marks for
complete requirements test coverage on this interface.

FossilOrigin-Name: a6fbb7ba0583b3981e2d8b809006b902b3e97e516dbd3ab7d905c5ea73df2272
2022-02-17 17:24:39 +00:00
drh dedd51aed4 Remove references to the now-defunct SQLITE_ENABLE_JSON1 compile-time option.
FossilOrigin-Name: db950192c93db7f5eb4ffcce41d0ea374c58450405945cfb8ebe0c93070b7c48
2022-02-17 14:33:13 +00:00
drh 24ea5fb3e8 Fix a testing error on Windows that was recently added to shell5.test.
FossilOrigin-Name: 6cace54320997dcbbdd49017f20eecafa88ebcc4b264ee800954f25d9605023d
2022-02-17 14:29:39 +00:00
drh be4e3c88f5 Make the sqlite3_error_offset() interface accessible from TCL using the
new "erroroffset" method on the sqlite3 object.

FossilOrigin-Name: 3454a1222bedefba527af98c0284ed0bfbd28dd941885d9a0ac9a44aea2fc8ec
2022-02-16 15:11:01 +00:00
drh 537a6bf189 Improved rendering of floating point numbers without a fractional part in
".dump" output from the CLI.
[forum:/forumpost/550d877659f37cb2|Forum post 550d877659f37cb2].

FossilOrigin-Name: 9edaeed56f2282fd4da935454178c38ab49d259aed96d4e720aae09050a53006
2022-02-15 13:23:09 +00:00
drh 0ca0988355 New assert() statements to help prove correctness of memjournal.c.
FossilOrigin-Name: d74ec88c2f9b9e056988add8322186750229e14a609d1a6969ba393a5b8c5174
2022-02-15 11:46:31 +00:00
drh e63b7bdac8 Generalize the in-memory journal so that it is able to accept writes that
begin at any offset less than or equal to the current file size.

FossilOrigin-Name: c039d5476e0836c16d8c1ad99a2620f7fd04eb4b0e5dcb2246b42dde2ae1f95a
2022-02-14 21:11:17 +00:00
larrybr 7d5113f0a3 CLI .import can auto-rename non-unique column names when it creates a new table
FossilOrigin-Name: 4b5d07ea7e6f5d6f1279c88bc474ee4bc8bd2cebe38a268f211f47e44569e4b1
2022-02-14 18:55:19 +00:00
drh 9a4e88604c Minor correction to the early corruption detection added by
[a6fda39e81d0da98|check-in a6fda39e81d0da98] so that it works even if
the page being cleared in page 1 of the database.

FossilOrigin-Name: a5ec16907ef6ab50e041101d87c5756c71469923872a86c3ab383f188673d7a5
2022-02-14 18:18:56 +00:00
drh 0aa0945111 Fix a bad assert() (it needs an "||CORRUPT_DB" term) in b-tree, discovered
by dbsqlfuzz.

FossilOrigin-Name: f5f263cc626d6a8bea3e85e28bb716e3eac0d9cd199cc060c0c8b0c77b280a45
2022-02-14 13:53:49 +00:00
larrybr 3363386145 CLI's .import column rename made more minimal, and reports renames.
FossilOrigin-Name: c626cff7f99ec502ebd46f9cdafc3d088697544ef5d6559b6b3ae85679b4f9fa
2022-02-14 01:12:46 +00:00
larrybr 42de1c52dd Sync w/trunk, fix zAutoColumns placement blunder, all to pass all TCL tests
FossilOrigin-Name: 67dc59f46d742ad69742fb34540a3074af163a3f1a0f9093f83db2276bf944ca
2022-02-13 22:18:22 +00:00
dan dfcb11de18 Do not run merge1.test with SQLITE_OMIT_VIRTUALTABLE builds.
FossilOrigin-Name: bf8dbfd499e732f14c7a8efee527e8ce155937dbb2a3e85213f8aa64ac497189
2022-02-12 18:56:24 +00:00
dan 02ede43da2 Fix a possible user-after-free in ALTER TABLE found by asan.
FossilOrigin-Name: 9252619d410293ddefd108f5cf81b6fb4932bd3f2ceaaa92abb7542e34f66111
2022-02-12 16:02:37 +00:00
dan 8443505dc9 Update fuzz.test to account for a change in error message made in the core.
FossilOrigin-Name: c57601b51f9b59e9d8f0eb06580fa14f49525e56bd0190c02865e478bd1f48e7
2022-02-12 13:45:02 +00:00
dan af7b8dcb58 Avoid dropping SQLITE_TOOBIG errors in the quote() function.
FossilOrigin-Name: 115c3051a1ff7567e84f14fc4c49efe61bc2850248533449b0195c305ab6516e
2022-02-12 13:37:27 +00:00
larrybr 43a196a3bb For .import auto-column, aid build-time override of rename decoration.
FossilOrigin-Name: 433e5ead2b711d1e3b0b62cf8cb5a8a65e2474c68ef2173317ed4323fc8bdc58
2022-02-12 13:12:03 +00:00
larrybr 0a704c3145 Fix auto-column bug noted by post https://sqlite.org/forum/forumpost/d102c15d63
FossilOrigin-Name: 689137e1b5bc78b0f16e5db86d16415b9fa77d22ded59e93d75e7033b465e673
2022-02-12 10:48:42 +00:00
larrybr 78138397b5 Sync w/trunk, allow build-time override of auto-column decorating character
FossilOrigin-Name: caaef4c592c980889efb349fa73b61303ec493172d90cd67d54ffde0855e4138
2022-02-12 02:15:37 +00:00
drh f17f607556 Fix a test in without_rowid1.test so that it is disabled without
ALTER TABLE support, as it uses ALTER TABLE.

FossilOrigin-Name: ca22a64e6f05a6688974f4cff1a0ff2c873aad1947f3cf6ffaeee8bb074b2627
2022-02-11 21:20:46 +00:00
dan 7b57aa3da9 Update some OOM tests of the ALTER TABLE command to account for an error message which may be returned if opening the temp db fails.
FossilOrigin-Name: 3409fd4150df059d7308f79fa3672a330af9cefe2ad9120c3da5ef1413921e96
2022-02-11 19:41:03 +00:00
drh eba21cd4be Load recent dbsqlfuzz finds into test/fuzzdata8.db.
FossilOrigin-Name: b275ad250d8aa286829647967ab7e75fcd2b5674caab1a34eab59d8486a34cd5
2022-02-11 17:47:58 +00:00
drh 11fc3c0fa7 Reference the wayback machine for the dead hyperlink to the MS support
page in the comments about why the extra typedef for va_arg().  No code
changes.

FossilOrigin-Name: ab1a9b5b78de7c00b38357b1df08e82ce5608a14f8c675ac20c5f2dad5212f50
2022-02-11 17:47:25 +00:00
drh 4ba1c5cc49 Fix an assert() in the pager by adding "|| CORRUPT_DB", in as much as the
assert() is not necessarily true if the database size in the header is
wrong.  dbsqlfuzz f2f996065b90988aa9b0ae425b66dbb296546a08.

FossilOrigin-Name: a51402e8c29fad2b24e32de55b10691fb0ebd6c2cebac941e43e54be211d5d39
2022-02-11 17:33:02 +00:00
dan 63a47336af Fix a problem in [c006515ae6faff65] causing an assert() to fail with some build configurations.
FossilOrigin-Name: d7ff262d6d1fd8b855bcb8f6f54ab1833663a4d8187701ddf045f6b5a62a5d1d
2022-02-11 16:10:18 +00:00
drh 85548fac8d Use the enhanced SQLITE_TESTCTRL_LOCALTIME_FAULT (2) capability to do better
testing of the 'localtime' and 'utc' modifiers to date/time functions.

FossilOrigin-Name: f38071946ac2e5bb61e6c0620507e4c94464999ac700d86c1a704b94eb1c009a
2022-02-11 14:08:05 +00:00
larrybr a03372745e Upon .import column renaming, issue message saying so. Test this.
FossilOrigin-Name: 8b6ca9304bff9a5b2897a6517ce77e4cd32f337b6c849b73ead5f757228d8ac8
2022-02-11 13:40:25 +00:00
drh fa3ee3b10b Fix the bind2.test test script so that it works even if
SQLITE_ENABLE_PREUPDATE_HOOK is not defined.
Fix for test-case breakage from check-in [c006515ae6faff65].

FossilOrigin-Name: 937d3a45b3fef354dbdea2085fbb7d9c752a96e8ebb62f61931deb5a64132946
2022-02-11 12:06:37 +00:00
drh 0d58ae010c Work around the MSVC bug that prevents the use of function pointer types in
the second argument of va_arg() by adding a typedef.

FossilOrigin-Name: eae3ab0a050079d050f339b2510eebd55afe4464e9b410ddacb7523f89981144
2022-02-11 11:37:12 +00:00
larrybr 4c5c6214b1 CLI auto-column rename revamped after forum discussion.
FossilOrigin-Name: 2da1f8e45eb0cb1ead6049df6a31a903bfad5a7abd27e92cd3dac25fe355aec3
2022-02-11 01:21:09 +00:00
drh b30af022da Fix SQLITE_TESTCTRL_LOCALTIME_FAULT so that it works even if mutexes are
enabled.

FossilOrigin-Name: 64537a0669553e8a6b610b9e9703ec084472516c86cfc22a7a6c73b6c66131ee
2022-02-10 23:12:58 +00:00
drh d7e185ce5d Enhance SQLITE_TESTCTRL_LOCALTIME_FAULT so that is able to install an
alternative localtime() interface so that the localtime logic an be better
tested.

FossilOrigin-Name: 6e25cb0890e8cdc63c9a21e841844d066267fc32ad143527843f7c8d05612b53
2022-02-10 21:26:53 +00:00
drh eadccaa926 Performance improve to the 'localtime' and 'utc' modifiers for date/time
functions.

FossilOrigin-Name: 85cb6014751a0572d28ebd839331d5d7a78de45c9e522adcd834a8a85746f32e
2022-02-10 15:40:40 +00:00
drh 522608d3a2 Faster implementation of the date(), time(), and datetime() functions.
FossilOrigin-Name: fa1b393bdb66b985f6552190a8242ed878f91d653a03352f65aa8d750de3cec4
2022-02-10 12:57:53 +00:00
drh ddd3fe6fc4 Fix the test harness so that it builds without SQLITE_ENABLE_PREUPDATE_HOOK.
Has been broken since [c006515ae6faff65].

FossilOrigin-Name: 4565f711291bae5daaff6dd2b7b2991b17e139a576b1b73bb1f81f08a4c1a13f
2022-02-10 12:31:37 +00:00
larrybr 58a53d6e7b A CLI feature. auto .import (new table) columns. WIP
FossilOrigin-Name: 7e3be36dfcb65c87a87344cf91c0c8f8d1aff0f2e4bcc23444a8f6b8ddcdae69
2022-02-10 03:21:48 +00:00
larrybr 208b7141d0 Create new branch named "auto-column"
FossilOrigin-Name: 066febe8931c5d90c009f05fe9ad0924ad35ec25a61ab42db63a9b9dbb1cecce
2022-02-10 02:09:43 +00:00
drh 0d36368601 Fix a typo in documentation. No code changes.
FossilOrigin-Name: e97c6ad4c915c82c2f0b347a0cdc8f80942c345194675a88174047ce0d0a43ad
2022-02-10 01:01:31 +00:00
drh e2adc0eea1 When process first moves a database into WAL mode and then tries to run
sqlite3_wal_checkpoint() without first performing a transaction, first
try to run a synthesized transaction to get the Pager caught up before
attemptingn the checkpoint.
[forum:/forumpost/fd0f19d229156939|forum post fd0f19d229156939].

FossilOrigin-Name: eee6de1967609f0b590ee4dbec088c3e7b03b08753267ed2909c5b03d60a0e18
2022-02-09 18:47:09 +00:00
dan 252fe67bdd Fix a problem with using sqlite3_bind_value() with sqlite3_value objects obtained from sqlite3_preupdate_new() when an integer value is written to a column with real affinity.
FossilOrigin-Name: c006515ae6faff6525d589827d99092b06004472e32b7f586845c00c4732d695
2022-02-09 18:42:15 +00:00
drh 9f4ce3b19f Writes to the subjournal should be all-or-nothing. Fix for
dbsqlfuzz fe3c397fb90029313446c4e0f4a6cd0c81dd9621.

FossilOrigin-Name: 22cc55e84f67f6f39b7dba07a4ef7ae958b2d926633faec91a278922053e50c6
2022-02-08 15:14:18 +00:00
drh 4e532958c1 Provide sqlite3_error_offset() data for some new errors.
FossilOrigin-Name: 1269206db810460e55a52e178ba3332add42a11f66c5f292f8f0d29ccd61a4b8
2022-02-08 13:41:23 +00:00
larrybr 07fc85a2bf comment-only change to sqlite3.h
FossilOrigin-Name: f815cf4a5f97778f177d373814700e8f2f6429dc467b68b799b5b349cc00b7a2
2022-02-08 12:24:43 +00:00
drh 633c798283 Do not show the error code number of CLI error messages unless the error
is something other than 1 (SQLITE_ERROR).

FossilOrigin-Name: b471601892df98c5103bb55132bbdecf3e4dfc428aaecc47bfec1e1d51e583c7
2022-02-08 12:13:16 +00:00
drh 3e46db21d4 Improved error message formatting in the shell. Distinguish between
"Parse errors" and "Runtime errors".

FossilOrigin-Name: ae3e322a029952f575e49c73fb50b46bbea55be6792cc225cb94f5e0cbd046d9
2022-02-08 11:52:45 +00:00
drh e1c4743121 Disable the sqlite3_error_offset() when the error occurs in a trigger or
view or some other bit of text that is not part of the original statement.

FossilOrigin-Name: 0e909e34fa74e7b9b7954e4ed4c39dd293c1d413b58fda03607faab74aa382ad
2022-02-07 18:52:56 +00:00
larrybr 6e85b27cbb When create table/view fails due to name taken, say which took it.
FossilOrigin-Name: 9a206e37fb49a203a7b5fdc93c41acc39e9ceb37144c78432a235e2f0d54a210
2022-02-07 01:09:49 +00:00
drh 5d20a21814 Fix unreachable branches in the sqlite3_error_offset() logic.
FossilOrigin-Name: 031381aea371892a35737e550121846af41241711a36c1a2086af3b0c11bf7b6
2022-02-06 23:54:41 +00:00
drh 51896e6fd7 The sqlite3_vtab_in() interface should return false for a vector IN constraint.
FossilOrigin-Name: 245d0241c78870c6a41af3e02b82b13151472e2102fbd62989672f8122feca73
2022-02-06 22:13:35 +00:00
drh 89e9baa2ca With the new ALTER TABLE under PRAGMA writable_schema=ON processing, do not
ignore non-parser errors such as OOMs.

FossilOrigin-Name: 36653ccef68cf61b6001000a713b06e951cb6fddced6b6a906c3b17d70a8af87
2022-02-06 21:13:59 +00:00
drh 2ef111168f Faster computation of Expr.nHeight.
FossilOrigin-Name: a7a5af327ba8bafcd58b828e3e7a10d0008bb780d55a6c573aa15896dcc8ab89
2022-02-06 11:51:23 +00:00
drh 17a93ae1b8 Record the error offset on INTEGER tokens.
FossilOrigin-Name: 38e057a580613be176552e230e40b4434a9ed57a82d407e92a23c7b8e62c0b0e
2022-02-06 11:26:51 +00:00
drh 62fc069eb4 Further improvements to localization of errors in input SQL.
FossilOrigin-Name: fa34676042720161ca03f3926814152eb1d144ec12fd2b44e5429408ea4ad5b0
2022-02-06 00:30:04 +00:00
drh 4f77c9208a Enhance sqlite3_error_offset() to report the position of unresolved
identifiers.

FossilOrigin-Name: 5b8d2577907abda10de29884716bacc10bff0df1451228a0ac40342dbea6d589
2022-02-05 23:11:19 +00:00
drh 796588ae07 Record the position of many identifiers in the parse using the new
Expr.w.iOfst field.  This is done with the idea of providing offset
results for sqlite3_error_offset() for a more kinds of errors, though that
part is not yet implemented.

FossilOrigin-Name: 32a3a53b62ab09ac2212905e7f42fe6f1b09d891e015203e5caf4cb16262f18e
2022-02-05 21:49:47 +00:00
drh 4734b3f9b7 Update stale evidence marks on sqlite3_vtab_rhs_value() test cases.
FossilOrigin-Name: 46744b83d5e1335bcbc59f9625e8ade3f360469d17f34e8d996f077ba9afa89e
2022-02-05 13:27:52 +00:00
drh dfce5b6dd5 When PRAGMA writable_schema=ON, allow ALTER TABLE to proceed even if there
are entries in the sqlite_schema table that do not parse.

FossilOrigin-Name: fc4c82e5694cbdae13f2cb90e5368ba9f6b826a220a81de32ead2ffe1bc5f31f
2022-02-05 12:39:17 +00:00
drh 569c10566e Fix a NULL pointer dereference that can occur after OOM. Problem
introduced by check-in [197cbabf1767d060].

FossilOrigin-Name: d4e6b9f0f7567b76760a667a701bca4d6158ade39f9a69d205b583c5a1c0c7f4
2022-02-05 12:05:43 +00:00
drh 6c758900c2 Fix documentation typo.
FossilOrigin-Name: 1a7d8bb5ea0d0e0c250312f89a701c0274cfbcaef9cd71995fb83bf939668504
2022-02-05 11:13:26 +00:00
drh d515ea5b56 Typo fixes in documentation.
FossilOrigin-Name: 1ec747d1c34ced9877709dd306e674376e79145de08b9c316d12bc5e06efc03e
2022-02-05 01:01:07 +00:00
drh bcd60d20a3 Test case for permissive ALTER TABLE RENAME when writable_schema=ON.
FossilOrigin-Name: 7ee44f66c896cdc7b6980811e8e4537dbd63b23060ead0104f25132d955890af
2022-02-04 20:16:00 +00:00
drh 10d29c7a94 One more case of disabling errors for ALTER TABLE RENAME when
writable_schema=ON.

FossilOrigin-Name: c52d0dd8f4f8fab4c3f33cbd26b4012569e76562282e85654018c836dca7b564
2022-02-04 20:07:24 +00:00
drh 0fab10991b Add a compile-time option to include vt02.c in fuzzcheck.
FossilOrigin-Name: c404c8c72600c11b181519d269bf949aff304eaafb90a50d1415c6fe84d2b092
2022-02-04 19:13:18 +00:00
drh 5a80050dd3 Allow ALTER TABLE RENAME COLUMN to proceed even if there are errors in
the schema, as long as PRAGMA writable_schema=ON is active.

FossilOrigin-Name: 197cbabf1767d0603928462fb75cf8100f6999f725e0db60d096c7ca20e3da28
2022-02-04 16:43:30 +00:00
drh 69b0ce33fd Fix various harmless compiler warnings.
FossilOrigin-Name: 70049342d5ad57ea3e863bba19253934b868bacdd1c26c9371bac024a829badf
2022-02-04 13:15:01 +00:00
drh 02e3e04134 For the MULTI-INDEX-OR optimization, when pushing down WHERE clause terms from
the main query into the various OR-term subqueries, do not push down slices
of a vector comparison, since the right-hand operand of the comparison might
have only been initialized in a different OR branch that was not taken.
dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1.

FossilOrigin-Name: 9f67ad00cd38b7c5ec6d14b379e1a611777bbdf6901d843a80712ba7d94d6d33
2022-02-04 13:05:29 +00:00
drh 7f1c111948 Minor typo fix in comment. No code changes.
FossilOrigin-Name: f9b763042c5c4446115c5375a8e4731e522e36ad9fc53e9ef775de9bc297ea19
2022-02-03 18:14:22 +00:00
drh 697c50b947 Do not allow the vdbe-compress.tcl script to generate structures named
"do" or "if".

FossilOrigin-Name: e35ab16dd0fd40b07a71d26e1cdb19ef664a2a628a4abcb2e130f5e555de8ca9
2022-02-03 14:37:06 +00:00
drh 3832c3c10f Prohibit schema changes within xBestIndex callbacks.
FossilOrigin-Name: bb0f056b3f2ecc3893e5e48e99c060788550ea6a8ed02b715953af051bafbad0
2022-02-03 14:19:26 +00:00
drh 19eef9af64 Improvement to the sqlite3_vtab_in_first() documentation.
FossilOrigin-Name: 403e7ac900e53407282393747b784dc0cd4303958394534e3936fce138bc1bc5
2022-02-02 21:06:40 +00:00
drh 044a017abc Add the sqlite3_vtab_in() interface that allows virtual tables to process
IN constraints all at once, rather than one value at a time.

FossilOrigin-Name: 52559af093809b572082b5ebaacf97b727ee1860ae118530761b62e937545163
2022-02-02 19:51:44 +00:00
drh cc0db61364 Additional test cases.
FossilOrigin-Name: 733d81c3a6a513b0b893a7d14894f36aebbbca9da375c326db8a72df4f0c6238
2022-02-02 19:30:24 +00:00
drh d96ab99588 Test cases for sqlite3_vtab_in() and sqlite3_vtab_distinct().
FossilOrigin-Name: 21afb81d0a73af39aacd9329b1441faa2b535a52a52036daec89fd303a8b344f
2022-02-02 19:15:53 +00:00
drh 2725db836b Improved documentation for sqlite3_vtab_in(). No code changes.
FossilOrigin-Name: c99df4ab5db2c32b044366c5b0ac70fd8887d1456d53323e75fede23cc61c236
2022-02-02 18:47:56 +00:00
drh 3d7a69e5ef Relax the restriction that the RHS of the IN operator must be a list in order
for sqlite3_vtab_in() to work.  Change an unreachable branch into an assert().

FossilOrigin-Name: 3bf2153440dce0e8c0572c4fd39e6b9f34ead75ccab2cea80a646d4ff9d19146
2022-02-02 16:24:01 +00:00
drh 38d1e44350 Be sure that sqlite3_vtab_in_first() and _next() set the correct encoding.
FossilOrigin-Name: 04edf36ee8e043c83235a5169a7ced23f211edd2f7ef3290d96413d5fd229ad7
2022-02-02 15:10:45 +00:00
drh 30e314e4cb Refactor sqlite3_vtab_in() to make use of the existing
sqlite3_value_pointer() mechanism for passing the list of IN operator
RHS values into xFilter, for improved memory safety.

FossilOrigin-Name: 8965929be236fe1a6994f31b94c1b7590c7c1e809470c542a76f3e0e275d032f
2022-02-02 14:36:58 +00:00
drh 9ede896ac1 Fix a harmless code indentation issue.
FossilOrigin-Name: 41d8d26e48a440da44582763f6b0c097febe3b8ac16adb662f688c3662c301bf
2022-02-02 11:37:49 +00:00
drh b30298d3ea Tweaks to the sqlite3_vtab_in() interface.
FossilOrigin-Name: 75040183b8e14f20bfedfdcc1a9fb968f2f0193bc698605d1b4791a3699b93d9
2022-02-01 21:59:43 +00:00
drh a9f18f0172 Index in 2nd argument to sqlite3_vtab_in() should be on the aConstraint[]
array, not the internal array of all constraints.

FossilOrigin-Name: 5acf90a931b27b7d627c0a8fee68170430e09b028d6643b959b0ec14fd59f7ac
2022-02-01 16:30:57 +00:00
drh 0fe7e7d924 Add new interfaces to enable virtual table to process IN operator constraints
all at once, rather than one element at a time.

FossilOrigin-Name: eb84b80e1f6d8c32bf0c9e1731f0233de0160a13f714f766779ae01fdf504e7b
2022-02-01 14:58:29 +00:00
drh e66532a63b CLI: Take extra care to not split a multi-byte unicode character when doing
wordwrap.

FossilOrigin-Name: 00b1b7020a564976da3237532434e47ccf17eb5d620e6ac45f3e70b5d5739200
2022-02-01 13:17:11 +00:00
drh ca1776b5f3 CLI: Add the --ww option as an alias for --wordwrap. Improve the wordwrap
algorithm so that it breaks at punctuation if it cannot find space.  Always
wordwrap with --ww even if there is a .width setting for the column.

FossilOrigin-Name: 1b528e31f8c62797e0814568b520c0680ff23a2ee877ca6aa70a167d40ebdf80
2022-02-01 12:28:17 +00:00
larrybr cc4d55c9cb Add "--wordwrap on/off" option for CLI columnar modes, qwbox shortcut
FossilOrigin-Name: 10dbc278708cd2cce7fef90738082dbe31750d93e44b5fa5413a9a32dae7703a
2022-02-01 02:50:45 +00:00
drh 5aabdaebd5 CLI: In ".mode column" output, if any row contains a newline or wraps, then
put a single blank line in between each pair of rows to provide additional
visual separately.

FossilOrigin-Name: fd42f4c304079356358e606dd96d4b84cf211c4334c586118b99fe9ad20e20ea
2022-02-01 00:00:08 +00:00
drh 47741b8de9 CLI: for columnar output modes, make sure the header is not too big.
Also, improve the help text.

FossilOrigin-Name: 070fae3a09cea675e722340870cb2bee9e1ac96954d3baacfdb7f5400ddb1b20
2022-01-31 22:14:53 +00:00
drh 3769501235 CLI: Fix a problem with tabs in the new qbox mode.
FossilOrigin-Name: ca96ab3ef78479d95e831cacdb80f23c119cbaa77b3821eac7a3f110bfe20cc9
2022-01-31 20:39:27 +00:00
drh 5dce6f96d1 Fix harmless compiler warnings in MSVC.
FossilOrigin-Name: 3ec6141c41a71eea0d96a65aa35c828e4d852d60e090513c312b925d0e257f9a
2022-01-31 16:29:06 +00:00
drh 87fb37efce Do not attempt to limit the number of columns used in a table to a prefix
if the table will be used to construct an automatic index or bloom filter.
dbsqlfuzz 787d9bd73164c6f0c85469e2e48b2aff19af6938.

FossilOrigin-Name: f8766231d2a77bb8b95726b514736d4c2d20b056f7fe60bdbc98ebf5e5b15ae9
2022-01-31 15:59:43 +00:00
drh e40f28618c CLI: Enhancements to columnar output modes. (See
[forum/forumpost/5b53cd851f66441f9|forum post 5b53cd851] for discussion.)
New output mode "qbox".  New output options "--quote" and "--wrap N".

FossilOrigin-Name: 539cef5214446a7181614793e9cf323e95ba00ba0f888585b14b598dd2ff0808
2022-01-31 14:14:29 +00:00
drh 92ecf306ec Fix an obscure problem in sqlite3_backup_init() caused by
[6a45d8fe8bfbc11a|check-in 6a45d8fe8bfbc11a].  See
[forum:/forumpost/8b39fbf3e7b5c278|forum post 8b39fbf3e7] for
the original bug report.

FossilOrigin-Name: 639fc7633bd740421d6b48617b9f68e6be525107e4049673fe720ea6158a393f
2022-01-31 12:29:14 +00:00
drh b617219bac CLI: Fix the new ".mode box" output so that it works with unicode characters.
FossilOrigin-Name: 454af48724c78bf8e06379a426e01b1597f56fcc83211ee062ff0dbeb6a140b1
2022-01-31 10:55:50 +00:00
drh 09a39ed522 CLI: For columnar modes ("box", "column", "table", "markdown") the ".width"
is now both the minimum and maximum width of the column.  Text that spans
multiple lines or that contains tabs is properly formatted.  If any part of
the output contains multi-line text, then extra separators are provided between
each row.

FossilOrigin-Name: c10ed4a7fe33fd9330967ab714b1f09ad57c972997160dfc71477e43b905f69c
2022-01-30 21:09:03 +00:00
drh e229ca0307 Always enable all JSON tests, now that JSON is included by default.
FossilOrigin-Name: 8c9f350182140604a71e11d226acb3f80d1f2b4f75e5c3b55ec8f8a7c02941f3
2022-01-30 11:44:17 +00:00
drh ddd166a350 Remove a faulty NEVER(). Fix for dbsqlfuzz 4678cf825d27f87c9b8343720121e12cf944b71a
FossilOrigin-Name: d4e402458dd4cadb623a30158eb9ff5f24f011240b3b1bc5b1d6ae3c5b855892
2022-01-30 11:42:56 +00:00
drh 86c756015b Documentation enhancements. No code changes.
FossilOrigin-Name: 312642d982f7861fd4db416e5eb24d863535b3ade40539a32f2dfe3f6fc45d46
2022-01-29 21:41:15 +00:00
drh 665b6b6b35 Add the SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
constraints to the sqlite3_index_info for the xBestIndex method of virtual
tables.

FossilOrigin-Name: 1e227ad9f413227f767b45b91e5439b82c98a3368fb20643414dab5c0f4818c6
2022-01-28 23:44:27 +00:00
drh f6f7888622 Add a NEVER() on an unreachable branch.
FossilOrigin-Name: 388926254b9da6169da7267bd4d5a1a66a26576be435c88269ab8db9eaedc079
2022-01-28 23:19:01 +00:00
drh 75863ec11c When nesting Parse objects, make sure the new one has nErr set if there
has been an OOM error.

FossilOrigin-Name: ae088cbc968a565c3e0a8dd74ce150cac4a87978b593a3204f475fa196f1603c
2022-01-28 21:39:29 +00:00
drh cee5cb484d Include hidden columns of table valued functions that are constrained
by the function arguments in the colUsed bitmask.

FossilOrigin-Name: 8f8cab0d0e219f0c4bc2b8061c0013d90a2a5e598dd6cf420d302dfd1b7cbe11
2022-01-28 19:53:37 +00:00
drh d0c7baf505 Remove a NEVER() that has become reachable now that we have the
sqlite3_vtab_rhs_value() interface.

FossilOrigin-Name: c4c30df7cd858315359bd9bfa90a07152d87a2301eaec865c5bc1c65e272eec8
2022-01-28 18:43:33 +00:00
drh 0ae56fbdd0 Enable SQLITE_INDEX_CONSTRAINT_LIMIT/OFFSET even if there are vector
comparison operators in the WHERE clause.  Also:  Do not enable
sqlite3_vtab_rhs_value() for LIMIT/OFFSET if the value is negative, as this
violates an invariant on Expr.u.iValue.

FossilOrigin-Name: 140480b3ec5466513b165d4818f1180cff6e4a5edcd47efb54cbff74a7107507
2022-01-28 13:18:40 +00:00
drh 8f2c0b59da Query planner always honors the aConstraintUsage[].omit flag for the
SQLITE_INDEX_CONSTRAINT_OFFSET constraint.

FossilOrigin-Name: 38c5151eb8cc789ad082a1b40d16b2ddb55454219bd685b6e420995af6a15f55
2022-01-27 21:18:14 +00:00
drh 233ba1b8eb Make LIMIT and OFFSET values available to sqlite3_vtab_rhs_value().
FossilOrigin-Name: b2d37c086c87fe4aee013bba4eab26f642207cd2a797fe4888a6ef868884c191
2022-01-27 18:45:26 +00:00
drh 895bab3383 Give the virtual table xBestIndex method access to (some) OFFSET and LIMIT
clauses.

FossilOrigin-Name: 74fa5757ee0a8499bcd6546dac1a3ecc6048ba9cff9e3e574e28e6e82e894a3d
2022-01-27 16:14:50 +00:00
drh 4b51e8bd68 Enforce the restriction that 'unixepoch' only works as the first modifier
after the time-value.  This has been documented since 2004, but has never
actually been enforced before.  Also add new test cases for date/time
functions with evidence marks.

FossilOrigin-Name: 64fa9e8c87179211cec248e6dfd7578502e6e969a19e91a4f0e21ed9b972a6bc
2022-01-27 13:52:01 +00:00
drh a5c9a70757 Minor adjustment to error handling in sqlite3FinishCoding().
FossilOrigin-Name: a8db69411b0d1275909adeb21027784ada17af24efe3a59ae0ae2a897659ff17
2022-01-25 00:03:25 +00:00
drh 15b01def1e Remove an unnecessary assert() that is sometimes not true following an OOM.
FossilOrigin-Name: e9361d72f362b390a31f667363b01cf9d4b78aa19ed5c97f21afe9da764b89c0
2022-01-24 21:47:00 +00:00
drh a2417ec75c New dbsqlfuzz cases added to test/fuzzdata8.db.
FossilOrigin-Name: d1fbf63330830c4b9549d0e67f6cdc19fe7a9dc3fcf509795fd1175499fddc82
2022-01-24 20:20:35 +00:00
drh b32b30930f One of the ALWAYS() macros in the previous check-in could sometimes be
false, following an OOM.  Remove it.  Problem found by dbsqlfuzz.

FossilOrigin-Name: 11df9187dad0eb33b0f6288b76d74f9700420ec855e8106b0bc71df48c485ad1
2022-01-24 20:16:37 +00:00
drh 1da88b5ce6 Add ALWAYS() macros. Change some existing ALWAYS() into assert(). Other
code simplifications.

FossilOrigin-Name: 4aa27b4fcd1ffd06c38357a87ba3f5776367570439c49652f0903873def0bb23
2022-01-24 19:38:56 +00:00
drh 0c7d3d399d Remove many redundant checks for sqlite3.mallocFailed now that any OOM should
cause Parse.nErr to be non-zero.

FossilOrigin-Name: 1f7fa46126ea33ed30e93186aff3df51068aeb4be6f79a102bfe8c4e44941d71
2022-01-24 16:47:12 +00:00
drh c692df2784 Make it so that any Parse object is always linked into the database conenction
while it is active.  Hence, an OOM will cause Parse.nErr to be set.

FossilOrigin-Name: 6a45d8fe8bfbc11a5b86d25237e1f8bccfb0f22f3dcaf004ba797aeb57b365ec
2022-01-24 15:34:55 +00:00
larrybr b5d4473221 Fix testcase for CLI .read recursion.
FossilOrigin-Name: 53d4404458fb6f0b6b2b69c2225d66b39f09099c356ba3c3e990474f14aba31a
2022-01-24 14:01:31 +00:00
drh 3cdb1394b9 Make sure the sqlite3OomFault() routine sets an error in the Parse object
if there is a Parse object active and linked to the database connection.

FossilOrigin-Name: ad7aace761c6b21ba453eaf43c68d985be7cbd5a200fe0d2e27a0c7150f99874
2022-01-24 12:48:54 +00:00
dan f5bc444077 Ensure that any error encountered while coding a trigger program is transfered to the main Parse structure before it is used with any other routine that might set the error code.
FossilOrigin-Name: 4293656578811b500786335de7cc9ac0d6ccc6fb273b9419a86968a095404c43
2022-01-24 11:25:42 +00:00
larrybr d48e88e56d Limit CLI input redirect nesting
FossilOrigin-Name: 7a073931752d16ba71f1a606091461e427ca5ccf4d135d3c5141bfdd4e67e2d5
2022-01-24 06:36:16 +00:00
drh bcba3655ee Add support for the sqlite3_vtab_distinct() interface. Virtual table
implementations can use this API to determine more detail about the ordering
requirements needed by the query plan and perhaps reduce the amount of
work required to compute a correct answer.  This is an optimization
opportunity for the virtual table implementation.  The correct answer should
still be obtained (though perhaps more slowly) even if sqlite3_vtab_distinct()
is ignored.

FossilOrigin-Name: e4caf1e3932b1bd0dea072df7fc9458aed98c84ea397b6948b89292603949c41
2022-01-22 22:28:32 +00:00
286 changed files with 67851 additions and 4248 deletions
+144 -5
View File
@@ -503,6 +503,7 @@ TESTSRC2 = \
$(TOP)/src/pcache1.c \
$(TOP)/src/select.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/treeview.c \
$(TOP)/src/utf.c \
$(TOP)/src/util.c \
$(TOP)/src/vdbeapi.c \
@@ -609,7 +610,7 @@ TESTOPTS = --verbose=file --output=test-out.txt
# Extra compiler options for various shell tools
#
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
SHELL_OPT = -DSQLITE_ENABLE_FTS4
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_RTREE
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
@@ -619,8 +620,8 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZERSHELL_OPT =
FUZZCHECK_OPT = -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
@@ -630,7 +631,7 @@ FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c $(TOP)/test/fuzzinvariants.c
DBFUZZ_OPT =
# This is the default Makefile target. The objects listed here
@@ -874,7 +875,7 @@ hash.lo: $(TOP)/src/hash.c $(HDR)
insert.lo: $(TOP)/src/insert.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c
json.lo: $(TOP)/src/json.c
json.lo: $(TOP)/src/json.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/json.c
legacy.lo: $(TOP)/src/legacy.c $(HDR)
@@ -1280,6 +1281,12 @@ valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessio
tcltest: ./testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Runs all the same tests cases as the "tcltest" target but uses
# the testrunner.tcl script to run them in multiple cores
# concurrently.
testrunner: testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
# Minimal testing that runs in less than 3 minutes
#
quicktest: ./testfixture$(TEXE)
@@ -1512,3 +1519,135 @@ sqlite3.def: $(REAL_LIBOBJ)
sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def
$(TCC) -shared -o $@ sqlite3.def \
-Wl,"--strip-all" $(REAL_LIBOBJ)
#
# fiddle/wasm section
#
fiddle_dir = ext/fiddle
fiddle_dir_abs = $(TOP)/$(fiddle_dir)
# ^^^ some emcc opts require absolute paths
fiddle_html = $(fiddle_dir)/fiddle.html
fiddle_module_js = $(fiddle_dir)/fiddle-module.js
sqlite3_wasm_js = $(fiddle_dir)/sqlite3.js
sqlite3_wasm = $(fiddle_dir)/sqlite3.wasm
#emcc_opt = -O0
#emcc_opt = -O1
#emcc_opt = -O2
#emcc_opt = -O3
emcc_opt = -Oz
emcc_flags = $(emcc_opt) -sALLOW_TABLE_GROWTH -sSTRICT_JS \
-sENVIRONMENT=web -sMODULARIZE \
-sEXPORTED_RUNTIME_METHODS=@$(fiddle_dir_abs)/EXPORTED_RUNTIME_METHODS \
-sDYNAMIC_EXECUTION=0 \
-I. $(SHELL_OPT)
$(fiddle_module_js): Makefile sqlite3.c shell.c \
$(fiddle_dir)/EXPORTED_RUNTIME_METHODS \
$(fiddle_dir)/EXPORTED_FUNCTIONS.fiddle
emcc -o $@ $(emcc_flags) \
-sEXPORT_NAME=initFiddleModule \
-sEXPORTED_FUNCTIONS=@$(fiddle_dir_abs)/EXPORTED_FUNCTIONS.fiddle \
-DSQLITE_SHELL_FIDDLE \
sqlite3.c shell.c
gzip < $@ > $@.gz
gzip < $(fiddle_dir)/fiddle-module.wasm > $(fiddle_dir)/fiddle-module.wasm.gz
$(sqlite3_wasm_js): Makefile sqlite3.c \
$(fiddle_dir)/sqlite3-api.js \
$(fiddle_dir)/EXPORTED_RUNTIME_METHODS \
$(fiddle_dir)/EXPORTED_FUNCTIONS.sqlite3-api
emcc -o $@ $(emcc_flags) \
-sEXPORT_NAME=initSqlite3Module \
-sEXPORTED_FUNCTIONS=@$(fiddle_dir_abs)/EXPORTED_FUNCTIONS.sqlite3-api \
--post-js=$(fiddle_dir)/sqlite3-api.js \
--no-entry \
sqlite3.c
gzip < $@ > $@.gz
gzip < $(sqlite3_wasm) > $(sqlite3_wasm).gz
gzip < $(fiddle_dir)/sqlite3-api.js > $(fiddle_dir)/sqlite3-api.js.gz
$(fiddle_dir)/fiddle.js.gz: $(fiddle_dir)/fiddle.js
gzip < $< > $@
$(fiddle_dir)/sqlite3-api.js.gz: $(fiddle_dir)/sqlite3-api.js
gzip < $< > $@
fiddle_generated = $(fiddle_module_js) $(fiddle_module_js).gz \
$(fiddle_dir)/fiddle-module.wasm \
$(fiddle_dir)/fiddle-module.wasm.gz \
$(fiddle_dir)/fiddle.js.gz
sqlite3_wasm_generated = \
$(sqlite3_wasm) $(sqlite3_wasm).gz \
$(sqlite3_wasm_js) $(sqlite3_wasm_js).gz \
$(fiddle_dir)/sqlite3.js.gz \
$(fiddle_dir)/sqlite3-api.js.gz
clean-wasm:
rm -f $(fiddle_generated) $(sqlite3_wasm_generated)
clean: clean-wasm
fiddle: $(fiddle_module_js) $(fiddle_dir)/fiddle.js.gz
sqlite3-wasm: $(sqlite3_wasm_js)
wasm: fiddle sqlite3-wasm
########################################################################
# Explanation of the emcc build flags follows. Full docs for these can
# be found at:
#
# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
#
# -sENVIRONMENT=web: elides bootstrap code related to non-web JS
# environments like node.js. Removing this makes the output a tiny
# tick larger but hypothetically makes it more portable to
# non-browser JS environments.
#
# -sMODULARIZE: changes how the generated code is structured to avoid
# declaring a global Module object and instead installing a function
# which loads and initialized the module. The function is named...
#
# -sEXPORT_NAME=jsFunctionName (see -sMODULARIZE)
#
# -sEXPORTED_RUNTIME_METHODS=@/absolute/path/to/file: a file
# containing a list of emscripten-supplied APIs, one per line, which
# must be exported into the generated JS. Must be an absolute path!
#
# -sEXPORTED_FUNCTIONS=@/absolute/path/to/file: a file containing a
# list of C functions, one per line, which must be exported via wasm
# so they're visible to JS. C symbols names in that file must all
# start with an underscore for reasons known only to the emcc
# developers. e.g., _sqlite3_open_v2 and _sqlite3_finalize. Must be
# an absolute path!
#
# -sSTRICT_JS ensures that the emitted JS code includes the 'use
# strict' option. Note that -sSTRICT is more broadly-scoped and
# results in build errors.
#
# -sALLOW_TABLE_GROWTH is required for (at a minimum) the UDF-binding
# feature.
#
# -sDYNAMIC_EXECUTION=0 disables eval() and the Function constructor.
# If the build runs without these, it's preferable to use this flag
# because certain execution environments disallow those constructs.
# This flag is not strictly necessary, however.
#
# -sWASM_BIGINT is UNTESTED but "should" allow the int64-using C APIs
# to work with JS/wasm, insofar as the JS environment supports the
# BigInt type. That support requires an extremely recent browser:
# Safari didn't get that support until late 2020.
#
# --no-entry: for compiling library code with no main(). If this is
# not supplied and the code has a main(), it is called as part of the
# module init process. Note that main() is #if'd out of shell.c
# (renamed) when building in wasm mode.
#
# --pre-js/--post-js=FILE relative or absolute paths to JS files to
# prepend/append to the emcc-generated bootstrapping JS. It's
# easier/faster to develop with separate JS files (reduces rebuilding
# requirements) but certain configurations, namely -sMODULARIZE, may
# require using at least a --pre-js file. They can be used
# individually and need not be paired.
#
# -O0..-O3 and -Oz: optimization levels affect not only C-style
# optimization but whether or not the resulting generated JS code
# gets minified. -O0 compiles _much_ more quickly than -O3 or -Oz,
# and doesn't minimize any JS code, so is recommended for
# development. -O3 or -Oz are recommended for deployment, but
# primarily because -Oz will shrink the wasm file notably. JS-side
# minification makes little difference in terms of overall
# distributable size.
########################################################################
+10 -6
View File
@@ -363,7 +363,6 @@ SQLITE_TCL_DEP =
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
@@ -1696,9 +1695,9 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
# <<mark>>
# Extra compiler options for various test tools.
#
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS =
FUZZCHECK_OPTS = -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS5
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
@@ -1706,7 +1705,7 @@ FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c $(TOP)\test\fuzzinvariants.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
@@ -2393,7 +2392,6 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
@@ -2477,6 +2475,12 @@ tcltest: testfixture.exe
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
# Runs all the same tests cases as the "tcltest" target but uses
# the testrunner.tcl script to run them in multiple cores
# concurrently.
testrunner: testfixture.exe
.\testfixture.exe $(TOP)\test\testrunner.tcl
smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
+14 -14
View File
@@ -1,7 +1,7 @@
<h1 align="center">SQLite Source Repository</h1>
This repository contains the complete source code for the
[SQLite database engine](https://sqlite.org/). Some test scripts
This repository contains the complete source code for the
[SQLite database engine](https://sqlite.org/). Some test scripts
are also included. However, many other test scripts
and most of the documentation are managed separately.
@@ -15,7 +15,7 @@ The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext.
If you are reading this on GitHub or some other Git repository or service,
then you are looking at a mirror. The names of check-ins and
other artifacts in a Git mirror are different from the official
names for those objects. The offical names for check-ins are
names for those objects. The official names for check-ins are
found in a footer on the check-in comment for authorized mirrors.
The official check-in name can also be seen in the `manifest.uuid` file
in the root of the tree. Always use the official name, not the
@@ -30,7 +30,7 @@ verify its integrity, there are hints on how to do that in the
If you do not want to use Fossil, you can download tarballs or ZIP
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
* Lastest trunk check-in as
* Latest trunk check-in as
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).
@@ -47,11 +47,11 @@ archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
then click on the "Tarball" or "ZIP Archive" links on the information
page.
If you do want to use Fossil to check out the source tree,
If you do want to use Fossil to check out the source tree,
first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
a stand-alone program. To install, simply download or build the single
a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH.)
Then run commands like this:
@@ -61,7 +61,7 @@ Then run commands like this:
fossil open ~/Fossils/sqlite.fossil
After setting up a repository using the steps above, you can always
update to the lastest version using:
update to the latest version using:
fossil update trunk ;# latest trunk check-in
fossil update release ;# latest official release
@@ -136,7 +136,7 @@ the "tclsqlite.c" file which implements the
extension and only later escaped to the wild as an independent library.)
Test scripts and programs are found in the **test/** subdirectory.
Addtional test code is found in other source repositories.
Additional test code is found in other source repositories.
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
additional information.
@@ -170,7 +170,7 @@ at just the right spots. Note that comment text in the sqlite3.h file is
used to generate much of the SQLite API documentation. The Tcl scripts
used to generate that documentation are in a separate source repository.
The SQL language parser is **parse.c** which is generate from a grammar in
The SQL language parser is **parse.c** which is generated from a grammar in
the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
@@ -180,7 +180,7 @@ generates parse.c.
The **opcodes.h** header file contains macros that define the numbers
corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
file is generated by the scanning the src/vdbe.c source file. The
file is generated by scanning the src/vdbe.c source file. The
Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h.
A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate
the **opcodes.c** source file, which contains a reverse mapping from
@@ -237,7 +237,7 @@ prepared statements, the description of
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
Years of effort have gone into optimizating SQLite, both
Years of effort have gone into optimizing SQLite, both
for small size and high performance. And optimizations tend to result in
complex code. So there is a lot of complexity in the current SQLite
implementation. It will not be the easiest library in the world to hack.
@@ -294,11 +294,11 @@ Key files:
building the "testfixture.exe" program. The testfixture.exe program is
an enhanced Tcl shell. The testfixture.exe program runs scripts in the
test/ folder to validate the core SQLite code. The testfixture program
(and some other test programs too) is build and run when you type
(and some other test programs too) is built and run when you type
"make test".
* **ext/misc/json1.c** - This file implements the various JSON functions
that are build into SQLite.
that are built into SQLite.
There are many other source files. Each has a succinct header comment that
describes its purpose and role within the larger system.
@@ -307,7 +307,7 @@ describes its purpose and role within the larger system.
## Verifying Code Authenticity
The `manifest` file at the root directory of the source tree
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
older files) for every source file in the repository.
The name of the version of the entire source tree is just the
SHA3-256 hash of the `manifest` file itself, possibly with the
+1 -1
View File
@@ -1 +1 @@
3.38.0
3.40.0
-1
View File
@@ -285,7 +285,6 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
+1 -1
View File
@@ -105,7 +105,7 @@ may be specified in this manner as some require the amalgamation to be built
with them enabled (see http://www.sqlite.org/compile.html). For example, the
following will work:
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_JSON=1"
However, the following will not compile unless the amalgamation was built
with it enabled:
-15
View File
@@ -173,21 +173,6 @@ else
fi
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# --enable-json1
#
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
[--enable-json1], [include json1 support [default=yes]])],
[],[enable_json1=yes])
AC_MSG_CHECKING([JSON functions])
if test x"$enable_json1" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
AC_MSG_RESULT([enabled])
else
AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# --enable-rtree
#
+109 -74
View File
@@ -11,8 +11,6 @@
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.59 2005/07/26 19:17:02 mdejong Exp $
#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
@@ -60,6 +58,8 @@ PKG_HEADERS = @PKG_HEADERS@
#========================================================================
PKG_LIB_FILE = @PKG_LIB_FILE@
PKG_LIB_FILE8 = @PKG_LIB_FILE8@
PKG_LIB_FILE9 = @PKG_LIB_FILE9@
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
lib_BINARIES = $(PKG_LIB_FILE)
@@ -73,10 +73,11 @@ exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
datarootdir = @datarootdir@
runstatedir = @runstatedir@
datadir = @datadir@
mandir = @mandir@
includedir = @includedir@
DESTDIR =
@@ -85,24 +86,25 @@ pkgdatadir = $(datadir)/$(PKG_DIR)
pkglibdir = $(libdir)/$(PKG_DIR)
pkgincludedir = $(includedir)/$(PKG_DIR)
top_builddir = .
top_builddir = @abs_top_builddir@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_OPTIONS =
INSTALL = @INSTALL@ $(INSTALL_OPTIONS)
INSTALL_DATA_DIR = @INSTALL_DATA_DIR@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_LIBRARY = @INSTALL_LIBRARY@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
CC = @CC@
CCLD = @CCLD@
CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
CFLAGS_WARNING = @CFLAGS_WARNING@
CLEANFILES = @CLEANFILES@
EXEEXT = @EXEEXT@
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
MAKE_LIB = @MAKE_LIB@
MAKE_SHARED_LIB = @MAKE_SHARED_LIB@
MAKE_STATIC_LIB = @MAKE_STATIC_LIB@
MAKE_STUB_LIB = @MAKE_STUB_LIB@
OBJEXT = @OBJEXT@
RANLIB = @RANLIB@
@@ -117,8 +119,6 @@ TCL_SRC_DIR = @TCL_SRC_DIR@
#TK_BIN_DIR = @TK_BIN_DIR@
#TK_SRC_DIR = @TK_SRC_DIR@
# This is no longer necessary even for packages that use private Tcl headers
#TCL_TOP_DIR_NATIVE = @TCL_TOP_DIR_NATIVE@
# Not used, but retained for reference of what libs Tcl required
#TCL_LIBS = @TCL_LIBS@
@@ -132,41 +132,52 @@ TCL_SRC_DIR = @TCL_SRC_DIR@
EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH = $(top_builddir)
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
@LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
PATH="$(EXTRA_PATH):$(PATH)" \
TCLLIBPATH="$(TCLLIBPATH)"
# TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
TCLSH_PROG = @TCLSH_PROG@
TCLSH = $(TCLSH_ENV) $(TCLSH_PROG)
TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG)
#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
#WISH_PROG = @WISH_PROG@
#WISH = $(TCLSH_ENV) $(WISH_PROG)
#WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG)
SHARED_BUILD = @SHARED_BUILD@
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I$(srcdir)/..
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I. -I$(srcdir)/..
#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@
PKG_CFLAGS = @PKG_CFLAGS@
# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.in checks for the necessary components
# must make sure that configure.ac checks for the necessary components
# that your library may use. TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
DEFS = @DEFS@ $(PKG_CFLAGS)
# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
CLEANFILES = @CLEANFILES@
CPPFLAGS = @CPPFLAGS@
LIBS = @PKG_LIBS@ @LIBS@
AR = @AR@
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LDFLAGS = @LDFLAGS@
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \
$(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS)
GDB = gdb
VALGRIND = valgrind
VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \
--leak-check=yes --show-reachable=yes -v
.SUFFIXES: .c .$(OBJEXT)
#========================================================================
# Start of user-definable TARGETS section
@@ -174,7 +185,7 @@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(C
#========================================================================
# TEA TARGETS. Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target inclues executable programs and
# independent files, and the "binaries:" target includes executable programs and
# platform-dependent libraries. Modify these targets so that they install
# the various pieces of your package. The make and install rules
# for the BINARIES that you specified above have already been done.
@@ -193,7 +204,6 @@ binaries: $(BINARIES)
libraries:
#========================================================================
# Your doc target should differentiate from doc builds (by the developer)
# and doc installs (see install-doc), which just install the docs on the
@@ -216,11 +226,11 @@ install-binaries: binaries install-lib-binaries install-bin-binaries
#========================================================================
install-libraries: libraries
@mkdir -p $(DESTDIR)$(includedir)
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(includedir)"
@echo "Installing header files in $(DESTDIR)$(includedir)"
@list='$(PKG_HEADERS)'; for i in $$list; do \
echo "Installing $(srcdir)/$$i" ; \
$(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
$(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \
done;
#========================================================================
@@ -229,12 +239,11 @@ install-libraries: libraries
#========================================================================
install-doc: doc
@mkdir -p $(DESTDIR)$(mandir)/mann
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(mandir)/mann"
@echo "Installing documentation in $(DESTDIR)$(mandir)"
@list='$(srcdir)/doc/*.n'; for i in $$list; do \
echo "Installing $$i"; \
rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
$(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
$(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \
done
test: binaries libraries
@@ -244,7 +253,21 @@ shell: binaries libraries
@$(TCLSH) $(SCRIPT)
gdb:
$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
$(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT)
gdb-test: binaries libraries
$(TCLSH_ENV) $(PKG_ENV) $(GDB) \
--args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \
$(TESTFLAGS) -singleproc 1 \
-load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \
[list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]"
valgrind: binaries libraries
$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \
`@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)
valgrindshell: binaries libraries
$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)
depend:
@@ -283,49 +306,70 @@ $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx
.c.@OBJEXT@:
$(COMPILE) -c `@CYGPATH@ $<` -o $@
tclsample.@OBJEXT@: sampleUuid.h
$(srcdir)/manifest.uuid:
printf "git-" >$(srcdir)/manifest.uuid
(cd $(srcdir); git rev-parse HEAD >>$(srcdir)/manifest.uuid || \
(printf "svn-r" >$(srcdir)/manifest.uuid ; \
svn info --show-item last-changed-revision >>$(srcdir)/manifest.uuid) || \
printf "unknown" >$(srcdir)/manifest.uuid)
sampleUuid.h: $(srcdir)/manifest.uuid
echo "#define SAMPLE_VERSION_UUID \\" >$@
cat $(srcdir)/manifest.uuid >>$@
echo "" >>$@
#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
#========================================================================
#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
COMPRESS = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
DIST_ROOT = /tmp/dist
DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644
DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755
dist-clean:
rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
dist: dist-clean
mkdir -p $(DIST_DIR)
cp -p $(srcdir)/README* $(srcdir)/license* \
$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
$(DIST_DIR)/
chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
dist: dist-clean $(srcdir)/manifest.uuid
$(INSTALL_DATA_DIR) $(DIST_DIR)
for i in $(srcdir)/*.[ch]; do \
if [ -f $$i ]; then \
cp -p $$i $(DIST_DIR)/ ; \
fi; \
done;
# TEA files
$(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \
$(srcdir)/aclocal.m4 $(srcdir)/configure.ac \
$(DIST_DIR)/
$(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/
mkdir $(DIST_DIR)/tclconfig
cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
$(DIST_DIR)/tclconfig/
chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
chmod +x $(DIST_DIR)/tclconfig/install-sh
$(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
$(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \
$(srcdir)/manifest.uuid \
$(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \
$(DIST_DIR)/tclconfig/
list='demos doc generic library mac tests unix win'; \
# Extension files
$(DIST_INSTALL_DATA) \
$(srcdir)/ChangeLog \
$(srcdir)/README.sha \
$(srcdir)/license.terms \
$(srcdir)/README \
$(srcdir)/pkgIndex.tcl.in \
$(DIST_DIR)/
list='demos doc generic library macosx tests unix win'; \
for p in $$list; do \
if test -d $(srcdir)/$$p ; then \
mkdir $(DIST_DIR)/$$p; \
cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
$(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \
$(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \
fi; \
done
@@ -337,10 +381,10 @@ dist: dist-clean
#========================================================================
# Don't modify the file to clean here. Instead, set the "CLEANFILES"
# variable in configure.in
# variable in configure.ac
#========================================================================
clean:
clean:
-test -z "$(BINARIES)" || rm -f $(BINARIES)
-rm -f *.$(OBJEXT) core *.core
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
@@ -348,7 +392,7 @@ clean:
distclean: clean
-rm -f *.tab.c
-rm -f $(CONFIG_CLEAN_FILES)
-rm -f config.h config.cache config.log config.status
-rm -f config.cache config.log config.status
#========================================================================
# Install binary object libraries. On Windows this includes both .dll and
@@ -362,25 +406,17 @@ distclean: clean
#========================================================================
install-lib-binaries: binaries
@mkdir -p $(DESTDIR)$(pkglibdir)
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)"
@list='$(lib_BINARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \
stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
if test "x$$stub" = "xstub"; then \
echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
else \
echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
fi; \
echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
$(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \
ext=`echo $$p|sed -e "s/.*\.//"`; \
if test "x$$ext" = "xdll"; then \
lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
if test -f $$lib; then \
echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
$(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
$(INSTALL_DATA) $$lib "$(DESTDIR)$(pkglibdir)/$$lib"; \
fi; \
fi; \
fi; \
@@ -389,12 +425,12 @@ install-lib-binaries: binaries
if test -f $(srcdir)/$$p; then \
destp=`basename $$p`; \
echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
$(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \
fi; \
done
@if test "x$(SHARED_BUILD)" = "x1"; then \
echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
$(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
$(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \
fi
#========================================================================
@@ -407,33 +443,32 @@ install-lib-binaries: binaries
#========================================================================
install-bin-binaries: binaries
@mkdir -p $(DESTDIR)$(bindir)
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)"
@list='$(bin_BINARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
$(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \
fi; \
done
.SUFFIXES: .c .$(OBJEXT)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
uninstall-binaries:
list='$(lib_BINARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
done
list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
p=`basename $$p`; \
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
done
list='$(bin_BINARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/$$p; \
rm -f "$(DESTDIR)$(bindir)/$$p"; \
done
.PHONY: all binaries clean depend distclean doc install libraries test
.PHONY: gdb gdb-test valgrind valgrindshell
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
+60 -34
View File
@@ -2,11 +2,9 @@
dnl This file is an input file used by the GNU "autoconf" program to
dnl generate the file "configure", which is run during Tcl installation
dnl to configure the system for the local environment.
#
# RCS: @(#) $Id: configure.in,v 1.43 2005/07/26 19:17:05 mdejong Exp $
#-----------------------------------------------------------------------
# Sample configure.in for Tcl Extensions. The only places you should
# Sample configure.ac for Tcl Extensions. The only places you should
# need to modify this file are marked by the string __CHANGE__
#-----------------------------------------------------------------------
@@ -17,9 +15,11 @@ dnl to configure the system for the local environment.
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided. These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME>
# so that we create the export library with the dll.
#-----------------------------------------------------------------------
AC_INIT([sqlite], [3.32.0])
AC_INIT([sqlite],[3.40.0])
#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
@@ -27,7 +27,7 @@ AC_INIT([sqlite], [3.32.0])
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------
TEA_INIT([3.9])
TEA_INIT()
AC_CONFIG_AUX_DIR(tclconfig)
@@ -55,8 +55,8 @@ TEA_PREFIX
#-----------------------------------------------------------------------
# Standard compiler checks.
# This sets up CC by using the CC env var, or looks for gcc otherwise.
# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
# the basic setup necessary to compile executables.
# This also calls AC_PROG_CC and a few others to create the basic setup
# necessary to compile executables.
#-----------------------------------------------------------------------
TEA_SETUP_COMPILER
@@ -73,11 +73,19 @@ TEA_SETUP_COMPILER
TEA_ADD_SOURCES([tclsqlite3.c])
TEA_ADD_HEADERS([])
TEA_ADD_INCLUDES([-I\"`\${CYGPATH} \${srcdir}/generic`\"])
TEA_ADD_INCLUDES([])
TEA_ADD_LIBS([])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS4=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS5=1])
TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_GEOPOLY=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_MATH_FUNCTIONS=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DESERIALIZE=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBPAGE_VTAB=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_BYTECODE_VTAB=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBSTAT_VTAB=1])
TEA_ADD_STUB_SOURCES([])
TEA_ADD_TCL_SOURCES([])
@@ -99,6 +107,31 @@ if test x$with_system_sqlite != xno; then
LIBS="$LIBS -lsqlite3"])])
fi
#--------------------------------------------------------------------
# __CHANGE__
#
# You can add more files to clean if your extension creates any extra
# files by extending CLEANFILES.
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#
# A few miscellaneous platform-specific items:
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------
#CLEANFILES="$CLEANFILES pkgIndex.tcl"
if test "${TEA_PLATFORM}" = "windows" ; then
# Ensure no empty if clauses
:
#TEA_ADD_SOURCES([win/winFile.c])
#TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
else
# Ensure no empty else clauses
:
#TEA_ADD_SOURCES([unix/unixFile.c])
#TEA_ADD_LIBS([-lsuperfly])
fi
#--------------------------------------------------------------------
# __CHANGE__
# Choose which headers you need. Extension authors should try very
@@ -151,28 +184,6 @@ TEA_CONFIG_CFLAGS
TEA_ENABLE_SYMBOLS
#--------------------------------------------------------------------
# Everyone should be linking against the Tcl stub library. If you
# can't for some reason, remove this definition. If you aren't using
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
# link against the non-stubbed Tcl library. Add Tk too if necessary.
#--------------------------------------------------------------------
AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
#--------------------------------------------------------------------
# Redefine fdatasync as fsync on systems that lack fdatasync
#--------------------------------------------------------------------
#
#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync))
# Check for library functions that SQLite can optionally use.
AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
AC_FUNC_STRERROR_R
#--------------------------------------------------------------------
# This macro generates a line to use when building a library. It
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
@@ -193,9 +204,24 @@ TEA_PROG_TCLSH
#TEA_PROG_WISH
#--------------------------------------------------------------------
# Finally, substitute all of the various values into the Makefile.
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting th AC variables in. Include these here.
# Setup a *Config.sh.in configuration file.
#--------------------------------------------------------------------
AC_OUTPUT([Makefile pkgIndex.tcl])
#TEA_EXPORT_CONFIG([sample])
#AC_SUBST(SAMPLE_VAR)
#--------------------------------------------------------------------
# Specify files to substitute AC variables in. You may alternatively
# have a special pkgIndex.tcl.in or other files which require
# substituting the AC variables in. Include these here.
#--------------------------------------------------------------------
AC_CONFIG_FILES([Makefile pkgIndex.tcl])
#AC_CONFIG_FILES([sampleConfig.sh])
#--------------------------------------------------------------------
# Finally, substitute all of the various values into the files
# specified with AC_CONFIG_FILES.
#--------------------------------------------------------------------
AC_OUTPUT
+9 -6
View File
@@ -1,7 +1,10 @@
# -*- tcl -*-
# Tcl package index file, version 1.1
#
# Tcl package index file
#
# Note sqlite*3* init specifically
#
package ifneeded sqlite3 @PACKAGE_VERSION@ \
[list load [file join $dir @PKG_LIB_FILE@] Sqlite3]
if {[package vsatisfies [package provide Tcl] 9.0-]} {
package ifneeded sqlite3 @PACKAGE_VERSION@ \
[list load [file join $dir @PKG_LIB_FILE9@] sqlite3]
} else {
package ifneeded sqlite3 @PACKAGE_VERSION@ \
[list load [file join $dir @PKG_LIB_FILE8@] sqlite3]
}
File diff suppressed because it is too large Load Diff
+12 -1
View File
@@ -251,7 +251,18 @@ INCLUDES = $(SQL_INCLUDES) $(TCL_INCLUDES) -I"$(WINDIR)" \
-I"$(GENERICDIR)" -I"$(ROOT)\.."
BASE_CLFAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) \
-DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
-DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1
-DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1 \
-DSQLITE_ENABLE_FTS4=1 \
-DSQLITE_ENABLE_FTS5=1 \
-DSQLITE_3_SUFFIX_ONLY=1 \
-DSQLITE_ENABLE_RTREE=1 \
-DSQLITE_ENABLE_GEOPOLY=1 \
-DSQLITE_ENABLE_MATH_FUNCTIONS=1 \
-DSQLITE_ENABLE_DESERIALIZE=1 \
-DSQLITE_ENABLE_DBPAGE_VTAB=1 \
-DSQLITE_ENABLE_BYTECODE_VTAB=1 \
-DSQLITE_ENABLE_DBSTAT_VTAB=1
CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE -DSQLITE_ENABLE_FTS3=1
TCL_CFLAGS = -DBUILD_sqlite -DUSE_TCL_STUBS \
-DPACKAGE_VERSION="\"$(DOTVERSION)\"" $(BASE_CLFAGS) \
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.38.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.40.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.38.0'
PACKAGE_STRING='sqlite 3.38.0'
PACKAGE_VERSION='3.40.0'
PACKAGE_STRING='sqlite 3.40.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1468,7 +1468,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.38.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.40.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1533,7 +1533,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.38.0:";;
short | recursive ) echo "Configuration of sqlite 3.40.0:";;
esac
cat <<\_ACEOF
@@ -1661,7 +1661,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.38.0
sqlite configure 3.40.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2080,7 +2080,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.38.0, which was
It was created by sqlite $as_me 3.40.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12390,7 +12390,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.38.0, which was
This file was extended by sqlite $as_me 3.40.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12456,7 +12456,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.38.0
sqlite config.status 3.40.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+1
View File
@@ -662,6 +662,7 @@ static int idxRegisterVtab(sqlite3expert *p){
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xShadowName2 */
};
return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
+7
View File
@@ -0,0 +1,7 @@
_fiddle_exec
_fiddle_interrupt
_fiddle_experiment
_fiddle_the_db
_fiddle_db_arg
_fiddle_db_filename
_fiddle_reset_db
+51
View File
@@ -0,0 +1,51 @@
_sqlite3_bind_blob
_sqlite3_bind_double
_sqlite3_bind_int
_sqlite3_bind_int64
_sqlite3_bind_null
_sqlite3_bind_parameter_count
_sqlite3_bind_parameter_index
_sqlite3_bind_text
_sqlite3_changes
_sqlite3_clear_bindings
_sqlite3_close_v2
_sqlite3_column_blob
_sqlite3_column_bytes
_sqlite3_column_count
_sqlite3_column_count
_sqlite3_column_double
_sqlite3_column_int
_sqlite3_column_int64
_sqlite3_column_name
_sqlite3_column_text
_sqlite3_column_type
_sqlite3_compileoption_get
_sqlite3_compileoption_used
_sqlite3_create_function_v2
_sqlite3_data_count
_sqlite3_db_filename
_sqlite3_errmsg
_sqlite3_exec
_sqlite3_finalize
_sqlite3_interrupt
_sqlite3_libversion
_sqlite3_open
_sqlite3_open_v2
_sqlite3_prepare_v2
_sqlite3_prepare_v2
_sqlite3_reset
_sqlite3_result_blob
_sqlite3_result_double
_sqlite3_result_error
_sqlite3_result_int
_sqlite3_result_null
_sqlite3_result_text
_sqlite3_sourceid
_sqlite3_sql
_sqlite3_step
_sqlite3_value_blob
_sqlite3_value_bytes
_sqlite3_value_double
_sqlite3_value_text
_sqlite3_value_type
_free
+14
View File
@@ -0,0 +1,14 @@
ALLOC_NORMAL
FS
UTF8ToString
addFunction
allocate
allocateUTF8OnStack
ccall
cwrap
getValue
removeFunction
setValue
stackAlloc
stackRestore
stackSave
+34
View File
@@ -0,0 +1,34 @@
# This GNU makefile exists primarily to simplify/speed up development
# from emacs. It is not part of the canonical build process.
default:
$(MAKE) -C ../.. wasm -e emcc_opt=-O0
clean:
$(MAKE) -C ../../ clean-wasm
fiddle_files = emscripten.css fiddle.html \
fiddle.js fiddle-module.js \
fiddle-module.wasm fiddle-worker.js \
$(wildcard *.wasm.gz) $(wildcard *.js.gz)
# fiddle_remote is the remote destination for the fiddle app. It
# must be a [user@]HOST:/path for rsync.
# Note that the target "should probably" contain a symlink of
# index.html -> fiddle.html.
fiddle_remote ?=
ifeq (,$(fiddle_remote))
ifneq (,$(wildcard /home/stephan))
fiddle_remote = wh2:www/wh/sqlite3/.
else ifneq (,$(wildcard /home/drh))
#fiddle_remote = if appropriate, add that user@host:/path here
endif
endif
$(fiddle_files): default
push-fiddle: $(fiddle_files)
@if [ x = "x$(fiddle_remote)" ]; then \
echo "fiddle_remote must be a [user@]HOST:/path for rsync"; \
exit 1; \
fi
rsync -va $(fiddle_files) $(fiddle_remote)
+144
View File
@@ -0,0 +1,144 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This file contains bootstrapping code used by various test scripts
which live in this file's directory.
*/
(function(){
/* querySelectorAll() proxy */
const EAll = function(/*[element=document,] cssSelector*/){
return (arguments.length>1 ? arguments[0] : document)
.querySelectorAll(arguments[arguments.length-1]);
};
/* querySelector() proxy */
const E = function(/*[element=document,] cssSelector*/){
return (arguments.length>1 ? arguments[0] : document)
.querySelector(arguments[arguments.length-1]);
};
/**
Helpers for writing sqlite3-specific tests.
*/
self/*window or worker*/.SqliteTestUtil = {
/** Running total of the number of tests run via
this API. */
counter: 0,
/**
If expr is a function, it is called and its result
is returned, coerced to a bool, else expr, coerced to
a bool, is returned.
*/
toBool: function(expr){
return (expr instanceof Function) ? !!expr() : !!expr;
},
/** abort() if expr is false. If expr is a function, it
is called and its result is evaluated.
*/
assert: function f(expr, msg){
if(!f._){
f._ = ('undefined'===typeof abort
? (msg)=>{throw new Error(msg)}
: abort);
}
++this.counter;
if(!this.toBool(expr)){
f._(msg || "Assertion failed.");
}
return this;
},
/** Identical to assert() but throws instead of calling
abort(). */
affirm: function(expr, msg){
++this.counter;
if(!this.toBool(expr)) throw new Error(msg || "Affirmation failed.");
return this;
},
/** Calls f() and squelches any exception it throws. If it
does not throw, this function throws. */
mustThrow: function(f, msg){
++this.counter;
let err;
try{ f(); } catch(e){err=e;}
if(!err) throw new Error(msg || "Expected exception.");
return this;
},
/** Throws if expr is truthy or expr is a function and expr()
returns truthy. */
throwIf: function(expr, msg){
++this.counter;
if(this.toBool(expr)) throw new Error(msg || "throwIf() failed");
return this;
},
/** Throws if expr is falsy or expr is a function and expr()
returns falsy. */
throwUnless: function(expr, msg){
++this.counter;
if(!this.toBool(expr)) throw new Error(msg || "throwUnless() failed");
return this;
}
};
/**
This is a module object for use with the emscripten-installed
initSqlite3Module() factory function.
*/
self.sqlite3TestModule = {
postRun: [
/* function(theModule){...} */
],
//onRuntimeInitialized: function(){},
/* Proxy for C-side stdout output. */
print: function(){
console.log.apply(console, Array.prototype.slice.call(arguments));
},
/* Proxy for C-side stderr output. */
printErr: function(){
console.error.apply(console, Array.prototype.slice.call(arguments));
},
/**
Called by the module init bits to report loading
progress. It gets passed an empty argument when loading is
done (after onRuntimeInitialized() and any this.postRun
callbacks have been run).
*/
setStatus: function f(text){
if(!f.last){
f.last = { text: '', step: 0 };
f.ui = {
status: E('#module-status'),
progress: E('#module-progress'),
spinner: E('#module-spinner')
};
}
if(text === f.last.text) return;
f.last.text = text;
if(f.ui.progress){
f.ui.progress.value = f.last.step;
f.ui.progress.max = f.last.step + 1;
}
++f.last.step;
if(text) {
f.ui.status.classList.remove('hidden');
f.ui.status.innerText = text;
}else{
if(f.ui.progress){
f.ui.progress.remove();
f.ui.spinner.remove();
delete f.ui.progress;
delete f.ui.spinner;
}
f.ui.status.classList.add('hidden');
}
}
};
})(self/*window or worker*/);
+24
View File
@@ -0,0 +1,24 @@
/* emcscript-related styling, used during the module load/intialization processes... */
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
#module-spinner { overflow: visible; }
#module-spinner > * {
margin-top: 1em;
}
.spinner {
height: 50px;
width: 50px;
margin: 0px auto;
animation: rotation 0.8s linear infinite;
border-left: 10px solid rgb(0,150,240);
border-right: 10px solid rgb(0,150,240);
border-bottom: 10px solid rgb(0,150,240);
border-top: 10px solid rgb(100,0,200);
border-radius: 100%;
background-color: rgb(200,100,250);
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
+301
View File
@@ -0,0 +1,301 @@
/*
2022-05-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.
***********************************************************************
This is the JS Worker file for the sqlite3 fiddle app. It loads the
sqlite3 wasm module and offers access to the db via the Worker
message-passing interface.
Forewarning: this API is still very much Under Construction and
subject to any number of changes as experience reveals what those
need to be.
Because we can have only a single message handler, as opposed to an
arbitrary number of discrete event listeners like with DOM elements,
we have to define a lower-level message API. Messages abstractly
look like:
{ type: string, data: type-specific value }
Where 'type' is used for dispatching and 'data' is a
'type'-dependent value.
The 'type' values expected by each side of the main/worker
connection vary. The types are described below but subject to
change at any time as this experiment evolves.
Workers-to-Main types
- stdout, stderr: indicate stdout/stderr output from the wasm
layer. The data property is the string of the output, noting
that the emscripten binding emits these one line at a time. Thus,
if a C-side puts() emits multiple lines in a single call, the JS
side will see that as multiple calls. Example:
{type:'stdout', data: 'Hi, world.'}
- module: Status text. This is intended to alert the main thread
about module loading status so that, e.g., the main thread can
update a progress widget and DTRT when the module is finished
loading and available for work. Status messages come in the form
{type:'module', data:{
type:'status',
data: {text:string|null, step:1-based-integer}
}
with an incrementing step value for each subsequent message. When
the module loading is complete, a message with a text value of
null is posted.
- working: data='start'|'end'. Indicates that work is about to be
sent to the module or has just completed. This can be used, e.g.,
to disable UI elements which should not be activated while work
is pending. Example:
{type:'working', data:'start'}
Main-to-Worker types:
- shellExec: data=text to execute as if it had been entered in the
sqlite3 CLI shell app (as opposed to sqlite3_exec()). This event
causes the worker to emit a 'working' event (data='start') before
it starts and a 'working' event (data='end') when it finished. If
called while work is currently being executed it emits stderr
message instead of doing actual work, as the underlying db cannot
handle concurrent tasks. Example:
{type:'shellExec', data: 'select * from sqlite_master'}
- More TBD as the higher-level db layer develops.
*/
/*
Apparent browser(s) bug: console messages emitted may be duplicated
in the console, even though they're provably only run once. See:
https://stackoverflow.com/questions/49659464
Noting that it happens in Firefox as well as Chrome. Harmless but
annoying.
*/
"use strict";
(function(){
/**
Posts a message in the form {type,data} unless passed more than 2
args, in which case it posts {type, data:[arg1...argN]}.
*/
const wMsg = function(type,data){
postMessage({
type,
data: arguments.length<3
? data
: Array.prototype.slice.call(arguments,1)
});
};
const stdout = function(){wMsg('stdout', Array.prototype.slice.call(arguments));};
const stderr = function(){wMsg('stderr', Array.prototype.slice.call(arguments));};
self.onerror = function(/*message, source, lineno, colno, error*/) {
const err = arguments[4];
if(err && 'ExitStatus'==err.name){
/* This is relevant for the sqlite3 shell binding but not the
lower-level binding. */
fiddleModule.isDead = true;
stderr("FATAL ERROR:", err.message);
stderr("Restarting the app requires reloading the page.");
wMsg('error', err);
}
console.error(err);
fiddleModule.setStatus('Exception thrown, see JavaScript console: '+err);
};
const Sqlite3Shell = {
/** Returns the name of the currently-opened db. */
dbFilename: function f(){
if(!f._) f._ = fiddleModule.cwrap('fiddle_db_filename', "string", ['string']);
return f._();
},
/**
Runs the given text through the shell as if it had been typed
in by a user. Fires a working/start event before it starts and
working/end event when it finishes.
*/
exec: function f(sql){
if(!f._) f._ = fiddleModule.cwrap('fiddle_exec', null, ['string']);
if(fiddleModule.isDead){
stderr("shell module has exit()ed. Cannot run SQL.");
return;
}
wMsg('working','start');
try {
if(f._running){
stderr('Cannot run multiple commands concurrently.');
}else{
f._running = true;
f._(sql);
}
} finally {
delete f._running;
wMsg('working','end');
}
},
resetDb: function f(){
if(!f._) f._ = fiddleModule.cwrap('fiddle_reset_db', null);
stdout("Resetting database.");
f._();
stdout("Reset",this.dbFilename());
},
/* Interrupt can't work: this Worker is tied up working, so won't get the
interrupt event which would be needed to perform the interrupt. */
interrupt: function f(){
if(!f._) f._ = fiddleModule.cwrap('fiddle_interrupt', null);
stdout("Requesting interrupt.");
f._();
}
};
self.onmessage = function f(ev){
ev = ev.data;
if(!f.cache){
f.cache = {
prevFilename: null
};
}
//console.debug("worker: onmessage.data",ev);
switch(ev.type){
case 'shellExec': Sqlite3Shell.exec(ev.data); return;
case 'db-reset': Sqlite3Shell.resetDb(); return;
case 'interrupt': Sqlite3Shell.interrupt(); return;
/** Triggers the export of the current db. Fires an
event in the form:
{type:'db-export',
data:{
filename: name of db,
buffer: contents of the db file (Uint8Array),
error: on error, a message string and no buffer property.
}
}
*/
case 'db-export': {
const fn = Sqlite3Shell.dbFilename();
stdout("Exporting",fn+".");
const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
try{
if(!fn2) throw new Error("DB appears to be closed.");
wMsg('db-export',{
filename: fn2,
buffer: fiddleModule.FS.readFile(fn, {encoding:"binary"})
});
}catch(e){
/* Post a failure message so that UI elements disabled
during the export can be re-enabled. */
wMsg('db-export',{
filename: fn,
error: e.message
});
}
return;
}
case 'open': {
/* Expects: {
buffer: ArrayBuffer | Uint8Array,
filename: for logging/informational purposes only
} */
const opt = ev.data;
let buffer = opt.buffer;
if(buffer instanceof Uint8Array){
}else if(buffer instanceof ArrayBuffer){
buffer = new Uint8Array(buffer);
}else{
stderr("'open' expects {buffer:Uint8Array} containing an uploaded db.");
return;
}
const fn = (
opt.filename
? opt.filename.split(/[/\\]/).pop().replace('"','_')
: ("db-"+((Math.random() * 10000000) | 0)+
"-"+((Math.random() * 10000000) | 0)+".sqlite3")
);
/* We cannot delete the existing db file until the new one
is installed, which means that we risk overflowing our
quota (if any) by having both the previous and current
db briefly installed in the virtual filesystem. */
fiddleModule.FS.createDataFile("/", fn, buffer, true, true);
const oldName = Sqlite3Shell.dbFilename();
Sqlite3Shell.exec('.open "/'+fn+'"');
if(oldName && oldName !== fn){
try{fiddleModule.FS.unlink(oldName);}
catch(e){/*ignored*/}
}
stdout("Replaced DB with",fn+".");
return;
}
};
console.warn("Unknown fiddle-worker message type:",ev);
};
/**
emscripten module for use with build mode -sMODULARIZE.
*/
const fiddleModule = {
print: stdout,
printErr: stderr,
/**
Intercepts status updates from the emscripting module init
and fires worker events with a type of 'status' and a
payload of:
{
text: string | null, // null at end of load process
step: integer // starts at 1, increments 1 per call
}
We have no way of knowing in advance how many steps will
be processed/posted, so creating a "percentage done" view is
not really practical. One can be approximated by giving it a
current value of message.step and max value of message.step+1,
though.
When work is finished, a message with a text value of null is
submitted.
After a message with text==null is posted, the module may later
post messages about fatal problems, e.g. an exit() being
triggered, so it is recommended that UI elements for posting
status messages not be outright removed from the DOM when
text==null, and that they instead be hidden until/unless
text!=null.
*/
setStatus: function f(text){
if(!f.last) f.last = { step: 0, text: '' };
else if(text === f.last.text) return;
f.last.text = text;
wMsg('module',{
type:'status',
data:{step: ++f.last.step, text: text||null}
});
}
};
importScripts('fiddle-module.js');
/**
initFiddleModule() is installed via fiddle-module.js due to
building with:
emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule
*/
initFiddleModule(fiddleModule).then(function(thisModule){
wMsg('fiddle-ready');
});
})();
+283
View File
@@ -0,0 +1,283 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>SQLite3 Fiddle</title>
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<!-- to add a togglable terminal-style view, uncomment the following
two lines and ensure that these files are on the web server. -->
<!--script src="jqterm/jqterm-bundle.min.js"></script>
<link rel="stylesheet" href="jqterm/jquery.terminal.min.css"/-->
<link rel="stylesheet" href="emscripten.css"/>
<style>
/* The following styles are for app-level use. */
:root {
--sqlite-blue: #044a64;
--textarea-color1: #044a64;
--textarea-color2: white;
}
textarea {
font-family: monospace;
flex: 1 1 auto;
background-color: var(--textarea-color1);
color: var(--textarea-color2);
}
textarea#input {
color: var(--textarea-color1);
background-color: var(--textarea-color2);
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--sqlite-blue);
color: white;
font-size: 120%;
font-weight: bold;
border-radius: 0.25em;
padding: 0.2em 0.5em;
}
header > .powered-by {
font-size: 80%;
}
header a, header a:visited, header a:hover {
color: inherit;
}
#main-wrapper {
display: flex;
flex-direction: column-reverse;
flex: 1 1 auto;
margin: 0.5em 0;
overflow: hidden;
}
#main-wrapper.side-by-side {
flex-direction: row;
}
#main-wrapper.side-by-side > fieldset {
margin-left: 0.25em;
margin-right: 0.25em;
}
#main-wrapper:not(.side-by-side) > fieldset {
margin-bottom: 0.25em;
}
#main-wrapper.swapio {
flex-direction: column;
}
#main-wrapper.side-by-side.swapio {
flex-direction: row-reverse;
}
.zone-wrapper{
display: flex;
margin: 0;
flex: 1 1 0%;
border-radius: 0.5em;
min-width: inherit/*important: resolves inability to scroll fieldset child element!*/;
padding: 0.35em 0 0 0;
}
.zone-wrapper textarea {
border-radius: 0.5em;
flex: 1 1 auto;
/*min/max width resolve an inexplicable margin on the RHS. The -1em
is for the padding, else we overlap the parent boundaries.*/
/*min-width: calc(100% - 1em);
max-width: calc(100% - 1em);
padding: 0 0.5em;*/
}
.zone-wrapper.input { flex: 10 1 auto; }
.zone-wrapper.output { flex: 20 1 auto; }
.zone-wrapper > div {
display:flex;
flex: 1 1 0%;
}
.zone-wrapper.output {}
.button-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
align-content: space-between;
justify-content: flex-start;
}
.button-bar > * {
margin: 0.05em 0.5em 0.05em 0;
flex: 0 1 auto;
align-self: auto;
}
label[for] {
cursor: pointer;
}
.error {
color: red;
background-color: yellow;
}
.hidden, .initially-hidden {
position: absolute !important;
opacity: 0 !important;
pointer-events: none !important;
display: none !important;
}
fieldset {
border-radius: 0.5em;
border: 1px inset;
padding: 0.25em;
}
fieldset.options {
font-size: 80%;
margin-top: 0.5em;
}
fieldset:not(.options) > legend {
font-size: 80%;
}
fieldset.options > div {
display: flex;
flex-wrap: wrap;
}
fieldset button {
font-size: inherit;
}
fieldset.collapsible > legend > .fieldset-toggle::after {
content: " [hide]";
position: relative;
}
fieldset.collapsible.collapsed > legend > .fieldset-toggle::after {
content: " [show]";
position: relative;
}
span.labeled-input {
padding: 0.25em;
margin: 0.05em 0.25em;
border-radius: 0.25em;
white-space: nowrap;
background: #0002;
display: flex;
align-items: center;
}
span.labeled-input > *:nth-child(2) {
margin-left: 0.3em;
}
.center { text-align: center; }
body.terminal-mode {
max-height: calc(100% - 2em);
display: flex;
flex-direction: column;
align-items: stretch;
}
#view-terminal {}
.app-view {
flex: 20 1 auto;
}
#view-split {
display: flex;
flex-direction: column-reverse;
}
</style>
</head>
<body>
<header id='titlebar'>
<span>SQLite3 Fiddle</span>
<span class='powered-by'>Powered by
<a href='https://sqlite.org'>SQLite3</a></span>
</header>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<div id='view-terminal' class='app-view hidden initially-hidden'>
This is a placeholder for a terminal-like view which is not in
the default build.
</div>
<div id='view-split' class='app-view initially-hidden'>
<fieldset class='options collapsible'>
<legend><button class='fieldset-toggle'>Options</button></legend>
<div class=''>
<span class='labeled-input'>
<input type='checkbox' id='opt-cb-sbs'
data-csstgt='#main-wrapper'
data-cssclass='side-by-side'
data-config='sideBySide'>
<label for='opt-cb-sbs'>Side-by-side</label>
</span>
<span class='labeled-input'>
<input type='checkbox' id='opt-cb-swapio'
data-csstgt='#main-wrapper'
data-cssclass='swapio'
data-config='swapInOut'>
<label for='opt-cb-swapio'>Swap in/out</label>
</span>
<span class='labeled-input'>
<input type='checkbox' id='opt-cb-autoscroll'
data-config='autoScrollOutput'>
<label for='opt-cb-autoscroll'>Auto-scroll output</label>
</span>
<span class='labeled-input'>
<input type='checkbox' id='opt-cb-autoclear'
data-config='autoClearOutput'>
<label for='opt-cb-autoclear'>Auto-clear output</label>
</span>
<span class='labeled-input'>
<input type='file' id='load-db' class='hidden'/>
<button id='btn-load-db'>Load DB...</button>
</span>
<span class='labeled-input'>
<button id='btn-export'>Download DB</button>
</span>
<span class='labeled-input'>
<button id='btn-reset'>Reset DB</button>
</span>
</div>
</fieldset><!-- .options -->
<div id='main-wrapper' class=''>
<fieldset class='zone-wrapper input'>
<legend><div class='button-bar'>
<button id='btn-shell-exec'>Run</button>
<button id='btn-clear'>Clear Input</button>
<!--button data-cmd='.help'>Help</button-->
<select id='select-examples'></select>
</div></legend>
<div><textarea id="input"
placeholder="Shell input. Ctrl-enter/shift-enter runs it.">
-- ==================================================
-- Use ctrl-enter or shift-enter to execute sqlite3
-- shell commands and SQL.
-- If a subset of the text is currently selected,
-- only that part is executed.
-- ==================================================
.nullvalue NULL
.headers on
</textarea></div>
</fieldset>
<fieldset class='zone-wrapper output'>
<legend><div class='button-bar'>
<button id='btn-clear-output'>Clear Output</button>
<button id='btn-interrupt' class='hidden' disabled>Interrupt</button>
<!-- interruption cannot work in the current configuration
because we cannot send an interrupt message when work
is currently underway. At that point the Worker is
tied up and will not receive the message. -->
</div></legend>
<div><textarea id="output" readonly
placeholder="Shell output."></textarea></div>
</fieldset>
</div>
</div> <!-- #view-split -->
<!-- Maintenance notes:
... TODO... currently being refactored...
-->
<script src="fiddle.js"></script>
</body>
</html>
+809
View File
@@ -0,0 +1,809 @@
/*
2022-05-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.
***********************************************************************
This is the main entry point for the sqlite3 fiddle app. It sets up the
various UI bits, loads a Worker for the db connection, and manages the
communication between the UI and worker.
*/
(function(){
'use strict';
/* Recall that the 'self' symbol, except where locally
overwritten, refers to the global window or worker object. */
const storage = (function(NS/*namespace object in which to store this module*/){
/* Pedantic licensing note: this code originated in the Fossil SCM
source tree, where it has a different license, but the person who
ported it into sqlite is the same one who wrote it for fossil. */
'use strict';
NS = NS||{};
/**
This module provides a basic wrapper around localStorage
or sessionStorage or a dummy proxy object if neither
of those are available.
*/
const tryStorage = function f(obj){
if(!f.key) f.key = 'storage.access.check';
try{
obj.setItem(f.key, 'f');
const x = obj.getItem(f.key);
obj.removeItem(f.key);
if(x!=='f') throw new Error(f.key+" failed")
return obj;
}catch(e){
return undefined;
}
};
/** Internal storage impl for this module. */
const $storage =
tryStorage(window.localStorage)
|| tryStorage(window.sessionStorage)
|| tryStorage({
// A basic dummy xyzStorage stand-in
$$$:{},
setItem: function(k,v){this.$$$[k]=v},
getItem: function(k){
return this.$$$.hasOwnProperty(k) ? this.$$$[k] : undefined;
},
removeItem: function(k){delete this.$$$[k]},
clear: function(){this.$$$={}}
});
/**
For the dummy storage we need to differentiate between
$storage and its real property storage for hasOwnProperty()
to work properly...
*/
const $storageHolder = $storage.hasOwnProperty('$$$') ? $storage.$$$ : $storage;
/**
A prefix which gets internally applied to all storage module
property keys so that localStorage and sessionStorage across the
same browser profile instance do not "leak" across multiple apps
being hosted by the same origin server. Such cross-polination is
still there but, with this key prefix applied, it won't be
immediately visible via the storage API.
With this in place we can justify using localStorage instead of
sessionStorage.
One implication of using localStorage and sessionStorage is that
their scope (the same "origin" and client application/profile)
allows multiple apps on the same origin to use the same
storage. Thus /appA/foo could then see changes made via
/appB/foo. The data do not cross user- or browser boundaries,
though, so it "might" arguably be called a
feature. storageKeyPrefix was added so that we can sandbox that
state for each separate app which shares an origin.
See: https://fossil-scm.org/forum/forumpost/4afc4d34de
Sidebar: it might seem odd to provide a key prefix and stick all
properties in the topmost level of the storage object. We do that
because adding a layer of object to sandbox each app would mean
(de)serializing that whole tree on every storage property change.
e.g. instead of storageObject.projectName.foo we have
storageObject[storageKeyPrefix+'foo']. That's soley for
efficiency's sake (in terms of battery life and
environment-internal storage-level effort).
*/
const storageKeyPrefix = (
$storageHolder===$storage/*localStorage or sessionStorage*/
? (
(NS.config ?
(NS.config.projectCode || NS.config.projectName
|| NS.config.shortProjectName)
: false)
|| window.location.pathname
)+'::' : (
'' /* transient storage */
)
);
/**
A proxy for localStorage or sessionStorage or a
page-instance-local proxy, if neither one is availble.
Which exact storage implementation is uses is unspecified, and
apps must not rely on it.
*/
NS.storage = {
storageKeyPrefix: storageKeyPrefix,
/** Sets the storage key k to value v, implicitly converting
it to a string. */
set: (k,v)=>$storage.setItem(storageKeyPrefix+k,v),
/** Sets storage key k to JSON.stringify(v). */
setJSON: (k,v)=>$storage.setItem(storageKeyPrefix+k,JSON.stringify(v)),
/** Returns the value for the given storage key, or
dflt if the key is not found in the storage. */
get: (k,dflt)=>$storageHolder.hasOwnProperty(
storageKeyPrefix+k
) ? $storage.getItem(storageKeyPrefix+k) : dflt,
/** Returns true if the given key has a value of "true". If the
key is not found, it returns true if the boolean value of dflt
is "true". (Remember that JS persistent storage values are all
strings.) */
getBool: function(k,dflt){
return 'true'===this.get(k,''+(!!dflt));
},
/** Returns the JSON.parse()'d value of the given
storage key's value, or dflt is the key is not
found or JSON.parse() fails. */
getJSON: function f(k,dflt){
try {
const x = this.get(k,f);
return x===f ? dflt : JSON.parse(x);
}
catch(e){return dflt}
},
/** Returns true if the storage contains the given key,
else false. */
contains: (k)=>$storageHolder.hasOwnProperty(storageKeyPrefix+k),
/** Removes the given key from the storage. Returns this. */
remove: function(k){
$storage.removeItem(storageKeyPrefix+k);
return this;
},
/** Clears ALL keys from the storage. Returns this. */
clear: function(){
this.keys().forEach((k)=>$storage.removeItem(/*w/o prefix*/k));
return this;
},
/** Returns an array of all keys currently in the storage. */
keys: ()=>Object.keys($storageHolder).filter((v)=>(v||'').startsWith(storageKeyPrefix)),
/** Returns true if this storage is transient (only available
until the page is reloaded), indicating that fileStorage
and sessionStorage are unavailable. */
isTransient: ()=>$storageHolder!==$storage,
/** Returns a symbolic name for the current storage mechanism. */
storageImplName: function(){
if($storage===window.localStorage) return 'localStorage';
else if($storage===window.sessionStorage) return 'sessionStorage';
else return 'transient';
},
/**
Returns a brief help text string for the currently-selected
storage type.
*/
storageHelpDescription: function(){
return {
localStorage: "Browser-local persistent storage with an "+
"unspecified long-term lifetime (survives closing the browser, "+
"but maybe not a browser upgrade).",
sessionStorage: "Storage local to this browser tab, "+
"lost if this tab is closed.",
"transient": "Transient storage local to this invocation of this page."
}[this.storageImplName()];
}
};
return NS.storage;
})({})/*storage API setup*/;
/** Name of the stored copy of SqliteFiddle.config. */
const configStorageKey = 'sqlite3-fiddle-config';
/**
The SqliteFiddle object is intended to be the primary
app-level object for the main-thread side of the sqlite
fiddle application. It uses a worker thread to load the
sqlite WASM module and communicate with it.
*/
const SF/*local convenience alias*/
= window.SqliteFiddle/*canonical name*/ = {
/* Config options. */
config: {
/* If true, SqliteFiddle.echo() will auto-scroll the
output widget to the bottom when it receives output,
else it won't. */
autoScrollOutput: true,
/* If true, the output area will be cleared before each
command is run, else it will not. */
autoClearOutput: false,
/* If true, SqliteFiddle.echo() will echo its output to
the console, in addition to its normal output widget.
That slows it down but is useful for testing. */
echoToConsole: false,
/* If true, display input/output areas side-by-side. */
sideBySide: true,
/* If true, swap positions of the input/output areas. */
swapInOut: false
},
/**
Emits the given text, followed by a line break, to the
output widget. If given more than one argument, they are
join()'d together with a space between each. As a special
case, if passed a single array, that array is used in place
of the arguments array (this is to facilitate receiving
lists of arguments via worker events).
*/
echo: function f(text) {
/* Maintenance reminder: we currently require/expect a textarea
output element. It might be nice to extend this to behave
differently if the output element is a non-textarea element,
in which case it would need to append the given text as a TEXT
node and add a line break. */
if(!f._){
f._ = document.getElementById('output');
f._.value = ''; // clear browser cache
}
if(arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
else if(1===arguments.length && Array.isArray(text)) text = text.join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
if(null===text){/*special case: clear output*/
f._.value = '';
return;
}else if(this.echo._clearPending){
delete this.echo._clearPending;
f._.value = '';
}
if(this.config.echoToConsole) console.log(text);
if(this.jqTerm) this.jqTerm.echo(text);
f._.value += text + "\n";
if(this.config.autoScrollOutput){
f._.scrollTop = f._.scrollHeight;
}
},
_msgMap: {},
/** Adds a worker message handler for messages of the given
type. */
addMsgHandler: function f(type,callback){
if(Array.isArray(type)){
type.forEach((t)=>this.addMsgHandler(t, callback));
return this;
}
(this._msgMap.hasOwnProperty(type)
? this._msgMap[type]
: (this._msgMap[type] = [])).push(callback);
return this;
},
/** Given a worker message, runs all handlers for msg.type. */
runMsgHandlers: function(msg){
const list = (this._msgMap.hasOwnProperty(msg.type)
? this._msgMap[msg.type] : false);
if(!list){
console.warn("No handlers found for message type:",msg);
return false;
}
//console.debug("runMsgHandlers",msg);
list.forEach((f)=>f(msg));
return true;
},
/** Removes all message handlers for the given message type. */
clearMsgHandlers: function(type){
delete this._msgMap[type];
return this;
},
/* Posts a message in the form {type, data} to the db worker. Returns this. */
wMsg: function(type,data){
this.worker.postMessage({type, data});
return this;
},
/**
Prompts for confirmation and, if accepted, deletes
all content and tables in the (transient) database.
*/
resetDb: function(){
if(window.confirm("Really destroy all content and tables "
+"in the (transient) db?")){
this.wMsg('db-reset');
}
return this;
},
/** Stores this object's config in the browser's storage. */
storeConfig: function(){
storage.setJSON(configStorageKey,this.config);
}
};
if(1){ /* Restore SF.config */
const storedConfig = storage.getJSON(configStorageKey);
if(storedConfig){
/* Copy all properties to SF.config which are currently in
storedConfig. We don't bother copying any other
properties: those have been removed from the app in the
meantime. */
Object.keys(SF.config).forEach(function(k){
if(storedConfig.hasOwnProperty(k)){
SF.config[k] = storedConfig[k];
}
});
}
}
SF.worker = new Worker('fiddle-worker.js');
SF.worker.onmessage = (ev)=>SF.runMsgHandlers(ev.data);
SF.addMsgHandler(['stdout', 'stderr'], (ev)=>SF.echo(ev.data));
/* querySelectorAll() proxy */
const EAll = function(/*[element=document,] cssSelector*/){
return (arguments.length>1 ? arguments[0] : document)
.querySelectorAll(arguments[arguments.length-1]);
};
/* querySelector() proxy */
const E = function(/*[element=document,] cssSelector*/){
return (arguments.length>1 ? arguments[0] : document)
.querySelector(arguments[arguments.length-1]);
};
/** Handles status updates from the Module object. */
SF.addMsgHandler('module', function f(ev){
ev = ev.data;
if('status'!==ev.type){
console.warn("Unexpected module-type message:",ev);
return;
}
if(!f.ui){
f.ui = {
status: E('#module-status'),
progress: E('#module-progress'),
spinner: E('#module-spinner')
};
}
const msg = ev.data;
if(f.ui.progres){
progress.value = msg.step;
progress.max = msg.step + 1/*we don't know how many steps to expect*/;
}
if(1==msg.step){
f.ui.progress.classList.remove('hidden');
f.ui.spinner.classList.remove('hidden');
}
if(msg.text){
f.ui.status.classList.remove('hidden');
f.ui.status.innerText = msg.text;
}else{
if(f.ui.progress){
f.ui.progress.remove();
f.ui.spinner.remove();
delete f.ui.progress;
delete f.ui.spinner;
}
f.ui.status.classList.add('hidden');
/* The module can post messages about fatal problems,
e.g. an exit() being triggered or assertion failure,
after the last "load" message has arrived, so
leave f.ui.status and message listener intact. */
}
});
/**
The 'fiddle-ready' event is fired (with no payload) when the
wasm module has finished loading. Interestingly, that happens
_before_ the final module:status event */
SF.addMsgHandler('fiddle-ready', function(){
SF.clearMsgHandlers('fiddle-ready');
self.onSFLoaded();
});
/**
Performs all app initialization which must wait until after the
worker module is loaded. This function removes itself when it's
called.
*/
self.onSFLoaded = function(){
delete this.onSFLoaded;
// Unhide all elements which start out hidden
EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
E('#btn-reset').addEventListener('click',()=>SF.resetDb());
const taInput = E('#input');
const btnClearIn = E('#btn-clear');
btnClearIn.addEventListener('click',function(){
taInput.value = '';
},false);
// Ctrl-enter and shift-enter both run the current SQL.
taInput.addEventListener('keydown',function(ev){
if((ev.ctrlKey || ev.shiftKey) && 13 === ev.keyCode){
ev.preventDefault();
ev.stopPropagation();
btnShellExec.click();
}
}, false);
const taOutput = E('#output');
const btnClearOut = E('#btn-clear-output');
btnClearOut.addEventListener('click',function(){
taOutput.value = '';
if(SF.jqTerm) SF.jqTerm.clear();
},false);
const btnShellExec = E('#btn-shell-exec');
btnShellExec.addEventListener('click',function(ev){
let sql;
ev.preventDefault();
if(taInput.selectionStart<taInput.selectionEnd){
sql = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
}else{
sql = taInput.value.trim();
}
if(sql) SF.dbExec(sql);
},false);
const btnInterrupt = E("#btn-interrupt");
//btnInterrupt.classList.add('hidden');
/** To be called immediately before work is sent to the
worker. Updates some UI elements. The 'working'/'end'
event will apply the inverse, undoing the bits this
function does. This impl is not in the 'working'/'start'
event handler because that event is given to us
asynchronously _after_ we need to have performed this
work.
*/
const preStartWork = function f(){
if(!f._){
const title = E('title');
f._ = {
btnLabel: btnShellExec.innerText,
pageTitle: title,
pageTitleOrig: title.innerText
};
}
f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig;
btnShellExec.setAttribute('disabled','disabled');
btnInterrupt.removeAttribute('disabled','disabled');
};
/* Sends the given text to the db module to evaluate as if it
had been entered in the sqlite3 CLI shell. If it's null or
empty, this is a no-op except that the very first call will
initialize the db and output an informational header. */
SF.dbExec = function f(sql){
if(this.config.autoClearOutput){
this.echo._clearPending = true;
}
preStartWork();
this.wMsg('shellExec',sql);
};
SF.addMsgHandler('working',function f(ev){
switch(ev.data){
case 'start': /* See notes in preStartWork(). */; return;
case 'end':
preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig;
btnShellExec.innerText = preStartWork._.btnLabel;
btnShellExec.removeAttribute('disabled');
btnInterrupt.setAttribute('disabled','disabled');
return;
}
console.warn("Unhandled 'working' event:",ev.data);
});
/* For each checkbox with data-csstgt, set up a handler which
toggles the given CSS class on the element matching
E(data-csstgt). */
EAll('input[type=checkbox][data-csstgt]')
.forEach(function(e){
const tgt = E(e.dataset.csstgt);
const cssClass = e.dataset.cssclass || 'error';
e.checked = tgt.classList.contains(cssClass);
e.addEventListener('change', function(){
tgt.classList[
this.checked ? 'add' : 'remove'
](cssClass)
}, false);
});
/* For each checkbox with data-config=X, set up a binding to
SF.config[X]. These must be set up AFTER data-csstgt
checkboxes so that those two states can be synced properly. */
EAll('input[type=checkbox][data-config]')
.forEach(function(e){
const confVal = !!SF.config[e.dataset.config];
if(e.checked !== confVal){
/* Ensure that data-csstgt mappings (if any) get
synced properly. */
e.checked = confVal;
e.dispatchEvent(new Event('change'));
}
e.addEventListener('change', function(){
SF.config[this.dataset.config] = this.checked;
SF.storeConfig();
}, false);
});
/* For each button with data-cmd=X, map a click handler which
calls SF.dbExec(X). */
const cmdClick = function(){SF.dbExec(this.dataset.cmd);};
EAll('button[data-cmd]').forEach(
e => e.addEventListener('click', cmdClick, false)
);
btnInterrupt.addEventListener('click',function(){
SF.wMsg('interrupt');
});
/** Initiate a download of the db. */
const btnExport = E('#btn-export');
const eLoadDb = E('#load-db');
const btnLoadDb = E('#btn-load-db');
btnLoadDb.addEventListener('click', ()=>eLoadDb.click());
/**
Enables (if passed true) or disables all UI elements which
"might," if timed "just right," interfere with an
in-progress db import/export/exec operation.
*/
const enableMutatingElements = function f(enable){
if(!f._elems){
f._elems = [
/* UI elements to disable while import/export are
running. Normally the export is fast enough
that this won't matter, but we really don't
want to be reading (from outside of sqlite) the
db when the user taps btnShellExec. */
btnShellExec, btnExport, eLoadDb
];
}
f._elems.forEach( enable
? (e)=>e.removeAttribute('disabled')
: (e)=>e.setAttribute('disabled','disabled') );
};
btnExport.addEventListener('click',function(){
enableMutatingElements(false);
SF.wMsg('db-export');
});
SF.addMsgHandler('db-export', function(ev){
enableMutatingElements(true);
ev = ev.data;
if(ev.error){
SF.echo("Export failed:",ev.error);
return;
}
const blob = new Blob([ev.buffer], {type:"application/x-sqlite3"});
const a = document.createElement('a');
document.body.appendChild(a);
a.href = window.URL.createObjectURL(blob);
a.download = ev.filename;
a.addEventListener('click',function(){
setTimeout(function(){
SF.echo("Exported (possibly auto-downloaded):",ev.filename);
window.URL.revokeObjectURL(a.href);
a.remove();
},500);
});
a.click();
});
/**
Handle load/import of an external db file.
*/
eLoadDb.addEventListener('change',function(){
const f = this.files[0];
const r = new FileReader();
const status = {loaded: 0, total: 0};
enableMutatingElements(false);
r.addEventListener('loadstart', function(){
SF.echo("Loading",f.name,"...");
});
r.addEventListener('progress', function(ev){
SF.echo("Loading progress:",ev.loaded,"of",ev.total,"bytes.");
});
const that = this;
r.addEventListener('load', function(){
enableMutatingElements(true);
SF.echo("Loaded",f.name+". Opening db...");
SF.wMsg('open',{
filename: f.name,
buffer: this.result
});
});
r.addEventListener('error',function(){
enableMutatingElements(true);
SF.echo("Loading",f.name,"failed for unknown reasons.");
});
r.addEventListener('abort',function(){
enableMutatingElements(true);
SF.echo("Cancelled loading of",f.name+".");
});
r.readAsArrayBuffer(f);
});
EAll('fieldset.collapsible').forEach(function(fs){
const btnToggle = E(fs,'legend > .fieldset-toggle'),
content = EAll(fs,':scope > div');
btnToggle.addEventListener('click', function(){
fs.classList.toggle('collapsed');
content.forEach((d)=>d.classList.toggle('hidden'));
}, false);
});
/**
Given a DOM element, this routine measures its "effective
height", which is the bounding top/bottom range of this element
and all of its children, recursively. For some DOM structure
cases, a parent may have a reported height of 0 even though
children have non-0 sizes.
Returns 0 if !e or if the element really has no height.
*/
const effectiveHeight = function f(e){
if(!e) return 0;
if(!f.measure){
f.measure = function callee(e, depth){
if(!e) return;
const m = e.getBoundingClientRect();
if(0===depth){
callee.top = m.top;
callee.bottom = m.bottom;
}else{
callee.top = m.top ? Math.min(callee.top, m.top) : callee.top;
callee.bottom = Math.max(callee.bottom, m.bottom);
}
Array.prototype.forEach.call(e.children,(e)=>callee(e,depth+1));
if(0===depth){
//console.debug("measure() height:",e.className, callee.top, callee.bottom, (callee.bottom - callee.top));
f.extra += callee.bottom - callee.top;
}
return f.extra;
};
}
f.extra = 0;
f.measure(e,0);
return f.extra;
};
/**
Returns a function, that, as long as it continues to be invoked,
will not be triggered. The function will be called after it stops
being called for N milliseconds. If `immediate` is passed, call
the callback immediately and hinder future invocations until at
least the given time has passed.
If passed only 1 argument, or passed a falsy 2nd argument,
the default wait time set in this function's $defaultDelay
property is used.
Source: underscore.js, by way of https://davidwalsh.name/javascript-debounce-function
*/
const debounce = function f(func, wait, immediate) {
var timeout;
if(!wait) wait = f.$defaultDelay;
return function() {
const context = this, args = Array.prototype.slice.call(arguments);
const later = function() {
timeout = undefined;
if(!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow) func.apply(context, args);
};
};
debounce.$defaultDelay = 500 /*arbitrary*/;
const ForceResizeKludge = (function(){
/* Workaround for Safari mayhem regarding use of vh CSS
units.... We cannot use vh units to set the main view
size because Safari chokes on that, so we calculate
that height here. Larger than ~95% is too big for
Firefox on Android, causing the input area to move
off-screen. */
const appViews = EAll('.app-view');
const elemsToCount = [
/* Elements which we need to always count in the
visible body size. */
E('body > header'),
E('body > footer')
];
const resized = function f(){
if(f.$disabled) return;
const wh = window.innerHeight;
var ht;
var extra = 0;
elemsToCount.forEach((e)=>e ? extra += effectiveHeight(e) : false);
ht = wh - extra;
appViews.forEach(function(e){
e.style.height =
e.style.maxHeight = [
"calc(", (ht>=100 ? ht : 100), "px",
" - 2em"/*fudge value*/,")"
/* ^^^^ hypothetically not needed, but both
Chrome/FF on Linux will force scrollbars on the
body if this value is too small. */
].join('');
});
};
resized.$disabled = true/*gets deleted when setup is finished*/;
window.addEventListener('resize', debounce(resized, 250), false);
return resized;
})();
/** Set up a selection list of examples */
(function(){
const xElem = E('#select-examples');
const examples = [
{name: "Help", sql:
`-- ================================================
-- Use ctrl-enter or shift-enter to execute sqlite3
-- shell commands and SQL.
-- If a subset of the text is currently selected,
-- only that part is executed.
-- ================================================
.help`},
{name: "Timer on", sql: ".timer on"},
{name: "Setup table T", sql:`.nullvalue NULL
CREATE TABLE t(a,b);
INSERT INTO t(a,b) VALUES('abc',123),('def',456),(NULL,789),('ghi',012);
SELECT * FROM t;`},
{name: "Table list", sql: ".tables"},
{name: "Box Mode", sql: ".mode box"},
{name: "JSON Mode", sql: ".mode json"},
{name: "Mandlebrot", sql: `WITH RECURSIVE
xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),
yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),
m(iter, cx, cy, x, y) AS (
SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis
UNION ALL
SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m
WHERE (x*x + y*y) < 4.0 AND iter<28
),
m2(iter, cx, cy) AS (
SELECT max(iter), cx, cy FROM m GROUP BY cx, cy
),
a(t) AS (
SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '')
FROM m2 GROUP BY cy
)
SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;`}
];
const newOpt = function(lbl,val){
const o = document.createElement('option');
o.value = val;
if(!val) o.setAttribute('disabled',true);
o.appendChild(document.createTextNode(lbl));
xElem.appendChild(o);
};
newOpt("Examples (replaces input!)");
examples.forEach((o)=>newOpt(o.name, o.sql));
//xElem.setAttribute('disabled',true);
xElem.selectedIndex = 0;
xElem.addEventListener('change', function(){
taInput.value = '-- ' +
this.selectedOptions[0].innerText +
'\n' + this.value;
SF.dbExec(this.value);
});
})()/* example queries */;
SF.echo(null/*clear any output generated by the init process*/);
if(window.jQuery && window.jQuery.terminal){
/* Set up the terminal-style view... */
const eTerm = window.jQuery('#view-terminal').empty();
SF.jqTerm = eTerm.terminal(SF.dbExec.bind(SF),{
prompt: 'sqlite> ',
greetings: false /* note that the docs incorrectly call this 'greeting' */
});
/* Set up a button to toggle the views... */
const head = E('header#titlebar');
const btnToggleView = document.createElement('button');
btnToggleView.appendChild(document.createTextNode("Toggle View"));
head.appendChild(btnToggleView);
btnToggleView.addEventListener('click',function f(){
EAll('.app-view').forEach(e=>e.classList.toggle('hidden'));
if(document.body.classList.toggle('terminal-mode')){
ForceResizeKludge();
}
}, false);
btnToggleView.click()/*default to terminal view*/;
}
SF.dbExec(null/*init the db and output the header*/);
SF.echo('This experimental app is provided in the hope that it',
'may prove interesting or useful but is not an officially',
'supported deliverable of the sqlite project. It is subject to',
'any number of changes or outright removal at any time.\n');
delete ForceResizeKludge.$disabled;
ForceResizeKludge();
btnShellExec.click();
}/*onSFLoaded()*/;
})();
+94
View File
@@ -0,0 +1,94 @@
This directory houses a "fiddle"-style application which embeds a
[Web Assembly (WASM)](https://en.wikipedia.org/wiki/WebAssembly)
build of the sqlite3 shell app into an HTML page, effectively running
the shell in a client-side browser.
It requires [emscripten][] and that the build environment be set up for
emscripten. A mini-HOWTO for setting that up follows...
First, install the Emscripten SDK, as documented
[here](https://emscripten.org/docs/getting_started/downloads.html) and summarized
below for Linux environments:
```
# Clone the emscripten repository:
$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk
# Download and install the latest SDK tools:
$ ./emsdk install latest
# Make the "latest" SDK "active" for the current user:
$ ./emsdk activate latest
```
Those parts only need to be run once. The following needs to be run for each
shell instance which needs the `emcc` compiler:
```
# Activate PATH and other environment variables in the current terminal:
$ source ./emsdk_env.sh
$ which emcc
/path/to/emsdk/upstream/emscripten/emcc
```
That `env` script needs to be sourced for building this application from the
top of the sqlite3 build tree:
```
$ make fiddle
```
Or:
```
$ cd ext/fiddle
$ make
```
That will generate the fiddle application under
[ext/fiddle](/dir/ext/fiddle), as `fiddle.html`. That application
cannot, due to XMLHttpRequest security limitations, run if the HTML
file is opened directly in the browser (i.e. if it is opened using a
`file://` URL), so it needs to be served via an HTTP server. For
example, using [althttpd][]:
```
$ cd ext/fiddle
$ althttpd -debug 1 -jail 0 -port 9090 -root .
```
Then browse to `http://localhost:9090/fiddle.html`.
Note that when serving this app via [althttpd][], it must be a version
from 2022-05-17 or newer so that it recognizes the `.wasm` file
extension and responds with the mimetype `application/wasm`, as the
WASM loader is pedantic about that detail.
# Known Quirks and Limitations
Some "impedence mismatch" between C and WASM/JavaScript is to be
expected.
## No I/O
sqlite3 shell commands which require file I/O or pipes are disabled in
the WASM build.
## `exit()` Triggered from C
When C code calls `exit()`, as happens (for example) when running an
"unsafe" command when safe mode is active, WASM's connection to the
sqlite3 shell environment has no sensible choice but to shut down
because `exit()` leaves it in a state we can no longer recover
from. The JavaScript-side application attempts to recognize this and
warn the user that restarting the application is necessary. Currently
the only way to restart it is to reload the page. Restructuring the
shell code such that it could be "rebooted" without restarting the
JS app would require some invasive changes which are not currently
on any TODO list but have not been entirely ruled out long-term.
[emscripten]: https://emscripten.org
[althttpd]: https://sqlite.org/althttpd
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
/*
2022-05-23
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This is a JS Worker file for the main sqlite3 api. It loads
sqlite3.js, initializes the module, and postMessage()'s a message
after the module is initialized:
{type: 'sqlite3-api', data: 'ready'}
This seemingly superfluous level of indirection is necessary when
loading sqlite3.js via a Worker. Loading sqlite3.js from the main
window thread elides the Worker-specific API. Instantiating a worker
with new Worker("sqlite.js") will not (cannot) call
initSqlite3Module() to initialize the module due to a
timing/order-of-operations conflict (and that symbol is not exported
in a way that a Worker loading it that way can see it). Thus JS
code wanting to load the sqlite3 Worker-specific API needs to pass
_this_ file (or equivalent) to the Worker constructor and then
listen for an event in the form shown above in order to know when
the module has completed initialization. sqlite3.js will fire a
similar event, with data:'loaded' as the final step in its loading
process. Whether or not we _really_ need both 'loaded' and 'ready'
events is unclear, but they are currently separate events primarily
for the sake of clarity in the timing of when it's okay to use the
loaded module. At the time the 'loaded' event is fired, it's
possible (but unknown and unknowable) that the emscripten-generated
module-setup infrastructure still has work to do. Thus it is
hypothesized that client code is better off waiting for the 'ready'
even before using the API.
*/
"use strict";
importScripts('sqlite3.js');
initSqlite3Module().then(function(){
setTimeout(()=>self.postMessage({type:'sqlite3-api',data:'ready'}), 0);
});
+31
View File
@@ -0,0 +1,31 @@
textarea {
font-family: monospace;
}
header {
font-size: 130%;
font-weight: bold;
}
.hidden, .initially-hidden {
position: absolute !important;
opacity: 0 !important;
pointer-events: none !important;
display: none !important;
}
fieldset.options {
font-size: 75%;
}
fieldset > legend {
padding: 0 0.5em;
}
span.labeled-input {
padding: 0.25em;
margin: 0.25em 0.5em;
border-radius: 0.25em;
white-space: nowrap;
background: #0002;
}
.center { text-align: center; }
.error {
color: red;
background-color: yellow;
}
+33
View File
@@ -0,0 +1,33 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="emscripten.css"/>
<link rel="stylesheet" href="testing.css"/>
<title>sqlite3-api.js tests</title>
<style></style>
</head>
<body>
<header id='titlebar'><span>sqlite3-api.js tests</span></header>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<div>Everything on this page happens in the dev console.</div>
<script src="sqlite3.js"></script>
<script src="SqliteTestUtil.js"></script>
<script src="testing1.js"></script>
</body>
</html>
+185
View File
@@ -0,0 +1,185 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic test script for sqlite3-api.js. This file must be run in
main JS thread and sqlite3.js must have been loaded before it.
*/
(function(){
const T = self.SqliteTestUtil;
const log = console.log.bind(console);
const assert = function(condition, text) {
if (!condition) {
throw new Error('Assertion failed' + (text ? ': ' + text : ''));
}
};
const test1 = function(db,sqlite3){
const api = sqlite3.api;
log("Basic sanity tests...");
T.assert(db._pDb);
let st = db.prepare("select 3 as a");
//log("statement =",st);
T.assert(st._pStmt)
.assert(!st._mayGet)
.assert('a' === st.getColumnName(0))
.assert(st === db._statements[st._pStmt])
.assert(1===st.columnCount)
.assert(0===st.parameterCount)
.mustThrow(()=>st.bind(1,null))
.assert(true===st.step())
.assert(3 === st.get(0))
.mustThrow(()=>st.get(1))
.mustThrow(()=>st.get(0,~api.SQLITE_INTEGER))
.assert(3 === st.get(0,api.SQLITE_INTEGER))
.assert(3 === st.getInt(0))
.assert('3' === st.get(0,api.SQLITE_TEXT))
.assert('3' === st.getString(0))
.assert(3.0 === st.get(0,api.SQLITE_FLOAT))
.assert(3.0 === st.getFloat(0))
.assert(st.get(0,api.SQLITE_BLOB) instanceof Uint8Array)
.assert(st.getBlob(0) instanceof Uint8Array)
.assert(3 === st.get([])[0])
.assert(3 === st.get({}).a)
.assert(3 === st.getJSON(0))
.assert(st._mayGet)
.assert(false===st.step())
.assert(!st._mayGet)
;
let pId = st._pStmt;
st.finalize();
T.assert(!st._pStmt)
.assert(!db._statements[pId]);
let list = [];
db.exec({
sql:`CREATE TABLE t(a,b);
INSERT INTO t(a,b) VALUES(1,2),(3,4),(?,?);`,
multi: true,
saveSql: list,
bind: [5,6]
});
T.assert(2 === list.length);
//log("Exec'd SQL:", list);
let counter = 0, colNames = [];
list.length = 0;
db.exec("SELECT a a, b b FROM t",{
rowMode: 'object',
resultRows: list,
columnNames: colNames,
callback: function(row,stmt){
++counter;
T.assert(row.a%2 && row.a<6);
}
});
T.assert(2 === colNames.length)
.assert('a' === colNames[0])
.assert(3 === counter)
.assert(3 === list.length);
list.length = 0;
db.exec("SELECT a a, b b FROM t",{
rowMode: 'array',
callback: function(row,stmt){
++counter;
T.assert(Array.isArray(row))
.assert(0===row[1]%2 && row[1]<7);
}
});
T.assert(6 === counter);
};
const testUDF = function(db){
log("Testing UDF...");
db.createFunction("foo",function(a,b){return a+b});
T.assert(7===db.selectValue("select foo(3,4)")).
assert(5===db.selectValue("select foo(3,?)",2)).
assert(5===db.selectValue("select foo(?,?)",[1,4])).
assert(5===db.selectValue("select foo($a,$b)",{$a:0,$b:5}));
db.createFunction("bar", {
arity: -1,
callback: function(){
var rc = 0;
for(let i = 0; i < arguments.length; ++i) rc += arguments[i];
return rc;
}
});
log("Testing DB::selectValue() w/ UDF...");
T.assert(0===db.selectValue("select bar()")).
assert(1===db.selectValue("select bar(1)")).
assert(3===db.selectValue("select bar(1,2)")).
assert(-1===db.selectValue("select bar(1,2,-4)"));
const eqApprox = function(v1,v2,factor=0.05){
return v1>=(v2-factor) && v1<=(v2+factor);
};
T.assert('hi' === db.selectValue("select ?",'hi')).
assert(null===db.selectValue("select null")).
assert(null === db.selectValue("select ?",null)).
assert(null === db.selectValue("select ?",[null])).
assert(null === db.selectValue("select $a",{$a:null})).
assert(eqApprox(3.1,db.selectValue("select 3.0 + 0.1")))
;
};
const testAttach = function(db){
log("Testing ATTACH...");
db.exec({
sql:[
"attach 'foo.db' as foo",
"create table foo.bar(a)",
"insert into foo.bar(a) values(1),(2),(3)"
].join(';'),
multi: true
});
T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
db.exec("detach foo");
T.mustThrow(()=>db.exec("select * from foo.bar"));
};
const runTests = function(Module){
T.assert(Module._free instanceof Function).
assert(Module.allocate instanceof Function).
assert(Module.addFunction instanceof Function).
assert(Module.removeFunction instanceof Function);
const sqlite3 = Module.sqlite3;
const api = sqlite3.api;
const oo = sqlite3.SQLite3;
console.log("Loaded module:",api.sqlite3_libversion(),
api.sqlite3_sourceid());
log("Build options:",oo.compileOptionUsed());
const db = new oo.DB();
try {
log("DB:",db.filename);
[
test1, testUDF, testAttach
].forEach((f)=>{
const t = T.counter;
f(db, sqlite3);
log("Test count:",T.counter - t);
});
}finally{
db.close();
}
log("Total Test count:",T.counter);
};
initSqlite3Module(self.sqlite3TestModule).then(function(theModule){
/** Use a timeout so that we are (hopefully) out from
under the module init stack when our setup gets
run. Just on principle, not because we _need_ to
be. */
//console.debug("theModule =",theModule);
setTimeout(()=>runTests(theModule), 0);
});
})();
+32
View File
@@ -0,0 +1,32 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="emscripten.css"/>
<link rel="stylesheet" href="testing.css"/>
<title>sqlite3-worker.js tests</title>
<style></style>
</head>
<body>
<header id='titlebar'><span>sqlite3-worker.js tests</span></header>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<div>Everything on this page happens in the dev console.</div>
<script src="testing-common.js"></script>
<script src="testing2.js"></script>
</body>
</html>
+235
View File
@@ -0,0 +1,235 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic test script for sqlite3-worker.js.
*/
(function(){
const T = self.SqliteTestUtil;
const SW = new Worker("sqlite3-worker.js");
/** Posts a worker message as {type:type, data:data}. */
const wMsg = function(type,data){
SW.postMessage({type, data});
return SW;
};
const log = console.log.bind(console);
const warn = console.warn.bind(console);
const error = console.error.bind(console);
SW.onerror = function(event){
error("onerror",event);
};
/**
A queue for callbacks which are to be run in response to async
DB commands. See the notes in runTests() for why we need
this. The event-handling plumbing of this file requires that
any DB command which includes a `messageId` property also have
a queued callback entry, as the existence of that property in
response payloads is how it knows whether or not to shift an
entry off of the queue.
*/
const MsgHandlerQueue = {
queue: [],
id: 0,
push: function(type,callback){
this.queue.push(callback);
return type + '-' + (++this.id);
},
shift: function(){
return this.queue.shift();
}
};
const testCount = ()=>log("Total test count:",T.counter);
const runOneTest = function(eventType, eventData, callback){
T.assert(eventData && 'object'===typeof eventData);
/* ^^^ that is for the testing and messageId-related code, not
a hard requirement of all of the Worker-exposed APIs. */
eventData.messageId = MsgHandlerQueue.push(eventType,function(ev){
log("runOneTest",eventType,"result",ev.data);
if(callback instanceof Function){
callback(ev);
testCount();
}
});
wMsg(eventType, eventData);
};
/** Methods which map directly to onmessage() event.type keys.
They get passed the inbound event.data. */
const dbMsgHandler = {
open: function(ev){
log("open result",ev.data);
},
exec: function(ev){
log("exec result",ev.data);
},
export: function(ev){
log("exec result",ev.data);
},
error: function(ev){
error("ERROR from the worker:",ev.data);
},
resultRowTest1: function f(ev){
if(undefined === f.counter) f.counter = 0;
if(ev.data) ++f.counter;
//log("exec() result row:",ev.data);
T.assert(null===ev.data || 'number' === typeof ev.data.b);
}
};
const runTests = function(){
const mustNotReach = ()=>{
throw new Error("This is not supposed to be reached.");
};
/**
"The problem" now is that the test results are async. We
know, however, that the messages posted to the worker will
be processed in the order they are passed to it, so we can
create a queue of callbacks to handle them. The problem
with that approach is that it's not error-handling
friendly, in that an error can cause us to bypass a result
handler queue entry. We have to perform some extra
acrobatics to account for that.
*/
runOneTest('open', {filename:'testing2.sqlite3'}, function(ev){
//log("open result",ev);
T.assert('testing2.sqlite3'===ev.data.filename)
.assert(ev.data.messageId);
});
runOneTest('exec',{
sql: ["create table t(a,b)",
"insert into t(a,b) values(1,2),(3,4),(5,6)"
].join(';'),
multi: true,
resultRows: [], columnNames: []
}, function(ev){
ev = ev.data;
T.assert(0===ev.resultRows.length)
.assert(0===ev.columnNames.length);
});
runOneTest('exec',{
sql: 'select a a, b b from t order by a',
resultRows: [], columnNames: [],
}, function(ev){
ev = ev.data;
T.assert(3===ev.resultRows.length)
.assert(1===ev.resultRows[0][0])
.assert(6===ev.resultRows[2][1])
.assert(2===ev.columnNames.length)
.assert('b'===ev.columnNames[1]);
});
runOneTest('exec',{
sql: 'select a a, b b from t order by a',
resultRows: [], columnNames: [],
rowMode: 'object'
}, function(ev){
ev = ev.data;
T.assert(3===ev.resultRows.length)
.assert(1===ev.resultRows[0].a)
.assert(6===ev.resultRows[2].b)
});
runOneTest('exec',{sql:'intentional_error'}, mustNotReach);
// Ensure that the message-handler queue survives ^^^ that error...
runOneTest('exec',{
sql:'select 1',
resultRows: [],
//rowMode: 'array', // array is the default in the Worker interface
}, function(ev){
ev = ev.data;
T.assert(1 === ev.resultRows.length)
.assert(1 === ev.resultRows[0][0]);
});
runOneTest('exec',{
sql: 'select a a, b b from t order by a',
callback: 'resultRowTest1',
rowMode: 'object'
}, function(ev){
T.assert(3===dbMsgHandler.resultRowTest1.counter);
dbMsgHandler.resultRowTest1.counter = 0;
});
runOneTest('exec',{sql: 'delete from t where a>3'});
runOneTest('exec',{
sql: 'select count(a) from t',
resultRows: []
},function(ev){
ev = ev.data;
T.assert(1===ev.resultRows.length)
.assert(2===ev.resultRows[0][0]);
});
runOneTest('export',{}, function(ev){
ev = ev.data;
T.assert('string' === typeof ev.filename)
.assert(ev.buffer instanceof Uint8Array)
.assert(ev.buffer.length > 1024)
.assert('application/x-sqlite3' === ev.mimetype);
});
/***** close() tests must come last. *****/
runOneTest('close',{unlink:true},function(ev){
ev = ev.data;
T.assert('string' === typeof ev.filename);
});
runOneTest('close',{unlink:true},function(ev){
ev = ev.data;
T.assert(undefined === ev.filename);
});
};
SW.onmessage = function(ev){
if(!ev.data || 'object'!==typeof ev.data){
warn("Unknown sqlite3-worker message type:",ev);
return;
}
ev = ev.data/*expecting a nested object*/;
//log("main window onmessage:",ev);
if(ev.data && ev.data.messageId){
/* We're expecting a queued-up callback handler. */
const f = MsgHandlerQueue.shift();
if('error'===ev.type){
dbMsgHandler.error(ev);
return;
}
T.assert(f instanceof Function);
f(ev);
return;
}
switch(ev.type){
case 'sqlite3-api':
switch(ev.data){
case 'loaded':
log("Message:",ev); return;
case 'ready':
log("Message:",ev);
self.sqlite3TestModule.setStatus(null);
setTimeout(runTests, 0);
return;
default:
warn("Unknown sqlite3-api message type:",ev);
return;
}
default:
if(dbMsgHandler.hasOwnProperty(ev.type)){
try{dbMsgHandler[ev.type](ev);}
catch(err){
error("Exception while handling db result message",
ev,":",err);
}
return;
}
warn("Unknown sqlite3-api message type:",ev);
}
};
log("Init complete, but async init bits may still be running.");
})();
+16 -8
View File
@@ -3980,8 +3980,13 @@ static int fts3ShadowName(const char *zName){
return 0;
}
static int fts3ShadowName2(sqlite3_vtab *pVtab, const char *zName){
UNUSED_PARAMETER(pVtab);
return fts3ShadowName(zName);
}
static const sqlite3_module fts3Module = {
/* iVersion */ 3,
/* iVersion */ 4,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
/* xBestIndex */ fts3BestIndexMethod,
@@ -4000,11 +4005,12 @@ static const sqlite3_module fts3Module = {
/* xCommit */ fts3CommitMethod,
/* xRollback */ fts3RollbackMethod,
/* xFindFunction */ fts3FindFunctionMethod,
/* xRename */ fts3RenameMethod,
/* xRename */ fts3RenameMethod,
/* xSavepoint */ fts3SavepointMethod,
/* xRelease */ fts3ReleaseMethod,
/* xRollbackTo */ fts3RollbackToMethod,
/* xShadowName */ fts3ShadowName,
/* xShadowName2 */ fts3ShadowName2
};
/*
@@ -4308,8 +4314,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
char *aPoslist = 0; /* Position list for deferred tokens */
int nPoslist = 0; /* Number of bytes in aPoslist */
int iPrev = -1; /* Token number of previous deferred token */
assert( pPhrase->doclist.bFreeList==0 );
char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0);
for(iToken=0; iToken<pPhrase->nToken; iToken++){
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -4323,6 +4328,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
if( pList==0 ){
sqlite3_free(aPoslist);
sqlite3_free(aFree);
pPhrase->doclist.pList = 0;
pPhrase->doclist.nList = 0;
return SQLITE_OK;
@@ -4343,6 +4349,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
nPoslist = (int)(aOut - aPoslist);
if( nPoslist==0 ){
sqlite3_free(aPoslist);
sqlite3_free(aFree);
pPhrase->doclist.pList = 0;
pPhrase->doclist.nList = 0;
return SQLITE_OK;
@@ -4382,6 +4389,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
}
pPhrase->doclist.pList = aOut;
assert( p1 && p2 );
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
pPhrase->doclist.bFreeList = 1;
pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
@@ -4394,6 +4402,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
}
}
if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree);
return SQLITE_OK;
}
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
@@ -5568,11 +5577,10 @@ static int fts3EvalTestExpr(
default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( pCsr->pDeferred
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
){
if( pCsr->pDeferred && (pExpr->bDeferred || (
pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList
))){
Fts3Phrase *pPhrase = pExpr->pPhrase;
assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
if( pExpr->bDeferred ){
fts3EvalInvalidatePoslist(pPhrase);
}
+2 -1
View File
@@ -545,7 +545,8 @@ int sqlite3Fts3InitAux(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc; /* Return code */
+2 -1
View File
@@ -362,7 +362,8 @@ int sqlite3Fts3InitTerm(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc; /* Return code */
+2 -1
View File
@@ -445,7 +445,8 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc; /* Return code */
+3
View File
@@ -3899,6 +3899,8 @@ static int fts3IncrmergePush(
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
}
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
assert( nPrefix+nSuffix<=nTerm );
assert( nPrefix>=0 );
memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
pBlk->n += nSuffix;
@@ -4021,6 +4023,7 @@ static int fts3IncrmergeAppend(
pLeaf = &pWriter->aNodeWriter[0];
nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nSpace = sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
+3
View File
@@ -1627,6 +1627,9 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
}else{
if( pRet->nPhrase>0 ){
Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
assert( pParse!=0 );
assert( pParse->apPhrase!=0 );
assert( pParse->nPhrase>=2 );
assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
if( pPhrase->nTerm==0 ){
fts5ExprPhraseFree(pPhrase);
+1 -1
View File
@@ -296,7 +296,7 @@ struct Fts5Index {
sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */
sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */
sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */
sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */
sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */
sqlite3_stmt *pIdxSelect;
int nRead; /* Total number of blocks read */
+9 -3
View File
@@ -804,7 +804,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
rc = sqlite3_step(pSorter->pStmt);
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
CsrFlagSet(pCsr, FTS5CSR_EOF);
CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
}else if( rc==SQLITE_ROW ){
const u8 *a;
const u8 *aBlob;
@@ -2811,9 +2811,14 @@ static int fts5ShadowName(const char *zName){
return 0;
}
static int fts5ShadowName2(sqlite3_vtab *pVtab, const char *zName){
UNUSED_PARAMETER(pVtab);
return fts5ShadowName(zName);
}
static int fts5Init(sqlite3 *db){
static const sqlite3_module fts5Mod = {
/* iVersion */ 3,
/* iVersion */ 4,
/* xCreate */ fts5CreateMethod,
/* xConnect */ fts5ConnectMethod,
/* xBestIndex */ fts5BestIndexMethod,
@@ -2836,7 +2841,8 @@ static int fts5Init(sqlite3 *db){
/* xSavepoint */ fts5SavepointMethod,
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
/* xShadowName */ fts5ShadowName
/* xShadowName */ fts5ShadowName,
/* xShadowName2 */ fts5ShadowName2
};
int rc;
+2 -1
View File
@@ -472,7 +472,8 @@ int sqlite3Fts5TestRegisterTok(sqlite3 *db, fts5_api *pApi){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc; /* Return code */
+2 -1
View File
@@ -783,7 +783,8 @@ int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
/* xShadowName */ 0,
/* xShadowName2 */ 0
};
void *p = (void*)pGlobal;
+1
View File
@@ -11,6 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
# TESTRUNNER: slow
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5ah
+154
View File
@@ -15366,6 +15366,160 @@ do_catchsql_test 79.2 {
INSERT INTO t1(t1) SELECT 'merge' FROM t2;
} {1 {query aborted}}
#-------------------------------------------------------------------------
reset_db
do_test 80.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 40960 pagesize 4096 filename crash-f928a9c1ec68dd.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
| 96: 00 00 00 00 0d 00 00 00 0d 0b 6e 00 0f a3 0f 4c ..........n....L
| 112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50 .....$...r.....P
| 128: 0b f8 0b b3 0b 6e 00 00 00 00 00 00 00 00 00 00 .....n..........
| 2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d ..............C.
| 2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43 .....utablet4t4C
| 2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
| 2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73 BLE t4 USING fts
| 2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f 5vocab('t2', 'ro
| 2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65 w')C......utable
| 3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55 t3t3CREATE VIRTU
| 3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e AL TABLE t3 USIN
| 3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27 G fts5vocab('t1'
| 3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d , 'row')V.......
| 3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32 tablet2_configt2
| 3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54 _config.CREATE T
| 3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27 ABLE 't2_config'
| 3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 (k PRIMARY KEY,
| 3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 v) WITHOUT ROWID
| 3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32 ^...!!...tablet2
| 3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65 _contentt2_conte
| 3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 nt.CREATE TABLE
| 3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 't2_content'(id
| 3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29 KEY, c0, c1, c2)
| 3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32 i.......-tablet2
| 3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54 _idxt2_idx.CREAT
| 3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27 E TABLE 't2_idx'
| 3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 (segid, term, pg
| 3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 no, PRIMARY KEY(
| 3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 segid, term)) WI
| 3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b THOUT ROWIDU....
| 3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61 ....tablet2_data
| 3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54 t2_data.CREATE T
| 3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69 ABLE 't2_data'(i
| 3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
| 3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f Y KEY, block BLO
| 3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65 B)X........table
| 3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55 t2t2CREATE VIRTU
| 3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e AL TABLE t2 USIN
| 3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22 G fts5('a',[b],.
| 3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63 c.,detail=none,c
| 3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17 olumnsize=0)V...
| 3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66 ....tablet1_conf
| 3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41 igt1_config.CREA
| 3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e TE TABLE 't1_con
| 3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
| 3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
| 3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62 OWID[...!!...tab
| 3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
| 3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
| 3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
| 3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 ARY KEY, sz BLOB
| 3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74 )^...!!...tablet
| 3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
| 3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
| 3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64 't1_content'(id
| 3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
| 3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 KEY, c0, c1, c2
| 3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74 )i.......-tablet
| 3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41 1_idxt1_idx.CREA
| 3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78 TE TABLE 't1_idx
| 3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 '(segid, term, p
| 3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 gno, PRIMARY KEY
| 3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 (segid, term)) W
| 3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17 ITHOUT ROWIDU...
| 3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74 .....tablet1_dat
| 3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20 at1_data.CREATE
| 3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28 TABLE 't1_data'(
| 3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
| 3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c RY KEY, block BL
| 4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c OB)[.......#tabl
| 4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
| 4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
| 4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 6e NG fts5(a,b unin
| 4064: 64 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65 dexed,c,tokenize
| 4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29 =.porter ascii.)
| page 2 offset 4096
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
| 3984: 01 02 02 01 01 68 02 08 03 01 02 03 01 01 69 02 .....h........i.
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 80 01 03 ........7.......
| 4016: 00 74 00 00 00 2e 02 30 61 01 02 02 01 01 62 01 .t.....0a.....b.
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
| 4048: 01 01 68 01 06 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
| page 5 offset 16384
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 01 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| page 7 offset 24576
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 00 00 00 00 ................
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 8 offset 28672
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 12 ................
| page 9 offset 32768
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
| page 10 offset 36864
| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 00 00 00 00 ........vers....
| end crash-f928a9c1ec68dd.db
}]} {}
do_catchsql_test 80.1 {
SELECT snippet(rowid, -1, '.', '..', '[', '(]'),snippet(rowid, -1, '.', '.', '', '(]'), highlight(t1, 29, 1 , '') FROM t1('g+ h') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY NOT (SELECT 1 FROM t1('g+ æ') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY rank);
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
+6 -2
View File
@@ -16,12 +16,16 @@ source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5fault4
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
set ::TMPDBERROR [list 1 \
{unable to open a temporary database file for storing temporary tables}
]
#-------------------------------------------------------------------------
# An OOM while dropping an fts5 table.
#
@@ -391,7 +395,7 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
} -body {
db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" }
} -test {
faultsim_test_result {0 {}}
faultsim_test_result {0 {}} $::TMPDBERROR
}
finish_test
+4 -10
View File
@@ -153,18 +153,12 @@ SQLite. Documentation follows.
the ICU extension LIKE operator is 50000, defined in source
file "icu.c".
3.3 Collation Sequence Security Issue
3.3 Collation Sequence Security
Internally, SQLite assumes that indices stored in database files
are sorted according to the collation sequence indicated by the
SQL schema. Changing the definition of a collation sequence after
an index has been built is therefore equivalent to database
corruption. The SQLite library is not very well tested under
these conditions, and may contain potential buffer overruns
or other programming errors that could be exploited by a malicious
programmer.
If the ICU extension is used in an environment where potentially
malicious users may execute arbitrary SQL (i.e. gears), they
should be prevented from invoking the icu_load_collation() function,
possibly using the authorisation callback.
corruption. The SQLite library is well tested for robustness in
the fact of database corruption. Database corruption may well
lead to incorrect answers, but should not cause memory errors.
+1 -1
View File
@@ -26,7 +26,7 @@
**
** The virtual table contains read-only hidden columns:
**
** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
** is BLOB or TEXT then this column is exactly the
** same as the key. For the UINT keytype, this column
** will be a variable-length integer encoding of the key.
+2 -1
View File
@@ -1475,7 +1475,8 @@ static sqlite3_module amatchModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+2 -1
View File
@@ -411,7 +411,8 @@ int sqlite3BinfoRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0);
}
+2 -1
View File
@@ -939,7 +939,8 @@ static sqlite3_module closureModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+2 -1
View File
@@ -470,7 +470,8 @@ static sqlite3_module completionModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+9 -2
View File
@@ -280,6 +280,7 @@ static char *csv_read_one_field(CsvReader *p){
}
p->cTerm = (char)c;
}
assert( p->z==0 || p->n<p->nAlloc );
if( p->z ) p->z[p->n] = 0;
p->bNotFirst = 1;
return p->z;
@@ -750,7 +751,7 @@ static int csvtabNext(sqlite3_vtab_cursor *cur){
i++;
}
}while( pCur->rdr.cTerm==',' );
if( z==0 || (pCur->rdr.cTerm==EOF && i<pTab->nCol) ){
if( z==0 && i==0 ){
pCur->iRowid = -1;
}else{
pCur->iRowid++;
@@ -811,6 +812,12 @@ static int csvtabFilter(
CsvCursor *pCur = (CsvCursor*)pVtabCursor;
CsvTable *pTab = (CsvTable*)pVtabCursor->pVtab;
pCur->iRowid = 0;
/* Ensure the field buffer is always allocated. Otherwise, if the
** first field is zero bytes in size, this may be mistaken for an OOM
** error in csvtabNext(). */
if( csv_append(&pCur->rdr, 0) ) return SQLITE_NOMEM;
if( pCur->rdr.in==0 ){
assert( pCur->rdr.zIn==pTab->zData );
assert( pTab->iStart>=0 );
@@ -941,7 +948,7 @@ int sqlite3_csv_init(
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
#ifndef SQLITE_OMIT_VIRTUALTABLE
#ifndef SQLITE_OMIT_VIRTUALTABLE
int rc;
SQLITE_EXTENSION_INIT2(pApi);
rc = sqlite3_create_module(db, "csv", &CsvModule, 0);
+2 -1
View File
@@ -828,7 +828,8 @@ static int sqlite3DbdataRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
+1
View File
@@ -293,6 +293,7 @@ static sqlite3_module explainModule = {
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+1
View File
@@ -983,6 +983,7 @@ static int fsdirRegister(sqlite3 *db){
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
+25 -24
View File
@@ -1035,30 +1035,31 @@ static int deltaparsevtabBestIndex(
** virtual table.
*/
static sqlite3_module deltaparsevtabModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ deltaparsevtabConnect,
/* xBestIndex */ deltaparsevtabBestIndex,
/* xDisconnect */ deltaparsevtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ deltaparsevtabOpen,
/* xClose */ deltaparsevtabClose,
/* xFilter */ deltaparsevtabFilter,
/* xNext */ deltaparsevtabNext,
/* xEof */ deltaparsevtabEof,
/* xColumn */ deltaparsevtabColumn,
/* xRowid */ deltaparsevtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ deltaparsevtabConnect,
/* xBestIndex */ deltaparsevtabBestIndex,
/* xDisconnect */ deltaparsevtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ deltaparsevtabOpen,
/* xClose */ deltaparsevtabClose,
/* xFilter */ deltaparsevtabFilter,
/* xNext */ deltaparsevtabNext,
/* xEof */ deltaparsevtabEof,
/* xColumn */ deltaparsevtabColumn,
/* xRowid */ deltaparsevtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0,
/* xShadowName2 */ 0
};
+1 -1
View File
@@ -284,7 +284,7 @@ int sqlite3_ieee_init(
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
SQLITE_UTF8|SQLITE_INNOCUOUS,
(void*)&aFunc[i].iAux,
aFunc[i].xFunc, 0, 0);
+1
View File
@@ -396,6 +396,7 @@ static sqlite3_module memstatModule = {
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+25 -24
View File
@@ -225,30 +225,31 @@ static int prefixesBestIndex(
** virtual table.
*/
static sqlite3_module prefixesModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ prefixesConnect,
/* xBestIndex */ prefixesBestIndex,
/* xDisconnect */ prefixesDisconnect,
/* xDestroy */ 0,
/* xOpen */ prefixesOpen,
/* xClose */ prefixesClose,
/* xFilter */ prefixesFilter,
/* xNext */ prefixesNext,
/* xEof */ prefixesEof,
/* xColumn */ prefixesColumn,
/* xRowid */ prefixesRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ prefixesConnect,
/* xBestIndex */ prefixesBestIndex,
/* xDisconnect */ prefixesDisconnect,
/* xDestroy */ 0,
/* xOpen */ prefixesOpen,
/* xClose */ prefixesClose,
/* xFilter */ prefixesFilter,
/* xNext */ prefixesNext,
/* xEof */ prefixesEof,
/* xColumn */ prefixesColumn,
/* xRowid */ prefixesRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0,
/* xShadowName2 */ 0
};
/*
+57 -31
View File
@@ -40,7 +40,7 @@
**
** Option 1 is the default behavior. 2 is use if there is a usable
** constraint on "flags" with an integer right-hand side that where the
** value of the right-hand side has its 0x01 bit set.
** value of the right-hand side has its 0x001 bit set.
**
** All constraints on columns "a" through "e" are marked as "omit".
**
@@ -48,6 +48,12 @@
** is an integer and that integer has its 0x02 bit set, then the
** orderByConsumed flag is set.
**
** FLAGS SUMMARY:
**
** 0x001 Columns 'a' through 'e' have INT values
** 0x002 orderByConsumed is set
** 0x004 OFFSET and LIMIT have omit set
**
** COMPILE:
**
** gcc -Wall -g -shared -fPIC -I. qpvtab.c -o qqvtab.so
@@ -103,7 +109,8 @@ static const char *azColname[] = {
"ux",
"rhs",
"a", "b", "c", "d", "e",
"flags"
"flags",
""
};
/*
@@ -143,6 +150,7 @@ static int qpvtabConnect(
#define QPVTAB_D 9
#define QPVTAB_E 10
#define QPVTAB_FLAGS 11
#define QPVTAB_NONE 12
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
@@ -226,7 +234,7 @@ static int qpvtabColumn(
sqlite3_result_text64(ctx, z, zEnd-z, SQLITE_TRANSIENT, SQLITE_UTF8);
}
}else if( i>=QPVTAB_A && i<=QPVTAB_E ){
if( pCur->flags & 1 ){
if( pCur->flags & 0x001 ){
sqlite3_result_int(ctx, i-QPVTAB_A+1);
}else{
char x = 'a'+i-QPVTAB_A;
@@ -338,19 +346,25 @@ static int qpvtabBestIndex(
for(i=0; i<pIdxInfo->nConstraint; i++){
sqlite3_value *pVal;
int iCol = pIdxInfo->aConstraint[i].iColumn;
int op = pIdxInfo->aConstraint[i].op;
if( iCol==QPVTAB_FLAGS && pIdxInfo->aConstraint[i].usable ){
pVal = 0;
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
assert( rc==SQLITE_OK || pVal==0 );
if( pVal ){
pIdxInfo->idxNum = sqlite3_value_int(pVal);
if( pIdxInfo->idxNum & 2 ) pIdxInfo->orderByConsumed = 1;
if( pIdxInfo->idxNum & 0x002 ) pIdxInfo->orderByConsumed = 1;
}
}
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
){
iCol = QPVTAB_NONE;
}
sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
i,
azColname[iCol],
pIdxInfo->aConstraint[i].op,
op,
pIdxInfo->aConstraint[i].usable);
pVal = 0;
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
@@ -359,9 +373,20 @@ static int qpvtabBestIndex(
qpvtabStrAppendValue(pStr, pVal);
}
sqlite3_str_append(pStr, "\n", 1);
}
for(i=0; i<pIdxInfo->nConstraint; i++){
int iCol = pIdxInfo->aConstraint[i].iColumn;
int op = pIdxInfo->aConstraint[i].op;
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
){
iCol = QPVTAB_NONE;
}
if( iCol>=QPVTAB_A && pIdxInfo->aConstraint[i].usable ){
pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
if( iCol<=QPVTAB_FLAGS || (pIdxInfo->idxNum & 0x004)!=0 ){
pIdxInfo->aConstraintUsage[i].omit = 1;
}
}
}
sqlite3_str_appendf(pStr, "nOrderBy,%d,,,,\n", pIdxInfo->nOrderBy);
@@ -391,30 +416,31 @@ static int qpvtabBestIndex(
** virtual table.
*/
static sqlite3_module qpvtabModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ qpvtabConnect,
/* xBestIndex */ qpvtabBestIndex,
/* xDisconnect */ qpvtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ qpvtabOpen,
/* xClose */ qpvtabClose,
/* xFilter */ qpvtabFilter,
/* xNext */ qpvtabNext,
/* xEof */ qpvtabEof,
/* xColumn */ qpvtabColumn,
/* xRowid */ qpvtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ qpvtabConnect,
/* xBestIndex */ qpvtabBestIndex,
/* xDisconnect */ qpvtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ qpvtabOpen,
/* xClose */ qpvtabClose,
/* xFilter */ qpvtabFilter,
/* xNext */ qpvtabNext,
/* xEof */ qpvtabEof,
/* xColumn */ qpvtabColumn,
/* xRowid */ qpvtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0,
/* xShadowName2 */ 0
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+117 -10
View File
@@ -72,6 +72,7 @@ SQLITE_EXTENSION_INIT1
/* The end-of-input character */
#define RE_EOF 0 /* End of input */
#define RE_START 0xfffffff /* Start of input - larger than an UTF-8 */
/* The NFA is implemented as sequence of opcodes taken from the following
** set. Each opcode has a single integer argument.
@@ -93,6 +94,33 @@ SQLITE_EXTENSION_INIT1
#define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE 16 /* Not a digit */
#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
#define RE_OP_ATSTART 18 /* Currently at the start of the string */
#if defined(SQLITE_DEBUG)
/* Opcode names used for symbolic debugging */
static const char *ReOpName[] = {
"EOF",
"MATCH",
"ANY",
"ANYSTAR",
"FORK",
"GOTO",
"ACCEPT",
"CC_INC",
"CC_EXC",
"CC_VALUE",
"CC_RANGE",
"WORD",
"NOTWORD",
"DIGIT",
"NOTDIGIT",
"SPACE",
"NOTSPACE",
"BOUNDARY",
"ATSTART",
};
#endif /* SQLITE_DEBUG */
/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;
@@ -127,7 +155,7 @@ struct ReCompiled {
int *aArg; /* Arguments to each operator */
unsigned (*xNextChar)(ReInput*); /* Next character function */
unsigned char zInit[12]; /* Initial text to match */
int nInit; /* Number of characters in zInit */
int nInit; /* Number of bytes in zInit */
unsigned nState; /* Number of entries in aOp[] and aArg[] */
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
};
@@ -200,7 +228,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
ReStateNumber *pToFree;
unsigned int i = 0;
unsigned int iSwap = 0;
int c = RE_EOF+1;
int c = RE_START;
int cPrev = 0;
int rc = 0;
ReInput in;
@@ -219,6 +247,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
in.i++;
}
if( in.i+pRe->nInit>in.mx ) return 0;
c = RE_START-1;
}
if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
@@ -247,6 +276,10 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ATSTART: {
if( cPrev==RE_START ) re_add_state(pThis, x+1);
break;
}
case RE_OP_ANY: {
if( c!=0 ) re_add_state(pNext, x+1);
break;
@@ -328,7 +361,9 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
}
}
for(i=0; i<pNext->nState; i++){
if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
int x = pNext->aState[i];
while( pRe->aOp[x]==RE_OP_GOTO ) x += pRe->aArg[x];
if( pRe->aOp[x]==RE_OP_ACCEPT ){ rc = 1; break; }
}
re_match_end:
sqlite3_free(pToFree);
@@ -483,7 +518,6 @@ static const char *re_subcompile_string(ReCompiled *p){
iStart = p->nState;
switch( c ){
case '|':
case '$':
case ')': {
p->sIn.i--;
return 0;
@@ -520,6 +554,14 @@ static const char *re_subcompile_string(ReCompiled *p){
re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
break;
}
case '$': {
re_append(p, RE_OP_MATCH, RE_EOF);
break;
}
case '^': {
re_append(p, RE_OP_ATSTART, 0);
break;
}
case '{': {
int m = 0, n = 0;
int sz, j;
@@ -538,6 +580,7 @@ static const char *re_subcompile_string(ReCompiled *p){
if( m==0 ){
if( n==0 ) return "both m and n are zero in '{m,n}'";
re_insert(p, iPrev, RE_OP_FORK, sz+1);
iPrev++;
n--;
}else{
for(j=1; j<m; j++) re_copy(p, iPrev, sz);
@@ -656,11 +699,7 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
re_free(pRe);
return zErr;
}
if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
re_append(pRe, RE_OP_MATCH, RE_EOF);
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else if( pRe->sIn.i>=pRe->sIn.mx ){
if( pRe->sIn.i>=pRe->sIn.mx ){
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else{
@@ -685,7 +724,7 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else{
@@ -744,6 +783,67 @@ static void re_sql_func(
}
}
#if defined(SQLITE_DEBUG)
/*
** This function is used for testing and debugging only. It is only available
** if the SQLITE_DEBUG compile-time option is used.
**
** Compile a regular expression and then convert the compiled expression into
** text and return that text.
*/
static void re_bytecode_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zPattern;
const char *zErr;
ReCompiled *pRe;
sqlite3_str *pStr;
int i;
int n;
char *z;
zPattern = (const char*)sqlite3_value_text(argv[0]);
if( zPattern==0 ) return;
zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
if( zErr ){
re_free(pRe);
sqlite3_result_error(context, zErr, -1);
return;
}
if( pRe==0 ){
sqlite3_result_error_nomem(context);
return;
}
pStr = sqlite3_str_new(0);
if( pStr==0 ) goto re_bytecode_func_err;
if( pRe->nInit>0 ){
sqlite3_str_appendf(pStr, "INIT ");
for(i=0; i<pRe->nInit; i++){
sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
}
sqlite3_str_appendf(pStr, "\n");
}
for(i=0; (unsigned)i<pRe->nState; i++){
sqlite3_str_appendf(pStr, "%-8s %4d\n",
ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
}
n = sqlite3_str_length(pStr);
z = sqlite3_str_finish(pStr);
if( n==0 ){
sqlite3_free(z);
}else{
sqlite3_result_text(context, z, n-1, sqlite3_free);
}
re_bytecode_func_err:
re_free(pRe);
}
#endif /* SQLITE_DEBUG */
/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
@@ -768,6 +868,13 @@ int sqlite3_regexp_init(
rc = sqlite3_create_function(db, "regexpi", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
(void*)db, re_sql_func, 0, 0);
#if defined(SQLITE_DEBUG)
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "regexp_bytecode", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
0, re_bytecode_func, 0, 0);
}
#endif /* SQLITE_DEBUG */
}
return rc;
}
+2 -1
View File
@@ -432,7 +432,8 @@ static sqlite3_module seriesModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+1 -1
View File
@@ -19,7 +19,7 @@
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
** X is NULL.
**
** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
** and returns a hash of their results.
**
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
+82 -44
View File
@@ -30,6 +30,16 @@ SQLITE_EXTENSION_INIT1
#ifndef SQLITE_OMIT_VIRTUALTABLE
#define STMT_NUM_INTEGER_COLUMN 10
typedef struct StmtRow StmtRow;
struct StmtRow {
sqlite3_int64 iRowid; /* Rowid value */
char *zSql; /* column "sql" */
int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */
StmtRow *pNext; /* Next row to return */
};
/* stmt_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a stmt virtual table
*/
@@ -47,8 +57,7 @@ typedef struct stmt_cursor stmt_cursor;
struct stmt_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this cursor */
sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */
sqlite3_int64 iRowid; /* The rowid */
StmtRow *pRow; /* Current row */
};
/*
@@ -92,7 +101,7 @@ static int stmtConnect(
"CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
"reprep,run,mem)");
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
pNew = sqlite3_malloc64( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
@@ -114,7 +123,7 @@ static int stmtDisconnect(sqlite3_vtab *pVtab){
*/
static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
stmt_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
pCur = sqlite3_malloc64( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((stmt_vtab*)p)->db;
@@ -122,10 +131,21 @@ static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
return SQLITE_OK;
}
static void stmtCsrReset(stmt_cursor *pCur){
StmtRow *pRow = 0;
StmtRow *pNext = 0;
for(pRow=pCur->pRow; pRow; pRow=pNext){
pNext = pRow->pNext;
sqlite3_free(pRow);
}
pCur->pRow = 0;
}
/*
** Destructor for a stmt_cursor.
*/
static int stmtClose(sqlite3_vtab_cursor *cur){
stmtCsrReset((stmt_cursor*)cur);
sqlite3_free(cur);
return SQLITE_OK;
}
@@ -136,8 +156,9 @@ static int stmtClose(sqlite3_vtab_cursor *cur){
*/
static int stmtNext(sqlite3_vtab_cursor *cur){
stmt_cursor *pCur = (stmt_cursor*)cur;
pCur->iRowid++;
pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt);
StmtRow *pNext = pCur->pRow->pNext;
sqlite3_free(pCur->pRow);
pCur->pRow = pNext;
return SQLITE_OK;
}
@@ -151,39 +172,11 @@ static int stmtColumn(
int i /* Which column to return */
){
stmt_cursor *pCur = (stmt_cursor*)cur;
switch( i ){
case STMT_COLUMN_SQL: {
sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
break;
}
case STMT_COLUMN_NCOL: {
sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
break;
}
case STMT_COLUMN_RO: {
sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
break;
}
case STMT_COLUMN_BUSY: {
sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
break;
}
default: {
assert( i==STMT_COLUMN_MEM );
i = SQLITE_STMTSTATUS_MEMUSED +
STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
/* Fall thru */
}
case STMT_COLUMN_NSCAN:
case STMT_COLUMN_NSORT:
case STMT_COLUMN_NAIDX:
case STMT_COLUMN_NSTEP:
case STMT_COLUMN_REPREP:
case STMT_COLUMN_RUN: {
sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
break;
}
StmtRow *pRow = pCur->pRow;
if( i==STMT_COLUMN_SQL ){
sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT);
}else{
sqlite3_result_int(ctx, pRow->aCol[i]);
}
return SQLITE_OK;
}
@@ -194,7 +187,7 @@ static int stmtColumn(
*/
static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
stmt_cursor *pCur = (stmt_cursor*)cur;
*pRowid = pCur->iRowid;
*pRowid = pCur->pRow->iRowid;
return SQLITE_OK;
}
@@ -204,7 +197,7 @@ static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
*/
static int stmtEof(sqlite3_vtab_cursor *cur){
stmt_cursor *pCur = (stmt_cursor*)cur;
return pCur->pStmt==0;
return pCur->pRow==0;
}
/*
@@ -219,9 +212,53 @@ static int stmtFilter(
int argc, sqlite3_value **argv
){
stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
pCur->pStmt = 0;
pCur->iRowid = 0;
return stmtNext(pVtabCursor);
sqlite3_stmt *p = 0;
sqlite3_int64 iRowid = 1;
StmtRow **ppRow = 0;
stmtCsrReset(pCur);
ppRow = &pCur->pRow;
for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){
const char *zSql = sqlite3_sql(p);
sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0;
StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql);
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(StmtRow));
if( zSql ){
pNew->zSql = (char*)&pNew[1];
memcpy(pNew->zSql, zSql, nSql);
}
pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p);
pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p);
pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p);
pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0
);
pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_SORT, 0
);
pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_AUTOINDEX, 0
);
pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_VM_STEP, 0
);
pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_REPREPARE, 0
);
pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_RUN, 0
);
pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_MEMUSED, 0
);
pNew->iRowid = iRowid++;
*ppRow = pNew;
ppRow = &pNew->pNext;
}
return SQLITE_OK;
}
/*
@@ -268,6 +305,7 @@ static sqlite3_module stmtModule = {
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+25 -24
View File
@@ -226,30 +226,31 @@ static int templatevtabBestIndex(
** virtual table.
*/
static sqlite3_module templatevtabModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ templatevtabConnect,
/* xBestIndex */ templatevtabBestIndex,
/* xDisconnect */ templatevtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ templatevtabOpen,
/* xClose */ templatevtabClose,
/* xFilter */ templatevtabFilter,
/* xNext */ templatevtabNext,
/* xEof */ templatevtabEof,
/* xColumn */ templatevtabColumn,
/* xRowid */ templatevtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ templatevtabConnect,
/* xBestIndex */ templatevtabBestIndex,
/* xDisconnect */ templatevtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ templatevtabOpen,
/* xClose */ templatevtabClose,
/* xFilter */ templatevtabFilter,
/* xNext */ templatevtabNext,
/* xEof */ templatevtabEof,
/* xColumn */ templatevtabColumn,
/* xRowid */ templatevtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0,
/* xShadowName2 */ 0
};
+2 -1
View File
@@ -1351,7 +1351,8 @@ static int createUnionVtab(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc;
+1
View File
@@ -493,6 +493,7 @@ static sqlite3_module vtablogModule = {
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xShadowName2 */
};
#ifdef _WIN32
+17 -1
View File
@@ -425,6 +425,16 @@ static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){
return rc;
}
static int vtshimShadowName2(sqlite3_vtab *pBase, const char *zName){
vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
vtshim_aux *pAux = pVtab->pAux;
int rc;
if( pAux->bDisposed ) return 0;
rc = pAux->pMod->xShadowName2(pVtab->pChild, zName);
VTSHIM_COPY_ERRMSG();
return rc;
}
/* The destructor function for a disposible module */
static void vtshimAuxDestructor(void *pXAux){
vtshim_aux *pAux = (vtshim_aux*)pXAux;
@@ -481,7 +491,7 @@ void *sqlite3_create_disposable_module(
pAux->zName = sqlite3_mprintf("%s", zName);
pAux->bDisposed = 0;
pAux->pAllVtab = 0;
pAux->sSelf.iVersion = p->iVersion<=2 ? p->iVersion : 2;
pAux->sSelf.iVersion = p->iVersion<=4 ? p->iVersion : 4;
pAux->sSelf.xCreate = p->xCreate ? vtshimCreate : 0;
pAux->sSelf.xConnect = p->xConnect ? vtshimConnect : 0;
pAux->sSelf.xBestIndex = p->xBestIndex ? vtshimBestIndex : 0;
@@ -510,6 +520,12 @@ void *sqlite3_create_disposable_module(
pAux->sSelf.xRelease = 0;
pAux->sSelf.xRollbackTo = 0;
}
pAux->sSelf.xShadowName = 0; /* v3 */
if( p->iVersion>=4 ){
pAux->sSelf.xShadowName2 = p->xShadowName2 ? vtshimShadowName2 : 0;
}else{
pAux->sSelf.xShadowName2 = 0;
}
rc = sqlite3_create_module_v2(db, zName, &pAux->sSelf,
pAux, vtshimAuxDestructor);
return rc==SQLITE_OK ? (void*)pAux : 0;
+10
View File
@@ -1262,9 +1262,14 @@ static int zipfileFilter(
zipfileCursorErr(pCsr, "zipfile() function requires an argument");
return SQLITE_ERROR;
}else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
static const u8 aEmptyBlob = 0;
const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
int nBlob = sqlite3_value_bytes(argv[0]);
assert( pTab->pFirstEntry==0 );
if( aBlob==0 ){
aBlob = &aEmptyBlob;
nBlob = 0;
}
rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
pCsr->pFreeEntry = pTab->pFirstEntry;
pTab->pFirstEntry = pTab->pLastEntry = 0;
@@ -2170,6 +2175,11 @@ static int zipfileRegister(sqlite3 *db){
zipfileRollback, /* xRollback */
zipfileFindFunction, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollback */
0, /* xShadowName */
0 /* xShadowName2 */
};
int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
+87
View File
@@ -0,0 +1,87 @@
# 2014 August 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbubusy
db close
sqlite3_shutdown
test_sqlite3_log xLog
reset_db
set db_sql {
CREATE TABLE t1(a PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(1000, 2000, 3000);
}
set rbu_sql {
CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(4, 5, 6, 0);
INSERT INTO data_t1 VALUES(7, 8, 9, 0);
}
do_test 1.1 {
forcedelete rbu.db
sqlite3 rbu rbu.db
rbu eval $rbu_sql
rbu close
db eval $db_sql
} {}
do_execsql_test 1.2 {
BEGIN;
SELECT * FROM t1
} {1000 2000 3000}
do_test 1.3 {
sqlite3rbu rbu test.db rbu.db
rbu step
} {SQLITE_OK}
do_test 1.4 {
while 1 {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
}
set rc
} {SQLITE_BUSY}
do_test 1.5 {
rbu step
} {SQLITE_BUSY}
do_test 1.6 {
db eval COMMIT
rbu step
} {SQLITE_BUSY}
catch { rbu close }
do_test 1.7 {
sqlite3rbu rbu test.db rbu.db
while 1 {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
}
set rc
} {SQLITE_DONE}
rbu close
db close
sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize
finish_test
-1
View File
@@ -4,7 +4,6 @@
*/
#define TCLSH_INIT_PROC sqlite3_checker_init_proc
#define SQLITE_ENABLE_DBPAGE_VTAB 1
#define SQLITE_ENABLE_JSON1 1
#undef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 0
#undef SQLITE_ENABLE_COLUMN_METADATA
+3 -2
View File
@@ -1736,7 +1736,7 @@ static int geopolyFindFunction(
static sqlite3_module geopolyModule = {
3, /* iVersion */
4, /* iVersion */
geopolyCreate, /* xCreate - create a table */
geopolyConnect, /* xConnect - connect to an existing table */
geopolyBestIndex, /* xBestIndex - Determine search strategy */
@@ -1759,7 +1759,8 @@ static sqlite3_module geopolyModule = {
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
rtreeShadowName /* xShadowName */
rtreeShadowName, /* xShadowName */
rtreeShadowName2 /* xShadowName2 */
};
static int sqlite3_geopoly_init(sqlite3 *db){
+8 -2
View File
@@ -3477,8 +3477,13 @@ static int rtreeShadowName(const char *zName){
return 0;
}
static int rtreeShadowName2(sqlite3_vtab *pVtab, const char *zName){
UNUSED_PARAMETER(pVtab);
return rtreeShadowName(zName);
}
static sqlite3_module rtreeModule = {
3, /* iVersion */
4, /* iVersion */
rtreeCreate, /* xCreate - create a table */
rtreeConnect, /* xConnect - connect to an existing table */
rtreeBestIndex, /* xBestIndex - Determine search strategy */
@@ -3501,7 +3506,8 @@ static sqlite3_module rtreeModule = {
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
rtreeShadowName /* xShadowName */
rtreeShadowName, /* xShadowName */
rtreeShadowName2 /* xShadowName2 */
};
static int rtreeSqlInit(
+23
View File
@@ -733,4 +733,27 @@ do_execsql_test 19.1 {
SELECT v0.x FROM v0, rt0 WHERE v0.x = rt0.b;
} {0.0}
# 2022-06-20 https://sqlite.org/forum/forumpost/57bdf2217d
#
reset_db
do_execsql_test 20.0 {
CREATE VIRTUAL TABLE rt0 USING rtree(id, x0, x1);
CREATE TABLE t0(a INT);
CREATE TABLE t1(b INT);
INSERT INTO rt0 VALUES(0, 0, 0);
}
do_catchsql_test 20.1 {
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE +x0 = 0;
} {1 {ON clause references tables to its right}}
do_catchsql_test 20.2 {
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE x0 = 0;
} {1 {ON clause references tables to its right}}
db null -
do_execsql_test 20.3 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE +x0 = 0;
} {- - 0 0.0 0.0}
do_execsql_test 20.4 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE x0 = 0;
} {- - 0 0.0 0.0}
finish_test
+6 -2
View File
@@ -23,6 +23,10 @@ ifcapable !rtree {
return
}
set ::TMPDBERROR [list 1 \
{unable to open a temporary database file for storing temporary tables}
]
# Test summary:
#
# rtree3-1: Test OOM in simple CREATE TABLE, INSERT, DELETE and SELECT
@@ -196,9 +200,9 @@ do_test rtree3-7.prep {
do_faultsim_test rtree3-7 -faults oom-* -prep {
faultsim_restore_and_reopen
} -body {
execsql { ALTER TABLE rt RENAME TO rt2 }
execsql { ALTER TABLE rt RENAME TO rt2 }
} -test {
faultsim_test_result {0 {}}
faultsim_test_result {0 {}} $::TMPDBERROR
}
do_faultsim_test rtree3-8 -faults oom-* -prep {
+1 -1
View File
@@ -342,7 +342,7 @@ do_eqp_execsql_test 7.2 {
QUERY PLAN
|--SCAN xdir
|--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
`--SCAN ydir
`--SCAN ydir LEFT-JOIN
} {
5 1 2 7 12 14 {}
5 2 2 7 8 12 10
+1 -1
View File
@@ -324,7 +324,7 @@ static int SQLITE_TCLAPI register_box_query(
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
pCtx = (BoxQueryCtx*)ckalloc(sizeof(BoxQueryCtx*));
pCtx = (BoxQueryCtx*)ckalloc(sizeof(BoxQueryCtx));
pCtx->interp = interp;
pCtx->pScript = Tcl_DuplicateObj(objv[2]);
Tcl_IncrRefCount(pCtx->pScript);
+15 -5
View File
@@ -423,6 +423,7 @@ TESTSRC2 = \
$(TOP)/src/select.c \
$(TOP)/src/threads.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/treeview.c \
$(TOP)/src/utf.c \
$(TOP)/src/util.c \
$(TOP)/src/vdbeapi.c \
@@ -529,7 +530,7 @@ TESTOPTS = --verbose=file --output=test-out.txt
# Extra compiler options for various shell tools
#
SHELL_OPT += -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_RTREE
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
@@ -538,8 +539,7 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT = -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
@@ -547,6 +547,9 @@ FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZSRC += $(TOP)/test/fuzzcheck.c
FUZZSRC += $(TOP)/test/ossfuzz.c
FUZZSRC += $(TOP)/test/fuzzinvariants.c
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_OPT = -DSQLITE_THREADSAFE=0
@@ -605,10 +608,10 @@ dbfuzz2$(EXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
$(TCCX) -I. -g -O0 -DSTANDALONE -o dbfuzz2$(EXE) \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS) $(THREADLIB)
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
fuzzcheck$(EXE): $(FUZZSRC) sqlite3.c sqlite3.h
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
$(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB)
$(FUZZSRC) sqlite3.c $(TLIBS) $(THREADLIB)
ossshell$(EXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
$(TCCX) -o ossshell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
@@ -955,6 +958,12 @@ valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionf
tcltest: ./testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Runs all the same tests cases as the "tcltest" target but uses
# the testrunner.tcl script to run them in multiple cores
# concurrently.
testrunner: testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/testrunner.tcl
# A very quick test using only testfixture and omitting all the slower
# tests. Designed to run in under 3 minutes on a workstation.
#
@@ -965,6 +974,7 @@ quicktest: ./testfixture$(EXE)
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
test: fuzztest sourcetest $(TESTPROGS) tcltest
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
#
+290 -250
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
4289edf3c5e32a05b51f232020099b33f6f5e79b0ceca2b96baf1186168d9af6
163c6cdf93451cb4ae7655266654d4aec2b94c4ceb0a6fc68859ecc73bf393a9
+101 -58
View File
@@ -324,7 +324,9 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
int r1; /* Temporary registers */
db = pParse->db;
if( pParse->nErr || db->mallocFailed ) return;
assert( db->pParse==pParse );
if( pParse->nErr ) return;
assert( db->mallocFailed==0 );
pNew = pParse->pNewTable;
assert( pNew );
@@ -629,7 +631,7 @@ void sqlite3AlterRenameColumn(
if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
}
if( iCol==pTab->nCol ){
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
goto exit_rename_column;
}
@@ -735,7 +737,9 @@ struct RenameCtx {
** following a valid object, it may not be used in comparison operations.
*/
static void renameTokenCheckAll(Parse *pParse, const void *pPtr){
if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
assert( pParse==pParse->db->pParse );
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
if( pParse->nErr==0 ){
const RenameToken *p;
u8 i = 0;
for(p=pParse->pRename; p; p=p->pNext){
@@ -854,11 +858,10 @@ static void unmapColumnIdlistNames(
Parse *pParse,
const IdList *pIdList
){
if( pIdList ){
int ii;
for(ii=0; ii<pIdList->nId; ii++){
sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName);
}
int ii;
assert( pIdList!=0 );
for(ii=0; ii<pIdList->nId; ii++){
sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName);
}
}
@@ -877,7 +880,7 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
}
}
@@ -886,8 +889,11 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
SrcList *pSrc = p->pSrc;
for(i=0; i<pSrc->nSrc; i++){
sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
sqlite3WalkExpr(pWalker, pSrc->a[i].pOn);
unmapColumnIdlistNames(pParse, pSrc->a[i].pUsing);
if( pSrc->a[i].fg.isUsing==0 ){
sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn);
}else{
unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing);
}
}
}
@@ -923,7 +929,7 @@ void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){
sWalker.xExprCallback = renameUnmapExprCb;
sqlite3WalkExprList(&sWalker, pEList);
for(i=0; i<pEList->nExpr; i++){
if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) ){
if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
}
}
@@ -1057,12 +1063,12 @@ static void renameColumnParseError(
const char *zN = (const char*)sqlite3_value_text(pObject);
char *zErr;
zErr = sqlite3_mprintf("error in %s %s%s%s: %s",
zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s",
zT, zN, (zWhen[0] ? " " : ""), zWhen,
pParse->zErrMsg
);
sqlite3_result_error(pCtx, zErr, -1);
sqlite3_free(zErr);
sqlite3DbFree(pParse->db, zErr);
}
/*
@@ -1081,7 +1087,7 @@ static void renameColumnElistNames(
int i;
for(i=0; i<pEList->nExpr; i++){
const char *zName = pEList->a[i].zEName;
if( ALWAYS(pEList->a[i].eEName==ENAME_NAME)
if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME)
&& ALWAYS(zName!=0)
&& 0==sqlite3_stricmp(zName, zOld)
){
@@ -1127,19 +1133,21 @@ static int renameParseSql(
){
int rc;
sqlite3ParseObjectInit(p, db);
if( zSql==0 ){
return SQLITE_NOMEM;
}
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
return SQLITE_CORRUPT_BKPT;
}
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
/* Parse the SQL statement passed as the first argument. If no error
** occurs and the parse does not result in a new table, index or
** trigger object, the database must be corrupt. */
memset(p, 0, sizeof(Parse));
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
rc = zSql ? sqlite3RunParser(p, zSql) : SQLITE_NOMEM;
rc = sqlite3RunParser(p, zSql);
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
&& p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
){
rc = SQLITE_CORRUPT_BKPT;
}
@@ -1309,27 +1317,33 @@ static int renameResolveTrigger(Parse *pParse){
if( rc==SQLITE_OK && pStep->zTarget ){
SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
if( pSrc ){
int i;
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pSrc->a[i];
p->iCursor = pParse->nTab++;
if( p->pSelect ){
sqlite3SelectPrep(pParse, p->pSelect, 0);
sqlite3ExpandSubquery(pParse, p);
assert( i>0 );
assert( pStep->pFrom->a[i-1].pSelect );
sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0);
}else{
p->pTab = sqlite3LocateTableItem(pParse, 0, p);
if( p->pTab==0 ){
rc = SQLITE_ERROR;
}else{
p->pTab->nTabRef++;
rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
Select *pSel = sqlite3SelectNew(
pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0
);
if( pSel==0 ){
pStep->pExprList = 0;
pSrc = 0;
rc = SQLITE_NOMEM;
}else{
sqlite3SelectPrep(pParse, pSel, 0);
rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList );
assert( pSrc==pSel->pSrc );
if( pStep->pExprList ) pSel->pEList = 0;
pSel->pSrc = 0;
sqlite3SelectDelete(db, pSel);
}
if( pStep->pFrom ){
int i;
for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pStep->pFrom->a[i];
if( p->pSelect ){
sqlite3SelectPrep(pParse, p->pSelect, 0);
}
}
}
if( rc==SQLITE_OK && db->mallocFailed ){
if( db->mallocFailed ){
rc = SQLITE_NOMEM;
}
sNC.pSrcList = pSrc;
@@ -1417,13 +1431,13 @@ static void renameParseCleanup(Parse *pParse){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->zErrMsg);
renameTokenFree(db, pParse->pRename);
sqlite3ParserReset(pParse);
sqlite3ParseObjectReset(pParse);
}
/*
** SQL function:
**
** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP)
**
** 0. zSql: SQL statement to rewrite
** 1. type: Type of object ("table", "view" etc.)
@@ -1441,7 +1455,8 @@ static void renameParseCleanup(Parse *pParse){
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
** It is only accessible to SQL created using sqlite3NestedParse(). It is
** not reachable from ordinary SQL passed into sqlite3_prepare().
** not reachable from ordinary SQL passed into sqlite3_prepare() unless the
** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled.
*/
static void renameColumnFunc(
sqlite3_context *context,
@@ -1590,7 +1605,9 @@ static void renameColumnFunc(
renameColumnFunc_done:
if( rc!=SQLITE_OK ){
if( sParse.zErrMsg ){
if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){
sqlite3_result_value(context, argv[0]);
}else if( sParse.zErrMsg ){
renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlite3_result_error_code(context, rc);
@@ -1778,6 +1795,15 @@ static void renameTableFunc(
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
}
if( pStep->pFrom ){
int i;
for(i=0; i<pStep->pFrom->nSrc; i++){
SrcItem *pItem = &pStep->pFrom->a[i];
if( 0==sqlite3_stricmp(pItem->zName, zOld) ){
renameTokenFind(&sParse, &sCtx, pItem->zName);
}
}
}
}
}
}
@@ -1789,7 +1815,9 @@ static void renameTableFunc(
rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote);
}
if( rc!=SQLITE_OK ){
if( sParse.zErrMsg ){
if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){
sqlite3_result_value(context, argv[3]);
}else if( sParse.zErrMsg ){
renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlite3_result_error_code(context, rc);
@@ -1814,10 +1842,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
/*
** The implementation of an SQL scalar function that rewrites DDL statements
** so that any string literals that use double-quotes are modified so that
** they use single quotes.
/* SQL function: sqlite_rename_quotefix(DB,SQL)
**
** Rewrite the DDL statement "SQL" so that any string literals that use
** double-quotes use single quotes instead.
**
** Two arguments must be passed:
**
@@ -1836,6 +1864,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
** returns the string:
**
** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
**
** If there is a error in the input SQL, then raise an error, except
** if PRAGMA writable_schema=ON, then just return the input string
** unmodified following an error.
*/
static void renameQuotefixFunc(
sqlite3_context *context,
@@ -1910,7 +1942,11 @@ static void renameQuotefixFunc(
renameTokenFree(db, sCtx.pList);
}
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(context, rc);
if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){
sqlite3_result_value(context, argv[1]);
}else{
sqlite3_result_error_code(context, rc);
}
}
renameParseCleanup(&sParse);
}
@@ -1922,7 +1958,8 @@ static void renameQuotefixFunc(
sqlite3BtreeLeaveAll(db);
}
/*
/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS)
**
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
@@ -1937,11 +1974,13 @@ static void renameQuotefixFunc(
** 5: "when" part of error message.
** 6: True to disable the DQS quirk when parsing SQL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
** The return value is computed as follows:
**
** * the SQL argument creates a trigger, and
** * the table that the trigger is attached to is in database zDb.
** A. If an error is seen and not in PRAGMA writable_schema=ON mode,
** then raise the error.
** B. Else if a trigger is created and the the table that the trigger is
** attached to is in database zDb, then return 1.
** C. Otherwise return NULL.
*/
static void renameTableTest(
sqlite3_context *context,
@@ -1986,12 +2025,16 @@ static void renameTableTest(
if( rc==SQLITE_OK ){
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
int i2 = sqlite3FindDbName(db, zDb);
if( i1==i2 ) sqlite3_result_int(context, 1);
if( i1==i2 ){
/* Handle output case B */
sqlite3_result_int(context, 1);
}
}
}
}
if( rc!=SQLITE_OK && zWhen ){
if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){
/* Output case A */
renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
}
renameParseCleanup(&sParse);
@@ -2107,7 +2150,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
}
iCol = sqlite3ColumnIndex(pTab, zCol);
if( iCol<0 ){
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol);
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName);
goto exit_drop_column;
}
+8 -2
View File
@@ -847,9 +847,14 @@ static void statGet(
** * "WHERE a=? AND b=?" matches 2 rows.
**
** If D is the count of distinct values and K is the total number of
** rows, then each estimate is computed as:
** rows, then each estimate is usually computed as:
**
** I = (K+D-1)/D
**
** In other words, I is K/D rounded up to the next whole integer.
** However, if I is between 1.0 and 1.1 (in other words if I is
** close to 1.0 but just a little larger) then do not round up but
** instead keep the I value at 1.0.
*/
sqlite3_str sStat; /* Text of the constructed "stat" line */
int i; /* Loop counter */
@@ -860,6 +865,7 @@ static void statGet(
for(i=0; i<p->nKeyCol; i++){
u64 nDistinct = p->current.anDLt[i] + 1;
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
sqlite3_str_appendf(&sStat, " %llu", iVal);
assert( p->current.anEq[i] );
}
@@ -1023,7 +1029,7 @@ static void analyzeOneTable(
memcpy(pStat1->zName, "sqlite_stat1", 13);
pStat1->nCol = 3;
pStat1->iPKey = -1;
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC);
}
#endif
+6 -2
View File
@@ -354,7 +354,7 @@ static void codeAttach(
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pAuthArg ){
if( ALWAYS(pAuthArg) ){
char *zAuthArg;
if( pAuthArg->op==TK_STRING ){
assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
@@ -480,7 +480,11 @@ static int fixSelectCb(Walker *p, Select *pSelect){
pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
if( pList->a[i].fg.isUsing==0
&& sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn)
){
return WRC_Abort;
}
#endif
}
if( pSelect->pWith ){
+2 -3
View File
@@ -85,14 +85,13 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
if( i==1 ){
Parse sParse;
int rc = 0;
memset(&sParse, 0, sizeof(sParse));
sParse.db = pDb;
sqlite3ParseObjectInit(&sParse,pDb);
if( sqlite3OpenTempDatabase(&sParse) ){
sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, sParse.zErrMsg);
sqlite3ParserReset(&sParse);
sqlite3ParseObjectReset(&sParse);
if( rc ){
return 0;
}
+289 -100
View File
@@ -214,7 +214,7 @@ static int hasSharedCacheTableLock(
int bSeen = 0;
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
Index *pIdx = (Index *)sqliteHashData(p);
if( pIdx->tnum==(int)iRoot ){
if( pIdx->tnum==iRoot ){
if( bSeen ){
/* Two or more indexes share the same root page. There must
** be imposter tables. So just return true. The assert is not
@@ -807,7 +807,7 @@ void sqlite3BtreeClearCursor(BtCursor *pCur){
/*
** In this version of BtreeMoveto, pKey is a packed index record
** such as is generated by the OP_MakeRecord opcode. Unpack the
** record and then call BtreeMovetoUnpacked() to do the work.
** record and then call sqlite3BtreeIndexMoveto() to do the work.
*/
static int btreeMoveto(
BtCursor *pCur, /* Cursor open on the btree to be searched */
@@ -1327,6 +1327,7 @@ static void btreeParseCell(
** the space used by the cell pointer.
**
** cellSizePtrNoPayload() => table internal nodes
** cellSizePtrTableLeaf() => table leaf nodes
** cellSizePtr() => all index nodes & table leaf nodes
*/
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
@@ -1352,13 +1353,6 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
}while( *(pIter)>=0x80 && pIter<pEnd );
}
pIter++;
if( pPage->intKey ){
/* pIter now points at the 64-bit integer key value, a variable length
** integer. The following block moves pIter to point at the first byte
** past the end of the key value. */
pEnd = &pIter[9];
while( (*pIter++)&0x80 && pIter<pEnd );
}
testcase( nSize==pPage->maxLocal );
testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize<=pPage->maxLocal ){
@@ -1398,6 +1392,58 @@ static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB );
return (u16)(pIter - pCell);
}
static u16 cellSizePtrTableLeaf(MemPage *pPage, u8 *pCell){
u8 *pIter = pCell; /* For looping over bytes of pCell */
u8 *pEnd; /* End mark for a varint */
u32 nSize; /* Size value to return */
#ifdef SQLITE_DEBUG
/* The value returned by this function should always be the same as
** the (CellInfo.nSize) value found by doing a full parse of the
** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
** this function verifies that this invariant is not violated. */
CellInfo debuginfo;
pPage->xParseCell(pPage, pCell, &debuginfo);
#endif
nSize = *pIter;
if( nSize>=0x80 ){
pEnd = &pIter[8];
nSize &= 0x7f;
do{
nSize = (nSize<<7) | (*++pIter & 0x7f);
}while( *(pIter)>=0x80 && pIter<pEnd );
}
pIter++;
/* pIter now points at the 64-bit integer key value, a variable length
** integer. The following block moves pIter to point at the first byte
** past the end of the key value. */
if( (*pIter++)&0x80
&& (*pIter++)&0x80
&& (*pIter++)&0x80
&& (*pIter++)&0x80
&& (*pIter++)&0x80
&& (*pIter++)&0x80
&& (*pIter++)&0x80
&& (*pIter++)&0x80 ){ pIter++; }
testcase( nSize==pPage->maxLocal );
testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize<=pPage->maxLocal ){
nSize += (u32)(pIter - pCell);
if( nSize<4 ) nSize = 4;
}else{
int minLocal = pPage->minLocal;
nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
testcase( nSize==pPage->maxLocal );
testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize>pPage->maxLocal ){
nSize = minLocal;
}
nSize += 4 + (u16)(pIter - pCell);
}
assert( nSize==debuginfo.nSize || CORRUPT_DB );
return (u16)nSize;
}
#ifdef SQLITE_DEBUG
@@ -1411,7 +1457,7 @@ static u16 cellSize(MemPage *pPage, int iCell){
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** The cell pCell is currently part of page pSrc but will ultimately be part
** of pPage. (pSrc and pPager are often the same.) If pCell contains a
** of pPage. (pSrc and pPage are often the same.) If pCell contains a
** pointer to an overflow page, insert an entry into the pointer-map for
** the overflow page that will be valid after pCell has been moved to pPage.
*/
@@ -1467,7 +1513,6 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
assert( pPage->nOverflow==0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
temp = 0;
src = data = pPage->aData;
hdr = pPage->hdrOffset;
cellOffset = pPage->cellOffset;
@@ -1522,39 +1567,38 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
cbrk = usableSize;
iCellLast = usableSize - 4;
iCellStart = get2byte(&data[hdr+5]);
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
pc = get2byte(pAddr);
testcase( pc==iCellFirst );
testcase( pc==iCellLast );
/* These conditions have already been verified in btreeInitPage()
** if PRAGMA cell_size_check=ON.
*/
if( pc<iCellStart || pc>iCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
if( nCell>0 ){
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
src = temp;
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
pc = get2byte(pAddr);
testcase( pc==iCellFirst );
testcase( pc==iCellLast );
/* These conditions have already been verified in btreeInitPage()
** if PRAGMA cell_size_check=ON.
*/
if( pc<iCellStart || pc>iCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrk<iCellStart || pc+size>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
memcpy(&data[cbrk], &src[pc], size);
}
assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrk<iCellStart || pc+size>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
if( temp==0 ){
if( cbrk==pc ) continue;
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
src = temp;
}
memcpy(&data[cbrk], &src[pc], size);
}
data[hdr+7] = 0;
defragment_out:
defragment_out:
assert( pPage->nFree>=0 );
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_PAGE(pPage);
@@ -1586,7 +1630,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
const int hdr = pPg->hdrOffset; /* Offset to page header */
u8 * const aData = pPg->aData; /* Page data */
int iAddr = hdr + 1; /* Address of ptr to pc */
int pc = get2byte(&aData[iAddr]); /* Address of a free slot */
u8 *pTmp = &aData[iAddr]; /* Temporary ptr into aData[] */
int pc = get2byte(pTmp); /* Address of a free slot */
int x; /* Excess size of the slot */
int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */
int size; /* Size of the free slot */
@@ -1596,7 +1641,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
** freeblock form a big-endian integer which is the size of the freeblock
** in bytes, including the 4-byte header. */
size = get2byte(&aData[pc+2]);
pTmp = &aData[pc+2];
size = get2byte(pTmp);
if( (x = size - nByte)>=0 ){
testcase( x==4 );
testcase( x==3 );
@@ -1609,6 +1655,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
testcase( pc+x>maxPC );
return &aData[pc];
}else if( x+pc > maxPC ){
/* This slot extends off the end of the usable part of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
@@ -1621,10 +1669,11 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
return &aData[pc + x];
}
iAddr = pc;
pc = get2byte(&aData[pc]);
if( pc<=iAddr+size ){
pTmp = &aData[pc];
pc = get2byte(pTmp);
if( pc<=iAddr ){
if( pc ){
/* The next slot in the chain is not past the end of the current slot */
/* The next slot in the chain comes before the current slot */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
}
return 0;
@@ -1655,6 +1704,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
u8 * const data = pPage->aData; /* Local cache of pPage->aData */
int top; /* First byte of cell content area */
int rc = SQLITE_OK; /* Integer return code */
u8 *pTmp; /* Temp ptr into data[] */
int gap; /* First byte of gap between cell pointers and cell content */
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -1673,7 +1723,8 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** then the cell content offset of an empty page wants to be 65536.
** However, that integer is too large to be stored in a 2-byte unsigned
** integer, so a value of 0 is used in its place. */
top = get2byte(&data[hdr+5]);
pTmp = &data[hdr+5];
top = get2byte(pTmp);
assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */
if( gap>top ){
if( top==0 && pPage->pBt->usableSize==65536 ){
@@ -1755,6 +1806,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
u16 x; /* Offset to cell content area */
u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
u8 *pTmp; /* Temporary ptr into data[] */
assert( pPage->pBt!=0 );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -1773,7 +1825,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */
}else{
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
if( iFreeBlk<iPtr+4 ){
if( iFreeBlk<=iPtr ){
if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -1782,7 +1834,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 );
assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
/* At this point:
** iFreeBlk: First freeblock after iStart, or zero if none
@@ -1817,7 +1869,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
data[hdr+7] -= nFrag;
}
x = get2byte(&data[hdr+5]);
pTmp = &data[hdr+5];
x = get2byte(pTmp);
if( iStart<=x ){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
@@ -1861,7 +1914,6 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf;
pPage->xCellSize = cellSizePtr;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
/* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an
@@ -1873,6 +1925,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->intKey = 1;
if( pPage->leaf ){
pPage->intKeyLeaf = 1;
pPage->xCellSize = cellSizePtrTableLeaf;
pPage->xParseCell = btreeParseCellPtr;
}else{
pPage->intKeyLeaf = 0;
@@ -1890,12 +1943,17 @@ static int decodeFlags(MemPage *pPage, int flagByte){
assert( (PTF_ZERODATA|PTF_LEAF)==10 );
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
pPage->xCellSize = cellSizePtr;
pPage->xParseCell = btreeParseCellPtrIndex;
pPage->maxLocal = pBt->maxLocal;
pPage->minLocal = pBt->minLocal;
}else{
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
** an error. */
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
pPage->xCellSize = cellSizePtr;
pPage->xParseCell = btreeParseCellPtrIndex;
return SQLITE_CORRUPT_PAGE(pPage);
}
pPage->max1bytePayload = pBt->max1bytePayload;
@@ -2053,7 +2111,7 @@ static int btreeInitPage(MemPage *pPage){
pPage->nOverflow = 0;
pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
pPage->aCellIdx = data + pPage->childPtrSize + 8;
pPage->aDataEnd = pPage->aData + pBt->usableSize;
pPage->aDataEnd = pPage->aData + pBt->pageSize;
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
** number of cells on the page. */
@@ -2088,7 +2146,7 @@ static void zeroPage(MemPage *pPage, int flags){
u8 hdr = pPage->hdrOffset;
u16 first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -2104,7 +2162,7 @@ static void zeroPage(MemPage *pPage, int flags){
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
pPage->cellOffset = first;
pPage->aDataEnd = &data[pBt->usableSize];
pPage->aDataEnd = &data[pBt->pageSize];
pPage->aCellIdx = &data[first];
pPage->aDataOfst = &data[pPage->childPtrSize];
pPage->nOverflow = 0;
@@ -2230,7 +2288,7 @@ static int getAndInitPage(
goto getAndInitPage_error2;
}
}
assert( (*ppPage)->pgno==pgno );
assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
/* If obtaining a child page for a cursor, we must verify that the page is
@@ -2249,7 +2307,7 @@ getAndInitPage_error1:
pCur->pPage = pCur->apPage[pCur->iPage];
}
testcase( pgno==0 );
assert( pgno!=0 || rc==SQLITE_CORRUPT );
assert( pgno!=0 || rc!=SQLITE_OK );
return rc;
}
@@ -3871,12 +3929,17 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
}
do {
MemPage *pFreePg;
Pgno dbSize = btreePagecount(pBt);
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
if( rc!=SQLITE_OK ){
releasePage(pLastPg);
return rc;
}
releasePage(pFreePg);
if( iFreePg>dbSize ){
releasePage(pLastPg);
return SQLITE_CORRUPT_BKPT;
}
}while( bCommit && iFreePg>nFin );
assert( iFreePg<iLastPg );
@@ -5186,8 +5249,6 @@ const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
** vice-versa).
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
BtShared *pBt = pCur->pBt;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
@@ -5201,7 +5262,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
return getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur,
pCur->curPagerFlags);
}
#ifdef SQLITE_DEBUG
@@ -5307,7 +5369,7 @@ static int moveToRoot(BtCursor *pCur){
}
sqlite3BtreeClearCursor(pCur);
}
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage,
0, pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
@@ -5317,7 +5379,7 @@ static int moveToRoot(BtCursor *pCur){
pCur->curIntKey = pCur->pPage->intKey;
}
pRoot = pCur->pPage;
assert( pRoot->pgno==pCur->pgnoRoot );
assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB );
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
@@ -5638,6 +5700,69 @@ moveto_table_finish:
return rc;
}
/*
** Compare the "idx"-th cell on the page the cursor pCur is currently
** pointing to to pIdxKey using xRecordCompare. Return negative or
** zero if the cell is less than or equal pIdxKey. Return positive
** if unknown.
**
** Return value negative: Cell at pCur[idx] less than pIdxKey
**
** Return value is zero: Cell at pCur[idx] equals pIdxKey
**
** Return value positive: Nothing is known about the relationship
** of the cell at pCur[idx] and pIdxKey.
**
** This routine is part of an optimization. It is always safe to return
** a positive value as that will cause the optimization to be skipped.
*/
static int indexCellCompare(
BtCursor *pCur,
int idx,
UnpackedRecord *pIdxKey,
RecordCompare xRecordCompare
){
MemPage *pPage = pCur->pPage;
int c;
int nCell; /* Size of the pCell cell in bytes */
u8 *pCell = findCellPastPtr(pPage, idx);
nCell = pCell[0];
if( nCell<=pPage->max1bytePayload ){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* If the record extends into overflow pages, do not attempt
** the optimization. */
c = 99;
}
return c;
}
/*
** Return true (non-zero) if pCur is current pointing to the last
** page of a table.
*/
static int cursorOnLastPage(BtCursor *pCur){
int i;
assert( pCur->eState==CURSOR_VALID );
for(i=0; i<pCur->iPage; i++){
MemPage *pPage = pCur->apPage[i];
if( pCur->aiIdx[i]<pPage->nCell ) return 0;
}
return 1;
}
/* Move the cursor so that it points to an entry in an index table
** near the key pIdxKey. Return a success code.
**
@@ -5688,6 +5813,43 @@ int sqlite3BtreeIndexMoveto(
|| pIdxKey->default_rc==-1
);
/* Check to see if we can skip a lot of work. Two cases:
**
** (1) If the cursor is already pointing to the very last cell
** in the table and the pIdxKey search key is greater than or
** equal to that last cell, then no movement is required.
**
** (2) If the cursor is on the last page of the table and the first
** cell on that last page is less than or equal to the pIdxKey
** search key, then we can start the search on the current page
** without needing to go back to root.
*/
if( pCur->eState==CURSOR_VALID
&& pCur->pPage->leaf
&& cursorOnLastPage(pCur)
){
int c;
if( pCur->ix==pCur->pPage->nCell-1
&& (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0
&& pIdxKey->errCode==SQLITE_OK
){
*pRes = c;
return SQLITE_OK; /* Cursor already pointing at the correct spot */
}
if( pCur->iPage>0
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
pCur->curFlags &= ~BTCF_ValidOvfl;
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
goto bypass_moveto_root; /* Start search on the current page */
}
pIdxKey->errCode = SQLITE_OK;
}
rc = moveToRoot(pCur);
if( rc ){
if( rc==SQLITE_EMPTY ){
@@ -5697,12 +5859,14 @@ int sqlite3BtreeIndexMoveto(
}
return rc;
}
bypass_moveto_root:
assert( pCur->pPage );
assert( pCur->pPage->isInit );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->pPage->nCell > 0 );
assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
assert( pCur->curIntKey || pIdxKey );
assert( pCur->curIntKey==0 );
assert( pIdxKey!=0 );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
@@ -5716,7 +5880,7 @@ int sqlite3BtreeIndexMoveto(
** be the right kind (index or table) of b-tree page. Otherwise
** a moveToChild() or moveToRoot() call would have detected corruption. */
assert( pPage->nCell>0 );
assert( pPage->intKey==(pIdxKey==0) );
assert( pPage->intKey==0 );
lwr = 0;
upr = pPage->nCell-1;
idx = upr>>1; /* idx = (lwr+upr)/2; */
@@ -5808,7 +5972,7 @@ int sqlite3BtreeIndexMoveto(
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->ix<pCur->pPage->nCell );
assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
@@ -6411,7 +6575,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
assert( CORRUPT_DB || iPage>1 );
assert( !pMemPage || pMemPage->pgno==iPage );
if( NEVER(iPage<2) || iPage>pBt->nPage ){
if( iPage<2 || iPage>pBt->nPage ){
return SQLITE_CORRUPT_BKPT;
}
if( pMemPage ){
@@ -8326,7 +8490,7 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
for(k=0; b.ixNx[k]<=j && ALWAYS(k<NB*2); k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
@@ -8577,7 +8741,6 @@ static int anotherValidCursor(BtCursor *pCur){
*/
static int balance(BtCursor *pCur){
int rc = SQLITE_OK;
const int nMin = pCur->pBt->usableSize * 2 / 3;
u8 aBalanceQuickSpace[13];
u8 *pFree = 0;
@@ -8589,7 +8752,11 @@ static int balance(BtCursor *pCur){
MemPage *pPage = pCur->pPage;
if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
/* No rebalance required as long as:
** (1) There are no overflow cells
** (2) The amount of free space on the page is less than 2/3rds of
** the total usable space on the page. */
break;
}else if( (iPage = pCur->iPage)==0 ){
if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
@@ -8809,7 +8976,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
** sqlite3BtreeIndexMoveto() to seek cursor pCur to (pKey,nKey) has already
** been performed. In other words, if seekResult!=0 then the cursor
** is currently pointing to a cell that will be adjacent to the cell
** to be inserted. If seekResult<0 then pCur points to a cell that is
@@ -8827,7 +8994,7 @@ int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const BtreePayload *pX, /* Content of the row to be inserted */
int flags, /* True if this is likely an append */
int seekResult /* Result of prior MovetoUnpacked() call */
int seekResult /* Result of prior IndexMoveto() call */
){
int rc;
int loc = seekResult; /* -1: before desired location +1: after */
@@ -8842,24 +9009,6 @@ int sqlite3BtreeInsert(
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
}
assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
** expecting an index b-tree, then the caller should be inserting blob
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
** In some cases, the call to btreeMoveto() below is a no-op. For
@@ -8884,6 +9033,29 @@ int sqlite3BtreeInsert(
}
}
/* Ensure that the cursor is not in the CURSOR_FAULT state and that it
** points to a valid cell.
*/
if( pCur->eState>=CURSOR_REQUIRESEEK ){
testcase( pCur->eState==CURSOR_REQUIRESEEK );
testcase( pCur->eState==CURSOR_FAULT );
rc = moveToRoot(pCur);
if( rc && rc!=SQLITE_EMPTY ) return rc;
}
assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
** expecting an index b-tree, then the caller should be inserting blob
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
@@ -8972,14 +9144,14 @@ int sqlite3BtreeInsert(
}
}
assert( pCur->eState==CURSOR_VALID
|| (pCur->eState==CURSOR_INVALID && loc)
|| CORRUPT_DB );
|| (pCur->eState==CURSOR_INVALID && loc) );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
if( NEVER(pCur->eState>CURSOR_INVALID) ){
/* ^^^^^--- due to the moveToRoot() call above */
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
@@ -8990,7 +9162,7 @@ int sqlite3BtreeInsert(
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
assert( pPage->isInit );
assert( pPage->isInit || CORRUPT_DB );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
if( flags & BTREE_PREFORMAT ){
@@ -9141,7 +9313,11 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
u32 nRem; /* Bytes of data still to copy */
getCellInfo(pSrc);
aOut += putVarint32(aOut, pSrc->info.nPayload);
if( pSrc->info.nPayload<0x80 ){
*(aOut++) = pSrc->info.nPayload;
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
nIn = pSrc->info.nLocal;
aIn = pSrc->info.pPayload;
@@ -9260,12 +9436,16 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState==CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
if( pCur->eState!=CURSOR_VALID ){
if( pCur->eState>=CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}else{
return SQLITE_CORRUPT_BKPT;
}
}
assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
assert( pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
@@ -9297,7 +9477,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
bPreserve = (flags & BTREE_SAVEPOSITION)!=0;
if( bPreserve ){
if( !pPage->leaf
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
|| (pPage->nFree+pPage->xCellSize(pPage,pCell)+2) >
(int)(pBt->usableSize*2/3)
|| pPage->nCell==1 /* See dbfuzz001.test for a test case */
){
/* A b-tree rebalance will be required after deleting this entry.
@@ -9393,7 +9574,15 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** been corrected, so be it. Otherwise, after balancing the leaf node,
** walk the cursor up the tree to the internal node and balance it as
** well. */
rc = balance(pCur);
assert( pCur->pPage->nOverflow==0 );
assert( pCur->pPage->nFree>=0 );
if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
/* Optimization: If the free space is less than 2/3rds of the page,
** then balance() will always be a no-op. No need to invoke it. */
rc = SQLITE_OK;
}else{
rc = balance(pCur);
}
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
releasePageNotNull(pCur->pPage);
pCur->iPage--;
@@ -9616,7 +9805,7 @@ static int clearDatabasePage(
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
if( rc ) return rc;
if( (pBt->openFlags & BTREE_SINGLE)==0
&& sqlite3PagerPageRefcount(pPage->pDbPage)!=1
&& sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
){
rc = SQLITE_CORRUPT_BKPT;
goto cleardatabasepage_out;
+4 -2
View File
@@ -293,7 +293,9 @@ struct MemPage {
u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
u8 *aDataEnd; /* One byte past the end of usable data */
u8 *aDataEnd; /* One byte past the end of the entire page - not just
** the usable space, the entire page. Used to prevent
** corruption-induced buffer overflow. */
u8 *aCellIdx; /* The cell index area */
u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
DbPage *pDbPage; /* Pager page handle */
@@ -598,7 +600,7 @@ struct BtCursor {
/*
** The database page the PENDING_BYTE occupies. This page is never used.
*/
# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
#define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1))
/*
** These macros define the location of the pointer-map entry for a
+156 -63
View File
@@ -143,11 +143,13 @@ void sqlite3FinishCoding(Parse *pParse){
assert( pParse->pToplevel==0 );
db = pParse->db;
assert( db->pParse==pParse );
if( pParse->nested ) return;
if( db->mallocFailed || pParse->nErr ){
if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
if( pParse->nErr ){
if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM;
return;
}
assert( db->mallocFailed==0 );
/* Begin by generating some termination code at the end of the
** vdbe program
@@ -170,9 +172,7 @@ void sqlite3FinishCoding(Parse *pParse){
int i;
int reg;
if( NEVER(pReturning->nRetCol==0) ){
assert( CORRUPT_DB );
}else{
if( pReturning->nRetCol ){
sqlite3VdbeAddOp0(v, OP_FkCheck);
addrRewind =
sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
@@ -212,7 +212,9 @@ void sqlite3FinishCoding(Parse *pParse){
int iDb, i;
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
sqlite3VdbeJumpHere(v, 0);
for(iDb=0; iDb<db->nDb; iDb++){
assert( db->nDb>0 );
iDb = 0;
do{
Schema *pSchema;
if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
sqlite3VdbeUsesBtree(v, iDb);
@@ -227,7 +229,7 @@ void sqlite3FinishCoding(Parse *pParse){
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
VdbeComment((v,
"usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
}
}while( ++iDb<db->nDb );
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
@@ -266,9 +268,7 @@ void sqlite3FinishCoding(Parse *pParse){
if( pParse->bReturning ){
Returning *pRet = pParse->u1.pReturning;
if( NEVER(pRet->nRetCol==0) ){
assert( CORRUPT_DB );
}else{
if( pRet->nRetCol ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
}
}
@@ -280,7 +280,9 @@ void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !db->mallocFailed ){
assert( v!=0 || pParse->nErr );
assert( db->mallocFailed==0 || pParse->nErr );
if( pParse->nErr==0 ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
assert( pParse->pAinc==0 || pParse->nTab>0 );
@@ -1289,7 +1291,8 @@ void sqlite3StartTable(
pTable = sqlite3FindTable(db, zName, zDb);
if( pTable ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
sqlite3ErrorMsg(pParse, "%s %T already exists",
(IsView(pTable)? "view" : "table"), pName);
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
@@ -1885,7 +1888,7 @@ void sqlite3AddPrimaryKey(
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags;
(void)sqlite3HasExplicitNulls(pParse, pList);
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -2379,15 +2382,16 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
pList->a[0].sortFlags = pParse->iPkSortOrder;
pList->a[0].fg.sortFlags = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab );
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
if( db->mallocFailed || pParse->nErr ){
if( pParse->nErr ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
}
assert( db->mallocFailed==0 );
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
@@ -2487,6 +2491,51 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Returns non-zero if the module supports at least one of the xShadowName
** or xShadowName2 methods.
*/
static int doesSupportShadowNames(
const sqlite3_module *pModule, /* The definition of the module */
VTable *pVTab /* The virtual table being asked */
){
int iVersion;
assert( pModule!=0 );
iVersion = pModule->iVersion;
if( pVTab!=0 && iVersion>=4 && pModule->xShadowName2!=0 ) return 1;
if( iVersion>=3 && pModule->xShadowName!=0 ) return 1;
return 0;
}
/*
** Attempts to calls one of the module xShadowName methods and returns its
** result. The xShadowName2 method will be preferred when supported (i.e.
** the module is version 4 or later and has an xShadowName2 method).
*/
static int isShadowTableOf(
sqlite3 *db, /* Database connection */
Table *pTab, /* The Table that refers to the virtual table */
Module *pMod, /* Definition of the module */
VTable *pVTab, /* The virtual table being asked */
const char *zName /* Table name that may refer to a shadow table */
){
int iVersion;
assert( pMod!=0 );
assert( pMod->pModule!=0 );
iVersion = pMod->pModule->iVersion;
assert( iVersion>=3 );
assert( zName!=0 );
assert( sqlite3Strlen30(zName)>0 );
if( pVTab!=0 && iVersion>=4 && pMod->pModule->xShadowName2!=0 ){
assert( pVTab->pVtab!=0 );
return pMod->pModule->xShadowName2(pVTab->pVtab, zName);
}
if( pMod->pModule->xShadowName!=0 ){
return pMod->pModule->xShadowName(zName);
}
return 0;
}
/*
** Return true if pTab is a virtual table and zName is a shadow table name
** for that virtual table.
@@ -2494,6 +2543,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
int nName; /* Length of zName */
Module *pMod; /* Module for the virtual table */
VTable *pVTab; /* The virtual table being asked */
if( !IsVirtual(pTab) ) return 0;
nName = sqlite3Strlen30(pTab->zName);
@@ -2501,9 +2551,10 @@ int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
if( zName[nName]!='_' ) return 0;
pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
if( pMod==0 ) return 0;
if( pMod->pModule->iVersion<3 ) return 0;
if( pMod->pModule->xShadowName==0 ) return 0;
return pMod->pModule->xShadowName(zName+nName+1);
if( NEVER(pMod->pModule==0) ) return 0;
pVTab = sqlite3GetVTable(db, pTab);
if( !doesSupportShadowNames(pMod->pModule, pVTab) ) return 0;
return isShadowTableOf(db, pTab, pMod, pVTab, zName+nName+1);
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
@@ -2517,14 +2568,15 @@ int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
int nName; /* Length of pTab->zName */
Module *pMod; /* Module for the virtual table */
VTable *pVTab; /* Virtual table instance */
HashElem *k; /* For looping through the symbol table */
assert( IsVirtual(pTab) );
pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
if( pMod==0 ) return;
if( NEVER(pMod->pModule==0) ) return;
if( pMod->pModule->iVersion<3 ) return;
if( pMod->pModule->xShadowName==0 ) return;
pVTab = sqlite3GetVTable(db, pTab);
if( !doesSupportShadowNames(pMod->pModule, pVTab) ) return;
assert( pTab->zName!=0 );
nName = sqlite3Strlen30(pTab->zName);
for(k=sqliteHashFirst(&pTab->pSchema->tblHash); k; k=sqliteHashNext(k)){
@@ -2534,7 +2586,7 @@ void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
if( pOther->tabFlags & TF_Shadow ) continue;
if( sqlite3StrNICmp(pOther->zName, pTab->zName, nName)==0
&& pOther->zName[nName]=='_'
&& pMod->pModule->xShadowName(pOther->zName+nName+1)
&& isShadowTableOf(db, pTab, pMod, pVTab, pOther->zName+nName+1)
){
pOther->tabFlags |= TF_Shadow;
}
@@ -2818,6 +2870,11 @@ void sqlite3EndTable(
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
if( IN_SPECIAL_PARSE ){
pParse->rc = SQLITE_ERROR;
pParse->nErr++;
return;
}
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
@@ -3044,7 +3101,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
Table *pSelTab; /* A fake table from which we get the result set */
Select *pSel; /* Copy of the SELECT that implements the view */
int nErr = 0; /* Number of errors encountered */
int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
#ifndef SQLITE_OMIT_VIRTUALTABLE
int rc;
@@ -3102,8 +3158,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
if( pSel ){
u8 eParseMode = pParse->eParseMode;
int nTab = pParse->nTab;
int nSelect = pParse->nSelect;
pParse->eParseMode = PARSE_MODE_NORMAL;
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
DisableLookaside;
@@ -3115,7 +3172,8 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
#else
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = n;
pParse->nTab = nTab;
pParse->nSelect = nSelect;
if( pSelTab==0 ){
pTable->nCol = 0;
nErr++;
@@ -3128,10 +3186,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
*/
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
if( db->mallocFailed==0
&& pParse->nErr==0
if( pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
assert( db->mallocFailed==0 );
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
SQLITE_AFF_NONE);
}
@@ -3750,7 +3808,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
tnum = pIndex->tnum;
}
pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
assert( pKey!=0 || pParse->nErr );
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
@@ -3860,8 +3918,8 @@ int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
if( pList ){
int i;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].bNulls ){
u8 sf = pList->a[i].sortFlags;
if( pList->a[i].fg.bNulls ){
u8 sf = pList->a[i].fg.sortFlags;
sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s",
(sf==0 || sf==3) ? "FIRST" : "LAST"
);
@@ -3914,9 +3972,11 @@ void sqlite3CreateIndex(
char *zExtra = 0; /* Extra space after the Index object */
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
if( db->mallocFailed || pParse->nErr>0 ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto exit_create_index;
}
assert( db->mallocFailed==0 );
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
goto exit_create_index;
}
@@ -3980,7 +4040,6 @@ void sqlite3CreateIndex(
pDb = &db->aDb[iDb];
assert( pTab!=0 );
assert( pParse->nErr==0 );
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
@@ -4213,7 +4272,7 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
requestedSortOrder = pListItem->sortFlags & sortOrderMask;
requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
}
@@ -4544,10 +4603,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
sqlite3 *db = pParse->db;
int iDb;
assert( pParse->nErr==0 ); /* Never called with prior errors */
if( db->mallocFailed ){
goto exit_drop_index;
}
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
@@ -4656,18 +4715,17 @@ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
if( pList==0 ){
pList = sqlite3DbMallocZero(db, sizeof(IdList) );
if( pList==0 ) return 0;
}else{
IdList *pNew;
pNew = sqlite3DbRealloc(db, pList,
sizeof(IdList) + pList->nId*sizeof(pList->a));
if( pNew==0 ){
sqlite3IdListDelete(db, pList);
return 0;
}
pList = pNew;
}
pList->a = sqlite3ArrayAllocate(
db,
pList->a,
sizeof(pList->a[0]),
&pList->nId,
&i
);
if( i<0 ){
sqlite3IdListDelete(db, pList);
return 0;
}
i = pList->nId++;
pList->a[i].zName = sqlite3NameFromToken(db, pToken);
if( IN_RENAME_OBJECT && pList->a[i].zName ){
sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken);
@@ -4681,10 +4739,10 @@ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
if( pList==0 ) return;
assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
for(i=0; i<pList->nId; i++){
sqlite3DbFree(db, pList->a[i].zName);
}
sqlite3DbFree(db, pList->a);
sqlite3DbFreeNN(db, pList);
}
@@ -4694,7 +4752,7 @@ void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
*/
int sqlite3IdListIndex(IdList *pList, const char *zName){
int i;
if( pList==0 ) return -1;
assert( pList!=0 );
for(i=0; i<pList->nId; i++){
if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
}
@@ -4897,8 +4955,11 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
if( pItem->pOn ) sqlite3ExprDelete(db, pItem->pOn);
if( pItem->pUsing ) sqlite3IdListDelete(db, pItem->pUsing);
if( pItem->fg.isUsing ){
sqlite3IdListDelete(db, pItem->u3.pUsing);
}else if( pItem->u3.pOn ){
sqlite3ExprDelete(db, pItem->u3.pOn);
}
}
sqlite3DbFreeNN(db, pList);
}
@@ -4926,14 +4987,13 @@ SrcList *sqlite3SrcListAppendFromTerm(
Token *pDatabase, /* Name of the database containing pTable */
Token *pAlias, /* The right-hand side of the AS subexpression */
Select *pSubquery, /* A subquery used in place of a table name */
Expr *pOn, /* The ON clause of a join */
IdList *pUsing /* The USING clause of a join */
OnOrUsing *pOnUsing /* Either the ON clause or the USING clause */
){
SrcItem *pItem;
sqlite3 *db = pParse->db;
if( !p && (pOn || pUsing) ){
if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){
sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
(pOn ? "ON" : "USING")
(pOnUsing->pOn ? "ON" : "USING")
);
goto append_from_error;
}
@@ -4953,15 +5013,27 @@ SrcList *sqlite3SrcListAppendFromTerm(
if( pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
pItem->pSelect = pSubquery;
pItem->pOn = pOn;
pItem->pUsing = pUsing;
if( pSubquery ){
pItem->pSelect = pSubquery;
if( pSubquery->selFlags & SF_NestedFrom ){
pItem->fg.isNestedFrom = 1;
}
}
assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
assert( pItem->fg.isUsing==0 );
if( pOnUsing==0 ){
pItem->u3.pOn = 0;
}else if( pOnUsing->pUsing ){
pItem->fg.isUsing = 1;
pItem->u3.pUsing = pOnUsing->pUsing;
}else{
pItem->u3.pOn = pOnUsing->pOn;
}
return p;
append_from_error:
assert( p==0 );
sqlite3ExprDelete(db, pOn);
sqlite3IdListDelete(db, pUsing);
sqlite3ClearOnOrUsing(db, pOnUsing);
sqlite3SelectDelete(db, pSubquery);
return 0;
}
@@ -5006,6 +5078,7 @@ SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
p1 = pNew;
memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
sqlite3DbFree(pParse->db, p2);
p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype);
}
}
return p1;
@@ -5042,14 +5115,34 @@ void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
** The operator is "natural cross join". The A and B operands are stored
** in p->a[0] and p->a[1], respectively. The parser initially stores the
** operator with A. This routine shifts that operator over to B.
**
** Additional changes:
**
** * All tables to the left of the right-most RIGHT JOIN are tagged with
** JT_LTORJ (mnemonic: Left Table Of Right Join) so that the
** code generator can easily tell that the table is part of
** the left operand of at least one RIGHT JOIN.
*/
void sqlite3SrcListShiftJoinType(SrcList *p){
if( p ){
int i;
for(i=p->nSrc-1; i>0; i--){
p->a[i].fg.jointype = p->a[i-1].fg.jointype;
}
void sqlite3SrcListShiftJoinType(Parse *pParse, SrcList *p){
(void)pParse;
if( p && p->nSrc>1 ){
int i = p->nSrc-1;
u8 allFlags = 0;
do{
allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype;
}while( (--i)>0 );
p->a[0].fg.jointype = 0;
/* All terms to the left of a RIGHT JOIN should be tagged with the
** JT_LTORJ flags */
if( allFlags & JT_RIGHT ){
for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){}
i--;
assert( i>=0 );
do{
p->a[i].fg.jointype |= JT_LTORJ;
}while( (--i)>=0 );
}
}
}
+3 -3
View File
@@ -307,9 +307,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_SELECTTRACE
"ENABLE_SELECTTRACE",
#endif
#ifdef SQLITE_ENABLE_SESSION
"ENABLE_SESSION",
#endif
@@ -331,6 +328,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
"ENABLE_STMT_SCANSTATUS",
#endif
#ifdef SQLITE_ENABLE_TREETRACE
"ENABLE_TREETRACE",
#endif
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
"ENABLE_UNKNOWN_SQL_FUNCTION",
#endif
+147 -73
View File
@@ -276,7 +276,7 @@ static void computeJD(DateTime *p){
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
p->validJD = 1;
if( p->validHMS ){
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
if( p->validTZ ){
p->iJD -= p->tz*60000;
p->validYMD = 0;
@@ -503,8 +503,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
** is available. This routine returns 0 on success and
** non-zero on any kind of error.
**
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
** routine will always fail.
** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
** routine will always fail. If bLocaltimeFault is nonzero and
** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
** invoked in place of the OS-defined localtime() function.
**
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
** library function localtime_r() is used to assist in the calculation of
@@ -520,7 +522,15 @@ static int osLocaltime(time_t *t, struct tm *pTm){
sqlite3_mutex_enter(mutex);
pX = localtime(t);
#ifndef SQLITE_UNTESTABLE
if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
if( sqlite3GlobalConfig.bLocaltimeFault ){
if( sqlite3GlobalConfig.xAltLocaltime!=0
&& 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
){
pX = pTm;
}else{
pX = 0;
}
}
#endif
if( pX ) *pTm = *pX;
#if SQLITE_THREADSAFE>0
@@ -529,7 +539,13 @@ static int osLocaltime(time_t *t, struct tm *pTm){
rc = pX==0;
#else
#ifndef SQLITE_UNTESTABLE
if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
if( sqlite3GlobalConfig.bLocaltimeFault ){
if( sqlite3GlobalConfig.xAltLocaltime!=0 ){
return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
}else{
return 1;
}
}
#endif
#if HAVE_LOCALTIME_R
rc = localtime_r(t, pTm)==0;
@@ -544,67 +560,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#ifndef SQLITE_OMIT_LOCALTIME
/*
** Compute the difference (in milliseconds) between localtime and UTC
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
** return this value and set *pRc to SQLITE_OK.
**
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
** is undefined in this case.
** Assuming the input DateTime is UTC, move it to its localtime equivalent.
*/
static sqlite3_int64 localtimeOffset(
DateTime *p, /* Date at which to calculate offset */
sqlite3_context *pCtx, /* Write error here if one occurs */
int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
static int toLocaltime(
DateTime *p, /* Date at which to calculate offset */
sqlite3_context *pCtx /* Write error here if one occurs */
){
DateTime x, y;
time_t t;
struct tm sLocal;
int iYearDiff;
/* Initialize the contents of sLocal to avoid a compiler warning. */
memset(&sLocal, 0, sizeof(sLocal));
x = *p;
computeYMD_HMS(&x);
if( x.Y<1971 || x.Y>=2038 ){
computeJD(p);
if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
|| p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
){
/* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
** works for years between 1970 and 2037. For dates outside this range,
** SQLite attempts to map the year into an equivalent year within this
** range, do the calculation, then map the year back.
*/
x.Y = 2000;
x.M = 1;
x.D = 1;
x.h = 0;
x.m = 0;
x.s = 0.0;
} else {
int s = (int)(x.s + 0.5);
x.s = s;
DateTime x = *p;
computeYMD_HMS(&x);
iYearDiff = (2000 + x.Y%4) - x.Y;
x.Y += iYearDiff;
x.validJD = 0;
computeJD(&x);
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
}else{
iYearDiff = 0;
t = (time_t)(p->iJD/1000 - 21086676*(i64)10000);
}
x.tz = 0;
x.validJD = 0;
computeJD(&x);
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
if( osLocaltime(&t, &sLocal) ){
sqlite3_result_error(pCtx, "local time unavailable", -1);
*pRc = SQLITE_ERROR;
return 0;
return SQLITE_ERROR;
}
y.Y = sLocal.tm_year + 1900;
y.M = sLocal.tm_mon + 1;
y.D = sLocal.tm_mday;
y.h = sLocal.tm_hour;
y.m = sLocal.tm_min;
y.s = sLocal.tm_sec;
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
y.rawS = 0;
y.validTZ = 0;
y.isError = 0;
computeJD(&y);
*pRc = SQLITE_OK;
return y.iJD - x.iJD;
p->Y = sLocal.tm_year + 1900 - iYearDiff;
p->M = sLocal.tm_mon + 1;
p->D = sLocal.tm_mday;
p->h = sLocal.tm_hour;
p->m = sLocal.tm_min;
p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
p->validYMD = 1;
p->validHMS = 1;
p->validJD = 0;
p->rawS = 0;
p->validTZ = 0;
p->isError = 0;
return SQLITE_OK;
}
#endif /* SQLITE_OMIT_LOCALTIME */
@@ -676,7 +681,9 @@ static int parseModifier(
if( !p->rawS || p->validJD ){
rc = 0;
p->rawS = 0;
}else if( p->s>=-210866760000 && p->s<=253402300799 ){
}else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
&& p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
){
r = p->s*1000.0 + 210866760000000.0;
clearYMD_HMS_TZ(p);
p->iJD = (sqlite3_int64)(r + 0.5);
@@ -697,7 +704,7 @@ static int parseModifier(
** SQLite (0..5373484.5) then the result will be NULL.
*/
if( sqlite3_stricmp(z, "julianday")==0 ){
if( idx>1 ) return 1;
if( idx>1 ) return 1; /* IMP: R-31176-64601 */
if( p->validJD && p->rawS ){
rc = 0;
p->rawS = 0;
@@ -713,9 +720,7 @@ static int parseModifier(
** show local time.
*/
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
computeJD(p);
p->iJD += localtimeOffset(p, pCtx, &rc);
clearYMD_HMS_TZ(p);
rc = toLocaltime(p, pCtx);
}
break;
}
@@ -728,6 +733,7 @@ static int parseModifier(
** seconds since 1970. Convert to a real julian day number.
*/
if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
if( idx>1 ) return 1; /* IMP: R-49255-55373 */
r = p->s*1000.0 + 210866760000000.0;
if( r>=0.0 && r<464269060800000.0 ){
clearYMD_HMS_TZ(p);
@@ -740,18 +746,31 @@ static int parseModifier(
#ifndef SQLITE_OMIT_LOCALTIME
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
if( p->tzSet==0 ){
sqlite3_int64 c1;
i64 iOrigJD; /* Original localtime */
i64 iGuess; /* Guess at the corresponding utc time */
int cnt = 0; /* Safety to prevent infinite loop */
int iErr; /* Guess is off by this much */
computeJD(p);
c1 = localtimeOffset(p, pCtx, &rc);
if( rc==SQLITE_OK ){
p->iJD -= c1;
clearYMD_HMS_TZ(p);
p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
}
iGuess = iOrigJD = p->iJD;
iErr = 0;
do{
DateTime new;
memset(&new, 0, sizeof(new));
iGuess -= iErr;
new.iJD = iGuess;
new.validJD = 1;
rc = toLocaltime(&new, pCtx);
if( rc ) return rc;
computeJD(&new);
iErr = new.iJD - iOrigJD;
}while( iErr && cnt++<3 );
memset(p, 0, sizeof(*p));
p->iJD = iGuess;
p->validJD = 1;
p->tzSet = 1;
}else{
rc = SQLITE_OK;
}
rc = SQLITE_OK;
}
#endif
break;
@@ -1001,11 +1020,38 @@ static void datetimeFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
char zBuf[100];
int Y, s;
char zBuf[24];
computeYMD_HMS(&x);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
Y = x.Y;
if( Y<0 ) Y = -Y;
zBuf[1] = '0' + (Y/1000)%10;
zBuf[2] = '0' + (Y/100)%10;
zBuf[3] = '0' + (Y/10)%10;
zBuf[4] = '0' + (Y)%10;
zBuf[5] = '-';
zBuf[6] = '0' + (x.M/10)%10;
zBuf[7] = '0' + (x.M)%10;
zBuf[8] = '-';
zBuf[9] = '0' + (x.D/10)%10;
zBuf[10] = '0' + (x.D)%10;
zBuf[11] = ' ';
zBuf[12] = '0' + (x.h/10)%10;
zBuf[13] = '0' + (x.h)%10;
zBuf[14] = ':';
zBuf[15] = '0' + (x.m/10)%10;
zBuf[16] = '0' + (x.m)%10;
zBuf[17] = ':';
s = (int)x.s;
zBuf[18] = '0' + (s/10)%10;
zBuf[19] = '0' + (s)%10;
zBuf[20] = 0;
if( x.Y<0 ){
zBuf[0] = '-';
sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT);
}else{
sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT);
}
}
}
@@ -1021,10 +1067,20 @@ static void timeFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
char zBuf[100];
int s;
char zBuf[16];
computeHMS(&x);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
zBuf[0] = '0' + (x.h/10)%10;
zBuf[1] = '0' + (x.h)%10;
zBuf[2] = ':';
zBuf[3] = '0' + (x.m/10)%10;
zBuf[4] = '0' + (x.m)%10;
zBuf[5] = ':';
s = (int)x.s;
zBuf[6] = '0' + (s/10)%10;
zBuf[7] = '0' + (s)%10;
zBuf[8] = 0;
sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT);
}
}
@@ -1040,10 +1096,28 @@ static void dateFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
char zBuf[100];
int Y;
char zBuf[16];
computeYMD(&x);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
Y = x.Y;
if( Y<0 ) Y = -Y;
zBuf[1] = '0' + (Y/1000)%10;
zBuf[2] = '0' + (Y/100)%10;
zBuf[3] = '0' + (Y/10)%10;
zBuf[4] = '0' + (Y)%10;
zBuf[5] = '-';
zBuf[6] = '0' + (x.M/10)%10;
zBuf[7] = '0' + (x.M)%10;
zBuf[8] = '-';
zBuf[9] = '0' + (x.D/10)%10;
zBuf[10] = '0' + (x.D)%10;
zBuf[11] = 0;
if( x.Y<0 ){
zBuf[0] = '-';
sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
}else{
sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
}
}
}
+8 -5
View File
@@ -156,6 +156,7 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
){
pIdxInfo->orderByConsumed = 1;
}
sqlite3VtabUsesAllSchemas(pIdxInfo);
return SQLITE_OK;
}
@@ -333,7 +334,7 @@ static int dbpageUpdate(
goto update_fail;
}
pBt = pTab->db->aDb[iDb].pBt;
if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
if( pgno<1 || pBt==0 || pgno>sqlite3BtreeLastPage(pBt) ){
zErr = "bad page number";
goto update_fail;
}
@@ -371,11 +372,12 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
DbpageTable *pTab = (DbpageTable *)pVtab;
sqlite3 *db = pTab->db;
int i;
for(i=0; i<db->nDb; i++){
int rc = SQLITE_OK;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
}
return SQLITE_OK;
return rc;
}
@@ -407,7 +409,8 @@ int sqlite3DbpageRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
}
+2 -1
View File
@@ -891,7 +891,8 @@ int sqlite3DbstatRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
}
+14 -5
View File
@@ -128,8 +128,8 @@ void sqlite3MaterializeView(
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
assert( pFrom->a[0].pOn==0 );
assert( pFrom->a[0].pUsing==0 );
assert( pFrom->a[0].fg.isUsing==0 );
assert( pFrom->a[0].u3.pOn==0 );
}
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
SF_IncludeHidden, pLimit);
@@ -293,12 +293,13 @@ void sqlite3DeleteFrom(
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto delete_from_cleanup;
}
assert( db->mallocFailed==0 );
assert( pTabList->nSrc==1 );
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
@@ -323,6 +324,14 @@ void sqlite3DeleteFrom(
# define isView 0
#endif
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
pOrderBy, pLimit, pTrigger);
}
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlite3LimitWhere(
@@ -476,7 +485,7 @@ void sqlite3DeleteFrom(
** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
if( pWInfo==0 ) goto delete_from_cleanup;
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
+162 -92
View File
@@ -769,9 +769,8 @@ static void heightOfSelect(const Select *pSelect, int *pnHeight){
** if appropriate.
*/
static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
heightOfExpr(p->pRight, &nHeight);
int nHeight = p->pLeft ? p->pLeft->nHeight : 0;
if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight;
if( ExprUseXSelect(p) ){
heightOfSelect(p->x.pSelect, &nHeight);
}else if( p->x.pList ){
@@ -1070,6 +1069,8 @@ Expr *sqlite3ExprFunction(
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
return 0;
}
assert( !ExprHasProperty(pNew, EP_InnerON|EP_OuterON) );
pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
if( pList
&& pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
&& !pParse->nested
@@ -1113,7 +1114,7 @@ void sqlite3ExprFunctionUsable(
** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
** that the schema is possibly tainted).
*/
sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName);
sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr);
}
}
}
@@ -1169,6 +1170,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
return;
}
x = (ynVar)i;
@@ -1196,6 +1198,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
pExpr->iColumn = x;
if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
}
}
@@ -1235,10 +1238,6 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
#endif
}
}
if( ExprHasProperty(p, EP_MemToken) ){
assert( !ExprHasProperty(p, EP_IntValue) );
sqlite3DbFree(db, p->u.zToken);
}
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbFreeNN(db, p);
}
@@ -1247,6 +1246,18 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/*
** Clear both elements of an OnOrUsing object
*/
void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
if( p==0 ){
/* Nothing to clear */
}else if( p->pOn ){
sqlite3ExprDeleteNN(db, p->pOn);
}else if( p->pUsing ){
sqlite3IdListDelete(db, p->pUsing);
}
}
/*
** Arrange to cause pExpr to be deleted when the pParse is deleted.
@@ -1333,8 +1344,7 @@ static int dupedExprStructSize(const Expr *p, int flags){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_FromJoin) );
assert( !ExprHasProperty(p, EP_MemToken) );
assert( !ExprHasProperty(p, EP_OuterON) );
assert( !ExprHasVVAProperty(p, EP_NoReduce) );
if( p->pLeft || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
@@ -1438,7 +1448,7 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){
}
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag;
ExprClearVVAProperties(pNew);
@@ -1513,6 +1523,7 @@ With *sqlite3WithDup(sqlite3 *db, With *p){
pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
pRet->a[i].eM10d = p->a[i].eM10d;
}
}
}
@@ -1613,11 +1624,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){
}
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->sortFlags = pOldItem->sortFlags;
pItem->eEName = pOldItem->eEName;
pItem->done = 0;
pItem->bNulls = pOldItem->bNulls;
pItem->bSorterRef = pOldItem->bSorterRef;
pItem->fg = pOldItem->fg;
pItem->fg.done = 0;
pItem->u = pOldItem->u;
}
return pNew;
@@ -1669,8 +1677,12 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
pTab->nTabRef++;
}
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
if( pOldItem->fg.isUsing ){
assert( pNewItem->fg.isUsing );
pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
}else{
pNewItem->u3.pOn = sqlite3ExprDup(db, pOldItem->u3.pOn, flags);
}
pNewItem->colUsed = pOldItem->colUsed;
}
return pNew;
@@ -1680,22 +1692,16 @@ IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
int i;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
assert( p->eU4!=EU4_EXPR );
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
if( pNew==0 ) return 0;
pNew->nId = p->nId;
pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
sqlite3DbFreeNN(db, pNew);
return 0;
}
/* Note that because the size of the allocation for p->a[] is not
** necessarily a power of two, sqlite3IdListAppend() may not be called
** on the duplicate created by this function. */
pNew->eU4 = p->eU4;
for(i=0; i<p->nId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
struct IdList_item *pOldItem = &p->a[i];
const struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->idx = pOldItem->idx;
pNewItem->u4 = pOldItem->u4;
}
return pNew;
}
@@ -1919,16 +1925,16 @@ void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){
);
pItem = &p->a[p->nExpr-1];
assert( pItem->bNulls==0 );
assert( pItem->fg.bNulls==0 );
if( iSortOrder==SQLITE_SO_UNDEFINED ){
iSortOrder = SQLITE_SO_ASC;
}
pItem->sortFlags = (u8)iSortOrder;
pItem->fg.sortFlags = (u8)iSortOrder;
if( eNulls!=SQLITE_SO_UNDEFINED ){
pItem->bNulls = 1;
pItem->fg.bNulls = 1;
if( iSortOrder!=eNulls ){
pItem->sortFlags |= KEYINFO_ORDER_BIGNULL;
pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL;
}
}
}
@@ -1954,7 +1960,7 @@ void sqlite3ExprListSetName(
assert( pList->nExpr>0 );
pItem = &pList->a[pList->nExpr-1];
assert( pItem->zEName==0 );
assert( pItem->eEName==ENAME_NAME );
assert( pItem->fg.eEName==ENAME_NAME );
pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote ){
/* If dequote==0, then pName->z does not point to part of a DDL
@@ -1989,7 +1995,7 @@ void sqlite3ExprListSetSpan(
assert( pList->nExpr>0 );
if( pItem->zEName==0 ){
pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
pItem->eEName = ENAME_SPAN;
pItem->fg.eEName = ENAME_SPAN;
}
}
}
@@ -2161,9 +2167,9 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->eCode is 2 then any term of the expression that comes from
** the ON or USING clauses of a left join disqualifies the expression
** the ON or USING clauses of an outer join disqualifies the expression
** from being considered constant. */
if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){
pWalker->eCode = 0;
return WRC_Abort;
}
@@ -2282,6 +2288,42 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
/*
** Check pExpr to see if it is an invariant constraint on data source pSrc.
** This is an optimization. False negatives will perhaps cause slower
** queries, but false positives will yield incorrect answers. So when in
** doubt, return 0.
**
** To be an invariant constraint, the following must be true:
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2) pExpr cannot use subqueries or non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
(4b) and specifically the ON clause associated with the LEFT JOIN.
**
** (5) If pSrc is not the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
*/
int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){
if( pSrc->fg.jointype & JT_LTORJ ){
return 0; /* rule (3) */
}
if( pSrc->fg.jointype & JT_LEFT ){
if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (4a) */
if( pExpr->w.iJoin!=pSrc->iCursor ) return 0; /* rule (4b) */
}else{
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */
}
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
}
/*
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
@@ -2609,7 +2651,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){
** all members of the RHS set, skipping duplicates.
**
** A cursor is opened on the b-tree object that is the RHS of the IN operator
** and pX->iTable is set to the index of that cursor.
** and the *piTab parameter is set to the index of that cursor.
**
** The returned value of this function indicates the b-tree type, as follows:
**
@@ -2629,7 +2671,10 @@ static int sqlite3InRhsIsConstant(Expr *pIn){
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephemeral table instead of an
** existing table.
** existing table. In this case, the creation and initialization of the
** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag
** will be set on pX and the pX->y.sub fields will be set to show where
** the subroutine is coded.
**
** The inFlags parameter must contain, at a minimum, one of the bits
** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains
@@ -2690,12 +2735,13 @@ int sqlite3FindInIndex(
){
Select *p; /* SELECT to the right of IN operator */
int eType = 0; /* Type of RHS table. IN_INDEX_* */
int iTab = pParse->nTab++; /* Cursor of the RHS table */
int iTab; /* Cursor of the RHS table */
int mustBeUnique; /* True if RHS must be unique */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
assert( pX->op==TK_IN );
mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
iTab = pParse->nTab++;
/* If the RHS of this IN(...) operator is a SELECT, and if it matters
** whether or not the SELECT result contains NULL values, check whether
@@ -2803,8 +2849,7 @@ int sqlite3FindInIndex(
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
int j;
assert( pReq!=0 || pRhs->iColumn==XN_ROWID
|| pParse->nErr || db->mallocFailed );
assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
for(j=0; j<nExpr; j++){
if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
assert( pIdx->azColl[j] );
@@ -2862,6 +2907,8 @@ int sqlite3FindInIndex(
&& ExprUseXList(pX)
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
){
pParse->nTab--; /* Back out the allocation of the unused cursor */
iTab = -1; /* Cursor is not allocated */
eType = IN_INDEX_NOOP;
}
@@ -3028,6 +3075,7 @@ void sqlite3CodeRhsOfIN(
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
return;
@@ -3039,8 +3087,7 @@ void sqlite3CodeRhsOfIN(
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
VdbeComment((v, "return address"));
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -3142,6 +3189,7 @@ void sqlite3CodeRhsOfIN(
** expression we need to rerun this code each time.
*/
if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
sqlite3VdbeChangeToNoop(v, addrOnce-1);
sqlite3VdbeChangeToNoop(v, addrOnce);
ExprClearProperty(pExpr, EP_Subrtn);
addrOnce = 0;
@@ -3162,8 +3210,11 @@ void sqlite3CodeRhsOfIN(
sqlite3VdbeJumpHere(v, addrOnce);
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
|| pParse->nErr );
sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr, 1);
VdbeCoverage(v);
sqlite3ClearTempRegCache(pParse);
}
}
@@ -3217,9 +3268,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
ExprSetProperty(pExpr, EP_Subrtn);
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
VdbeComment((v, "return address"));
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
/* The evaluation of the EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
@@ -3271,7 +3320,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
pLimit = sqlite3PExpr(pParse, TK_NE,
sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit);
}
sqlite3ExprDelete(db, pSel->pLimit->pLeft);
sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft);
pSel->pLimit->pLeft = pLimit;
}else{
/* If there is no pre-existing limit add a limit of 1 */
@@ -3280,10 +3329,8 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
if( pParse->nErr ){
pExpr->op2 = pExpr->op;
pExpr->op = TK_ERROR;
}
pExpr->op2 = pExpr->op;
pExpr->op = TK_ERROR;
return 0;
}
pExpr->iTable = rReg = dest.iSDParm;
@@ -3294,8 +3341,11 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
|| pParse->nErr );
sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr, 1);
VdbeCoverage(v);
sqlite3ClearTempRegCache(pParse);
return rReg;
}
@@ -3500,10 +3550,9 @@ static void sqlite3ExprCodeIN(
}else{
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
@@ -3641,11 +3690,12 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
c = sqlite3DecOrHexToI64(z, &value);
if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr);
#else
#ifndef SQLITE_OMIT_HEX_INTEGER
if( sqlite3_strnicmp(z,"0x",2)==0 ){
sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T",
negFlag?"-":"",pExpr);
}else
#endif
{
@@ -3729,6 +3779,7 @@ void sqlite3ExprCodeGetColumnOfTable(
}
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
VdbeComment((v, "%s.rowid", pTab->zName));
}else{
int op;
int x;
@@ -3899,7 +3950,17 @@ static int exprCodeInlineFunction(
caseExpr.x.pList = pFarg;
return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
}
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
case INLINEFUNC_sqlite_offset: {
Expr *pArg = pFarg->a[0].pExpr;
if( pArg->op==TK_COLUMN && pArg->iTable>=0 ){
sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
break;
}
#endif
default: {
/* The UNLIKELY() function is a no-op. The result is the value
** of the first argument.
@@ -4146,6 +4207,7 @@ expr_code_doover:
int n;
const char *z;
char *zBlob;
if( pParse->nErr ) return target;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
@@ -4321,7 +4383,7 @@ expr_code_doover:
|| NEVER(pExpr->iAgg>=pInfo->nFunc)
){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr);
}else{
return pInfo->aFunc[pExpr->iAgg].iMem;
}
@@ -4362,7 +4424,7 @@ expr_code_doover:
}
#endif
if( pDef==0 || pDef->xFinalize!=0 ){
sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr);
break;
}
if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
@@ -4438,20 +4500,8 @@ expr_code_doover:
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
if( (pDef->funcFlags & SQLITE_FUNC_OFFSET)!=0 && ALWAYS(pFarg!=0) ){
Expr *pArg = pFarg->a[0].pExpr;
if( pArg->op==TK_COLUMN ){
sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
}else
#endif
{
sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
pDef, pExpr->op2);
}
sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
pDef, pExpr->op2);
if( nFarg ){
if( constMask==0 ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
@@ -4481,16 +4531,18 @@ expr_code_doover:
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
Expr *pLeft = pExpr->pLeft;
if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){
pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft);
pLeft->op2 = pParse->withinRJSubrtn;
}
assert( pExpr->pLeft->op==TK_SELECT || pExpr->pLeft->op==TK_ERROR );
n = sqlite3ExprVectorSize(pExpr->pLeft);
assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR );
n = sqlite3ExprVectorSize(pLeft);
if( pExpr->iTable!=n ){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
}
return pExpr->pLeft->iTable + pExpr->iColumn;
return pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
int destIfFalse = sqlite3VdbeMakeLabel(pParse);
@@ -4521,8 +4573,24 @@ expr_code_doover:
exprCodeBetween(pParse, pExpr, target, 0, 0);
return target;
}
case TK_COLLATE: {
if( !ExprHasProperty(pExpr, EP_Collate)
&& ALWAYS(pExpr->pLeft)
&& pExpr->pLeft->op==TK_FUNCTION
){
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
if( inReg!=target ){
sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
inReg = target;
}
sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg);
return inReg;
}else{
pExpr = pExpr->pLeft;
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */
}
}
case TK_SPAN:
case TK_COLLATE:
case TK_UPLUS: {
pExpr = pExpr->pLeft;
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
@@ -4763,7 +4831,9 @@ int sqlite3ExprCodeRunJustOnce(
struct ExprList_item *pItem;
int i;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
if( pItem->fg.reusable
&& sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0
){
return pItem->u.iConstExprReg;
}
}
@@ -4786,7 +4856,7 @@ int sqlite3ExprCodeRunJustOnce(
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
pItem->reusable = regDest<0;
pItem->fg.reusable = regDest<0;
if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
}
@@ -4920,7 +4990,7 @@ int sqlite3ExprCodeExprList(
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( pItem->bSorterRef ){
if( pItem->fg.bSorterRef ){
i--;
n--;
}else
@@ -5014,8 +5084,8 @@ static void exprCodeBetween(
** so that the sqlite3ExprCodeTarget() routine will not attempt to move
** it into the Parse.pConstExpr list. We should use a new bit for this,
** for clarity, but we are out of bits in the Expr.flags field so we
** have to reuse the EP_FromJoin bit. Bummer. */
pDel->flags |= EP_FromJoin;
** have to reuse the EP_OuterON bit. Bummer. */
pDel->flags |= EP_OuterON;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
sqlite3ReleaseTempReg(pParse, regFree1);
@@ -5545,7 +5615,7 @@ int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB, int iTab){
int res;
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1;
if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1;
if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res;
}
return 0;
@@ -5700,7 +5770,7 @@ int sqlite3ExprImpliesExpr(
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
case TK_ISNULL:
@@ -5797,8 +5867,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
** False positives are not allowed, however. A false positive may result
** in an incorrect answer.
**
** Terms of p that are marked with EP_FromJoin (and hence that come from
** the ON or USING clauses of LEFT JOINS) are excluded from the analysis.
** Terms of p that are marked with EP_OuterON (and hence that come from
** the ON or USING clauses of OUTER JOINS) are excluded from the analysis.
**
** This routine is used to check if a LEFT JOIN can be converted into
** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE
+14 -15
View File
@@ -390,7 +390,6 @@ static void fkLookupParent(
}else{
int nCol = pFKey->nCol;
int regTemp = sqlite3GetTempRange(pParse, nCol);
int regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
@@ -429,12 +428,11 @@ static void fkLookupParent(
}
sqlite3VdbeGoto(v, iOk);
}
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0,
sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol);
VdbeCoverage(v);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
}
@@ -536,14 +534,10 @@ static Expr *exprTableColumn(
** Operation | FK type | Action taken
** --------------------------------------------------------------------------
** DELETE immediate Increment the "immediate constraint counter".
** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
** throw a "FOREIGN KEY constraint failed" exception.
**
** INSERT immediate Decrement the "immediate constraint counter".
**
** DELETE deferred Increment the "deferred constraint counter".
** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
** throw a "FOREIGN KEY constraint failed" exception.
**
** INSERT deferred Decrement the "deferred constraint counter".
**
@@ -651,7 +645,7 @@ static void fkScanChildren(
** clause. For each row found, increment either the deferred or immediate
** foreign key constraint counter. */
if( pParse->nErr==0 ){
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0);
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
if( pWInfo ){
sqlite3WhereEnd(pWInfo);
@@ -1191,9 +1185,9 @@ int sqlite3FkRequired(
**
** It returns a pointer to a Trigger structure containing a trigger
** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
** returned (these actions require no special handling by the triggers
** sub-system, code for them is created by fkScanChildren()).
** If the action is "NO ACTION" then a NULL pointer is returned (these actions
** require no special handling by the triggers sub-system, code for them is
** created by fkScanChildren()).
**
** For example, if pFKey is the foreign key and pTab is table "p" in
** the following schema:
@@ -1322,18 +1316,23 @@ static Trigger *fkActionTrigger(
nFrom = sqlite3Strlen30(zFrom);
if( action==OE_Restrict ){
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
Token tFrom;
Token tDb;
Expr *pRaise;
tFrom.z = zFrom;
tFrom.n = nFrom;
tDb.z = db->aDb[iDb].zDbSName;
tDb.n = sqlite3Strlen30(tDb.z);
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(pParse, 0, &tFrom, 0),
sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom),
pWhere,
0, 0, 0, 0, 0
);
+7 -6
View File
@@ -106,6 +106,7 @@ static void subtypeFunc(
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
sqlite3_result_int(context, sqlite3_value_subtype(argv[0]));
}
@@ -1119,8 +1120,9 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3QuoteValue(&str,argv[0]);
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
SQLITE_DYNAMIC);
if( str.accError==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
if( str.accError!=SQLITE_OK ){
sqlite3_result_null(context);
sqlite3_result_error_code(context, str.accError);
}
}
@@ -2096,11 +2098,11 @@ static void logFunc(
switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
case 1:
/* Convert from natural logarithm to log base 10 */
ans *= 1.0/M_LN10;
ans /= M_LN10;
break;
case 2:
/* Convert from natural logarithm to log base 2 */
ans *= 1.0/M_LN2;
ans /= M_LN2;
break;
default:
break;
@@ -2239,8 +2241,7 @@ void sqlite3RegisterBuiltinFunctions(void){
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
SQLITE_FUNC_TYPEOF),
INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+5 -1
View File
@@ -286,9 +286,13 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
0, /* xAltLocaltime */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
0, /* iPrngSeed */
#ifdef SQLITE_DEBUG
{0,0,0,0,0,0} /* aTune */
#endif
};
/*
@@ -343,7 +347,7 @@ int sqlite3PendingByte = 0x40000000;
/*
** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
*/
u32 sqlite3SelectTrace = 0;
u32 sqlite3TreeTrace = 0;
u32 sqlite3WhereTrace = 0;
#include "opcodes.h"
+28 -14
View File
@@ -181,7 +181,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}
for(i=j=0; i<pTab->nCol; i++){
assert( pTab->aCol[i].affinity!=0 );
assert( pTab->aCol[i].affinity!=0 || sqlite3VdbeParser(v)->nErr>0 );
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
zColAff[j++] = pTab->aCol[i].affinity;
}
@@ -715,9 +715,11 @@ void sqlite3Insert(
#endif
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto insert_cleanup;
}
assert( db->mallocFailed==0 );
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
/* If the Select object is really just a simple VALUES() list with a
@@ -763,6 +765,14 @@ void sqlite3Insert(
#endif
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList,
onError, pUpsert, pTrigger);
}
#endif
/* If pTab is really a view, make sure it has been initialized.
** ViewGetColumnNames() is a no-op if pTab is not a view.
*/
@@ -793,7 +803,11 @@ void sqlite3Insert(
**
** This is the 2nd template.
*/
if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
if( pColumn==0
&& pSelect!=0
&& pTrigger==0
&& xferOptimization(pParse, pTab, pSelect, onError, iDb)
){
assert( !pTrigger );
assert( pList==0 );
goto insert_end;
@@ -837,13 +851,15 @@ void sqlite3Insert(
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
assert( pColumn->eU4!=EU4_EXPR );
pColumn->eU4 = EU4_IDX;
for(i=0; i<pColumn->nId; i++){
pColumn->a[i].idx = -1;
pColumn->a[i].u4.idx = -1;
}
for(i=0; i<pColumn->nId; i++){
for(j=0; j<pTab->nCol; j++){
if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
pColumn->a[i].idx = j;
pColumn->a[i].u4.idx = j;
if( i!=j ) bIdListInOrder = 0;
if( j==pTab->iPKey ){
ipkColumn = i; assert( !withoutRowid );
@@ -893,7 +909,9 @@ void sqlite3Insert(
dest.nSdst = pTab->nCol;
rc = sqlite3Select(pParse, pSelect, &dest);
regFromSelect = dest.iSdst;
if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
assert( db->pParse==pParse );
if( rc || pParse->nErr ) goto insert_cleanup;
assert( db->mallocFailed==0 );
sqlite3VdbeEndCoroutine(v, regYield);
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
assert( pSelect->pEList );
@@ -1143,7 +1161,8 @@ void sqlite3Insert(
}
}
if( pColumn ){
for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
assert( pColumn->eU4==EU4_IDX );
for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){}
if( j>=pColumn->nId ){
/* A column not named in the insert column list gets its
** default value */
@@ -2274,7 +2293,7 @@ void sqlite3GenerateConstraintChecks(
if( isUpdate ){
/* If currently processing the PRIMARY KEY of a WITHOUT ROWID
** table, only conflict if the new PRIMARY KEY values are actually
** different from the old.
** different from the old. See TH3 withoutrowid04.test.
**
** For a UNIQUE index, only conflict if the PRIMARY KEY values
** of the matched index row are different from the original PRIMARY
@@ -2762,18 +2781,13 @@ static int xferOptimization(
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
int regData, regRowid; /* Registers holding data and rowid */
if( pSelect==0 ){
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
}
assert( pSelect!=0 );
if( pParse->pWith || pSelect->pWith ){
/* Do not attempt to process this query if there are an WITH clauses
** attached to it. Proceeding may generate a false "no such table: xxx"
** error if pSelect reads from a CTE named "xxx". */
return 0;
}
if( sqlite3TriggerList(pParse, pDest) ){
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pDest) ){
return 0; /* tab1 must not be a virtual table */
+40 -14
View File
@@ -1119,14 +1119,15 @@ static JsonNode *jsonLookupStep(
*pzErr = zPath;
return 0;
}
testcase( nKey==0 );
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
nKey = i;
}
if( nKey==0 ){
*pzErr = zPath;
return 0;
if( nKey==0 ){
*pzErr = zPath;
return 0;
}
}
j = 1;
for(;;){
@@ -1625,7 +1626,7 @@ static JsonNode *jsonMergePatch(
if( pPatch->eType!=JSON_OBJECT ){
return pPatch;
}
assert( iTarget>=0 && iTarget<pParse->nNode );
assert( iTarget<pParse->nNode );
pTarget = &pParse->aNode[iTarget];
assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
if( pTarget->eType!=JSON_OBJECT ){
@@ -2274,6 +2275,33 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
return SQLITE_OK;
}
/* Append an object label to the JSON Path being constructed
** in pStr.
*/
static void jsonAppendObjectPathElement(
JsonString *pStr,
JsonNode *pNode
){
int jj, nn;
const char *z;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
assert( pNode->eU==1 );
z = pNode->u.zJContent;
nn = pNode->n;
assert( nn>=2 );
assert( z[0]=='"' );
assert( z[nn-1]=='"' );
if( nn>2 && sqlite3Isalpha(z[1]) ){
for(jj=2; jj<nn-1 && sqlite3Isalnum(z[jj]); jj++){}
if( jj==nn-1 ){
z++;
nn -= 2;
}
}
jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
}
/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
@@ -2298,10 +2326,7 @@ static void jsonEachComputePath(
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
assert( pNode->eU==1 );
jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
jsonAppendObjectPathElement(pStr, pNode);
}
}
@@ -2372,8 +2397,7 @@ static int jsonEachColumn(
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
assert( pThis->eU==1 );
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
jsonAppendObjectPathElement(&x, pThis);
}
}
jsonResult(&x);
@@ -2582,7 +2606,8 @@ static sqlite3_module jsonEachModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
/* The methods of the json_tree virtual table. */
@@ -2610,7 +2635,8 @@ static sqlite3_module jsonTreeModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xShadowName */
0, /* xShadowName */
0 /* xShadowName2 */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* !defined(SQLITE_OMIT_JSON) */
@@ -2666,7 +2692,7 @@ int sqlite3JsonTableFunctions(sqlite3 *db){
{ "json_each", &jsonEachModule },
{ "json_tree", &jsonTreeModule },
};
int i;
unsigned int i;
for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
}
+20
View File
@@ -487,8 +487,28 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_autovacuum_pages,
/* Version 3.38.0 and later */
sqlite3_error_offset,
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_vtab_rhs_value,
sqlite3_vtab_distinct,
sqlite3_vtab_in,
sqlite3_vtab_in_first,
sqlite3_vtab_in_next,
#else
0,
0,
0,
0,
0,
#endif
/* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
sqlite3_deserialize,
sqlite3_serialize,
#else
0,
0,
#endif
sqlite3_db_name
};
/* True if x is the directory separator character
+77 -17
View File
@@ -4029,12 +4029,16 @@ int sqlite3_test_control(int op, ...){
** sqlite3_test_control().
*/
case SQLITE_TESTCTRL_FAULT_INSTALL: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961
/* A bug in MSVC prevents it from understanding pointers to functions
** types in the second argument to va_arg(). Work around the problem
** using a typedef.
** http://support.microsoft.com/kb/47961 <-- dead hyperlink
** Search at http://web.archive.org/ to find the 2015-03-16 archive
** of the link above to see the original text.
** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
*/
typedef int(*TESTCALLBACKFUNC_t)(int);
sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
typedef int(*sqlite3FaultFuncType)(int);
sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType);
rc = sqlite3FaultSim(0);
break;
}
@@ -4093,6 +4097,28 @@ int sqlite3_test_control(int op, ...){
volatile int x = 0;
assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
rc = x;
#if defined(SQLITE_DEBUG)
/* Invoke these debugging routines so that the compiler does not
** issue "defined but not used" warnings. */
if( x==9999 ){
sqlite3ShowExpr(0);
sqlite3ShowExpr(0);
sqlite3ShowExprList(0);
sqlite3ShowIdList(0);
sqlite3ShowSrcList(0);
sqlite3ShowWith(0);
sqlite3ShowUpsert(0);
sqlite3ShowTriggerStep(0);
sqlite3ShowTriggerStepList(0);
sqlite3ShowTrigger(0);
sqlite3ShowTriggerList(0);
#ifndef SQLITE_OMIT_WINDOWFUNC
sqlite3ShowWindow(0);
sqlite3ShowWinFunc(0);
#endif
sqlite3ShowSelect(0);
}
#endif
break;
}
@@ -4161,13 +4187,27 @@ int sqlite3_test_control(int op, ...){
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
**
** If parameter onoff is non-zero, subsequent calls to localtime()
** and its variants fail. If onoff is zero, undo this setting.
** If parameter onoff is 1, subsequent calls to localtime() fail.
** If 2, then invoke xAlt() instead of localtime(). If 0, normal
** processing.
**
** xAlt arguments are void pointers, but they really want to be:
**
** int xAlt(const time_t*, struct tm*);
**
** xAlt should write results in to struct tm object of its 2nd argument
** and return zero on success, or return non-zero on failure.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
if( sqlite3GlobalConfig.bLocaltimeFault==2 ){
typedef int(*sqlite3LocaltimeType)(const void*,void*);
sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType);
}else{
sqlite3GlobalConfig.xAltLocaltime = 0;
}
break;
}
@@ -4340,8 +4380,8 @@ int sqlite3_test_control(int op, ...){
**
** "ptr" is a pointer to a u32.
**
** op==0 Store the current sqlite3SelectTrace in *ptr
** op==1 Set sqlite3SelectTrace to the value *ptr
** op==0 Store the current sqlite3TreeTrace in *ptr
** op==1 Set sqlite3TreeTrace to the value *ptr
** op==3 Store the current sqlite3WhereTrace in *ptr
** op==3 Set sqlite3WhereTrace to the value *ptr
*/
@@ -4349,10 +4389,10 @@ int sqlite3_test_control(int op, ...){
int opTrace = va_arg(ap, int);
u32 *ptr = va_arg(ap, u32*);
switch( opTrace ){
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
case 0: *ptr = sqlite3TreeTrace; break;
case 1: sqlite3TreeTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
@@ -4369,10 +4409,12 @@ int sqlite3_test_control(int op, ...){
case SQLITE_TESTCTRL_LOGEST: {
double rIn = va_arg(ap, double);
LogEst rLogEst = sqlite3LogEstFromDouble(rIn);
u64 iInt = sqlite3LogEstToInt(rLogEst);
va_arg(ap, int*)[0] = rLogEst;
va_arg(ap, u64*)[0] = iInt;
va_arg(ap, int*)[0] = sqlite3LogEst(iInt);
int *pI1 = va_arg(ap,int*);
u64 *pU64 = va_arg(ap,u64*);
int *pI2 = va_arg(ap,int*);
*pI1 = rLogEst;
*pU64 = sqlite3LogEstToInt(rLogEst);
*pI2 = sqlite3LogEst(*pU64);
break;
}
@@ -4587,6 +4629,24 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
return iDb<0 ? 0 : db->aDb[iDb].pBt;
}
/*
** Return the name of the N-th database schema. Return NULL if N is out
** of range.
*/
const char *sqlite3_db_name(sqlite3 *db, int N){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
if( N<0 || N>=db->nDb ){
return 0;
}else{
return db->aDb[N].zDbSName;
}
}
/*
** Return the filename of the database associated with a database
** connection.
+17 -2
View File
@@ -750,8 +750,9 @@ char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
** Free any prior content in *pz and replace it with a copy of zNew.
*/
void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
char *z = sqlite3DbStrDup(db, zNew);
sqlite3DbFree(db, *pz);
*pz = sqlite3DbStrDup(db, zNew);
*pz = z;
}
/*
@@ -759,8 +760,15 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
** has happened. This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
**
** Always return a NULL pointer so that this routine can be invoked using
**
** return sqlite3OomFault(db);
**
** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
** common case where no OOM occurs.
*/
void sqlite3OomFault(sqlite3 *db){
void *sqlite3OomFault(sqlite3 *db){
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
db->mallocFailed = 1;
if( db->nVdbeExec>0 ){
@@ -768,9 +776,16 @@ void sqlite3OomFault(sqlite3 *db){
}
DisableLookaside;
if( db->pParse ){
Parse *pParse;
sqlite3ErrorMsg(db->pParse, "out of memory");
db->pParse->rc = SQLITE_NOMEM_BKPT;
for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){
pParse->nErr++;
pParse->rc = SQLITE_NOMEM;
}
}
}
return 0;
}
/*

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