Compare commits

..

73 Commits

Author SHA1 Message Date
dan 8ba2a38363 Do not run test script walrestart.test with the "memsubsys1" permutation.
FossilOrigin-Name: 703cbb0f760515eac1e6f72a5e5cd928258c71378e4a976082b6518c90128135
2026-03-03 18:34:38 +00:00
drh bb80d688ac Minor tweaks to the previous, for testability.
FossilOrigin-Name: decb69015457b4f70cf574aeef87d40f9de60b94965f4a915e8d0cd7559ef2ae
2026-03-03 18:21:22 +00:00
dan fe57e14b49 Avoid an obscure race condition between a checkpointer and a writer wrapping around to the start of the wal file.
FossilOrigin-Name: 053bd3930f827156fd67ea4546a36227cffbb6f8bada3b5d1a7cf5f1867ac624
2026-03-03 17:34:01 +00:00
drh 18f99f43bc Convert many sqlite3_realloc() calls to sqlite3_realloc64().
FossilOrigin-Name: 88dce64242552e7443d9fb496f6f3ad71dc5b4a882ce21b7ef1d5ea4e26f1e61
2026-03-02 17:11:44 +00:00
drh f6c8adf3a2 Omit explain_i calls from TCL test scripts.
FossilOrigin-Name: 204f25c882832058c3291d4d6a0a6ac2711c081cb91b19feb2cf94a25ed61ecf
2026-03-02 16:40:16 +00:00
drh 72afb50a6d Fix TEMP INSTEAD OF triggers so that they work on TEMP views.
[forum:/forumpost/2026-02-28T23:33:04z|Forum post 2026-02-28T23:33:04z].

FossilOrigin-Name: 0596bd508f0bc548158858a1dc113af2235d02632ce8c41cd27d1029e1a7e48d
2026-03-02 15:34:16 +00:00
drh 7fa89ea907 Change some sqlite3_realloc() calls into sqlite3_realloc64().
FossilOrigin-Name: a391f5646926787fd9a004225ea406b61d20f282c852c0282fd26cada644b601
2026-03-02 15:06:59 +00:00
drh c1454ee833 Remove the experimental and incomplete ext/repair extension, to prevent AIs
from scanning the (incomplete) code and reporting bugs against it.

FossilOrigin-Name: 213b1c6608af4b3e9d6e0d8de6432cc6857931427baf4beac1e0a4294e4dc6ce
2026-03-02 13:44:04 +00:00
drh ea6b2a87d1 Disable test shell1-5.0 as it is causing a use of initialized deep inside
of TCL.

FossilOrigin-Name: 440bd6091e3767f0a2f42ffdc92ca5e4736c0a73324fdd15397c3b5dbbc31fb8
2026-03-02 13:43:08 +00:00
drh f270460366 Use only 64-bit memory allocation in FTS5. Fix for UAF reported by
Zijie Zhao.

FossilOrigin-Name: e8976d5041c929675772039b7a8fc4ff0b609537d86f9aa6e445ecd512a10673
2026-03-02 11:41:48 +00:00
dan 33478099c9 Fix a possible 9-byte buffer overread in the zipfile extension hit when processing a corrupt zip file. Forum post [forum:/forumpost/721a05d2c5 | 721a05d2c5].
FossilOrigin-Name: 5db21813d126554d80db903be6d36ab6c1f73f9135a54af6dcfcfce0bcc18e68
2026-03-02 11:22:28 +00:00
drh 93ad2e083e The intck01.sql test should only be run if virtual tables work.
FossilOrigin-Name: 641d6f31a7f7b4901061e24d4e624da5ed92282e79771bb019b82a882e5d1ae9
2026-03-02 00:06:02 +00:00
drh ffaf9110f6 More floating point conversion test cases.
FossilOrigin-Name: 44a736a700ab12b398873400dc06cd334817842b4fa08bf8070a9ad6dbff0b51
2026-03-01 23:23:52 +00:00
drh 7e4e866baf New floating-point test case.
FossilOrigin-Name: f353399932e9797198e635405a594c2987850070e3f9aee87a05c5a65d4c1e00
2026-03-01 23:01:17 +00:00
drh e293b2d835 Fix an OOB read in the incremental integrity-check extension.
FossilOrigin-Name: abecc8e388e294311aa0b572e0a984b8ddad2afbf829c1246e1682fa549c8fac
2026-03-01 22:36:02 +00:00
drh 83de60bd7b Simplified rounding logic in sqlite3Fp10Convert2().
FossilOrigin-Name: 8ac63ebc5c04ba555bbf0d878a70e25deba5fcc75ff44c464600b92c27e5dcb0
2026-03-01 20:22:08 +00:00
drh a000db9754 Code changes in sqlite3Fp10Convert2() for easier maintenance. Does not
affect the generated machine code.

FossilOrigin-Name: 21c8fc7100e23b632b77934cbbafb98dfd3e6e73bab702446ef6345b378c9d36
2026-02-28 20:22:10 +00:00
drh 7ac310d0c6 Improvements to power-of-ten computations used for text ↔ binary64
conversions.

FossilOrigin-Name: 0780bce854b962fb2d4a1a19c55c9b5790a9669f26e1ff8b5f1f1733cfc647e0
2026-02-27 22:59:46 +00:00
drh afaf7ea2e4 Minor simplification to the text→binary64 conversion algorithm.
FossilOrigin-Name: 6632d51f1673e9a6b6e26baebc7aaa1ae27024ad5db1baff6ee5fcf865099f43
2026-02-27 20:37:03 +00:00
stephan f707e2ec5d Two code comment typo fixes reported in the forum. No code changes.
FossilOrigin-Name: 3fbd28fabc5509a0bf2026cb60891d6d3efe251910baa3a3934225d0a7187bfa
2026-02-27 18:32:12 +00:00
drh 7d9fbe6476 Fix an off-by-one error in the indentation of multi-line outputs in
QRF_STYLE_Line mode.

FossilOrigin-Name: d47499b21c893cc8749a1cafe1cf712dacfeaa6cfe2cdb75d1fc450f3cb6879f
2026-02-27 13:25:42 +00:00
drh c67a538168 Add an assert() to sqlite3RegisterLikeFunctions() to hopefully prevent
future false-positive bug reports coming out of CodeQL.

FossilOrigin-Name: 7c5f4dcd748baa60097bbf68d7aca99cc959bb1f7da92bd9ad86a4425a37d391
2026-02-27 11:36:43 +00:00
stephan 57d7a20ce7 Another nano-optimization in kvvfs v2.
FossilOrigin-Name: a9d60190d693504742a894918f145111908d7d6cb9e853ba7a2356529046372a
2026-02-27 06:33:28 +00:00
stephan d22d0edc48 JS: slight performance improvements in KVVfsStorage.
FossilOrigin-Name: 56edf2addb155dbb60269fe563ecb5f6132672c6c61f6f9d18ebdff72111298d
2026-02-27 03:21:47 +00:00
drh 5dfccfb0bb Fix typos in the SQLITE_PREPARE_FROM_DDL documentation.
FossilOrigin-Name: 9174e7dacf867c1f80e73ccf5e0ee7b9e84fbe9f2e53559d06b72206b1cde3c6
2026-02-26 16:19:21 +00:00
drh 5a6eef2fb2 Improvements to the SQLITE_PREPARE_FROM_DDL documentation.
FossilOrigin-Name: c3288f16848866a2c846221c33631785f7b39938078bb95c61895f789395aa1d
2026-02-26 13:35:38 +00:00
drh 8bc78bebfb Fix an inconsequential typo in the output of the datedebug() SQL function.
FossilOrigin-Name: 3a92a53d8cf77822c22618dbf35851a20d27c4a659d23db2d24e7ccb3f61c7fc
2026-02-26 12:17:19 +00:00
dan a86c6017e7 Fix a problem where the wrong collation could be used as part of a row-value comparison between columns with different collation sequences. [forum:/forumpost/6ceca07fc3 | Forum post 6ceca07fc3].
FossilOrigin-Name: 212c68249cc0e8904fc36d8e90646d04604f2b3b9d4c32eaeac7d920fa0fba99
2026-02-26 11:03:22 +00:00
drh 1a152ea92a The GCC bug is fixed in GCC-15.
FossilOrigin-Name: 21f9abe6c9d1e2ce99ed75c2984103dcd2356b5d53bca3f3732176bb856bf3f7
2026-02-25 21:19:20 +00:00
drh f45c695471 Reinstant the work-around for [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270|GCC compiler bug 96270]
which is apparently still an issue as of gcc 13.3.0 with -m32 on Mint Linux.
The test case in the bug report is fixed, but the vdbeMemRenderNum() routine
in SQLite still shows the problem.

FossilOrigin-Name: 7fae321095ebec775de1b39b974fb1f295d5efbd5723e9cb29a981c97a4262c8
2026-02-25 12:44:19 +00:00
drh 46bf39e396 Use a 64-bit hash for the testing option SQLITE_CHECK_PAGES to maintain
page alignment.

FossilOrigin-Name: 75a35cd8f97f8a6cd2311c829685bd3b1cfb394de15174aef347f15cfb1913a1
2026-02-25 01:04:22 +00:00
drh b1a73ba34d Adjust the changes to shell8.test from [5da9bf09cc00faf9] so that they
work with older versions of TCL.

FossilOrigin-Name: c3b9e2cee3565da50bcc92766f700c31142391a697cbab7465774cf20a307dd8
2026-02-24 19:50:27 +00:00
drh 9d65290207 Rename SQLITE_ENABLE_MULTITHREADED_CHECKS to SQLITE_THREAD_MISUSE_WARNINGS.
Run test cases with that option. Also add the
SQLITE_THREAD_MISUSE_ABORT option.

FossilOrigin-Name: be8c8b9cb7b618a1571a988bc1cfdc15d99a8bf144d699385c0076e940b9f7f5
2026-02-24 19:37:16 +00:00
drh da67225f04 Fix an assert() that is incorrect when the SQLITE_DBCONFIG_FP_DIGITS setting
is on a non-default value.

FossilOrigin-Name: 3ca1ed81c4fa41f5f9fdbebf0929dd8421a4e29f95764fe1027d4d8706a41480
2026-02-23 19:51:54 +00:00
drh d2e27e5d54 Add test cases for the symlink defenses of the previous check-in.
FossilOrigin-Name: 5da9bf09cc00faf98cc515fb5a10a0af325b8f7608893808d031dfef62380be2
2026-02-23 13:29:29 +00:00
drh ffd9892a02 Change the SQLAR archive extraction algorithm in the CLI so that it
uses the newly enhanced realpath() SQL function to guard against
attacks that use symlinks to try to write files outside of the
destination directory.
[forum:/forumpost/641b09daa17d9086|Forum post 641b09daa17d9086].

FossilOrigin-Name: 7cced53e8c508fbf1816162c5358c77a712f76a38fd18f07171efc3c028a3c57
2026-02-23 12:19:05 +00:00
drh 9235f9b049 Enhance the realpath() SQL function in the fileio.c extension
so that it works ever for pathnames that do not exist.

FossilOrigin-Name: 27a5735fb1e194d763ab9fdb933fad4f694fb2f8ad19205d17ac81caebd82548
2026-02-23 11:44:30 +00:00
drh 9dac613f04 When doing an SQLAR archive extraction in the CLI, postpone creating symlinks until after
all files and directories have been created.  This prevents a hostile archive from
creating a symlink through which it can subsequently write content outside of the target
directory.  [forum:forumpost/9e176adfef91c207|Forum post 9e176adfef91c207].

FossilOrigin-Name: 9719034d4d3becda127dc294f7f58ded9c982509c690dd55b56310912957eb51
2026-02-23 01:34:14 +00:00
drh 95fe5b9c38 Improved implementation of realpath() in the fileio.c extension that does not require
the last element of the path to actually exist.

FossilOrigin-Name: 4df4999484d9008d8af3c9c340810e0cf5f57161ba053ed5501276b450577039
2026-02-23 00:57:00 +00:00
drh 9bc017423c Add the realpath() SQL function to the fileio.c extension. And clean up
the UTF8 handling on the Windows side of that extension while we are at it.

FossilOrigin-Name: 8bb8941930378b436f1353603be194644568b55fe347475be0caddddad40efa3
2026-02-22 20:44:52 +00:00
drh 60f132bf12 Fix typos and include wording in the documentation for
SQLITE_DBCONFIG_FP_DIGITS.

FossilOrigin-Name: c30cee1224904eb2092daa0ad9494aec7c7a8c6c1661f5b91b62c3ef0c5ea95b
2026-02-21 21:19:41 +00:00
drh f8681fb638 Fix a harmless warning in the decimal extension.
FossilOrigin-Name: f16c7c4000f2b992f7245dcaf669f13ed464579f8894f3c16842eebf41285c70
2026-02-21 20:20:06 +00:00
drh 283f33233b Improved rounding of double→text conversions for rounding digits
of 17.  Add the new sqlite3_db_config(), SQLITE_DBCONFIG_FP_DIGITS,
to specify the number of significant digits to preserve on conversions.

FossilOrigin-Name: 78c12b4f6ae869c3ea5e368c97b45991442bdd2d3a60935f1e6fc02a8e01cd41
2026-02-21 20:03:47 +00:00
drh 8642ca2025 New sqlite3_db_config(SQLITE_DBCONFIG_FP_DIGITS) that let's the application
specify the number of significant digits that double→text conversions
will attempt to preserve.

FossilOrigin-Name: 3f16985dcc47a366b54164c5024f920a79dddd76faeac5e36b4770732ed72c0a
2026-02-21 19:26:58 +00:00
drh 699959ff25 New test cases for floating-point conversions.
FossilOrigin-Name: 3033fe97b14ba0531278d4aa444bc5340e044b87a72b3a4341032ddee442000f
2026-02-21 13:57:40 +00:00
drh 7aba858597 Remove an unreachable branch.
FossilOrigin-Name: 93f90eacc0c5b2ae0042ec525359298883f8473e24967208feef4029d9fa2d08
2026-02-21 13:40:07 +00:00
drh 4428aa842c Increase the precision of double → text conversions that happen in
sqlite3_column_text(), or sqlite3_value_text(), or in the CAST() operator,
or similar, so that round-tripping the value back to double results in
exactly the same value.

FossilOrigin-Name: ef0049e3ade304f64e1ab97e52e1e21379e4db461f3fa80dac8e544fb90d622f
2026-02-21 10:57:02 +00:00
drh 24ef9fbb19 Further simplification, performance gain, and size reduction in
sqlite3FpDecode().

FossilOrigin-Name: 5954f22ceb6b43ed160ec085cd86b66299d8aab3e349a41941a4f1c2eade7457
2026-02-21 00:56:11 +00:00
drh aec283385e Small performance increase and size reduction in sqlite3FpDecode() by using
local variables instead of structure elements.

FossilOrigin-Name: b4c378bba582205aa676e45b21ffa17ad6199e2a017ec73cf41a0243f693b589
2026-02-21 00:20:29 +00:00
drh ac5ee556eb Inconsequential changes to floating-point conversion, amounting to mere
code cleanup to aid comprehension.

FossilOrigin-Name: 6d9c29123b6b143b0f7c8f5d018f170c72edfc5b1a4d67edd45e5552def2af6c
2026-02-20 20:43:25 +00:00
drh 62546d4b1f In the decimal extension, an optional second argument to the
decimal() and decimal_exp() functions rounds the value to the
number of significant digits specified by that argument.

FossilOrigin-Name: cb24edf1afc3f9083a4963c5fe232933eccc7c0cb8872aa5fcd336d226b885ef
2026-02-20 16:21:58 +00:00
stephan 9e395efec6 Fix a cse in the fiddle.debug build where it could not overwrite its read-only/generated index.html.
FossilOrigin-Name: 7adb2c0f438a97d377760436b1ac81fffab36e541a2b5ee733bfc7108e0180e5
2026-02-20 14:22:09 +00:00
drh d447df4205 Add new functions ieee754_to_int() and ieee754_from_int() to the
ieee754 extension.  No changes to the core SQLite.

FossilOrigin-Name: 8660d3e94cbe892693554df282bce0fa8c7aedbc5e020cab647cbbff3d7e55b7
2026-02-20 14:20:33 +00:00
drh 20c65785cd Improved rounding of floating-point conversions in some corner cases.
FossilOrigin-Name: 436dccd42650a6ab0a74459ae42fdb3e36d853f934324acc2bc961f87c001852
2026-02-20 12:27:52 +00:00
drh e8750019c2 In the CLI, the ".quit" command in a --cmd argument causes an immediate
exit.  [forum:/forumpost/f057122b68|Forum post f057122b68].

FossilOrigin-Name: 4731cc8856aa4dcfad5db501648bfd0afef43d8c5f339e7b11a1e3ee64348b87
2026-02-19 17:20:40 +00:00
drh cac09127e1 Improvements to rounding behavior in the new floating-point conversion logic.
FossilOrigin-Name: e540f6c370675ae043af8cdbb80f7eb17c08e50f7634e0b78f0b1dccf7bd4b18
2026-02-19 12:59:42 +00:00
drh 37ee141d25 Restore the CLI function dtostr() back to its original purpose of converting
floating point values to decimal using the host computer's C-library.

FossilOrigin-Name: f3cc05ba7fa9cb77573de5cd28ab90f10844567692ed57a706c5dc35b1348009
2026-02-17 20:28:25 +00:00
drh 7549e784a8 Minor fixes to tmstmpvfs.c.
FossilOrigin-Name: 091bd90ed5a6a326fd532e93bd17903e052476da14dc6aee2599a9acf75a3276
2026-02-17 14:28:18 +00:00
drh 8c3e8dce41 Increase the number of floating-point precision test cases by 9x, and
increase the require precision to 16 digits.

FossilOrigin-Name: 62c2cf74db5e47f975d1f47818f82f060ddecad4b68c4d4dbc6190cc9a8fc397
2026-02-17 14:02:27 +00:00
drh 31d4e56b29 Fix a harmless compiler warning from MSVC.
FossilOrigin-Name: 12f3a6d0aaff8818c427d79e2b9394328625b3a60ccaa7b628d064084c65cfaf
2026-02-17 12:23:12 +00:00
drh 530f536ce7 New assert()s for the return value from sqlite3SchemaToIndex().
FossilOrigin-Name: 2610105a439e25c050b2deb32953861187c81b1d97407f41dc188e6627e0ac4d
2026-02-17 11:28:48 +00:00
drh eb8c4c5742 Further simplifications, performance improvements, and size reductions
to the numeric to text conversion logic.

FossilOrigin-Name: dd5af703e1082951a4295a3453611db12b23cfbcfee4258ec3985abe96ab54ba
2026-02-17 01:04:23 +00:00
drh 0b5e944480 Faster conversion of integers to text, by converting two digits at a time.
FossilOrigin-Name: 90300e02f0de45b57d53976cae72928b3e56532d90b8b8cdc988e14762777930
2026-02-17 00:37:12 +00:00
drh 63338e3ba8 Simplifications to sqlite3AtoF(), resulting in slightly faster performance
and slightly smaller size.

FossilOrigin-Name: 6b9ab641763bc1620a01beec71589506b3b0827bff1c6cd98a5d17c6070050b3
2026-02-16 23:52:51 +00:00
drh 6315919ba8 Fix a bad assert() in the previous check-in.
FossilOrigin-Name: a4540582b5b704af13b570b3dc609dbacada719302372a038cf74eee3688d5e7
2026-02-16 17:22:17 +00:00
drh 5c977eaa0a Refactor the sqlite3AtoF() routine so that it requires a zero-terminated
UTF-8 input.  When the need arises to convert UTF16 or non-terminated
strings, wrapper functions are used.  Together, this makes the code slightly
smaller and faster.

FossilOrigin-Name: 67c7c72e9bdf04c920d77006538a202c923fa74b47c81dc3014c2929dac7277d
2026-02-16 16:56:59 +00:00
dan 1105c33900 Fix another case where SQLite might fail to identify an ON clause on a RIGHT or FULL join that refers to FROM-clause elements to its right.
FossilOrigin-Name: e956b36063e77b5ad0d8b8afb5dc942665f570d762929ff277e320c06ded8ce6
2026-02-16 16:56:25 +00:00
dan 7b93f1a387 Fix a problem with identifying ON clauses attached to RIGHT or FULL JOINs (which is an error) if the join appeared in a flattened sub-query.
FossilOrigin-Name: cf2dc6dfad275dad8fef763a57baaaf6301b0d3bf1916be90f22200cbe0115d0
2026-02-16 11:59:14 +00:00
drh c47bc0ffca Performance improvement in floating-point conversions.
FossilOrigin-Name: b5ebbd004183f81902fa79a143222204b33dbe1cacb918194556b8dac67bd567
2026-02-16 11:14:59 +00:00
drh 990d861038 Add new assert() statements to demonstrate that the complaint given in
[forum:/forumpost/56ad8b632c|forum post 56ad8b632c] is not a real bug.

FossilOrigin-Name: d62999907d5f5987fe0030e1a4a7144c898e55595ac116eec966741a5099322b
2026-02-13 16:02:27 +00:00
drh 23e57bc7cd Use only a single bit, rather than a whole byte, to store infrequently
accessed boolean values in the Parse object.

FossilOrigin-Name: e1bcd7e1cf6d6b1add49deac65e1b64bcae52fbbad094e561846bb92959db76a
2026-02-13 12:20:57 +00:00
drh 7d49eb1dff Add a "const" to avoid a harmless false-positive compiler warning.
FossilOrigin-Name: d44af6cc093ab6b5a196249a84681148bbae3f624abf4bc8cc42c88f3f7320b2
2026-02-13 11:40:28 +00:00
drh df59c5da78 Respect "const" strings in the sqlite3ShadowTableName() function.
Patch moved to trunk, where it was intended.

FossilOrigin-Name: 51b5afdfac401cbf74af6383d4559439cb6defe2ce23ebcf7ed9a5b526a07b51
2026-02-12 18:15:26 +00:00
86 changed files with 1433 additions and 2775 deletions
-17
View File
@@ -2660,23 +2660,6 @@ sqltclsh.exe: sqltclsh.c $(SHELL_CORE_DEP) $(LIBRESOBJS)
sqlite3_expert.exe: $(SQLITE3C) $(TOP)\ext\expert\sqlite3expert.h $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c
$(LTLINK) $(NO_WARN) $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c $(SQLITE3C) $(TLIBS)
CHECKER_DEPS =\
$(TOP)\tool\mkccode.tcl \
sqlite3.c \
tclsqlite-ex.c \
$(TOP)\ext\repair\sqlite3_checker.tcl \
$(TOP)\ext\repair\checkindex.c \
$(TOP)\ext\repair\checkfreelist.c \
$(TOP)\ext\misc\btreeinfo.c \
$(TOP)\ext\repair\sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
+1 -1
View File
@@ -455,7 +455,7 @@ static void fts5SnippetFunction(
iBestCol = (iCol>=0 ? iCol : 0);
nPhrase = pApi->xPhraseCount(pFts);
aSeen = sqlite3_malloc(nPhrase);
aSeen = sqlite3_malloc64(nPhrase);
if( aSeen==0 ){
rc = SQLITE_NOMEM;
}
+1 -1
View File
@@ -288,7 +288,7 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
if( nIn<0 ){
nIn = (int)strlen(pIn);
}
zRet = (char*)sqlite3_malloc(nIn+1);
zRet = (char*)sqlite3_malloc64((i64)nIn+1);
if( zRet ){
memcpy(zRet, pIn, nIn);
zRet[nIn] = '\0';
+1 -3
View File
@@ -576,7 +576,7 @@ int sqlite3Fts5ConfigParse(
sqlite3_int64 nByte;
int bUnindexed = 0; /* True if there are one or more UNINDEXED */
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
*ppOut = pRet = (Fts5Config*)sqlite3_malloc64(sizeof(Fts5Config));
if( pRet==0 ) return SQLITE_NOMEM;
memset(pRet, 0, sizeof(Fts5Config));
pRet->pGlobal = pGlobal;
@@ -1123,5 +1123,3 @@ void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){
va_end(ap);
}
+2 -2
View File
@@ -314,7 +314,7 @@ int sqlite3Fts5ExprNew(
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
if( sParse.rc==SQLITE_OK ){
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
*ppNew = pNew = sqlite3_malloc64(sizeof(Fts5Expr));
if( pNew==0 ){
sParse.rc = SQLITE_NOMEM;
sqlite3Fts5ParseNodeFree(sParse.pExpr);
@@ -466,7 +466,7 @@ int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
p2->pRoot = 0;
if( sParse.rc==SQLITE_OK ){
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc64(
p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
);
if( ap==0 ){
+1 -1
View File
@@ -91,7 +91,7 @@ int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
int rc = SQLITE_OK;
Fts5Hash *pNew;
*ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
*ppNew = pNew = (Fts5Hash*)sqlite3_malloc64(sizeof(Fts5Hash));
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
+15 -14
View File
@@ -2093,7 +2093,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
/* If necessary, grow the pIter->aRowidOffset[] array. */
if( iRowidOffset>=pIter->nRowidOffset ){
int nNew = pIter->nRowidOffset + 8;
i64 nNew = pIter->nRowidOffset + 8;
int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
@@ -6418,16 +6418,16 @@ struct Fts5TokenDataMap {
** aMap[] variables.
*/
struct Fts5TokenDataIter {
int nMapAlloc; /* Allocated size of aMap[] in entries */
int nMap; /* Number of valid entries in aMap[] */
i64 nMapAlloc; /* Allocated size of aMap[] in entries */
i64 nMap; /* Number of valid entries in aMap[] */
Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
/* The following are used for prefix-queries only. */
Fts5Buffer terms;
/* The following are used for other full-token tokendata queries only. */
int nIter;
int nIterAlloc;
i64 nIter;
i64 nIterAlloc;
Fts5PoslistReader *aPoslistReader;
int *aPoslistToIter;
Fts5Iter *apIter[FLEXARRAY];
@@ -6483,11 +6483,11 @@ static void fts5TokendataIterAppendMap(
){
if( p->rc==SQLITE_OK ){
if( pT->nMap==pT->nMapAlloc ){
int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
int nAlloc = nNew * sizeof(Fts5TokenDataMap);
i64 nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
i64 nAlloc = nNew * sizeof(Fts5TokenDataMap);
Fts5TokenDataMap *aNew;
aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
aNew = (Fts5TokenDataMap*)sqlite3_realloc64(pT->aMap, nAlloc);
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
return;
@@ -6513,7 +6513,7 @@ static void fts5TokendataIterAppendMap(
*/
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
Fts5TokenDataMap *aTmp = 0;
int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
i64 nByte = pT->nMap * sizeof(Fts5TokenDataMap);
aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( aTmp ){
@@ -7047,9 +7047,10 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
if( p->rc==SQLITE_OK ){
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
i64 nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
i64 nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
Fts5TokenDataIter *pNew;
pNew = (Fts5TokenDataIter*)sqlite3_realloc64(pIn, nByte);
if( pNew==0 ){
p->rc = SQLITE_NOMEM;
@@ -7146,8 +7147,8 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
/* Ensure the token-mapping is large enough */
if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){
int nNew = (pT->nMapAlloc + nByte) * 2;
Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc(
i64 nNew = (pT->nMapAlloc + nByte) * 2;
Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc64(
pT->aMap, nNew*sizeof(Fts5TokenDataMap)
);
if( aNew==0 ){
+2 -2
View File
@@ -631,7 +631,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_ERROR;
}
idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
idxStr = (char*)sqlite3_malloc64((i64)pInfo->nConstraint * 8 + 1);
if( idxStr==0 ) return SQLITE_NOMEM;
pInfo->idxStr = idxStr;
pInfo->needToFreeIdxStr = 1;
@@ -3763,7 +3763,7 @@ static int fts5Init(sqlite3 *db){
int rc;
Fts5Global *pGlobal = 0;
pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
pGlobal = (Fts5Global*)sqlite3_malloc64(sizeof(Fts5Global));
if( pGlobal==0 ){
rc = SQLITE_NOMEM;
}else{
+4 -4
View File
@@ -391,7 +391,7 @@ static int SQLITE_TCLAPI xF5tApi(
break;
}
CASE(12, "xSetAuxdata") {
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc64(sizeof(F5tAuxData));
if( pData==0 ){
Tcl_AppendResult(interp, "out of memory", (char*)0);
return TCL_ERROR;
@@ -780,7 +780,7 @@ static int SQLITE_TCLAPI f5tTokenize(
}
if( nText>0 ){
pCopy = sqlite3_malloc(nText);
pCopy = sqlite3_malloc64(nText);
if( pCopy==0 ){
tokenizer.xDelete(pTok);
Tcl_AppendResult(interp, "error in sqlite3_malloc()", (char*)0);
@@ -1420,7 +1420,7 @@ static int f5tOrigintextCreate(
void *pTokCtx = 0;
int rc = SQLITE_OK;
pTok = (OriginTextTokenizer*)sqlite3_malloc(sizeof(OriginTextTokenizer));
pTok = (OriginTextTokenizer*)sqlite3_malloc64(sizeof(OriginTextTokenizer));
if( pTok==0 ){
rc = SQLITE_NOMEM;
}else if( nArg<1 ){
@@ -1480,7 +1480,7 @@ static int xOriginToken(
int nReq = nToken + 1 + (iEnd-iStart);
if( nReq>p->nBuf ){
sqlite3_free(p->aBuf);
p->aBuf = sqlite3_malloc(nReq*2);
p->aBuf = sqlite3_malloc64(nReq*2);
if( p->aBuf==0 ) return SQLITE_NOMEM;
p->nBuf = nReq*2;
}
+5 -5
View File
@@ -194,7 +194,7 @@ static int fts5tokConnectMethod(
}
if( rc==SQLITE_OK ){
pTab = (Fts5tokTable*)sqlite3_malloc(sizeof(Fts5tokTable));
pTab = (Fts5tokTable*)sqlite3_malloc64(sizeof(Fts5tokTable));
if( pTab==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -275,7 +275,7 @@ static int fts5tokBestIndexMethod(
static int fts5tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
Fts5tokCursor *pCsr;
pCsr = (Fts5tokCursor *)sqlite3_malloc(sizeof(Fts5tokCursor));
pCsr = (Fts5tokCursor *)sqlite3_malloc64(sizeof(Fts5tokCursor));
if( pCsr==0 ){
return SQLITE_NOMEM;
}
@@ -347,7 +347,7 @@ static int fts5tokCb(
if( pCsr->nRow ){
pRow->iPos = pRow[-1].iPos + ((tflags & FTS5_TOKEN_COLOCATED) ? 0 : 1);
}
pRow->zToken = sqlite3_malloc(nToken+1);
pRow->zToken = sqlite3_malloc64((sqlite3_int64)nToken+1);
if( pRow->zToken==0 ) return SQLITE_NOMEM;
memcpy(pRow->zToken, pToken, nToken);
pRow->zToken[nToken] = 0;
@@ -373,8 +373,8 @@ static int fts5tokFilterMethod(
fts5tokResetCursor(pCsr);
if( idxNum==1 ){
const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
int nByte = sqlite3_value_bytes(apVal[0]);
pCsr->zInput = sqlite3_malloc(nByte+1);
sqlite3_int64 nByte = sqlite3_value_bytes(apVal[0]);
pCsr->zInput = sqlite3_malloc64(nByte+1);
if( pCsr->zInput==0 ){
rc = SQLITE_NOMEM;
}else{
+4 -4
View File
@@ -72,7 +72,7 @@ static int fts5AsciiCreate(
if( nArg%2 ){
rc = SQLITE_ERROR;
}else{
p = sqlite3_malloc(sizeof(AsciiTokenizer));
p = sqlite3_malloc64(sizeof(AsciiTokenizer));
if( p==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -367,7 +367,7 @@ static int fts5UnicodeCreate(
if( nArg%2 ){
rc = SQLITE_ERROR;
}else{
p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer));
p = (Unicode61Tokenizer*)sqlite3_malloc64(sizeof(Unicode61Tokenizer));
if( p ){
const char *zCat = "L* N* Co";
int i;
@@ -590,7 +590,7 @@ static int fts5PorterCreate(
zBase = azArg[0];
}
pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer));
pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
if( pRet ){
memset(pRet, 0, sizeof(PorterTokenizer));
rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2);
@@ -1297,7 +1297,7 @@ static int fts5TriCreate(
rc = SQLITE_ERROR;
}else{
int i;
pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
pNew = (TrigramTokenizer*)sqlite3_malloc64(sizeof(*pNew));
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
+1 -1
View File
@@ -666,7 +666,7 @@ static int fts5VocabFilterMethod(
const char *zCopy = (const char *)sqlite3_value_text(pLe);
if( zCopy==0 ) zCopy = "";
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
pCsr->zLeTerm = sqlite3_malloc64((i64)pCsr->nLeTerm+1);
if( pCsr->zLeTerm==0 ){
rc = SQLITE_NOMEM;
}else{
-3
View File
@@ -379,9 +379,6 @@ do_execsql_test 12.2 {
db close
sqlite3 db test.db -readonly 1
explain_i {
PRAGMA integrity_check
}
do_execsql_test 12.3 {
PRAGMA integrity_check
} {ok}
+1 -1
View File
@@ -319,7 +319,7 @@ static int intckGetToken(const char *z){
char c = z[0];
int iRet = 1;
if( c=='\'' || c=='"' || c=='`' ){
while( 1 ){
while( z[iRet] ){
if( z[iRet]==c ){
iRet++;
if( z[iRet]!=c ) break;
+38 -5
View File
@@ -291,12 +291,36 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_text(pCtx, z, i, sqlite3_free);
}
/*
** Round a decimal value to N significant digits. N must be positive.
*/
static void decimal_round(Decimal *p, int N){
int i;
int nZero;
if( N<1 ) return;
for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
N += nZero;
if( p->nDigit<=N ) return;
if( p->a[N]>4 ){
p->a[N-1]++;
for(i=N-1; i>0 && p->a[i]>9; i--){
p->a[i] = 0;
p->a[i-1]++;
}
if( p->a[0]>9 ){
p->a[0] = 1;
p->nFrac--;
}
}
memset(&p->a[N], 0, p->nDigit - N);
}
/*
** Make the given Decimal the result in an format similar to '%+#e'.
** In other words, show exponential notation with leading and trailing
** zeros omitted.
*/
static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p, int N){
char *z; /* The output buffer */
int i; /* Loop counter */
int nZero; /* Number of leading zeros */
@@ -314,7 +338,8 @@ static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_null(pCtx);
return;
}
for(nDigit=p->nDigit; nDigit>0 && p->a[nDigit-1]==0; nDigit--){}
if( N<1 ) N = 0;
for(nDigit=p->nDigit; nDigit>N && p->a[nDigit-1]==0; nDigit--){}
for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
nFrac = p->nFrac + (nDigit - p->nDigit);
nDigit -= nZero;
@@ -677,10 +702,16 @@ static void decimalFunc(
sqlite3_value **argv
){
Decimal *p = decimal_new(context, argv[0], 0);
UNUSED_PARAMETER(argc);
int N;
if( argc==2 ){
N = sqlite3_value_int(argv[1]);
if( N>0 ) decimal_round(p, N);
}else{
N = 0;
}
if( p ){
if( sqlite3_user_data(context)!=0 ){
decimal_result_sci(context, p);
decimal_result_sci(context, p, N);
}else{
decimal_result(context, p);
}
@@ -850,7 +881,7 @@ static void decimalPow2Func(
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
Decimal *pA = decimalPow2(sqlite3_value_int(argv[0]));
decimal_result_sci(context, pA);
decimal_result_sci(context, pA, 0);
decimal_free(pA);
}
}
@@ -871,7 +902,9 @@ int sqlite3_decimal_init(
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "decimal", 1, 0, decimalFunc },
{ "decimal", 2, 0, decimalFunc },
{ "decimal_exp", 1, 1, decimalFunc },
{ "decimal_exp", 2, 1, decimalFunc },
{ "decimal_cmp", 2, 0, decimalCmpFunc },
{ "decimal_add", 2, 0, decimalAddFunc },
{ "decimal_sub", 2, 0, decimalSubFunc },
+173 -57
View File
@@ -94,12 +94,16 @@ SQLITE_EXTENSION_INIT1
# include <utime.h>
# include <sys/time.h>
# define STRUCT_STAT struct stat
# include <limits.h>
# include <stdlib.h>
#else
# include "windirent.h"
# include <direct.h>
# define STRUCT_STAT struct _stat
# define chmod(path,mode) fileio_chmod(path,mode)
# define mkdir(path,mode) fileio_mkdir(path)
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
#endif
#include <time.h>
#include <errno.h>
@@ -131,12 +135,9 @@ SQLITE_EXTENSION_INIT1
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_chmod(const char *zPath, int pmode){
sqlite3_int64 sz = strlen(zPath);
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return -1;
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
b1[sz] = 0;
rc = _wchmod(b1, pmode);
sqlite3_free(b1);
return rc;
@@ -148,12 +149,9 @@ static int fileio_chmod(const char *zPath, int pmode){
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_mkdir(const char *zPath){
sqlite3_int64 sz = strlen(zPath);
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return -1;
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
b1[sz] = 0;
rc = _wmkdir(b1);
sqlite3_free(b1);
return rc;
@@ -266,50 +264,7 @@ static sqlite3_uint64 fileTimeToUnixTime(
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
}
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
# /* To allow a standalone DLL, use this next replacement function: */
# undef sqlite3_win32_utf8_to_unicode
# define sqlite3_win32_utf8_to_unicode utf8_to_utf16
#
LPWSTR utf8_to_utf16(const char *z){
int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
return rv;
sqlite3_free(rv);
return 0;
}
#endif
/*
** This function attempts to normalize the time values found in the stat()
** buffer to UTC. This is necessary on Win32, where the runtime library
** appears to return these values as local times.
*/
static void statTimesToUtc(
const char *zPath,
STRUCT_STAT *pStatBuf
){
HANDLE hFindFile;
WIN32_FIND_DATAW fd;
LPWSTR zUnicodeName;
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
if( zUnicodeName ){
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
hFindFile = FindFirstFileW(zUnicodeName, &fd);
if( hFindFile!=NULL ){
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
FindClose(hFindFile);
}
sqlite3_free(zUnicodeName);
}
}
#endif
#endif /* _WIN32 */
/*
** This function is used in place of stat(). On Windows, special handling
@@ -321,14 +276,22 @@ static int fileStat(
STRUCT_STAT *pStatBuf
){
#if defined(_WIN32)
sqlite3_int64 sz = strlen(zPath);
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
if( b1==0 ) return 1;
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
b1[sz] = 0;
rc = _wstat(b1, pStatBuf);
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
if( rc==0 ){
HANDLE hFindFile;
WIN32_FIND_DATAW fd;
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
hFindFile = FindFirstFileW(b1, &fd);
if( hFindFile!=NULL ){
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
FindClose(hFindFile);
}
}
sqlite3_free(b1);
return rc;
#else
@@ -1093,6 +1056,154 @@ static int fsdirRegister(sqlite3 *db){
# define fsdirRegister(x) SQLITE_OK
#endif
/*
** This version of realpath() works on any system. The string
** returned is held in memory allocated using sqlite3_malloc64().
** The caller is responsible for calling sqlite3_free().
*/
static char *portable_realpath(const char *zPath){
#if !defined(_WIN32) /* BEGIN unix */
char *zOut = 0; /* Result */
char *z; /* Temporary buffer */
#if defined(PATH_MAX)
char zBuf[PATH_MAX+1]; /* Space for the temporary buffer */
#endif
if( zPath==0 ) return 0;
#if defined(PATH_MAX)
z = realpath(zPath, zBuf);
if( z ){
zOut = sqlite3_mprintf("%s", zBuf);
}
#endif /* defined(PATH_MAX) */
if( zOut==0 ){
/* Try POSIX.1-2008 malloc behavior */
z = realpath(zPath, NULL);
if( z ){
zOut = sqlite3_mprintf("%s", z);
free(z);
}
}
return zOut;
#else /* End UNIX, Begin WINDOWS */
wchar_t *zPath16; /* UTF16 translation of zPath */
char *zOut = 0; /* Result */
wchar_t *z = 0; /* Temporary buffer */
if( zPath==0 ) return 0;
zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
if( zPath16==0 ) return 0;
z = _wfullpath(NULL, zPath16, 0);
sqlite3_free(zPath16);
if( z ){
zOut = sqlite3_win32_unicode_to_utf8(z);
free(z);
}
return zOut;
#endif /* End WINDOWS, Begin common code */
}
/*
** SQL function: realpath(X)
**
** Try to convert file or pathname X into its real, absolute pathname.
** Return NULL if unable.
**
** The file or directory X is not required to exist. The answer is formed
** by calling system realpath() on the prefix of X that does exist and
** appending the tail of X that does not (yet) exist.
*/
static void realpathFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zPath; /* Original input path */
char *zCopy; /* An editable copy of zPath */
char *zOut; /* The result */
char cSep = 0; /* Separator turned into \000 */
size_t len; /* Prefix length before cSep */
#ifdef _WIN32
const int isWin = 1;
#else
const int isWin = 0;
#endif
(void)argc;
zPath = (const char*)sqlite3_value_text(argv[0]);
if( zPath==0 ) return;
if( zPath[0]==0 ) zPath = ".";
zCopy = sqlite3_mprintf("%s",zPath);
len = strlen(zCopy);
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
len--;
}
zCopy[len] = 0;
while( 1 /*exit-by-break*/ ){
zOut = portable_realpath(zCopy);
zCopy[len] = cSep;
if( zOut ){
if( cSep ){
zOut = sqlite3_mprintf("%z%s",zOut,&zCopy[len]);
}
break;
}else{
size_t i = len-1;
while( i>0 ){
if( zCopy[i]=='/' || (isWin && zCopy[i]=='\\') ) break;
i--;
}
if( i<=0 ){
if( zCopy[0]=='/' ){
zOut = zCopy;
zCopy = 0;
}else if( (zOut = portable_realpath("."))!=0 ){
zOut = sqlite3_mprintf("%z/%s", zOut, zCopy);
}
break;
}
cSep = zCopy[i];
zCopy[i] = 0;
len = i;
}
}
sqlite3_free(zCopy);
if( zOut ){
/* Simplify any "/./" or "/../" that might have snuck into the
** pathname due to appending of zCopy. We only have to consider
** unix "/" separators, because the _wfilepath() system call on
** Windows will have already done this simplification for us. */
size_t i, j, n;
n = strlen(zOut);
for(i=j=0; i<n; i++){
if( zOut[i]=='/' ){
if( zOut[i+1]=='/' ) continue;
if( zOut[i+1]=='.' && i+2<n && zOut[i+2]=='/' ){
i += 1;
continue;
}
if( zOut[i+1]=='.' && i+3<n && zOut[i+2]=='.' && zOut[i+3]=='/' ){
while( j>0 && zOut[j-1]!='/' ){ j--; }
if( j>0 ){ j--; }
i += 2;
continue;
}
}
zOut[j++] = zOut[i];
}
zOut[j] = 0;
/* Return the result */
sqlite3_result_text(context, zOut, -1, sqlite3_free);
}
}
#ifdef _WIN32
__declspec(dllexport)
#endif
@@ -1119,5 +1230,10 @@ int sqlite3_fileio_init(
if( rc==SQLITE_OK ){
rc = fsdirRegister(db);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "realpath", 1,
SQLITE_UTF8, 0,
realpathFunc, 0, 0);
}
return rc;
}
+1 -1
View File
@@ -617,7 +617,7 @@ static int fuzzerRender(
int *pnBuf /* Size of the buffer */
){
const fuzzer_rule *pRule = pStem->pRule;
int n; /* Size of output term without nul-term */
sqlite3_int64 n; /* Size of output term without nul-term */
char *z; /* Buffer to assemble output term in */
n = pStem->nBasis + pRule->nTo - pRule->nFrom;
+34
View File
@@ -259,6 +259,38 @@ static void ieee754func_to_blob(
}
}
/*
** Functions to convert between 64-bit integers and floats.
**
** The bit patterns are copied. The numeric values are different.
*/
static void ieee754func_from_int(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
double r;
sqlite3_int64 v = sqlite3_value_int64(argv[0]);
memcpy(&r, &v, sizeof(r));
sqlite3_result_double(context, r);
}
}
static void ieee754func_to_int(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_FLOAT ){
double r = sqlite3_value_double(argv[0]);
sqlite3_uint64 v;
memcpy(&v, &r, sizeof(v));
sqlite3_result_int64(context, v);
}
}
/*
** SQL Function: ieee754_inc(r,N)
**
@@ -311,6 +343,8 @@ int sqlite3_ieee_init(
{ "ieee754_exponent", 1, 2, ieee754func },
{ "ieee754_to_blob", 1, 0, ieee754func_to_blob },
{ "ieee754_from_blob", 1, 0, ieee754func_from_blob },
{ "ieee754_to_int", 1, 0, ieee754func_to_int },
{ "ieee754_from_int", 1, 0, ieee754func_from_int },
{ "ieee754_inc", 2, 0, ieee754inc },
};
unsigned int i;
+8 -4
View File
@@ -484,6 +484,7 @@ static void tmstmpPutU32(u32 v, unsigned char *a){
/* Free a TmstmpLog object */
static void tmstmpLogFree(TmstmpLog *pLog){
if( pLog==0 ) return;
if( pLog->log ) fclose(pLog->log);
sqlite3_free(pLog->zLogname);
sqlite3_free(pLog);
}
@@ -502,6 +503,7 @@ static int tmstmpLogFlush(TmstmpFile *p){
}
}
(void)fwrite(pLog->a, pLog->n, 1, pLog->log);
fflush(pLog->log);
pLog->n = 0;
return 0;
}
@@ -619,7 +621,7 @@ static int tmstmpWrite(
u32 x = 0;
p->iFrame = (iOfst - 32)/(p->pgsz+24)+1;
p->pgno = tmstmpGetU32((const u8*)zBuf);
p->salt1 = tmstmpGetU32(((const u8*)zBuf)+16);
p->salt1 = tmstmpGetU32(((const u8*)zBuf)+8);
memcpy(&x, ((const u8*)zBuf)+4, 4);
p->isCommit = (x!=0);
p->iOfst = iOfst;
@@ -637,7 +639,7 @@ static int tmstmpWrite(
memset(s, 0, TMSTMP_RESERVE);
tmstmpPutTS(p, s+2);
tmstmpPutU32(p->iFrame, s+8);
tmstmpPutU32(p->pPartner->salt1, s+12);
tmstmpPutU32(p->pPartner->salt1 & 0xffffff, s+12);
assert( p->pgsz>0 );
tmstmpEvent(p, ELOG_CKPT_PAGE, 0, (iOfst/p->pgsz)+1, p->iFrame, 0);
}else if( p->pPartner==0 ){
@@ -647,7 +649,7 @@ static int tmstmpWrite(
tmstmpPutTS(p, s+2);
s[12] = 2;
assert( p->pgsz>0 );
tmstmpEvent(p, ELOG_DB_PAGE, 0, (u32)(iOfst/p->pgsz), 0, s+2);
tmstmpEvent(p, ELOG_DB_PAGE, 0, (u32)(iOfst/p->pgsz)+1, 0, s+2);
}
return pSub->pMethods->xWrite(pSub,zBuf,iAmt,iOfst);
}
@@ -879,7 +881,9 @@ static int tmstmpOpen(
r1 = 0;
pLog = sqlite3_malloc64( sizeof(TmstmpLog) );
if( pLog==0 ){
return SQLITE_NOMEM;
pSubFile->pMethods->xClose(pSubFile);
rc = SQLITE_NOMEM;
goto tmstmp_open_done;
}
memset(pLog, 0, sizeof(pLog[0]));
p->pLog = pLog;
+6 -1
View File
@@ -705,7 +705,12 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
u8 *p = aExtra;
u8 *pEnd = &aExtra[nExtra];
while( p<pEnd ){
/* Stop when there are less than 9 bytes left to scan in the buffer. This
** is because the timestamp field requires exactly 9 bytes - 4 bytes of
** header fields and 5 bytes of data. If there are less than 9 bytes
** remaining, either it is some other field or else the extra data
** is corrupt. Either way, do not process it. */
while( p+(2*sizeof(u16) + 1 + sizeof(u32))<=pEnd ){
u16 id = zipfileRead16(p);
u16 nByte = zipfileRead16(p);
+2 -2
View File
@@ -2630,7 +2630,7 @@ static void qrfOneSimpleRow(Qrf *p){
do{
int nThis, nWide, iNext;
qrfWrapLine(zVal, mxW, bWW, &nThis, &nWide, &iNext);
if( cnt ) sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+3,' ');
if( cnt ) sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+2,' ');
cnt++;
if( cnt>p->mxHeight ){
zVal = "...";
@@ -2900,7 +2900,7 @@ static void qrfFinalize(Qrf *p){
char *zCombined;
sz = strlen(p->spec.pzOutput[0]);
n = sqlite3_str_length(p->pOut);
zCombined = sqlite3_realloc(p->spec.pzOutput[0], sz+n+1);
zCombined = sqlite3_realloc64(p->spec.pzOutput[0], sz+n+1);
if( zCombined==0 ){
sqlite3_free(p->spec.pzOutput[0]);
p->spec.pzOutput[0] = 0;
+2 -2
View File
@@ -2269,8 +2269,8 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
/* If necessary, grow the pIter->aIdxCol[] array */
if( iIdxCol==nIdxAlloc ){
RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc(
pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan)
RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc64(
pIter->aIdxCol, nIdxAlloc*sizeof(RbuSpan) + 16*sizeof(RbuSpan)
);
if( aIdxCol==0 ){
rc = SQLITE_NOMEM;
-16
View File
@@ -1,16 +0,0 @@
This folder contains extensions and utility programs intended to analyze
live database files, detect problems, and possibly fix them.
As SQLite is being used on larger and larger databases, database sizes
are growing into the terabyte range. At that size, hardware malfunctions
and/or cosmic rays will occasionally corrupt a database file. Detecting
problems and fixing errors a terabyte-sized databases can take hours or days,
and it is undesirable to take applications that depend on the databases
off-line for such a long time.
The utilities in the folder are intended to provide mechanisms for
detecting and fixing problems in large databases while those databases
are in active use.
The utilities and extensions in this folder are experimental and under
active development at the time of this writing (2017-10-12). If and when
they stabilize, this README will be updated to reflect that fact.
-310
View File
@@ -1,310 +0,0 @@
/*
** 2017 October 11
**
** 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 module exports a single C function:
**
** int sqlite3_check_freelist(sqlite3 *db, const char *zDb);
**
** This function checks the free-list in database zDb (one of "main",
** "temp", etc.) and reports any errors by invoking the sqlite3_log()
** function. It returns SQLITE_OK if successful, or an SQLite error
** code otherwise. It is not an error if the free-list is corrupted but
** no IO or OOM errors occur.
**
** If this file is compiled and loaded as an SQLite loadable extension,
** it adds an SQL function "checkfreelist" to the database handle, to
** be invoked as follows:
**
** SELECT checkfreelist(<database-name>);
**
** This function performs the same checks as sqlite3_check_freelist(),
** except that it returns all error messages as a single text value,
** separated by newline characters. If the freelist is not corrupted
** in any way, an empty string is returned.
**
** To compile this module for use as an SQLite loadable extension:
**
** gcc -Os -fPIC -shared checkfreelist.c -o checkfreelist.so
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#ifndef SQLITE_AMALGAMATION
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
# endif
# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X) (1)
# define NEVER(X) (0)
# elif !defined(NDEBUG)
# define ALWAYS(X) ((X)?1:(assert(0),0))
# define NEVER(X) ((X)?(assert(0),1):0)
# else
# define ALWAYS(X) (X)
# define NEVER(X) (X)
# endif
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#define get4byte(x) ( \
((u32)((x)[0])<<24) + \
((u32)((x)[1])<<16) + \
((u32)((x)[2])<<8) + \
((u32)((x)[3])) \
)
#endif
/*
** Execute a single PRAGMA statement and return the integer value returned
** via output parameter (*pnOut).
**
** The SQL statement passed as the third argument should be a printf-style
** format string containing a single "%s" which will be replace by the
** value passed as the second argument. e.g.
**
** sqlGetInteger(db, "main", "PRAGMA %s.page_count", pnOut)
**
** executes "PRAGMA main.page_count" and stores the results in (*pnOut).
*/
static int sqlGetInteger(
sqlite3 *db, /* Database handle */
const char *zDb, /* Database name ("main", "temp" etc.) */
const char *zFmt, /* SQL statement format */
u32 *pnOut /* OUT: Integer value */
){
int rc, rc2;
char *zSql;
sqlite3_stmt *pStmt = 0;
int bOk = 0;
zSql = sqlite3_mprintf(zFmt, zDb);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
*pnOut = (u32)sqlite3_column_int(pStmt, 0);
bOk = 1;
}
rc2 = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ) rc = rc2;
if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_ERROR;
return rc;
}
/*
** Argument zFmt must be a printf-style format string and must be
** followed by its required arguments. If argument pzOut is NULL,
** then the results of printf()ing the format string are passed to
** sqlite3_log(). Otherwise, they are appended to the string
** at (*pzOut).
*/
static int checkFreelistError(char **pzOut, const char *zFmt, ...){
int rc = SQLITE_OK;
char *zErr = 0;
va_list ap;
va_start(ap, zFmt);
zErr = sqlite3_vmprintf(zFmt, ap);
if( zErr==0 ){
rc = SQLITE_NOMEM;
}else{
if( pzOut ){
*pzOut = sqlite3_mprintf("%s%z%s", *pzOut?"\n":"", *pzOut, zErr);
if( *pzOut==0 ) rc = SQLITE_NOMEM;
}else{
sqlite3_log(SQLITE_ERROR, "checkfreelist: %s", zErr);
}
sqlite3_free(zErr);
}
va_end(ap);
return rc;
}
static int checkFreelist(
sqlite3 *db,
const char *zDb,
char **pzOut
){
/* This query returns one row for each page on the free list. Each row has
** two columns - the page number and page content. */
const char *zTrunk =
"WITH freelist_trunk(i, d, n) AS ("
"SELECT 1, NULL, sqlite_readint32(data, 32) "
"FROM sqlite_dbpage(:1) WHERE pgno=1 "
"UNION ALL "
"SELECT n, data, sqlite_readint32(data) "
"FROM freelist_trunk, sqlite_dbpage(:1) WHERE pgno=n "
")"
"SELECT i, d FROM freelist_trunk WHERE i!=1;";
int rc, rc2; /* Return code */
sqlite3_stmt *pTrunk = 0; /* Compilation of zTrunk */
u32 nPage = 0; /* Number of pages in db */
u32 nExpected = 0; /* Expected number of free pages */
u32 nFree = 0; /* Number of pages on free list */
if( zDb==0 ) zDb = "main";
if( (rc = sqlGetInteger(db, zDb, "PRAGMA %s.page_count", &nPage))
|| (rc = sqlGetInteger(db, zDb, "PRAGMA %s.freelist_count", &nExpected))
){
return rc;
}
rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
u32 i;
u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
u32 nData = (u32)sqlite3_column_bytes(pTrunk, 1);
u32 iNext = get4byte(&aData[0]);
u32 nLeaf = get4byte(&aData[4]);
if( nLeaf>((nData/4)-2-6) ){
rc = checkFreelistError(pzOut,
"leaf count out of range (%d) on trunk page %d",
(int)nLeaf, (int)iTrunk
);
nLeaf = (nData/4) - 2 - 6;
}
nFree += 1+nLeaf;
if( iNext>nPage ){
rc = checkFreelistError(pzOut,
"trunk page %d is out of range", (int)iNext
);
}
for(i=0; rc==SQLITE_OK && i<nLeaf; i++){
u32 iLeaf = get4byte(&aData[8 + 4*i]);
if( iLeaf==0 || iLeaf>nPage ){
rc = checkFreelistError(pzOut,
"leaf page %d is out of range (child %d of trunk page %d)",
(int)iLeaf, (int)i, (int)iTrunk
);
}
}
}
if( rc==SQLITE_OK && nFree!=nExpected ){
rc = checkFreelistError(pzOut,
"free-list count mismatch: actual=%d header=%d",
(int)nFree, (int)nExpected
);
}
rc2 = sqlite3_finalize(pTrunk);
if( rc==SQLITE_OK ) rc = rc2;
return rc;
}
int sqlite3_check_freelist(sqlite3 *db, const char *zDb){
return checkFreelist(db, zDb, 0);
}
static void checkfreelist_function(
sqlite3_context *pCtx,
int nArg,
sqlite3_value **apArg
){
const char *zDb;
int rc;
char *zOut = 0;
sqlite3 *db = sqlite3_context_db_handle(pCtx);
assert( nArg==1 );
zDb = (const char*)sqlite3_value_text(apArg[0]);
rc = checkFreelist(db, zDb, &zOut);
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, zOut?zOut:"ok", -1, SQLITE_TRANSIENT);
}else{
sqlite3_result_error_code(pCtx, rc);
}
sqlite3_free(zOut);
}
/*
** An SQL function invoked as follows:
**
** sqlite_readint32(BLOB) -- Decode 32-bit integer from start of blob
*/
static void readint_function(
sqlite3_context *pCtx,
int nArg,
sqlite3_value **apArg
){
const u8 *zBlob;
int nBlob;
int iOff = 0;
u32 iRet = 0;
if( nArg!=1 && nArg!=2 ){
sqlite3_result_error(
pCtx, "wrong number of arguments to function sqlite_readint32()", -1
);
return;
}
if( nArg==2 ){
iOff = sqlite3_value_int(apArg[1]);
}
zBlob = sqlite3_value_blob(apArg[0]);
nBlob = sqlite3_value_bytes(apArg[0]);
if( nBlob>=(iOff+4) ){
iRet = get4byte(&zBlob[iOff]);
}
sqlite3_result_int64(pCtx, (sqlite3_int64)iRet);
}
/*
** Register the SQL functions.
*/
static int cflRegister(sqlite3 *db){
int rc = sqlite3_create_function(
db, "sqlite_readint32", -1, SQLITE_UTF8, 0, readint_function, 0, 0
);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_create_function(
db, "checkfreelist", 1, SQLITE_UTF8, 0, checkfreelist_function, 0, 0
);
return rc;
}
/*
** Extension load function.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_checkfreelist_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi);
return cflRegister(db);
}
-929
View File
@@ -1,929 +0,0 @@
/*
** 2017 October 27
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
/*
** Stuff that is available inside the amalgamation, but which we need to
** declare ourselves if this module is compiled separately.
*/
#ifndef SQLITE_AMALGAMATION
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#define get4byte(x) ( \
((u32)((x)[0])<<24) + \
((u32)((x)[1])<<16) + \
((u32)((x)[2])<<8) + \
((u32)((x)[3])) \
)
#endif
typedef struct CidxTable CidxTable;
typedef struct CidxCursor CidxCursor;
struct CidxTable {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db;
};
struct CidxCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
sqlite3_int64 iRowid; /* Row number of the output */
char *zIdxName; /* Copy of the index_name parameter */
char *zAfterKey; /* Copy of the after_key parameter */
sqlite3_stmt *pStmt; /* SQL statement that generates the output */
};
typedef struct CidxColumn CidxColumn;
struct CidxColumn {
char *zExpr; /* Text for indexed expression */
int bDesc; /* True for DESC columns, otherwise false */
int bKey; /* Part of index, not PK */
};
typedef struct CidxIndex CidxIndex;
struct CidxIndex {
char *zWhere; /* WHERE clause, if any */
int nCol; /* Elements in aCol[] array */
CidxColumn aCol[1]; /* Array of indexed columns */
};
static void *cidxMalloc(int *pRc, int n){
void *pRet = 0;
assert( n!=0 );
if( *pRc==SQLITE_OK ){
pRet = sqlite3_malloc(n);
if( pRet ){
memset(pRet, 0, n);
}else{
*pRc = SQLITE_NOMEM;
}
}
return pRet;
}
static void cidxCursorError(CidxCursor *pCsr, const char *zFmt, ...){
va_list ap;
va_start(ap, zFmt);
assert( pCsr->base.pVtab->zErrMsg==0 );
pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
va_end(ap);
}
/*
** Connect to the incremental_index_check virtual table.
*/
static int cidxConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
int rc = SQLITE_OK;
CidxTable *pRet;
#define IIC_ERRMSG 0
#define IIC_CURRENT_KEY 1
#define IIC_INDEX_NAME 2
#define IIC_AFTER_KEY 3
#define IIC_SCANNER_SQL 4
rc = sqlite3_declare_vtab(db,
"CREATE TABLE xyz("
" errmsg TEXT," /* Error message or NULL if everything is ok */
" current_key TEXT," /* SQLite quote() text of key values */
" index_name HIDDEN," /* IN: name of the index being scanned */
" after_key HIDDEN," /* IN: Start scanning after this key */
" scanner_sql HIDDEN" /* debugging info: SQL used for scanner */
")"
);
pRet = cidxMalloc(&rc, sizeof(CidxTable));
if( pRet ){
pRet->db = db;
}
*ppVtab = (sqlite3_vtab*)pRet;
return rc;
}
/*
** Disconnect from or destroy an incremental_index_check virtual table.
*/
static int cidxDisconnect(sqlite3_vtab *pVtab){
CidxTable *pTab = (CidxTable*)pVtab;
sqlite3_free(pTab);
return SQLITE_OK;
}
/*
** idxNum and idxStr are not used. There are only three possible plans,
** which are all distinguished by the number of parameters.
**
** No parameters: A degenerate plan. The result is zero rows.
** 1 Parameter: Scan all of the index starting with first entry
** 2 parameters: Scan the index starting after the "after_key".
**
** Provide successively smaller costs for each of these plans to encourage
** the query planner to select the one with the most parameters.
*/
static int cidxBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pInfo){
int iIdxName = -1;
int iAfterKey = -1;
int i;
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
if( p->usable==0 ) continue;
if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( p->iColumn==IIC_INDEX_NAME ){
iIdxName = i;
}
if( p->iColumn==IIC_AFTER_KEY ){
iAfterKey = i;
}
}
if( iIdxName<0 ){
pInfo->estimatedCost = 1000000000.0;
}else{
pInfo->aConstraintUsage[iIdxName].argvIndex = 1;
pInfo->aConstraintUsage[iIdxName].omit = 1;
if( iAfterKey<0 ){
pInfo->estimatedCost = 1000000.0;
}else{
pInfo->aConstraintUsage[iAfterKey].argvIndex = 2;
pInfo->aConstraintUsage[iAfterKey].omit = 1;
pInfo->estimatedCost = 1000.0;
}
}
return SQLITE_OK;
}
/*
** Open a new btreeinfo cursor.
*/
static int cidxOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
CidxCursor *pRet;
int rc = SQLITE_OK;
pRet = cidxMalloc(&rc, sizeof(CidxCursor));
*ppCursor = (sqlite3_vtab_cursor*)pRet;
return rc;
}
/*
** Close a btreeinfo cursor.
*/
static int cidxClose(sqlite3_vtab_cursor *pCursor){
CidxCursor *pCsr = (CidxCursor*)pCursor;
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->zIdxName);
sqlite3_free(pCsr->zAfterKey);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** Move a btreeinfo cursor to the next entry in the file.
*/
static int cidxNext(sqlite3_vtab_cursor *pCursor){
CidxCursor *pCsr = (CidxCursor*)pCursor;
int rc = sqlite3_step(pCsr->pStmt);
if( rc!=SQLITE_ROW ){
rc = sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
if( rc!=SQLITE_OK ){
sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
cidxCursorError(pCsr, "Cursor error: %s", sqlite3_errmsg(db));
}
}else{
pCsr->iRowid++;
rc = SQLITE_OK;
}
return rc;
}
/* We have reached EOF if previous sqlite3_step() returned
** anything other than SQLITE_ROW;
*/
static int cidxEof(sqlite3_vtab_cursor *pCursor){
CidxCursor *pCsr = (CidxCursor*)pCursor;
return pCsr->pStmt==0;
}
static char *cidxMprintf(int *pRc, const char *zFmt, ...){
char *zRet = 0;
va_list ap;
va_start(ap, zFmt);
zRet = sqlite3_vmprintf(zFmt, ap);
if( *pRc==SQLITE_OK ){
if( zRet==0 ){
*pRc = SQLITE_NOMEM;
}
}else{
sqlite3_free(zRet);
zRet = 0;
}
va_end(ap);
return zRet;
}
static sqlite3_stmt *cidxPrepare(
int *pRc, CidxCursor *pCsr, const char *zFmt, ...
){
sqlite3_stmt *pRet = 0;
char *zSql;
va_list ap; /* ... printf arguments */
va_start(ap, zFmt);
zSql = sqlite3_vmprintf(zFmt, ap);
if( *pRc==SQLITE_OK ){
if( zSql==0 ){
*pRc = SQLITE_NOMEM;
}else{
sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
*pRc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
if( *pRc!=SQLITE_OK ){
cidxCursorError(pCsr, "SQL error: %s", sqlite3_errmsg(db));
}
}
}
sqlite3_free(zSql);
va_end(ap);
return pRet;
}
static void cidxFinalize(int *pRc, sqlite3_stmt *pStmt){
int rc = sqlite3_finalize(pStmt);
if( *pRc==SQLITE_OK ) *pRc = rc;
}
char *cidxStrdup(int *pRc, const char *zStr){
char *zRet = 0;
if( *pRc==SQLITE_OK ){
int n = (int)strlen(zStr);
zRet = cidxMalloc(pRc, n+1);
if( zRet ) memcpy(zRet, zStr, n+1);
}
return zRet;
}
static void cidxFreeIndex(CidxIndex *pIdx){
if( pIdx ){
int i;
for(i=0; i<pIdx->nCol; i++){
sqlite3_free(pIdx->aCol[i].zExpr);
}
sqlite3_free(pIdx->zWhere);
sqlite3_free(pIdx);
}
}
static int cidx_isspace(char c){
return c==' ' || c=='\t' || c=='\r' || c=='\n';
}
static int cidx_isident(char c){
return c<0
|| (c>='0' && c<='9') || (c>='a' && c<='z')
|| (c>='A' && c<='Z') || c=='_';
}
#define CIDX_PARSE_EOF 0
#define CIDX_PARSE_COMMA 1 /* "," */
#define CIDX_PARSE_OPEN 2 /* "(" */
#define CIDX_PARSE_CLOSE 3 /* ")" */
/*
** Argument zIn points into the start, middle or end of a CREATE INDEX
** statement. If argument pbDoNotTrim is non-NULL, then this function
** scans the input until it finds EOF, a comma (",") or an open or
** close parenthesis character. It then sets (*pzOut) to point to said
** character and returns a CIDX_PARSE_XXX constant as appropriate. The
** parser is smart enough that special characters inside SQL strings
** or comments are not returned for.
**
** Or, if argument pbDoNotTrim is NULL, then this function sets *pzOut
** to point to the first character of the string that is not whitespace
** or part of an SQL comment and returns CIDX_PARSE_EOF.
**
** Additionally, if pbDoNotTrim is not NULL and the element immediately
** before (*pzOut) is an SQL comment of the form "-- comment", then
** (*pbDoNotTrim) is set before returning. In all other cases it is
** cleared.
*/
static int cidxFindNext(
const char *zIn,
const char **pzOut,
int *pbDoNotTrim /* OUT: True if prev is -- comment */
){
const char *z = zIn;
while( 1 ){
while( cidx_isspace(*z) ) z++;
if( z[0]=='-' && z[1]=='-' ){
z += 2;
while( z[0]!='\n' ){
if( z[0]=='\0' ) return CIDX_PARSE_EOF;
z++;
}
while( cidx_isspace(*z) ) z++;
if( pbDoNotTrim ) *pbDoNotTrim = 1;
}else
if( z[0]=='/' && z[1]=='*' ){
z += 2;
while( z[0]!='*' || z[1]!='/' ){
if( z[1]=='\0' ) return CIDX_PARSE_EOF;
z++;
}
z += 2;
}else{
*pzOut = z;
if( pbDoNotTrim==0 ) return CIDX_PARSE_EOF;
switch( *z ){
case '\0':
return CIDX_PARSE_EOF;
case '(':
return CIDX_PARSE_OPEN;
case ')':
return CIDX_PARSE_CLOSE;
case ',':
return CIDX_PARSE_COMMA;
case '"':
case '\'':
case '`': {
char q = *z;
z++;
while( *z ){
if( *z==q ){
z++;
if( *z!=q ) break;
}
z++;
}
break;
}
case '[':
while( *z++!=']' );
break;
default:
z++;
break;
}
*pbDoNotTrim = 0;
}
}
assert( 0 );
return -1;
}
static int cidxParseSQL(CidxCursor *pCsr, CidxIndex *pIdx, const char *zSql){
const char *z = zSql;
const char *z1;
int e;
int rc = SQLITE_OK;
int nParen = 1;
int bDoNotTrim = 0;
CidxColumn *pCol = pIdx->aCol;
e = cidxFindNext(z, &z, &bDoNotTrim);
if( e!=CIDX_PARSE_OPEN ) goto parse_error;
z1 = z+1;
z++;
while( nParen>0 ){
e = cidxFindNext(z, &z, &bDoNotTrim);
if( e==CIDX_PARSE_EOF ) goto parse_error;
if( (e==CIDX_PARSE_COMMA || e==CIDX_PARSE_CLOSE) && nParen==1 ){
const char *z2 = z;
if( pCol->zExpr ) goto parse_error;
if( bDoNotTrim==0 ){
while( cidx_isspace(z[-1]) ) z--;
if( !sqlite3_strnicmp(&z[-3], "asc", 3) && 0==cidx_isident(z[-4]) ){
z -= 3;
while( cidx_isspace(z[-1]) ) z--;
}else
if( !sqlite3_strnicmp(&z[-4], "desc", 4) && 0==cidx_isident(z[-5]) ){
z -= 4;
while( cidx_isspace(z[-1]) ) z--;
}
while( cidx_isspace(z1[0]) ) z1++;
}
pCol->zExpr = cidxMprintf(&rc, "%.*s", z-z1, z1);
pCol++;
z = z1 = z2+1;
}
if( e==CIDX_PARSE_OPEN ) nParen++;
if( e==CIDX_PARSE_CLOSE ) nParen--;
z++;
}
/* Search for a WHERE clause */
cidxFindNext(z, &z, 0);
if( 0==sqlite3_strnicmp(z, "where", 5) ){
pIdx->zWhere = cidxMprintf(&rc, "%s\n", &z[5]);
}else if( z[0]!='\0' ){
goto parse_error;
}
return rc;
parse_error:
cidxCursorError(pCsr, "Parse error in: %s", zSql);
return SQLITE_ERROR;
}
static int cidxLookupIndex(
CidxCursor *pCsr, /* Cursor object */
const char *zIdx, /* Name of index to look up */
CidxIndex **ppIdx, /* OUT: Description of columns */
char **pzTab /* OUT: Table name */
){
int rc = SQLITE_OK;
char *zTab = 0;
CidxIndex *pIdx = 0;
sqlite3_stmt *pFindTab = 0;
sqlite3_stmt *pInfo = 0;
/* Find the table for this index. */
pFindTab = cidxPrepare(&rc, pCsr,
"SELECT tbl_name, sql FROM sqlite_schema WHERE name=%Q AND type='index'",
zIdx
);
if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
const char *zSql = (const char*)sqlite3_column_text(pFindTab, 1);
zTab = cidxStrdup(&rc, (const char*)sqlite3_column_text(pFindTab, 0));
pInfo = cidxPrepare(&rc, pCsr, "PRAGMA index_xinfo(%Q)", zIdx);
if( rc==SQLITE_OK ){
int nAlloc = 0;
int iCol = 0;
while( sqlite3_step(pInfo)==SQLITE_ROW ){
const char *zName = (const char*)sqlite3_column_text(pInfo, 2);
const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
CidxColumn *p;
if( zName==0 ) zName = "rowid";
if( iCol==nAlloc ){
int nByte = sizeof(CidxIndex) + sizeof(CidxColumn)*(nAlloc+8);
pIdx = (CidxIndex*)sqlite3_realloc(pIdx, nByte);
nAlloc += 8;
}
p = &pIdx->aCol[iCol++];
p->bDesc = sqlite3_column_int(pInfo, 3);
p->bKey = sqlite3_column_int(pInfo, 5);
if( zSql==0 || p->bKey==0 ){
p->zExpr = cidxMprintf(&rc, "\"%w\" COLLATE %s",zName,zColl);
}else{
p->zExpr = 0;
}
pIdx->nCol = iCol;
pIdx->zWhere = 0;
}
cidxFinalize(&rc, pInfo);
}
if( rc==SQLITE_OK && zSql ){
rc = cidxParseSQL(pCsr, pIdx, zSql);
}
}
cidxFinalize(&rc, pFindTab);
if( rc==SQLITE_OK && zTab==0 ){
rc = SQLITE_ERROR;
}
if( rc!=SQLITE_OK ){
sqlite3_free(zTab);
cidxFreeIndex(pIdx);
}else{
*pzTab = zTab;
*ppIdx = pIdx;
}
return rc;
}
static int cidxDecodeAfter(
CidxCursor *pCsr,
int nCol,
const char *zAfterKey,
char ***pazAfter
){
char **azAfter;
int rc = SQLITE_OK;
int nAfterKey = (int)strlen(zAfterKey);
azAfter = cidxMalloc(&rc, sizeof(char*)*nCol + nAfterKey+1);
if( rc==SQLITE_OK ){
int i;
char *zCopy = (char*)&azAfter[nCol];
char *p = zCopy;
memcpy(zCopy, zAfterKey, nAfterKey+1);
for(i=0; i<nCol; i++){
while( *p==' ' ) p++;
/* Check NULL values */
if( *p=='N' ){
if( memcmp(p, "NULL", 4) ) goto parse_error;
p += 4;
}
/* Check strings and blob literals */
else if( *p=='X' || *p=='\'' ){
azAfter[i] = p;
if( *p=='X' ) p++;
if( *p!='\'' ) goto parse_error;
p++;
while( 1 ){
if( *p=='\0' ) goto parse_error;
if( *p=='\'' ){
p++;
if( *p!='\'' ) break;
}
p++;
}
}
/* Check numbers */
else{
azAfter[i] = p;
while( (*p>='0' && *p<='9')
|| *p=='.' || *p=='+' || *p=='-' || *p=='e' || *p=='E'
){
p++;
}
}
while( *p==' ' ) p++;
if( *p!=(i==(nCol-1) ? '\0' : ',') ){
goto parse_error;
}
*p++ = '\0';
}
}
*pazAfter = azAfter;
return rc;
parse_error:
sqlite3_free(azAfter);
*pazAfter = 0;
cidxCursorError(pCsr, "%s", "error parsing after value");
return SQLITE_ERROR;
}
static char *cidxWhere(
int *pRc, CidxColumn *aCol, char **azAfter, int iGt, int bLastIsNull
){
char *zRet = 0;
const char *zSep = "";
int i;
for(i=0; i<iGt; i++){
zRet = cidxMprintf(pRc, "%z%s(%s) IS %s", zRet,
zSep, aCol[i].zExpr, (azAfter[i] ? azAfter[i] : "NULL")
);
zSep = " AND ";
}
if( bLastIsNull ){
zRet = cidxMprintf(pRc, "%z%s(%s) IS NULL", zRet, zSep, aCol[iGt].zExpr);
}
else if( azAfter[iGt] ){
zRet = cidxMprintf(pRc, "%z%s(%s) %s %s", zRet,
zSep, aCol[iGt].zExpr, (aCol[iGt].bDesc ? "<" : ">"),
azAfter[iGt]
);
}else{
zRet = cidxMprintf(pRc, "%z%s(%s) IS NOT NULL", zRet, zSep,aCol[iGt].zExpr);
}
return zRet;
}
#define CIDX_CLIST_ALL 0
#define CIDX_CLIST_ORDERBY 1
#define CIDX_CLIST_CURRENT_KEY 2
#define CIDX_CLIST_SUBWHERE 3
#define CIDX_CLIST_SUBEXPR 4
/*
** This function returns various strings based on the contents of the
** CidxIndex structure and the eType parameter.
*/
static char *cidxColumnList(
int *pRc, /* IN/OUT: Error code */
const char *zIdx,
CidxIndex *pIdx, /* Indexed columns */
int eType /* True to include ASC/DESC */
){
char *zRet = 0;
if( *pRc==SQLITE_OK ){
const char *aDir[2] = {"", " DESC"};
int i;
const char *zSep = "";
for(i=0; i<pIdx->nCol; i++){
CidxColumn *p = &pIdx->aCol[i];
assert( pIdx->aCol[i].bDesc==0 || pIdx->aCol[i].bDesc==1 );
switch( eType ){
case CIDX_CLIST_ORDERBY:
zRet = cidxMprintf(pRc, "%z%s%d%s", zRet, zSep, i+1, aDir[p->bDesc]);
zSep = ",";
break;
case CIDX_CLIST_CURRENT_KEY:
zRet = cidxMprintf(pRc, "%z%squote(i%d)", zRet, zSep, i);
zSep = "||','||";
break;
case CIDX_CLIST_SUBWHERE:
if( p->bKey==0 ){
zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet,
zSep, p->zExpr, i
);
zSep = " AND ";
}
break;
case CIDX_CLIST_SUBEXPR:
if( p->bKey==1 ){
zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet,
zSep, p->zExpr, i
);
zSep = " AND ";
}
break;
default:
assert( eType==CIDX_CLIST_ALL );
zRet = cidxMprintf(pRc, "%z%s(%s) AS i%d", zRet, zSep, p->zExpr, i);
zSep = ", ";
break;
}
}
}
return zRet;
}
/*
** Generate SQL (in memory obtained from sqlite3_malloc()) that will
** continue the index scan for zIdxName starting after zAfterKey.
*/
int cidxGenerateScanSql(
CidxCursor *pCsr, /* The cursor which needs the new statement */
const char *zIdxName, /* index to be scanned */
const char *zAfterKey, /* start after this key, if not NULL */
char **pzSqlOut /* OUT: Write the generated SQL here */
){
int rc;
char *zTab = 0;
char *zCurrentKey = 0;
char *zOrderBy = 0;
char *zSubWhere = 0;
char *zSubExpr = 0;
char *zSrcList = 0;
char **azAfter = 0;
CidxIndex *pIdx = 0;
*pzSqlOut = 0;
rc = cidxLookupIndex(pCsr, zIdxName, &pIdx, &zTab);
zOrderBy = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ORDERBY);
zCurrentKey = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_CURRENT_KEY);
zSubWhere = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBWHERE);
zSubExpr = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBEXPR);
zSrcList = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ALL);
if( rc==SQLITE_OK && zAfterKey ){
rc = cidxDecodeAfter(pCsr, pIdx->nCol, zAfterKey, &azAfter);
}
if( rc==SQLITE_OK ){
if( zAfterKey==0 ){
*pzSqlOut = cidxMprintf(&rc,
"SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
"FROM (SELECT %s FROM %Q INDEXED BY %Q %s%sORDER BY %s) AS i",
zSubExpr, zTab, zSubWhere, zCurrentKey,
zSrcList, zTab, zIdxName,
(pIdx->zWhere ? "WHERE " : ""), (pIdx->zWhere ? pIdx->zWhere : ""),
zOrderBy
);
}else{
const char *zSep = "";
char *zSql;
int i;
zSql = cidxMprintf(&rc,
"SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
zSubExpr, zTab, zSubWhere, zCurrentKey
);
for(i=pIdx->nCol-1; i>=0; i--){
int j;
if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
for(j=0; j<2; j++){
char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
zSql = cidxMprintf(&rc, "%z"
"%sSELECT * FROM ("
"SELECT %s FROM %Q INDEXED BY %Q WHERE %s%s%z ORDER BY %s"
")",
zSql, zSep, zSrcList, zTab, zIdxName,
pIdx->zWhere ? pIdx->zWhere : "",
pIdx->zWhere ? " AND " : "",
zWhere, zOrderBy
);
zSep = " UNION ALL ";
if( pIdx->aCol[i].bDesc==0 ) break;
}
}
*pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
}
}
sqlite3_free(zTab);
sqlite3_free(zCurrentKey);
sqlite3_free(zOrderBy);
sqlite3_free(zSubWhere);
sqlite3_free(zSubExpr);
sqlite3_free(zSrcList);
cidxFreeIndex(pIdx);
sqlite3_free(azAfter);
return rc;
}
/*
** Position a cursor back to the beginning.
*/
static int cidxFilter(
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
int rc = SQLITE_OK;
CidxCursor *pCsr = (CidxCursor*)pCursor;
const char *zIdxName = 0;
const char *zAfterKey = 0;
sqlite3_free(pCsr->zIdxName);
pCsr->zIdxName = 0;
sqlite3_free(pCsr->zAfterKey);
pCsr->zAfterKey = 0;
sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
if( argc>0 ){
zIdxName = (const char*)sqlite3_value_text(argv[0]);
if( argc>1 ){
zAfterKey = (const char*)sqlite3_value_text(argv[1]);
}
}
if( zIdxName ){
char *zSql = 0;
pCsr->zIdxName = sqlite3_mprintf("%s", zIdxName);
pCsr->zAfterKey = zAfterKey ? sqlite3_mprintf("%s", zAfterKey) : 0;
rc = cidxGenerateScanSql(pCsr, zIdxName, zAfterKey, &zSql);
if( zSql ){
pCsr->pStmt = cidxPrepare(&rc, pCsr, "%z", zSql);
}
}
if( pCsr->pStmt ){
assert( rc==SQLITE_OK );
rc = cidxNext(pCursor);
}
pCsr->iRowid = 1;
return rc;
}
/*
** Return a column value.
*/
static int cidxColumn(
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
int iCol
){
CidxCursor *pCsr = (CidxCursor*)pCursor;
assert( iCol>=IIC_ERRMSG && iCol<=IIC_SCANNER_SQL );
switch( iCol ){
case IIC_ERRMSG: {
const char *zVal = 0;
if( sqlite3_column_type(pCsr->pStmt, 0)==SQLITE_INTEGER ){
if( sqlite3_column_int(pCsr->pStmt, 0)==0 ){
zVal = "row data mismatch";
}
}else{
zVal = "row missing";
}
sqlite3_result_text(ctx, zVal, -1, SQLITE_STATIC);
break;
}
case IIC_CURRENT_KEY: {
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 1));
break;
}
case IIC_INDEX_NAME: {
sqlite3_result_text(ctx, pCsr->zIdxName, -1, SQLITE_TRANSIENT);
break;
}
case IIC_AFTER_KEY: {
sqlite3_result_text(ctx, pCsr->zAfterKey, -1, SQLITE_TRANSIENT);
break;
}
case IIC_SCANNER_SQL: {
char *zSql = 0;
cidxGenerateScanSql(pCsr, pCsr->zIdxName, pCsr->zAfterKey, &zSql);
sqlite3_result_text(ctx, zSql, -1, sqlite3_free);
break;
}
}
return SQLITE_OK;
}
/* Return the ROWID for the sqlite_btreeinfo table */
static int cidxRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
CidxCursor *pCsr = (CidxCursor*)pCursor;
*pRowid = pCsr->iRowid;
return SQLITE_OK;
}
/*
** Register the virtual table modules with the database handle passed
** as the only argument.
*/
static int ciInit(sqlite3 *db){
static sqlite3_module cidx_module = {
0, /* iVersion */
0, /* xCreate */
cidxConnect, /* xConnect */
cidxBestIndex, /* xBestIndex */
cidxDisconnect, /* xDisconnect */
0, /* xDestroy */
cidxOpen, /* xOpen - open a cursor */
cidxClose, /* xClose - close a cursor */
cidxFilter, /* xFilter - configure scan constraints */
cidxNext, /* xNext - advance a cursor */
cidxEof, /* xEof - check for end of scan */
cidxColumn, /* xColumn - read data */
cidxRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
return sqlite3_create_module(db, "incremental_index_check", &cidx_module, 0);
}
/*
** Extension load function.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_checkindex_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi);
return ciInit(db);
}
-85
View File
@@ -1,85 +0,0 @@
/*
** Read an SQLite database file and analyze its space utilization. Generate
** text on standard output.
*/
#define TCLSH_INIT_PROC sqlite3_checker_init_proc
#define SQLITE_ENABLE_DBPAGE_VTAB 1
#undef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 0
#undef SQLITE_ENABLE_COLUMN_METADATA
#define SQLITE_OMIT_DECLTYPE 1
#define SQLITE_OMIT_DEPRECATED 1
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
#define SQLITE_OMIT_SHARED_CACHE 1
#define SQLITE_DEFAULT_MEMSTATUS 0
#define SQLITE_MAX_EXPR_DEPTH 0
INCLUDE sqlite3.c
INCLUDE $ROOT/src/tclsqlite.c
INCLUDE $ROOT/ext/misc/btreeinfo.c
INCLUDE $ROOT/ext/repair/checkindex.c
INCLUDE $ROOT/ext/repair/checkfreelist.c
/*
** Decode a pointer to an sqlite3 object.
*/
int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
struct SqliteDb *p;
Tcl_CmdInfo cmdInfo;
if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
p = (struct SqliteDb*)cmdInfo.objClientData;
*ppDb = p->db;
return TCL_OK;
}else{
*ppDb = 0;
return TCL_ERROR;
}
return TCL_OK;
}
/*
** sqlite3_imposter db main rootpage {CREATE TABLE...} ;# setup an imposter
** sqlite3_imposter db main ;# rm all imposters
*/
static int sqlite3_imposter(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db;
const char *zSchema;
int iRoot;
const char *zSql;
if( objc!=3 && objc!=5 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
zSchema = Tcl_GetString(objv[2]);
if( objc==3 ){
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1);
}else{
if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR;
zSql = Tcl_GetString(objv[4]);
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0);
}
return TCL_OK;
}
#include <stdio.h>
const char *sqlite3_checker_init_proc(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3_imposter",
(Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0);
sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init);
sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init);
sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init);
return
BEGIN_STRING
INCLUDE $ROOT/ext/repair/sqlite3_checker.tcl
END_STRING
;
}
-264
View File
@@ -1,264 +0,0 @@
# This TCL script is the main driver script for the sqlite3_checker utility
# program.
#
# Special case:
#
# sqlite3_checker --test FILENAME ARGS
#
# uses FILENAME in place of this script.
#
if {[lindex $argv 0]=="--test" && [llength $argv]>1} {
set ::argv0 [lindex $argv 1]
set argv [lrange $argv 2 end]
source $argv0
exit 0
}
# Emulate a TCL shell
#
proc tclsh {} {
set line {}
while {![eof stdin]} {
if {$line!=""} {
puts -nonewline "> "
} else {
puts -nonewline "% "
}
flush stdout
append line [gets stdin]
if {[info complete $line]} {
if {[catch {uplevel #0 $line} result]} {
puts stderr "Error: $result"
} elseif {$result!=""} {
puts $result
}
set line {}
} else {
append line \n
}
}
}
# Do an incremental integrity check of a single index
#
proc check_index {idxname batchsize bTrace} {
set i 0
set more 1
set nerr 0
set pct 00.0
set max [db one {SELECT nEntry FROM sqlite_btreeinfo('main')
WHERE name=$idxname}]
puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
flush stdout
if {$bTrace} {
set sql {SELECT errmsg, current_key AS key,
CASE WHEN rowid=1 THEN scanner_sql END AS traceOut
FROM incremental_index_check($idxname)
WHERE after_key=$key
LIMIT $batchsize}
} else {
set sql {SELECT errmsg, current_key AS key, NULL AS traceOut
FROM incremental_index_check($idxname)
WHERE after_key=$key
LIMIT $batchsize}
}
while {$more} {
set more 0
db eval $sql {
set more 1
if {$errmsg!=""} {
incr nerr
puts "$idxname: key($key): $errmsg"
} elseif {$traceOut!=""} {
puts "$idxname: $traceOut"
}
incr i
}
set x [format {%.1f} [expr {($i*100.0)/$max}]]
if {$x!=$pct} {
puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
flush stdout
set pct $x
}
}
puts "$idxname: $nerr errors out of $i entries"
}
# Print a usage message on standard error, then quit.
#
proc usage {} {
set argv0 [file rootname [file tail [info nameofexecutable]]]
puts stderr "Usage: $argv0 OPTIONS database-filename"
puts stderr {
Do sanity checking on a live SQLite3 database file specified by the
"database-filename" argument.
Options:
--batchsize N Number of rows to check per transaction
--freelist Perform a freelist check
--index NAME Run a check of the index NAME
--summary Print summary information about the database
--table NAME Run a check of all indexes for table NAME
--tclsh Run the built-in TCL interpreter (for debugging)
--trace (Debugging only:) Output trace information on the scan
--version Show the version number of SQLite
}
exit 1
}
set file_to_analyze {}
append argv {}
set bFreelistCheck 0
set bSummary 0
set zIndex {}
set zTable {}
set batchsize 1000
set bAll 1
set bTrace 0
set argc [llength $argv]
for {set i 0} {$i<$argc} {incr i} {
set arg [lindex $argv $i]
if {[regexp {^-+tclsh$} $arg]} {
tclsh
exit 0
}
if {[regexp {^-+version$} $arg]} {
sqlite3 mem :memory:
puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
mem close
exit 0
}
if {[regexp {^-+freelist$} $arg]} {
set bFreelistCheck 1
set bAll 0
continue
}
if {[regexp {^-+summary$} $arg]} {
set bSummary 1
set bAll 0
continue
}
if {[regexp {^-+trace$} $arg]} {
set bTrace 1
continue
}
if {[regexp {^-+batchsize$} $arg]} {
incr i
if {$i>=$argc} {
puts stderr "missing argument on $arg"
exit 1
}
set batchsize [lindex $argv $i]
continue
}
if {[regexp {^-+index$} $arg]} {
incr i
if {$i>=$argc} {
puts stderr "missing argument on $arg"
exit 1
}
set zIndex [lindex $argv $i]
set bAll 0
continue
}
if {[regexp {^-+table$} $arg]} {
incr i
if {$i>=$argc} {
puts stderr "missing argument on $arg"
exit 1
}
set zTable [lindex $argv $i]
set bAll 0
continue
}
if {[regexp {^-} $arg]} {
puts stderr "Unknown option: $arg"
usage
}
if {$file_to_analyze!=""} {
usage
} else {
set file_to_analyze $arg
}
}
if {$file_to_analyze==""} usage
# If a TCL script is specified on the command-line, then run that
# script.
#
if {[file extension $file_to_analyze]==".tcl"} {
source $file_to_analyze
exit 0
}
set root_filename $file_to_analyze
regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
if {![file exists $root_filename]} {
puts stderr "No such file: $root_filename"
exit 1
}
if {![file readable $root_filename]} {
puts stderr "File is not readable: $root_filename"
exit 1
}
if {[catch {sqlite3 db $file_to_analyze} res]} {
puts stderr "Cannot open datababase $root_filename: $res"
exit 1
}
if {$bFreelistCheck || $bAll} {
puts -nonewline "freelist-check: "
flush stdout
db eval BEGIN
puts [db one {SELECT checkfreelist('main')}]
db eval END
}
if {$bSummary} {
set scale 0
set pgsz [db one {PRAGMA page_size}]
db eval {SELECT nPage*$pgsz AS sz, name, tbl_name
FROM sqlite_btreeinfo
WHERE type='index'
ORDER BY 1 DESC, name} {
if {$scale==0} {
if {$sz>10000000} {
set scale 1000000.0
set unit MB
} else {
set scale 1000.0
set unit KB
}
}
puts [format {%7.1f %s index %s of table %s} \
[expr {$sz/$scale}] $unit $name $tbl_name]
}
}
if {$zIndex!=""} {
check_index $zIndex $batchsize $bTrace
}
if {$zTable!=""} {
foreach idx [db eval {SELECT name FROM sqlite_master
WHERE type='index' AND rootpage>0
AND tbl_name=$zTable}] {
check_index $idx $batchsize $bTrace
}
}
if {$bAll} {
set allidx [db eval {SELECT name FROM sqlite_btreeinfo('main')
WHERE type='index' AND rootpage>0
ORDER BY nEntry}]
foreach idx $allidx {
check_index $idx $batchsize $bTrace
}
}
-13
View File
@@ -1,13 +0,0 @@
To run these tests, first build sqlite3_checker:
> make sqlite3_checker
Then run the "test.tcl" script using:
> ./sqlite3_checker --test $path/test.tcl
Optionally add the full pathnames of individual *.test modules
-92
View File
@@ -1,92 +0,0 @@
# 2017-10-11
set testprefix checkfreelist
do_execsql_test 1.0 {
PRAGMA page_size=1024;
CREATE TABLE t1(a, b);
}
do_execsql_test 1.2 { SELECT checkfreelist('main') } {ok}
do_execsql_test 1.3 {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
)
INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
DELETE FROM t1 WHERE rowid%3;
PRAGMA freelist_count;
} {6726}
do_execsql_test 1.4 { SELECT checkfreelist('main') } {ok}
do_execsql_test 1.5 {
WITH freelist_trunk(i, d, n) AS (
SELECT 1, NULL, sqlite_readint32(data, 32) FROM sqlite_dbpage WHERE pgno=1
UNION ALL
SELECT n, data, sqlite_readint32(data)
FROM freelist_trunk, sqlite_dbpage WHERE pgno=n
)
SELECT i FROM freelist_trunk WHERE i!=1;
} {
10009 9715 9343 8969 8595 8222 7847 7474 7102 6727 6354 5982 5608 5234
4860 4487 4112 3740 3367 2992 2619 2247 1872 1499 1125 752 377 5
}
do_execsql_test 1.6 { SELECT checkfreelist('main') } {ok}
proc set_int {blob idx newval} {
binary scan $blob I* ints
lset ints $idx $newval
binary format I* $ints
}
db func set_int set_int
proc get_int {blob idx} {
binary scan $blob I* ints
lindex $ints $idx
}
db func get_int get_int
do_execsql_test 1.7 {
BEGIN;
UPDATE sqlite_dbpage
SET data = set_int(data, 1, get_int(data, 1)-1)
WHERE pgno=4860;
SELECT checkfreelist('main');
ROLLBACK;
} {{free-list count mismatch: actual=6725 header=6726}}
do_execsql_test 1.8 {
BEGIN;
UPDATE sqlite_dbpage
SET data = set_int(data, 5, (SELECT * FROM pragma_page_count)+1)
WHERE pgno=4860;
SELECT checkfreelist('main');
ROLLBACK;
} {{leaf page 10092 is out of range (child 3 of trunk page 4860)}}
do_execsql_test 1.9 {
BEGIN;
UPDATE sqlite_dbpage
SET data = set_int(data, 5, 0)
WHERE pgno=4860;
SELECT checkfreelist('main');
ROLLBACK;
} {{leaf page 0 is out of range (child 3 of trunk page 4860)}}
do_execsql_test 1.10 {
BEGIN;
UPDATE sqlite_dbpage
SET data = set_int(data, get_int(data, 1)+1, 0)
WHERE pgno=5;
SELECT checkfreelist('main');
ROLLBACK;
} {{leaf page 0 is out of range (child 247 of trunk page 5)}}
do_execsql_test 1.11 {
BEGIN;
UPDATE sqlite_dbpage
SET data = set_int(data, 1, 249)
WHERE pgno=5;
SELECT checkfreelist('main');
ROLLBACK;
} {{leaf count out of range (249) on trunk page 5}}
-349
View File
@@ -1,349 +0,0 @@
# 2017-10-11
#
set testprefix checkindex
do_execsql_test 1.0 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
INSERT INTO t1 VALUES('one', 2);
INSERT INTO t1 VALUES('two', 4);
INSERT INTO t1 VALUES('three', 6);
INSERT INTO t1 VALUES('four', 8);
INSERT INTO t1 VALUES('five', 10);
CREATE INDEX i2 ON t1(a DESC);
} {}
proc incr_index_check {idx nStep} {
set Q {
SELECT errmsg, current_key FROM incremental_index_check($idx, $after)
LIMIT $nStep
}
set res [list]
while {1} {
unset -nocomplain current_key
set res1 [db eval $Q]
if {[llength $res1]==0} break
set res [concat $res $res1]
set after [lindex $res end]
}
return $res
}
proc do_index_check_test {tn idx res} {
uplevel [list do_execsql_test $tn.1 "
SELECT errmsg, current_key FROM incremental_index_check('$idx');
" $res]
uplevel [list do_test $tn.2 "incr_index_check $idx 1" [list {*}$res]]
uplevel [list do_test $tn.3 "incr_index_check $idx 2" [list {*}$res]]
uplevel [list do_test $tn.4 "incr_index_check $idx 5" [list {*}$res]]
}
do_execsql_test 1.2.1 {
SELECT rowid, errmsg IS NULL, current_key FROM incremental_index_check('i1');
} {
1 1 'five',5
2 1 'four',4
3 1 'one',1
4 1 'three',3
5 1 'two',2
}
do_execsql_test 1.2.2 {
SELECT errmsg IS NULL, current_key, index_name, after_key, scanner_sql
FROM incremental_index_check('i1') LIMIT 1;
} {
1
'five',5
i1
{}
{SELECT (SELECT a IS i.i0 FROM 't1' AS t WHERE "rowid" COLLATE BINARY IS i.i1), quote(i0)||','||quote(i1) FROM (SELECT (a) AS i0, ("rowid" COLLATE BINARY) AS i1 FROM 't1' INDEXED BY 'i1' ORDER BY 1,2) AS i}
}
do_index_check_test 1.3 i1 {
{} 'five',5
{} 'four',4
{} 'one',1
{} 'three',3
{} 'two',2
}
do_index_check_test 1.4 i2 {
{} 'two',2
{} 'three',3
{} 'one',1
{} 'four',4
{} 'five',5
}
do_test 1.5 {
set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t1' }]
sqlite3_imposter db main $tblroot {CREATE TABLE xt1(a,b)}
db eval {
UPDATE xt1 SET a='six' WHERE rowid=3;
DELETE FROM xt1 WHERE rowid = 5;
}
sqlite3_imposter db main
} {}
do_index_check_test 1.6 i1 {
{row missing} 'five',5
{} 'four',4
{} 'one',1
{row data mismatch} 'three',3
{} 'two',2
}
do_index_check_test 1.7 i2 {
{} 'two',2
{row data mismatch} 'three',3
{} 'one',1
{} 'four',4
{row missing} 'five',5
}
#--------------------------------------------------------------------------
do_execsql_test 2.0 {
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c, d);
INSERT INTO t2 VALUES(1, NULL, 1, 1);
INSERT INTO t2 VALUES(2, 1, NULL, 1);
INSERT INTO t2 VALUES(3, 1, 1, NULL);
INSERT INTO t2 VALUES(4, 2, 2, 1);
INSERT INTO t2 VALUES(5, 2, 2, 2);
INSERT INTO t2 VALUES(6, 2, 2, 3);
INSERT INTO t2 VALUES(7, 2, 2, 1);
INSERT INTO t2 VALUES(8, 2, 2, 2);
INSERT INTO t2 VALUES(9, 2, 2, 3);
CREATE INDEX i3 ON t2(b, c, d);
CREATE INDEX i4 ON t2(b DESC, c DESC, d DESC);
CREATE INDEX i5 ON t2(d, c DESC, b);
} {}
do_index_check_test 2.1 i3 {
{} NULL,1,1,1
{} 1,NULL,1,2
{} 1,1,NULL,3
{} 2,2,1,4
{} 2,2,1,7
{} 2,2,2,5
{} 2,2,2,8
{} 2,2,3,6
{} 2,2,3,9
}
do_index_check_test 2.2 i4 {
{} 2,2,3,6
{} 2,2,3,9
{} 2,2,2,5
{} 2,2,2,8
{} 2,2,1,4
{} 2,2,1,7
{} 1,1,NULL,3
{} 1,NULL,1,2
{} NULL,1,1,1
}
do_index_check_test 2.3 i5 {
{} NULL,1,1,3
{} 1,2,2,4
{} 1,2,2,7
{} 1,1,NULL,1
{} 1,NULL,1,2
{} 2,2,2,5
{} 2,2,2,8
{} 3,2,2,6
{} 3,2,2,9
}
#--------------------------------------------------------------------------
do_execsql_test 3.0 {
CREATE TABLE t3(w, x, y, z PRIMARY KEY) WITHOUT ROWID;
CREATE INDEX t3wxy ON t3(w, x, y);
CREATE INDEX t3wxy2 ON t3(w DESC, x DESC, y DESC);
INSERT INTO t3 VALUES(NULL, NULL, NULL, 1);
INSERT INTO t3 VALUES(NULL, NULL, NULL, 2);
INSERT INTO t3 VALUES(NULL, NULL, NULL, 3);
INSERT INTO t3 VALUES('a', NULL, NULL, 4);
INSERT INTO t3 VALUES('a', NULL, NULL, 5);
INSERT INTO t3 VALUES('a', NULL, NULL, 6);
INSERT INTO t3 VALUES('a', 'b', NULL, 7);
INSERT INTO t3 VALUES('a', 'b', NULL, 8);
INSERT INTO t3 VALUES('a', 'b', NULL, 9);
} {}
do_index_check_test 3.1 t3wxy {
{} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3
{} 'a',NULL,NULL,4 {} 'a',NULL,NULL,5 {} 'a',NULL,NULL,6
{} 'a','b',NULL,7 {} 'a','b',NULL,8 {} 'a','b',NULL,9
}
do_index_check_test 3.2 t3wxy2 {
{} 'a','b',NULL,7 {} 'a','b',NULL,8 {} 'a','b',NULL,9
{} 'a',NULL,NULL,4 {} 'a',NULL,NULL,5 {} 'a',NULL,NULL,6
{} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3
}
#--------------------------------------------------------------------------
# Test with an index that uses non-default collation sequences.
#
do_execsql_test 4.0 {
CREATE TABLE t4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT);
INSERT INTO t4 VALUES(1, 'aaa', 'bbb');
INSERT INTO t4 VALUES(2, 'AAA', 'CCC');
INSERT INTO t4 VALUES(3, 'aab', 'ddd');
INSERT INTO t4 VALUES(4, 'AAB', 'EEE');
CREATE INDEX t4cc ON t4(c1 COLLATE nocase, c2 COLLATE nocase);
}
do_index_check_test 4.1 t4cc {
{} 'aaa','bbb',1
{} 'AAA','CCC',2
{} 'aab','ddd',3
{} 'AAB','EEE',4
}
do_test 4.2 {
set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t4' }]
sqlite3_imposter db main $tblroot \
{CREATE TABLE xt4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT)}
db eval {
UPDATE xt4 SET c1='hello' WHERE rowid=2;
DELETE FROM xt4 WHERE rowid = 3;
}
sqlite3_imposter db main
} {}
do_index_check_test 4.3 t4cc {
{} 'aaa','bbb',1
{row data mismatch} 'AAA','CCC',2
{row missing} 'aab','ddd',3
{} 'AAB','EEE',4
}
#--------------------------------------------------------------------------
# Test an index on an expression.
#
do_execsql_test 5.0 {
CREATE TABLE t5(x INTEGER PRIMARY KEY, y TEXT, UNIQUE(y));
INSERT INTO t5 VALUES(1, '{"x":1, "y":1}');
INSERT INTO t5 VALUES(2, '{"x":2, "y":2}');
INSERT INTO t5 VALUES(3, '{"x":3, "y":3}');
INSERT INTO t5 VALUES(4, '{"w":4, "z":4}');
INSERT INTO t5 VALUES(5, '{"x":5, "y":5}');
CREATE INDEX t5x ON t5( json_extract(y, '$.x') );
CREATE INDEX t5y ON t5( json_extract(y, '$.y') DESC );
}
do_index_check_test 5.1.1 t5x {
{} NULL,4 {} 1,1 {} 2,2 {} 3,3 {} 5,5
}
do_index_check_test 5.1.2 t5y {
{} 5,5 {} 3,3 {} 2,2 {} 1,1 {} NULL,4
}
do_index_check_test 5.1.3 sqlite_autoindex_t5_1 {
{} {'{"w":4, "z":4}',4}
{} {'{"x":1, "y":1}',1}
{} {'{"x":2, "y":2}',2}
{} {'{"x":3, "y":3}',3}
{} {'{"x":5, "y":5}',5}
}
do_test 5.2 {
set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t5' }]
sqlite3_imposter db main $tblroot \
{CREATE TABLE xt5(a INTEGER PRIMARY KEY, c1 TEXT);}
db eval {
UPDATE xt5 SET c1='{"x":22, "y":11}' WHERE rowid=1;
DELETE FROM xt5 WHERE rowid = 4;
}
sqlite3_imposter db main
} {}
do_index_check_test 5.3.1 t5x {
{row missing} NULL,4
{row data mismatch} 1,1
{} 2,2
{} 3,3
{} 5,5
}
do_index_check_test 5.3.2 sqlite_autoindex_t5_1 {
{row missing} {'{"w":4, "z":4}',4}
{row data mismatch} {'{"x":1, "y":1}',1}
{} {'{"x":2, "y":2}',2}
{} {'{"x":3, "y":3}',3}
{} {'{"x":5, "y":5}',5}
}
#-------------------------------------------------------------------------
#
do_execsql_test 6.0 {
CREATE TABLE t6(x INTEGER PRIMARY KEY, y, z);
CREATE INDEX t6x1 ON t6(y, /* one,two,three */ z);
CREATE INDEX t6x2 ON t6(z, -- hello,world,
y);
CREATE INDEX t6x3 ON t6(z -- hello,world
, y);
INSERT INTO t6 VALUES(1, 2, 3);
INSERT INTO t6 VALUES(4, 5, 6);
}
do_index_check_test 6.1 t6x1 {
{} 2,3,1
{} 5,6,4
}
do_index_check_test 6.2 t6x2 {
{} 3,2,1
{} 6,5,4
}
do_index_check_test 6.2 t6x3 {
{} 3,2,1
{} 6,5,4
}
#-------------------------------------------------------------------------
#
do_execsql_test 7.0 {
CREATE TABLE t7(x INTEGER PRIMARY KEY, y, z);
INSERT INTO t7 VALUES(1, 1, 1);
INSERT INTO t7 VALUES(2, 2, 0);
INSERT INTO t7 VALUES(3, 3, 1);
INSERT INTO t7 VALUES(4, 4, 0);
CREATE INDEX t7i1 ON t7(y) WHERE z=1;
CREATE INDEX t7i2 ON t7(y) /* hello,world */ WHERE z=1;
CREATE INDEX t7i3 ON t7(y) WHERE -- yep
z=1;
CREATE INDEX t7i4 ON t7(y) WHERE z=1 -- yep;
}
do_index_check_test 7.1 t7i1 {
{} 1,1 {} 3,3
}
do_index_check_test 7.2 t7i2 {
{} 1,1 {} 3,3
}
do_index_check_test 7.3 t7i3 {
{} 1,1 {} 3,3
}
do_index_check_test 7.4 t7i4 {
{} 1,1 {} 3,3
}
-67
View File
@@ -1,67 +0,0 @@
# Run this script using
#
# sqlite3_checker --test $thisscript $testscripts
#
# The $testscripts argument is optional. If omitted, all *.test files
# in the same directory as $thisscript are run.
#
set NTEST 0
set NERR 0
# Invoke the do_test procedure to run a single test
#
# The $expected parameter is the expected result. The result is the return
# value from the last TCL command in $cmd.
#
# Normally, $expected must match exactly. But if $expected is of the form
# "/regexp/" then regular expression matching is used. If $expected is
# "~/regexp/" then the regular expression must NOT match. If $expected is
# of the form "#/value-list/" then each term in value-list must be numeric
# and must approximately match the corresponding numeric term in $result.
# Values must match within 10%. Or if the $expected term is A..B then the
# $result term must be in between A and B.
#
proc do_test {name cmd expected} {
if {[info exists ::testprefix]} {
set name "$::testprefix$name"
}
incr ::NTEST
puts -nonewline $name...
flush stdout
if {[catch {uplevel #0 "$cmd;\n"} result]} {
puts -nonewline $name...
puts "\nError: $result"
incr ::NERR
} else {
set ok [expr {[string compare $result $expected]==0}]
if {!$ok} {
puts "\n! $name expected: \[$expected\]\n! $name got: \[$result\]"
incr ::NERR
} else {
puts " Ok"
}
}
flush stdout
}
#
# do_execsql_test TESTNAME SQL RES
#
proc do_execsql_test {testname sql {result {}}} {
uplevel [list do_test $testname [list db eval $sql] [list {*}$result]]
}
if {[llength $argv]==0} {
set dir [file dirname $argv0]
set argv [glob -nocomplain $dir/*.test]
}
foreach testfile $argv {
file delete -force test.db
sqlite3 db test.db
source $testfile
catch {db close}
}
puts "$NERR errors out of $NTEST tests"
+1 -1
View File
@@ -200,7 +200,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
/* The sqlite3AtoF() routine is much much faster than atof(), if it
** is available */
double r;
(void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
(void)sqlite3AtoF((const char*)p->z, &r);
*pVal = r;
#else
*pVal = (GeoCoord)atof((const char*)p->z);
+1 -1
View File
@@ -206,7 +206,7 @@ b.mkdir@ = if [ ! -d $(dir $@) ]; then \
# $1 = logtag, $2 = src file(s). $3 = dest dir
b.cp = $(call b.mkdir@); \
echo '$(logtag.$(1)) $(emo.disk) $(2) ==> $3'; \
cp -p $(2) $(3) || exit
cp -f -p $(2) $(3) || exit
#
# $(call b.c-pp.shcmd,LOGTAG,src,dest,-Dx=y...)
+16 -8
View File
@@ -209,17 +209,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
and recreating it whenever a property index might be invalidated.
*/
class KVVfsStorage {
#map;
#keys;
#getKeys(){return this.#keys ??= Object.keys(this.#map);}
#map = Object.create(null);
#keys = null;
#size = 0;
constructor(){
this.clear();
}
#getKeys(){
return this.#keys ??= Object.keys(this.#map);
}
key(n){
const k = this.#getKeys();
return n<k.length ? k[n] : null;
if(n < 0 || n >= this.#size) return null;
return this.#getKeys()[n];
}
getItem(k){
@@ -227,14 +231,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
setItem(k,v){
if( !hop(this.#map, k) ){
if( !(k in this.#map) ){
++this.#size;
this.#keys = null;
}
this.#map[k] = ''+v;
}
removeItem(k){
if( delete this.#map[k] ){
if( k in this.#map ){
delete this.#map[k];
--this.#size;
this.#keys = null;
}
}
@@ -242,10 +249,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
clear(){
this.#map = Object.create(null);
this.#keys = null;
this.#size = 0;
}
get length() {
return this.#getKeys().length;
return this.#size;
}
}/*KVVfsStorage*/;
+9 -2
View File
@@ -994,10 +994,17 @@ static void mk_fiddle(void){
pf("$(out.%s.js): $(MAKEFILE_LIST) "
"$(EXPORTED_FUNCTIONS.fiddle) "
"$(fiddle.c.in) "
"$(pre-post.%s.deps)\n",
"$(pre-post.%s.deps)",
zBuildName, zBuildName);
if( isDebug ){
pf(" $(dir.fiddle)/fiddle-worker.js"
" $(dir.fiddle)/fiddle.js"
" $(dir.fiddle)/index.html");
}
ps("");
emit_compile_start(zBuildName);
pf("\t$(b.cmd@)$(bin.emcc) -o $@"
pf("\t@$(call b.mkdir@)\n"
"\t$(b.cmd@)$(bin.emcc) -o $@"
" $(emcc.flags.%s)" /* set in GNUmakefile */
" $(pre-post.%s.flags)"
" $(fiddle.c.in)"
-18
View File
@@ -1971,24 +1971,6 @@ sqlite3_expert$(T.exe): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqli
$(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert $(LDFLAGS.libsqlite3)
xbin: sqlite3_expert$(T.exe)
CHECKER_DEPS =\
$(TOP)/tool/mkccode.tcl \
sqlite3.c \
tclsqlite-ex.c \
$(TOP)/ext/repair/sqlite3_checker.tcl \
$(TOP)/ext/repair/checkindex.c \
$(TOP)/ext/repair/checkfreelist.c \
$(TOP)/ext/misc/btreeinfo.c \
$(TOP)/ext/repair/sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
$(B.tclsh) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
sqlite3_checker$(T.exe): $(T.tcl.env.sh) sqlite3_checker.c
$(T.link.tcl) sqlite3_checker.c -o $@ $$TCL_INCLUDE_SPEC \
$$TCL_LIB_SPEC $(LDFLAGS.libsqlite3)
xbin: sqlite3_checker$(T.exe)
dbdump$(T.exe): $(TOP)/ext/misc/dbdump.c sqlite3.o
$(T.link) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.o $(LDFLAGS.libsqlite3)
+80 -85
View File
@@ -1,12 +1,12 @@
C Avoid\sthe\sbig\spower-of-ten\slookup\stable.
D 2026-02-15T18:41:29.104
C Do\snot\srun\stest\sscript\swalrestart.test\swith\sthe\s"memsubsys1"\spermutation.
D 2026-03-03T18:34:38.064
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
F Makefile.in 3ce07126d7e87c7464301482e161fdae6a51d0a2aa06b200b8f0000ef4d6163b
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 1fa179beafd6d438b8479146cae77fb1724dd35b330b09dbfebd8a2f0823c62a
F Makefile.msc 174764cb7e80c80f9003c46b3e388d74c68c8c40230208904b3af8fcabee5f4e
F README.md 3fa51fc7ababc32edd175ae8b2986c86d5ea120c1cb1e57c7f7849492d1405ec
F VERSION 74672bfd4c7826c0fc6f84762488a707c52e7d2d94af42ccb0edcc6c74311c41
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -108,21 +108,21 @@ F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a0
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
F ext/fts5/fts5Int.h 8d98f8e180fe28d6067e240ed45b9011735d29d5cfb5bac194e1e376baa7c708
F ext/fts5/fts5_aux.c da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
F ext/fts5/fts5_expr.c b8c32da1127bafaf10d6b4768b0dcb92285798524bed2d87a8686f99a8e8d259
F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
F ext/fts5/fts5_index.c 9b8118bfd0c2a4c3d3482d69ad28ba811fcc2d32e6ff7cf0634cec1c00b9d3da
F ext/fts5/fts5_main.c 4e7dc11824e681215c2ac6b702124918b946616f85e0d54f88d0f156152387ee
F ext/fts5/fts5_aux.c 042da27e97d38071312c111cf18f3cb7983b75ba5e724aa1c3164e61e90f428a
F ext/fts5/fts5_buffer.c dcc3f0352339fe79c9d8abbc1c2009bc3469206467880bf43558447ef4f846fb
F ext/fts5/fts5_config.c bfba970fe1e4eed18ee57c8d51458e226db9a960ddf775c5e50e3d76603a667e
F ext/fts5/fts5_expr.c 71d48e8cf0358deace4949276647d317ff7665db6db09f40b81e2e7fe6664c7c
F ext/fts5/fts5_hash.c d5871df92ce3fa210a650cf419ee916b87c29977e86084d06612edf772bff6f5
F ext/fts5/fts5_index.c f8cfa37bb7397e5ede20242e4c9cb030bc8b4584ce3f23a5e2495038c0ae64bd
F ext/fts5/fts5_main.c 6889f1373c469d515e792fb3d783c2218e63c560433ebd66edc0f740ab086c1b
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
F ext/fts5/fts5_tokenize.c 49aea8cc400a690a6c4f83c4cedc67f4f8830c6789c4ee343404f62bcaebca7b
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c 23e263ad94ac357cfffd19bd7e001c3f15c4420fb10fa35b5993142127e780e6
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl c5aa7cf7148b6dcffb5b61520ae18212baf169936af734ab265143f59db328fe
@@ -199,7 +199,7 @@ F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14
F ext/fts5/test/fts5integrity.test c423ce16fd1ccadcac7fc22f794226b2bb00f5a187c0ab1d9f8502521b1bae05
F ext/fts5/test/fts5integrity.test 613efcebe16b2d7a4096f03bcfb164f79a000b3354420ceda4a6f3e035090789
F ext/fts5/test/fts5integrity2.test 4c3636615c0201232c44a8105d5cb14fd5499fd0ee3014d7ffd7e83aac76ece8
F ext/fts5/test/fts5interrupt.test af7834ac6c2e71c05aea42d92f272eef3655e89b7a14a5620a2cd9de35e2e8ea
F ext/fts5/test/fts5join.test 48b7ed36956948c5b8456c8bcaa5b087808d99000675918a43c4f51a925f1514
@@ -285,7 +285,7 @@ F ext/intck/intck_common.tcl a61fd2697ae55b0a3d89847ca0b590c6e0d8ff64bebb70920d9
F ext/intck/intckbusy.test d5ed4ef85a4b1dc1dee2484bd14a4bb68529659cca743327df0c775f005fa387
F ext/intck/intckcorrupt.test f6c302792326fb3db9dcfc70b554c55369bc4b52882eaaf039cfe0b74c821029
F ext/intck/intckfault.test cff3f75dff74abb3edfcb13f6aa53f6436746ab64b09fe5e2028f051e985efab
F ext/intck/sqlite3intck.c b1c8a86f90fc00741d13314db9c58f7e2f92d1d19c5ad1c6904ec83a6bbd5c96
F ext/intck/sqlite3intck.c 3c4a166645a1624731f63acd342e24e81e4ffd497116d94a427d72e6cc6caa69
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
F ext/intck/test_intck.c 4f9eaadaedccb9df1d26ba41116a0a8e5b0c5556dc3098c8ff68633adcccdea8
F ext/jni/GNUmakefile 8a94e3a1953b88cf117fb2a5380480feada8b4f5316f02572cab425030a720b4
@@ -370,13 +370,13 @@ F ext/misc/completion.c c27b64fdd0943c1b7f152376599814cee2641f7d67a7bb9bd2b957c2
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
F ext/misc/csv.c e82124eabee0e692d7b90ab8b2c34fadbf7b375279f102567fa06e4da4b771bf
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
F ext/misc/decimal.c d4883de142f6dcd36eda23da40b55e2b51374e7b01eb54a7173940191389fc5e
F ext/misc/decimal.c e1da22eee70d7e3eaa99a6b761bc03c4d01d7ffa554bf3178b1f1f184932806c
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
F ext/misc/fileio.c 452300ca34fadafd2bb9eb09557de5a518da1fd2349f9f9cedd22b1566a7164f
F ext/misc/fileio.c 33165b3cd99f83dcd333a338eb51491f6b01c8d96cb6ae81f96a6a096834e030
F ext/misc/fossildelta.c 86dfa83f85f7ccd640591d8a5c6865346d0c2ee6a949d78591eceb892f1cbfec
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c 7d7ecdd9490f6746ad88e0aa4f073ea66422341dce062d24d1b4d47d2e9050d6
F ext/misc/fuzzer.c 684a4996b523ea89f495b38fd8a14a2ae00695089a88031366a4df6adc2c873b
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
F ext/misc/memstat.c 43705d795090efb78c85c736b89251e743c291e23daaa8382fe7a0df2c6a283d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
@@ -403,7 +403,7 @@ F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bf
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
F ext/misc/tmstmpvfs.c 3eb28a9f22f58883f38085daa312467e31ddfd2042c21dcc07173e02a01d68d8
F ext/misc/tmstmpvfs.c 240caad4441328dc52bd2871f48811db46dff858d5598030e389176837a2f4df
F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762bc3a8
F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
@@ -416,11 +416,11 @@ F ext/misc/vtablog.c 402496fb38add7dd2c50f2a0ad20f83a9916ceab48dcd31e62ad621e663
F ext/misc/vtshim.c e5bce24ab8c532f4fdc600148718fe1802cb6ed57417f1c1032d8961f72b0e8f
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
F ext/misc/zipfile.c 837591f0505d21f7f7937ea046c9b0fc594f7fa3ca00c2bd54ffa1c94bfccd63
F ext/misc/zipfile.c c8ee04e1b349270b5df401ad732f5d7c387146e69b33c02fa90322760cc6fee0
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
F ext/qrf/README.md e6e0ce2700acf6fd06312b42726a8f08ca240f30e1b122bff87c71c602046352
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
F ext/qrf/qrf.c 9216879683752773fa612849b8bc6a26b74f2a7cb9253bcbdd168092d8bfbbe2
F ext/qrf/qrf.c cd48c23500c3b129be5e0627ce9d41b5df3c2d715525b00a6ccbd1f30689fb17
F ext/qrf/qrf.h 2ac14b0aaacf44636d8c81051bfeab4afae50a98fbb2e10ff5aed0c28a87b2b2
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
@@ -466,7 +466,7 @@ F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f3237
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
F ext/rbu/sqlite3rbu.c 3fb2390575b261c365d3f6fea61ff15e74d5d89e373f2a2bfa4d80c24321e793
F ext/rbu/sqlite3rbu.c e99400d29d029936075e27495b269a2dcdceae3cf8c86b1d0869b4af487be3ab
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
@@ -488,17 +488,8 @@ F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
F ext/repair/checkindex.c 7639b4f8928f82c10b950169e60cc45a7f6798df0b299771d17bef025736f657
F ext/repair/sqlite3_checker.c.in 445118c5f7fea958b36fba1b2c464283e60ed4842039ddee3265f1698115ebf7
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
F ext/rtree/geopoly.c bd1971479184d559499ff3087c37f2823977d7b0ec80916141ae66f70345c88d
F ext/rtree/rtree.c 9331997a76b88a9bc04e156bdfd6e2fe35c0aa93bc338ebc6aa0ae470fe4a852
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
@@ -581,7 +572,7 @@ F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009e
F ext/session/sqlite3session.c 6ebd02be470f36d41c4bd78927f39d507b62051ba025eacaed9936c769902a07
F ext/session/sqlite3session.h 7404723606074fcb2afdc6b72c206072cdb2b7d8ba097ca1559174a80bc26f7a
F ext/session/test_session.c 190110e3bd9463717248dec1272b44fe9943e57b7646d0b4200dcf11e4dccee6
F ext/wasm/GNUmakefile a2698072853b67c39e92ca19835c65fbaa8b8884078a99c4e54b72b9ede8306e
F ext/wasm/GNUmakefile 79236447d750609aa6beda30feec1314180c5462a493ad94214122887232bfd4
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -603,7 +594,7 @@ F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1041dd645e8e821c082b628cd8d9acf70c667
F ext/wasm/api/sqlite3-license-version-header.js 98d90255a12d02214db634e041c8e7f2f133d9361a8ebf000ba9c9af4c6761cc
F ext/wasm/api/sqlite3-opfs-async-proxy.js 92d6d327a862f1627ff3e88e60fdfea9def06ad539d98929ba46490e64372736
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 17b16db29e2e0c75d00f675c17710539269e30f853da6bac9044879e298c270f
F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 2ccf4322f42063aefc150972943e750c77f7926b866f1639d40eec05df075b6e
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 1575ea6bbcf2da1e6df6892c17521a0c1c1c199a672e9090176ea0b88de48bd9
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 88ce2078267a2d1af57525a32d896295f4a8db7664de0e17e82dc9ff006ed8d3
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81
@@ -634,7 +625,7 @@ F ext/wasm/index.html 475bc283338749db4e3fbf24cf3f5aa020cc85a1fffb780d400a915fcb
F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
F ext/wasm/mkwasmbuilds.c 5d7baa9258299fd492351578a93dff960317822a08ee3ad6dd91ef5d21209812
F ext/wasm/mkwasmbuilds.c 0e9198eb90acae4bcf57cf62d7186f6af5aaac02efdb075a1aded33614b3805a
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
@@ -660,7 +651,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 9393d5982db60f26e72c5af24a8c11cf39374ff5e695fadb5a4e7376f28150c6
F main.mk e1a03e9206f6a042a9147035915cb944e9242d570779bc3ccd7ed6a39df10cae
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -681,28 +672,28 @@ F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c b744bf69d520534751c742cababe7ad28c3892f1e3a75242e75a20bca15a834a
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 4e1afafc56504ed6253e1b115c1502de4243c2287a0c799f4967fcd2d7716ad9
F src/build.c b993e4adef4c4cdfd7abf62e2676c467bb1923f25f40c3c7ab2a7bfbace3de7f
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 901499bed747c3b4b2be45be1abe912ba50a3f6a40ba88cc006ccf279f2d0e97
F src/expr.c c4ff8dcacbc8962fb670fc7c9723c8346398795b16ce2f78439234769baee2e6
F src/expr.c 8c3b23cb35f43c2d0570c1058b9a269e561e769e09c81ba192992c95022c1939
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c c065da737307a29e4d240ac727758dbf4102cb3218a1f651eb689b6a6fa12531
F src/func.c efbcfe7cb7fc92fe5299c9aaa141075eb60d2108253e99bc235384ed6a90d937
F src/fkey.c fb0f74c57d19a2d3f113f3476826919d68feda7ff334abfdb479a9a6353b9fcd
F src/func.c 6e7de3551ae0f8205006e5109f025223246edd20186d54d90746dee7c1c5c093
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/json.c af766b62caee01c735cfe7795cc91ffea5a5e1c555a5d8a9aa5a301f00a1b0ad
F src/json.c 8b6341a419150b28530cc21e3951b2238c35cdc312f11b2ca29017fe4b1dedc0
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
F src/main.c e95aa130478fc98a49181ddf094baab45f319286411129253618efe0008f0dc4
F src/main.c 31a13302193fbd51279c7e69cdfa0320d0de7629f9151e0964c1d320e8bdd7a4
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -712,7 +703,7 @@ F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
F src/mutex.c 06bcd9c3dbf2d9b21fcd182606c00fafb9bfe0287983c8e17acd13d2c81a2fa9
F src/mutex.c 5dc0dd69c4216dd976bd463f4ee62a0fa0c24860c0815238ff205f62e194431f
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
@@ -723,33 +714,33 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
F src/os_unix.c dcf7988ddbdd68619b821c9a722f9377abb46f1d26c9279eb5a50402fd43d749
F src/os_unix.c fa5e09b4df35ad845440cad67b86908cfe1fd4c28c51915f82e23633d1992bf4
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
F src/pager.c a81461de271ac4886ad75b7ca2cca8157a48635820c4646cd2714acdc2c17e5f
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y 7c2184b5665c671258c4e96a10bbc9dbf7e1ede462ebc4e614249de0d54c8a26
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pragma.c ecec75795c1821520266e4f93fa8840cce48979af532db06f085e36a7813860f
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
F src/printf.c b1b29b5e58e1530d5daeee5963d3c318d8ab2d7e38437580e28755753e0c1ded
F src/printf.c 9cff219dba73b1aa9a8113e83e962f03f7bea8b6eb51cefb25bc468d5a69fb2d
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 47aa7fdc9ec4c19b103ac5e79d7887d30119b5675309facf5eed1118391c868b
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 3bbcb0dbdac61a856b1ba3e2ed64d609935eca884b20208e5df5eeb183e2413f
F src/shell.c.in b944a21d98cc4c6107bfd1ec702440579cb4bf86435125b67ff661180e9453b5
F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61
F src/select.c 8fe87c39a45037dac2e3dc02e1dc13ca09c1155cc14df9daaa65e5318179beaf
F src/shell.c.in 2acdfca982deb70cdfefb8b422822d4e0234fe4dde6ff2bd9020b26445853917
F src/sqlite.h.in 1f853f1d836af3e5a0b451521041d05658988a45f6978aaae08286e483fee5ac
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
F src/sqliteInt.h b30f6ec44e695d00d83f83bdf3b8dd31a6537c48d909c7abb78643c49784d988
F src/sqliteInt.h 185abb373dc2a311e3292540ef177ea301d8140b976ecd8ba381a5a0162cd6e9
F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 85b5a20df96016e5d1d8fdc68c8a4c279c5b93e2049b77cd806c2cc50b9d8c56
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
F src/test1.c 302cc00a5f0bbfa36d73b299d600c073b02ffa7f2b59fd2c81091983ccd574a8
F src/test1.c 3e3b013f59ffcb57dce00c90d55907072d71d4e970cb0a590cb261efe11bae9c
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -762,7 +753,7 @@ F src/test_backup.c a2bfd90d2ff2511b8635507bdb30fa9b605ade19c16b533066cae3077f5b
F src/test_bestindex.c d75fad21369d80910238032bcf8d9ca1f2bffda13c1ceec63bfbb7f704448b15
F src/test_blob.c 77b994e17f2c87055f44fd96c9a206c5a7155bae2cda2769af60c2f3582f962c
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
F src/test_config.c 9b6dac5bc4ab56c9c6289ca9a6a73a156e178e58bcfdac19a69f6e17e28ad5ac
F src/test_config.c e02566c2c4ee2916324ce17123a798b47663cead2de546cfbd71d8cddb46bb26
F src/test_delete.c d0e8f6dc55cfc98a7c27c057fb88d512260564bf0b611482656c68b8f7f401ed
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
@@ -799,31 +790,31 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c f297bbf02037639e7a93b37d9c6e4415b3de1273395ee8fa8183e741e1e7fb72
F src/treeview.c feaa59f14db4f7b5aacca9c5ad5aeb562c1f98262c1ffd74371f4186ade91fc5
F src/trigger.c cb894db98083c68c4a17c72566ed39434aa91286db20d2891279ee49e6bfec0c
F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 0cc410d538fe13a2cda90a8d0087c82cf4c1ab0d5055b8e3a595f28266f190c7
F src/util.c eccfa8b3b414bb64c6543421c9fd10e5f07e103baae36427a273a9131527694c
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c fa28a8f740f3d94c4e6b6d42ba90c220472683486268e753017512a70ef715f5
F src/vdbe.c 5328c99dd256ee8132383565a86e253543a85daccfd7477c52f20bac6b385a7f
F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9
F src/vdbeInt.h c45d0195dad0a9099132109e3b63697f4f119baddeb391c36ca226cee530a485
F src/vdbeInt.h 42488247a80cd9d300627833c6c85ace067ae5011a99e7614e2358130d62feea
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
F src/vdbeaux.c 396d38a62a357b807eabae0cae441fc89d2767a57ab08026b7072bf7aa2dd00c
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
F src/vdbemem.c 699d2fb0a59a00cf9b77898653167673de60fa5577e07bd6bee6adaef5fdc374
F src/vdbemem.c 317ec5e870ddb16951b606c9fe8be22baef22ecbe46f58fdefc259662238afb7
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 5437ce986db2f70e639ce8a3fe68dcdfe64b0f1abb14eaebecdabd5e0766cc68
F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
F src/wal.c 505a98fbc599a971d92cb90371cf54546c404cd61e04fd093e7b0c8ff978f9b6
F src/wal.c 88d94fd15a75f6eda831fa32d1148a267ea37bf0a4b69829a73dfde06244b08f
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 7a7fe745dd8104d0276a3d3f6e6ac7f087af3dd9f34a90bc937e5e7aea817e15
F src/where.c 9f09ee7b260010138d5f9fb5f195b98051119eae3096a99d72ff16c83230f4af
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
F src/wherecode.c 783ecd30061c875c919a5163e4b55f9a0eccdaf7c9b17ad2908a1668a8766bc4
F src/whereexpr.c bb649ce81bd6dc0eabfa2533ff5656fc7a16411e520a6c59be43e73e51503cce
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
@@ -872,6 +863,7 @@ F test/analyzeF.test 40b5cc3ad7b10e81020d7ca86f1417647ecfae7477cfd88acc5aa7ae106
F test/analyzeG.test 623be33038c49648872746c8dd8b23b5792c08fef173c55e82f1b12fca259852
F test/analyzer1.test b6a624ec0af92eec209e1328465b66937c8fdf2fb442a3fa45321ddb3700f4aa
F test/atof1.test bd21c4a0e718ab1470de07a2a79f2544d7903be34feebcc80de04beee4807b00
F test/atof2.test 12912add57230495450e2fc94cb8ad1c9f3277f8843a3bc27079cae45c9782a1
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
@@ -916,7 +908,7 @@ F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c
F test/bestindex8.test 4d8b1e8f30a7f405988ce4dbcc2b95c0775f0bed9ec08e0291a07e2f35f7e653
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
F test/bestindexB.test 14db2f66ec9cc5064a74996033b74e5eec0fd2f3a327fbe34ff18de67e9d2671
F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc
F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3
F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49
@@ -1070,7 +1062,7 @@ F test/e_createtable.test 31b9bcb6ac8876bc7ec342d86d9c231a84c62b442093a6651dfd0f
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
F test/e_expr.test 0a1e175caddc78b27306647cb4ce2362c55790190f8cdd178b75fd6262eb8f76
F test/e_expr.test 9bdb347b78b9f4eff9153ea97797facc179a821898588471a70808b4471a69b0
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
@@ -1130,7 +1122,8 @@ F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958
F test/fork-test.c 9ac2e6423a1d38df3d6be0e8ac15608b545de21e2b19d9d876254c5931b63edb
F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
F test/fp-speed-1.c b37de94eba034e1703668816225f54510ec60fb0685406608cc707afe6b8234d
F test/fpconv1.test d5d8aa0c427533006c112fb1957cdd1ea68c1d0709470dabb9ca02c2e4c06ad8
F test/fpconv1.test 63f352682fa65601a326563ad633086df6ab194e6ed5e7366786f38a525a7fd7
F test/fptest01.sql 210562ad8d5a7895f26273dd3be56561a41bcb51d78a28a337af0f1ceaa3bb8d
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
@@ -1314,6 +1307,7 @@ F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c77
F test/instr.test 67ba309e9697c24a304e98a7c8f372456177dd4e32237d2a305e1e05f7bb79c2
F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd0e0f44c
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
@@ -1342,7 +1336,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
F test/joinI.test fc7d24a2b1e444979b83bd92c30ebb975cebb5b9eae4442ce94969bd8d083053
F test/joinI.test 249802b168ce96d8d57943ef9abafc1e36e28d91829f68bc2b6e87f2b4d33241
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
@@ -1453,7 +1447,7 @@ F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4d
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
F test/mutex1.test 42cb5e244c3a77bb0ef2b967e06fa5e7ba7d32d90a9b20bed98f6f5ede185a25
F test/mutex1.test 2cdc320a3320521d73b8090a04a2245c1e625e5f90672882517bf5fedcec8f13
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 73ea63ab43668313e2f8cc9ef9e9a966672c7934f3ce76926fbe991235d07d91
F test/nockpt.test 3db354270fc63b6871eebd40285d4c55324fb27be629c958adbff6d7fcaa8e14
@@ -1518,7 +1512,7 @@ F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224c
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd
F test/qrf01.test 1d69175c966a95c7b2897a1831ca49ba84afc1107b32f7c455e05125ac7c8d11
F test/qrf01.test abc3e558a75ae2678a3172051b39960dc6fd4b298b6d594afa50939759f4037f
F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
F test/qrf03.test e7efe46d204671726b4707585126cd78d107368de4a7d0c7b8d5157cdd8624ed
F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
@@ -1562,7 +1556,7 @@ F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test 06ec0aca725bf683313d03793aa2943bc7f45a901848c7056a9665b769c8fc38
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
F test/rowvalue9.test 7499a8fd7ca3a3f0e19d94e135355439aa2b596f86b775ca8de79672da2ca378
F test/rowvalueA.test be8d6ad8b476eb24c151bb20bfd487e0d50c5e99618b7b0e656035069d2fc2cf
F test/rowvalueA.test 1c5ed13f3b0641452ae35e6488d6ecc16cefce99f2adf7c07c513530e2aac6b7
F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972d511c54fff
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
@@ -1618,17 +1612,17 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 5055a13bde31e92590311c91777d6b646082dc13250de8c07dc0db1efbdd864d
F test/shell1.test 2d658ceee13d9e4361d04d0ea16340ad17784ddf378fb6e9ca6d49c682cb4bae
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
F test/shell3.test 603b448e917537cf77be0f265c05c6f63bc677c63a533c8e96aae923b56f4a0e
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
F test/shell5.test a9cd2c8b62e125049ef500937674f47dd6787f0157ac0515aa554044a4dc3ea9
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
F test/shell8.test 641cf21a99c59404c24e3062923734951c4099a6b6b6520de00cf7a1249ee871
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
F test/shellB.test b2afd5c28aba750c066996a082210d6a4fcab8fd042cad076d9c1023164af9b1
F test/shellB.test 7123d231158588401f332bf278754687b83ba5fc5b352ec8679fb19edfb4cc0a
F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1714,7 +1708,7 @@ F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3f
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
F test/testrunner.tcl 78d67079fc39caf2af3fd9d4c30bdac78dae7ec50b9fc802835e7a5189581e07 x
F test/testrunner_data.tcl 87b8afd37c8e517fa87b7936540b2fc1ede8291f0567fb88744b9bff272a2e8b
F test/testrunner_data.tcl 078e251983c8fc573567125147655f68132210f226c92922daf21fb913779717
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
@@ -1946,7 +1940,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
F test/values.test 0eda08a6ce6545f1ab012dff4cc72a7dd0fee2510f42444136bb2b2b5ed84bc0
F test/values.test 0e037c50789ac2a308746567d07b53b2f6026c1bb3a435d1b099424600e64caf
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
@@ -2010,6 +2004,7 @@ F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
F test/walpersist.test 8d78a1ec91299163451417b451a2bac3481f8eb9f455b1ca507a6625c927ca6e
F test/walprotocol.test 1b3f922125e341703f6e946d77fdc564d38fb3e07a9385cfdc6c99cac1ecf878
F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db868eebc131
F test/walrestart.test 3b0a9198ad2eb9f716d8f3846b133ba9f4619fb56decb1e67bba27743c766289
F test/walro.test 78a84bc0fdae1385c06b017215c426b6845734d6a5a3ac75c918dd9b801b1b9d
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
@@ -2099,7 +2094,7 @@ F test/zeroblob.test 7b74cefc7b281dfa2b07cd237987fbe94b4a2037a7771e9e83f2d5f608b
F test/zeroblobfault.test 861d8191a0d944dfebb3cb4d2c5b4e46a5a119eaec5a63dd996c2389f8063441
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
F test/zipfile.test a3fcfc43115e4226fdddadd43bdf31c8ca805ad08dad435634f1633d8f5840d9
F test/zipfile2.test a577e0775e32ef8972e7d5e9a45bc071a5ae061b5b965a08c9c4b709ad036a25
F test/zipfile2.test 21afaffcf4f7769df38bf16e4a9c4dfa6ba1b0f5b695f844ec61fafb92db0db7
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e04534bbf
@@ -2156,7 +2151,7 @@ F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e54
F tool/mkwinarm64ec.tcl 171f79234fa53552a129b360356df5599fdab15239caffb3d29c571292728033
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
F tool/omittest.tcl bec70ef0e16255c8d9eb06ecd7edf823c07a60a836186cdbce3528fb34b67995
F tool/omittest.tcl 436b7072e00e25e9b77145a9f67aa8e0eeabd186168827435fd03f8f981aac32
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c f98909b4168d9cac11a2de7f031adea0e2f3131faa7515a72807c03ec58eafeb
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
@@ -2173,7 +2168,7 @@ F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdadd
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
F tool/sqldiff.c 68f88017de3bed3aa65c93a4cf3a04d0989d158bc6fad8f1475beeeea1aae3ac
F tool/sqldiff.c 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
@@ -2194,8 +2189,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P a80c847169f307a4d2e524b6732ea557bf7f312f1a319d6c6c2e81adb0907596
R 3eb7e8d20bd192b2f6690ce98ebbba28
U drh
Z 4720cdecbf1fe28948310be768602949
P decb69015457b4f70cf574aeef87d40f9de60b94965f4a915e8d0cd7559ef2ae
R 081029f3feecf24cb4be31bd4056634e
U dan
Z 6e3cc1dc135fda8b3b63884b6a3aae0a
# Remove this line to create a well-formed Fossil manifest.
+2 -2
View File
@@ -1,2 +1,2 @@
branch fp-perf
tag fp-perf
branch wal-restart-fix
tag wal-restart-fix
+1 -1
View File
@@ -1 +1 @@
245ac7d9ec61e14fcef13a731e290fc5e8979efef6f4345f875eab9b882b0713
703cbb0f760515eac1e6f72a5e5cd928258c71378e4a976082b6518c90128135
+9 -4
View File
@@ -486,6 +486,7 @@ Table *sqlite3LocateTableItem(
const char *zDb;
if( p->fg.fixedSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
assert( iDb>=0 && iDb<pParse->db->nDb );
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
assert( !p->fg.isSubquery );
@@ -2570,13 +2571,14 @@ void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
** restored to its original value prior to this routine returning.
*/
int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
char *zTail; /* Pointer to the last "_" in zName */
const char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
char *zCopy;
zTail = strrchr(zName, '_');
if( zTail==0 ) return 0;
*zTail = 0;
pTab = sqlite3FindTable(db, zName, 0);
*zTail = '_';
zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName));
pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0;
sqlite3DbFree(db, zCopy);
if( pTab==0 ) return 0;
if( !IsVirtual(pTab) ) return 0;
return sqlite3IsShadowTableOf(db, pTab, zName);
@@ -2729,6 +2731,7 @@ void sqlite3EndTable(
convertToWithoutRowidTable(pParse, p);
}
iDb = sqlite3SchemaToIndex(db, p->pSchema);
assert( iDb>=0 && iDb<=db->nDb );
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
@@ -3024,6 +3027,7 @@ void sqlite3CreateView(
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
assert( iDb>=0 && iDb<db->nDb );
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
@@ -4620,6 +4624,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
goto exit_drop_index;
}
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
assert( iDb>=0 && iDb<db->nDb );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
+11 -5
View File
@@ -429,7 +429,7 @@ static int parseDateOrTime(
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
return setDateTimeToCurrent(context, p);
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
}else if( sqlite3AtoF(zDate, &r)>0 ){
setRawDateNumber(p, r);
return 0;
}else if( (sqlite3StrICmp(zDate,"subsec")==0
@@ -875,7 +875,7 @@ static int parseModifier(
** date is already on the appropriate weekday, this is a no-op.
*/
if( sqlite3_strnicmp(z, "weekday ", 8)==0
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
&& sqlite3AtoF(&z[8], &r)>0
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
sqlite3_int64 Z;
computeYMD_HMS(p);
@@ -946,9 +946,11 @@ static int parseModifier(
case '8':
case '9': {
double rRounder;
int i;
int i, rx;
int Y,M,D,h,m,x;
const char *z2 = z;
char *zCopy;
sqlite3 *db = sqlite3_context_db_handle(pCtx);
char z0 = z[0];
for(n=1; z[n]; n++){
if( z[n]==':' ) break;
@@ -958,7 +960,11 @@ static int parseModifier(
if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
}
}
if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
zCopy = sqlite3DbStrNDup(db, z, n);
if( zCopy==0 ) break;
rx = sqlite3AtoF(zCopy, &r)<=0;
sqlite3DbFree(db, zCopy);
if( rx ){
assert( rc==1 );
break;
}
@@ -1778,7 +1784,7 @@ static void datedebugFunc(
char *zJson;
zJson = sqlite3_mprintf(
"{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d,"
"s:%.3f,validJD:%d,validYMS:%d,validHMS:%d,"
"s:%.3f,validJD:%d,validYMD:%d,validHMS:%d,"
"nFloor:%d,rawS:%d,isError:%d,useSubsec:%d,"
"isUtc:%d,isLocal:%d}",
x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz,
+1 -1
View File
@@ -4303,7 +4303,7 @@ sqlite3ExprCodeIN_oom_error:
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
if( ALWAYS(z!=0) ){
double value;
sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
sqlite3AtoF(z, &value);
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
if( negateFlag ) value = -value;
sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
+1
View File
@@ -908,6 +908,7 @@ void sqlite3FkCheck(
if( !IsOrdinaryTable(pTab) ) return;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=00 && iDb<db->nDb );
zDb = db->aDb[iDb].zDbSName;
/* Loop through all the foreign key constraints for which pTab is the
+5 -3
View File
@@ -466,7 +466,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_result_error_nomem(context);
return;
}
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
sqlite3AtoF(zBuf, &r);
sqlite3_free(zBuf);
}
sqlite3_result_double(context, r);
@@ -1104,7 +1104,7 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){
sqlite3_str_appendf(pStr, "%!0.15g", r1);
zVal = sqlite3_str_value(pStr);
if( zVal ){
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
sqlite3AtoF(zVal, &r2);
if( r1!=r2 ){
sqlite3_str_reset(pStr);
sqlite3_str_appendf(pStr, "%!0.20e", r1);
@@ -1201,7 +1201,7 @@ static void unistrFunc(
}
i = j = 0;
while( i<nIn ){
char *z = strchr(&zIn[i],'\\');
const char *z = strchr(&zIn[i],'\\');
if( z==0 ){
n = nIn - i;
memmove(&zOut[j], &zIn[i], n);
@@ -2364,6 +2364,8 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc,
0, 0, 0, 0, 0);
pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0);
assert( pDef!=0 ); /* The sqlite3CreateFunc() call above cannot fail
** because the "like" SQL-function already exists */
pDef->funcFlags |= flags;
pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE;
}
+1 -1
View File
@@ -3266,7 +3266,7 @@ static void jsonReturnFromBlob(
to_double:
z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz);
if( z==0 ) goto returnfromblob_oom;
rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
rc = sqlite3AtoF(z, &r);
sqlite3DbFree(db, z);
if( rc<=0 ) goto returnfromblob_malformed;
sqlite3_result_double(pCtx, r);
+10 -1
View File
@@ -971,6 +971,14 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
rc = setupLookaside(db, pBuf, sz, cnt);
break;
}
case SQLITE_DBCONFIG_FP_DIGITS: {
int nIn = va_arg(ap, int);
int *pOut = va_arg(ap, int*);
if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn;
if( pOut ) *pOut = db->nFpDigit;
rc = SQLITE_OK;
break;
}
default: {
static const struct {
int op; /* The opcode */
@@ -3378,7 +3386,7 @@ static int openDatabase(
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
if( isThreadsafe
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
#if defined(SQLITE_THREAD_MISUSE_WARNINGS)
|| sqlite3GlobalConfig.bCoreMutex
#endif
){
@@ -3399,6 +3407,7 @@ static int openDatabase(
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
db->nFpDigit = 17;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
+16 -8
View File
@@ -27,23 +27,28 @@ static SQLITE_WSD int mutexIsInit = 0;
#ifndef SQLITE_MUTEX_OMIT
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
#ifdef SQLITE_THREAD_MISUSE_WARNINGS
/*
** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
** This block (enclosed by SQLITE_THREAD_MISUSE_WARNINGS) contains
** the implementation of a wrapper around the system default mutex
** implementation (sqlite3DefaultMutex()).
**
** Most calls are passed directly through to the underlying default
** mutex implementation. Except, if a mutex is configured by calling
** sqlite3MutexWarnOnContention() on it, then if contention is ever
** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
** encountered within xMutexEnter() then a warning is emitted via
** sqlite3_log(). Furthermore, if SQLITE_THREAD_MISUSE_ABORT is
** defined then abort() is called after the sqlite3_log() warning.
**
** This type of mutex is used as the database handle mutex when testing
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
** This type of mutex is used on the database handle mutex when testing
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. A failure
** indicates that the app ought to be using SQLITE_OPEN_FULLMUTEX or
** similar because it is trying to use the same database handle from
** two different connections at the same time.
*/
/*
** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
** Type for all mutexes used when SQLITE_THREAD_MISUSE_WARNINGS
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
** allocated by the system mutex implementation. Variable iType is usually set
** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
@@ -160,6 +165,9 @@ static void checkMutexEnter(sqlite3_mutex *p){
sqlite3_log(SQLITE_MISUSE,
"illegal multi-threaded access to database connection"
);
#if SQLITE_THREAD_MISUSE_ABORT
abort();
#endif
}
pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
}
@@ -211,7 +219,7 @@ void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
}
}
#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
#endif /* ifdef SQLITE_THREAD_MISUSE_WARNINGS */
/*
** Initialize the mutex system.
@@ -228,7 +236,7 @@ int sqlite3MutexInit(void){
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
if( sqlite3GlobalConfig.bCoreMutex ){
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
#ifdef SQLITE_THREAD_MISUSE_WARNINGS
pFrom = multiThreadedCheckMutex();
#else
pFrom = sqlite3DefaultMutex();
+1 -1
View File
@@ -5190,7 +5190,7 @@ static int unixShmMap(
}
/* Map the requested memory region into this processes address space. */
apNew = (char **)sqlite3_realloc(
apNew = (char **)sqlite3_realloc64(
pShmNode->apRegion, nReqRegion*sizeof(char *)
);
if( !apNew ){
+4 -4
View File
@@ -1235,17 +1235,17 @@ static int jrnlBufferSize(Pager *pPager){
*/
#ifdef SQLITE_CHECK_PAGES
/*
** Return a 32-bit hash of the page data for pPage.
** Return a 64-bit hash of the page data for pPage.
*/
static u32 pager_datahash(int nByte, unsigned char *pData){
u32 hash = 0;
static u64 pager_datahash(int nByte, unsigned char *pData){
u64 hash = 0;
int i;
for(i=0; i<nByte; i++){
hash = (hash*1039) + pData[i];
}
return hash;
}
static u32 pager_pagehash(PgHdr *pPage){
static u64 pager_pagehash(PgHdr *pPage){
return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
}
static void pager_set_pagehash(PgHdr *pPage){
+1 -1
View File
@@ -1427,7 +1427,7 @@ expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
expr(A) ::= expr(A) ISNULL|NOTNULL(E). {A = sqlite3PExprIsNull(pParse,@E,A);}
expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExprIsNull(pParse,TK_NOTNULL,A);}
// expr1 IS expr2 same as expr1 IS NOT DISTICT FROM expr2
// expr1 IS expr2 same as expr1 IS NOT DISTINCT FROM expr2
// expr1 IS NOT expr2 same as expr1 IS DISTINCT FROM expr2
//
expr(A) ::= expr(A) IS expr(Y). {
+2 -2
View File
@@ -29,10 +29,10 @@ struct PgHdr {
PCache *pCache; /* PRIVATE: Cache that owns this page */
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
Pager *pPager; /* The pager this page is part of */
Pgno pgno; /* Page number for this page */
#ifdef SQLITE_CHECK_PAGES
u32 pageHash; /* Hash of page content */
u64 pageHash; /* Hash of page content */
#endif
Pgno pgno; /* Page number for this page */
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
+1 -1
View File
@@ -549,7 +549,7 @@ void sqlite3_str_vappendf(
}else{
iRound = precision+1;
}
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16);
if( s.isSpecial ){
if( s.isSpecial==2 ){
bufpt = flag_zeropad ? "null" : "NaN";
+9 -1
View File
@@ -936,7 +936,7 @@ static int exprProbability(Expr *p){
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
assert( !ExprHasProperty(p, EP_IntValue) );
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
sqlite3AtoF(p->u.zToken, &r);
assert( r>=0.0 );
if( r>1.0 ) return -1;
return (int)(r*134217728.0);
@@ -2073,6 +2073,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
/* If the SELECT statement contains ON clauses that were moved into
** the WHERE clause, go through and verify that none of the terms
** in the ON clauses reference tables to the right of the ON clause. */
if( (p->selFlags & SF_OnToWhere) ){
sqlite3SelectCheckOnClauses(pParse, p);
if( pParse->nErr ) return WRC_Abort;
}
/* Advance to the next term of the compound
*/
p = p->pPrior;
+2 -14
View File
@@ -21,7 +21,7 @@
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */
u8 isTnct; /* 0: Not distinct. 1: DISTINCT 2: DISTINCT and ORDER BY */
u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
int tabTnct; /* Ephemeral table used for DISTINCT processing */
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
@@ -7491,7 +7491,7 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
** Check all ON clauses in pSelect to verify that they do not reference
** columns to the right.
*/
static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){
Walker w;
CheckOnCtx sCtx;
int ii;
@@ -7671,18 +7671,6 @@ int sqlite3Select(
}
#endif
/* If the SELECT statement contains ON clauses that were moved into
** the WHERE clause, go through and verify that none of the terms
** in the ON clauses reference tables to the right of the ON clause.
** Do this now, after name resolution, but before query flattening
*/
if( p->selFlags & SF_OnToWhere ){
selectCheckOnClauses(pParse, p);
if( pParse->nErr ){
goto select_end;
}
}
/* If the SF_UFSrcCheck flag is set, then this function is being called
** as part of populating the temp table for an UPDATE...FROM statement.
** In this case, it is an error if the target object (pSrc->a[0]) name
+38 -21
View File
@@ -931,7 +931,7 @@ static void shellDtostr(
char z[400];
if( n<1 ) n = 1;
if( n>350 ) n = 350;
sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
sprintf(z, "%#+.*e", n, r);
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
}
@@ -6665,11 +6665,15 @@ static int arRemoveCommand(ArCommand *pAr){
*/
static int arExtractCommand(ArCommand *pAr){
const char *zSql1 =
"SELECT "
" ($dir || name),"
" writefile(($dir || name), %s, mode, mtime) "
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
" AND name NOT GLOB '*..[/\\]*'";
"WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n"
"SELECT ($dir || name),\n"
" CASE WHEN $dryrun THEN 0\n"
" ELSE writefile($dir||name, %s, mode, mtime) END\n"
" FROM dest CROSS JOIN %s\n"
" WHERE (%s)\n"
" AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */
" AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
" AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
const char *azExtraArg[] = {
"sqlar_uncompress(data, sz)",
@@ -6704,24 +6708,28 @@ static int arExtractCommand(ArCommand *pAr){
if( rc==SQLITE_OK ){
j = sqlite3_bind_parameter_index(pSql, "$dir");
sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
j = sqlite3_bind_parameter_index(pSql, "$dryrun");
sqlite3_bind_int(pSql, j, pAr->bDryRun);
/* Run the SELECT statement twice. The first time, writefile() is called
** for all archive members that should be extracted. The second time,
** only for the directories. This is because the timestamps for
** extracted directories must be reset after they are populated (as
** populating them changes the timestamp). */
/* Run the SELECT statement twice
** (0) writefile() all files and directories
** (1) writefile() for directory again
** The second pass is so that the timestamps for extracted directories
** will be reset to the value in the archive, since populating them
** in the first pass will have changed the timestamp. */
for(i=0; i<2; i++){
j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
j = sqlite3_bind_parameter_index(pSql, "$pass");
sqlite3_bind_int(pSql, j, i);
if( pAr->bDryRun ){
cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
}else{
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
if( i==0 && pAr->bVerbose ){
cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
}
if( pAr->bVerbose==0 ) break;
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
if( i==0 && pAr->bVerbose ){
cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
}
}
if( pAr->bDryRun ) break;
shellReset(&rc, pSql);
}
shellFinalize(&rc, pSql);
@@ -9267,6 +9275,7 @@ static int do_meta_command(const char *zLine, ShellState *p){
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "fp_digits", SQLITE_DBCONFIG_FP_DIGITS },
{ "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
{ "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
@@ -9283,11 +9292,19 @@ static int do_meta_command(const char *zLine, ShellState *p){
for(ii=0; ii<ArraySize(aDbConfig); ii++){
if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
if( nArg>=3 ){
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
sqlite3_db_config(p->db, aDbConfig[ii].op, atoi(azArg[2]), 0);
}else{
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
}
}
sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
cli_printf(p->out, "%19s %s\n",
aDbConfig[ii].zName, v ? "on" : "off");
if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
cli_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v);
}else{
cli_printf(p->out, "%19s %s\n",
aDbConfig[ii].zName, v ? "on" : "off");
}
if( nArg>1 ) break;
}
if( nArg>1 && ii==ArraySize(aDbConfig) ){
@@ -13346,7 +13363,7 @@ int SQLITE_CDECL main(int argc, char **argv){
z = cmdline_option_value(argc,argv,++i);
if( z[0]=='.' ){
rc = do_meta_command(z, &data);
if( rc && bail_on_error ){
if( rc && (bail_on_error || rc==2) ){
if( rc==2 ) rc = 0;
goto shell_main_exit;
}
+36 -17
View File
@@ -2648,6 +2648,22 @@ struct sqlite3_mem_methods {
** comments are allowed in SQL text after processing the first argument.
** </dd>
**
** [[SQLITE_DBCONFIG_FP_DIGITS]]
** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt>
** <dd>The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines
** the number of significant digits that SQLite will attempt to preserve when
** converting floating point numbers (IEEE 754 "doubles") into text. The
** default value 17, as of SQLite version 3.52.0. The value was 15 in all
** prior versions.<p>
** This option takes two arguments which are an integer and a pointer
** to an integer. The first argument is a small integer, between 3 and 23, or
** zero. The FP_DIGITS setting is changed to that small integer, or left
** altered if the first argument is zero or out of range. The second argument
** is a pointer to an integer. If the pointer is not NULL, then the value of
** the FP_DIGITS setting, after possibly being modified by the first
** arguments, is written into the integer to which the second argument points.
** </dd>
**
** </dl>
**
** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3>
@@ -2665,9 +2681,10 @@ struct sqlite3_mem_methods {
** the first argument.
**
** <p>While most SQLITE_DBCONFIG options use the argument format
** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME]
** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the
** documentation of those exceptional options for details.
** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME],
** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options
** are different. See the documentation of those exceptional options for
** details.
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
@@ -2692,7 +2709,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */
#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -4435,19 +4453,20 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** logs the error.
**
** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
** the SQL statement is part of a database schema. This makes a difference
** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
** SQL functions may not be called unless they are tagged with
** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
** when preparing SQL that is derived from parts of the database
** schema. In particular, virtual table implementations that
** run SQL statements based on the arguments to their CREATE VIRTUAL
** TABLE statement should use [sqlite3_prepare_v3()] and set the
** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce
** security constraints that would otherwise only be enforced when parsing
** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag
** causes the SQL compiler to treat the SQL statement being prepared as if
** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and
** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called
** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only
** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice
** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that
** is derived from parts of the database schema. In particular, virtual
** table implementations that run SQL statements that are derived from
** arguments to their CREATE VIRTUAL TABLE statement should always use
** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to
** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
+29 -14
View File
@@ -1692,6 +1692,7 @@ struct sqlite3 {
u8 noSharedCache; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
u8 eOpenState; /* Current condition of the connection */
u8 nFpDigit; /* Significant digits to keep on double->text */
int nextPagesize; /* Pagesize after VACUUM if >0 */
i64 nChange; /* Value returned by sqlite3_changes() */
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
@@ -3881,17 +3882,12 @@ struct Parse {
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */
u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
u8 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
@@ -3900,10 +3896,15 @@ struct Parse {
u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
** and ALTER TABLE ADD COLUMN. */
#endif
bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
bft bHasWith :1; /* True if statement contains WITH */
bft okConstFactor :1; /* OK to factor out constants */
bft checkSchema :1; /* Causes schema cookie check after an error */
bft disableTriggers:1; /* True to disable triggers */
bft mayAbort :1; /* True if statement may throw an ABORT exception */
bft hasCompound :1; /* Need to invoke convertCompoundSelectToSubquery() */
bft bReturning :1; /* Coding a RETURNING trigger */
bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */
bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
bft bHasWith :1; /* True if statement contains WITH */
bft okConstFactor:1; /* OK to factor out constants */
bft checkSchema :1; /* Causes schema cookie check after an error */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -4786,7 +4787,20 @@ int sqlite3LookasideUsed(sqlite3*,int*);
sqlite3_mutex *sqlite3Pcache1Mutex(void);
sqlite3_mutex *sqlite3MallocMutex(void);
#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
/* The SQLITE_THREAD_MISUSE_WARNINGS compile-time option used to be called
** SQLITE_ENABLE_MULTITHREADED_CHECKS. Keep that older macro for backwards
** compatibility, at least for a while... */
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
# define SQLITE_THREAD_MISUSE_WARNINGS 1
#endif
/* SQLITE_THREAD_MISUSE_ABORT implies SQLITE_THREAD_MISUSE_WARNINGS */
#ifdef SQLITE_THREAD_MISUSE_ABORT
# define SQLITE_THREAD_MISUSE_WARNINGS 1
#endif
#if defined(SQLITE_THREAD_MISUSE_WARNINGS) && !defined(SQLITE_MUTEX_OMIT)
void sqlite3MutexWarnOnContention(sqlite3_mutex*);
#else
# define sqlite3MutexWarnOnContention(x)
@@ -4820,12 +4834,12 @@ struct PrintfArguments {
** value into an approximate decimal representation.
*/
struct FpDecode {
char sign; /* '+' or '-' */
char isSpecial; /* 1: Infinity 2: NaN */
int n; /* Significant digits in the decode */
int iDP; /* Location of the decimal point */
char *z; /* Start of significant digits */
char zBuf[24]; /* Storage for significant digits */
char zBuf[20]; /* Storage for significant digits */
char sign; /* '+' or '-' */
char isSpecial; /* 1: Infinity 2: NaN */
};
void sqlite3FpDecode(FpDecode*,double,int,int);
@@ -5068,6 +5082,7 @@ Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
void sqlite3SelectDeleteGeneric(sqlite3*,void*);
void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -5289,7 +5304,7 @@ int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64);
i64 sqlite3RealToI64(double);
int sqlite3Int64ToText(i64,char*);
int sqlite3AtoF(const char *z, double*, int, u8);
int sqlite3AtoF(const char *z, double*);
int sqlite3GetInt32(const char *, int*);
int sqlite3GetUInt32(const char*, u32*);
int sqlite3Atoi(const char*);
+1
View File
@@ -8644,6 +8644,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
{ "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
{ "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS },
{ "FP_DIGITS", SQLITE_DBCONFIG_FP_DIGITS },
};
int i;
int v = 0;
+8
View File
@@ -679,6 +679,14 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_THREAD_MISUSE_WARNINGS
Tcl_SetVar2(interp, "sqlite_options", "thread_misuse_warnings",
"1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "thread_misuse_warnings",
"0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_TRIGGER
Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
#else
+2
View File
@@ -336,6 +336,7 @@ void sqlite3FinishTrigger(
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
zName = pTrig->zName;
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
assert( iDb>=00 && iDb<db->nDb );
pTrig->step_list = pStepList;
while( pStepList ){
pStepList->pTrig = pTrig;
@@ -819,6 +820,7 @@ static SQLITE_NOINLINE Trigger *triggersReallyExist(
p = pList;
if( (pParse->db->flags & SQLITE_EnableTrigger)==0
&& pTab->pTrigger!=0
&& sqlite3SchemaToIndex(pParse->db, pTab->pTrigger->pSchema)!=1
){
/* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that
** only TEMP triggers are allowed. Truncate the pList so that it
+192 -161
View File
@@ -546,28 +546,28 @@ static u64 powerOfTen(int p){
static const u64 aScale[] = {
0x8049a4ac0c5811aeLLU, /* 0: 1.0e-351 << 1229 */
0xcf42894a5dce35eaLLU, /* 1: 1.0e-324 << 1140 */
0xa76c582338ed2621LLU, /* 2: 1.0e-297 << 1050 */
0xa76c582338ed2622LLU, /* 2: 1.0e-297 << 1050 */
0x873e4f75e2224e68LLU, /* 3: 1.0e-270 << 960 */
0xda7f5bf590966848LLU, /* 4: 1.0e-243 << 871 */
0xb080392cc4349decLLU, /* 5: 1.0e-216 << 781 */
0xda7f5bf590966849LLU, /* 4: 1.0e-243 << 871 */
0xb080392cc4349dedLLU, /* 5: 1.0e-216 << 781 */
0x8e938662882af53eLLU, /* 6: 1.0e-189 << 691 */
0xe65829b3046b0afaLLU, /* 7: 1.0e-162 << 602 */
0xba121a4650e4ddebLLU, /* 8: 1.0e-135 << 512 */
0xba121a4650e4ddecLLU, /* 8: 1.0e-135 << 512 */
0x964e858c91ba2655LLU, /* 9: 1.0e-108 << 422 */
0xf2d56790ab41c2a2LLU, /* 10: 1.0e-81 << 333 */
0xc428d05aa4751e4cLLU, /* 11: 1.0e-54 << 243 */
0xf2d56790ab41c2a3LLU, /* 10: 1.0e-81 << 333 */
0xc428d05aa4751e4dLLU, /* 11: 1.0e-54 << 243 */
0x9e74d1b791e07e48LLU, /* 12: 1.0e-27 << 153 */
0x8000000000000000LLU, /* 13: 1.0e+0 << 63 */
0xcecb8f27f4200f3aLLU, /* 14: 1.0e+27 >> 26 */
0xa70c3c40a64e6c51LLU, /* 15: 1.0e+54 >> 116 */
0xa70c3c40a64e6c52LLU, /* 15: 1.0e+54 >> 116 */
0x86f0ac99b4e8dafdLLU, /* 16: 1.0e+81 >> 206 */
0xda01ee641a708de9LLU, /* 17: 1.0e+108 >> 295 */
0xda01ee641a708deaLLU, /* 17: 1.0e+108 >> 295 */
0xb01ae745b101e9e4LLU, /* 18: 1.0e+135 >> 385 */
0x8e41ade9fbebc27dLLU, /* 19: 1.0e+162 >> 475 */
0xe5d3ef282a242e81LLU, /* 20: 1.0e+189 >> 564 */
0xe5d3ef282a242e82LLU, /* 20: 1.0e+189 >> 564 */
0xb9a74a0637ce2ee1LLU, /* 21: 1.0e+216 >> 654 */
0x95f83d0a1fb69cd9LLU, /* 22: 1.0e+243 >> 744 */
0xf24a01a73cf2dccfLLU, /* 23: 1.0e+270 >> 833 */
0xf24a01a73cf2dcd0LLU, /* 23: 1.0e+270 >> 833 */
0xc3b8358109e84f07LLU, /* 24: 1.0e+297 >> 923 */
0x9e19db92b4e31ba9LLU, /* 25: 1.0e+324 >> 1013 */
};
@@ -594,7 +594,7 @@ static u64 powerOfTen(int p){
}
x = sqlite3Multiply128(aBase[n],y);
if( (U64_BIT(63) & x)==0 ){
x <<= 1;
x = (x<<1)|1;
}
return x;
}
@@ -648,13 +648,18 @@ static int countLeadingZeros(u64 m){
*/
static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
int p;
u64 h, out;
u64 h;
assert( n>=1 && n<=18 );
p = n - 1 - pwr2to10(e+63);
h = sqlite3Multiply128(m, powerOfTen(p));
assert( -(e + pwr10to2(p) + 3) >=0 );
assert( -(e + pwr10to2(p) + 3) <64 );
out = h >> -(e + pwr10to2(p) + 3);
*pD = (out + 2 + ((out>>2)&1)) >> 2;
assert( -(e + pwr10to2(p) + 2) >= 0 );
assert( -(e + pwr10to2(p) + 1) <= 63 );
if( n==18 ){
h >>= -(e + pwr10to2(p) + 2);
*pD = (h + ((h<<1)&2))>>1;
}else{
*pD = h >> -(e + pwr10to2(p) + 1);
}
*pP = -p;
}
@@ -663,10 +668,10 @@ static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
*/
static double sqlite3Fp10Convert2(u64 d, int p){
u64 out;
int b;
int e1;
int e2;
int lz;
int lp;
int x;
u64 h;
double r;
assert( (d & U64_BIT(63))==0 );
@@ -677,26 +682,26 @@ static double sqlite3Fp10Convert2(u64 d, int p){
if( p>POWERSOF10_LAST ){
return INFINITY;
}
b = 64 - countLeadingZeros(d);
lz = countLeadingZeros(d);
lp = pwr10to2(p);
e1 = 53 - b - lp;
e1 = lz - (lp + 11);
if( e1>1074 ){
if( -(b + lp) >= 1077 ) return 0.0;
if( e1>=1130 ) return 0.0;
e1 = 1074;
}
e2 = e1 - (64-b);
h = sqlite3Multiply128(d<<(64-b), powerOfTen(p));
assert( -(e2 + lp + 3) >=0 );
assert( -(e2 + lp + 3) <64 );
out = (h >> -(e2 + lp + 3)) | 1;
h = sqlite3Multiply128(d<<lz, powerOfTen(p));
x = lz - (e1 + lp + 3);
assert( x >= 0 );
assert( x <= 63 );
out = h >> x;
if( out >= U64_BIT(55)-2 ){
out = (out>>1) | (out&1);
out >>= 1;
e1--;
}
if( e1<=(-972) ){
return INFINITY;
}
out = (out + 1 + ((out>>2)&1)) >> 2;
out = (out + 2) >> 2;
if( (out & U64_BIT(52))!=0 ){
out = (out & ~U64_BIT(52)) | ((u64)(1075-e1)<<52);
}
@@ -708,8 +713,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
** The string z[] is an text representation of a real number.
** Convert this string to a double and write it into *pResult.
**
** The string z[] is length bytes in length (bytes, not characters) and
** uses the encoding enc. The string is not necessarily zero-terminated.
** z[] must be UTF-8 and zero-terminated.
**
** Return TRUE if the result is a valid real number (or integer) and FALSE
** if the string is empty or contains extraneous text. More specifically
@@ -736,141 +740,131 @@ static double sqlite3Fp10Convert2(u64 d, int p){
#if defined(_MSC_VER)
#pragma warning(disable : 4756)
#endif
int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
int sqlite3AtoF(const char *z, double *pResult){
#ifndef SQLITE_OMIT_FLOATING_POINT
int incr;
const char *zEnd;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
u64 s = 0; /* significand */
int d = 0; /* adjust exponent for shifting decimal point */
int esign = 1; /* sign of exponent */
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
int neg = 0; /* True for a negative value */
u64 s = 0; /* mantissa */
int d = 0; /* Value is s * pow(10,d) */
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
int eType = 1; /* 1: pure integer, 2+: fractional */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
if( length==0 ) return 0;
if( enc==SQLITE_UTF8 ){
incr = 1;
zEnd = z + length;
}else{
int i;
incr = 2;
length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
testcase( enc==SQLITE_UTF16LE );
testcase( enc==SQLITE_UTF16BE );
for(i=3-enc; i<length && z[i]==0; i+=2){}
if( i<length ) eType = -100;
zEnd = &z[i^1];
z += (enc&1);
}
/* skip leading spaces */
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
if( z>=zEnd ) return 0;
while( sqlite3Isspace(*z) ) z++;
/* get sign of significand */
if( *z=='-' ){
sign = -1;
z+=incr;
neg = 1;
z++;
}else if( *z=='+' ){
z+=incr;
z++;
}
/* copy max significant digits to significand */
while( z<zEnd && sqlite3Isdigit(*z) ){
while( sqlite3Isdigit(*z) ){
s = s*10 + (*z - '0');
z+=incr; nDigit++;
z++; nDigit++;
if( s>=((LARGEST_INT64-9)/10) ){
/* skip non-significant significand digits
** (increase exponent by d to shift decimal left) */
while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
while( sqlite3Isdigit(*z) ){ z++; d++; }
}
}
if( z>=zEnd ) goto do_atof_calc;
/* if decimal point is present */
if( *z=='.' ){
z+=incr;
z++;
eType++;
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
while( z<zEnd && sqlite3Isdigit(*z) ){
while( sqlite3Isdigit(*z) ){
if( s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
d--;
nDigit++;
}
z+=incr;
z++;
}
}
if( z>=zEnd ) goto do_atof_calc;
/* if exponent is present */
if( *z=='e' || *z=='E' ){
z+=incr;
eValid = 0;
int esign = 1; /* sign of exponent */
z++;
eType++;
/* This branch is needed to avoid a (harmless) buffer overread. The
** special comment alerts the mutation tester that the correct answer
** is obtained even if the branch is omitted */
if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
/* get sign of exponent */
if( *z=='-' ){
esign = -1;
z+=incr;
z++;
}else if( *z=='+' ){
z+=incr;
z++;
}
/* copy digits to exponent */
while( z<zEnd && sqlite3Isdigit(*z) ){
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
z+=incr;
eValid = 1;
if( sqlite3Isdigit(*z) ){
int exp = *z - '0';
z++;
while( sqlite3Isdigit(*z) ){
exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000;
z++;
}
d += esign*exp;
}else{
eType = -1;
}
}
/* skip trailing spaces */
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
while( sqlite3Isspace(*z) ) z++;
do_atof_calc:
/* Zero is a special case */
if( s==0 ){
*pResult = sign<0 ? -0.0 : +0.0;
goto atof_return;
*pResult = neg ? -0.0 : +0.0;
}else{
*pResult = sqlite3Fp10Convert2(s,d);
if( neg ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
}
/* adjust exponent by d, and update sign */
e = (e*esign) + d;
*pResult = sqlite3Fp10Convert2(s,e);
if( sign<0 ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
atof_return:
/* return true if number and no extra non-whitespace characters after */
if( z==zEnd && nDigit>0 && eValid && eType>0 ){
if( z[0]==0 && nDigit>0 ){
return eType;
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
}else if( eType>=2 && nDigit>0 ){
return -1;
}else{
return 0;
}
#else
return !sqlite3Atoi64(z, pResult, length, enc);
return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
#if defined(_MSC_VER)
#pragma warning(default : 4756)
#endif
/*
** Digit pairs used to convert a U64 or I64 into text, two digits
** at a time.
*/
static const union {
char a[201];
short int forceAlignment;
} sqlite3DigitPairs = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
/*
** Render an signed 64-bit integer as text. Store the result in zOut[] and
** return the length of the string that was stored, in bytes. The value
@@ -882,23 +876,35 @@ atof_return:
int sqlite3Int64ToText(i64 v, char *zOut){
int i;
u64 x;
char zTemp[22];
if( v<0 ){
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}else{
union {
char a[23];
u16 forceAlignment;
} u;
if( v>0 ){
x = v;
}else if( v==0 ){
zOut[0] = '0';
zOut[1] = 0;
return 1;
}else{
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}
i = sizeof(zTemp)-2;
zTemp[sizeof(zTemp)-1] = 0;
while( 1 /*exit-by-break*/ ){
zTemp[i] = (x%10) + '0';
x = x/10;
if( x==0 ) break;
i--;
};
if( v<0 ) zTemp[--i] = '-';
memcpy(zOut, &zTemp[i], sizeof(zTemp)-i);
return sizeof(zTemp)-1-i;
i = sizeof(u.a)-1;
u.a[i] = 0;
while( x>=10 ){
int kk = (x%100)*2;
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) );
*(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
x /= 100;
}
if( x ){
u.a[--i] = x + '0';
}
if( v<0 ) u.a[--i] = '-';
memcpy(zOut, &u.a[i], sizeof(u.a)-i);
return sizeof(u.a)-1-i;
}
/*
@@ -1155,7 +1161,7 @@ int sqlite3Atoi(const char *z){
** representation.
**
** If iRound<=0 then round to -iRound significant digits to the
** the left of the decimal point, or to a maximum of mxRound total
** the right of the decimal point, or to a maximum of mxRound total
** significant digits.
**
** If iRound>0 round to min(iRound,mxRound) significant digits total.
@@ -1168,12 +1174,14 @@ int sqlite3Atoi(const char *z){
** The p->z[] array is *not* zero-terminated.
*/
void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
int i;
u64 v;
int e, exp = 0;
int i; /* Index into zBuf[] where to put next character */
int n; /* Number of digits */
u64 v; /* mantissa */
int e, exp = 0; /* Base-2 and base-10 exponent */
char *zBuf; /* Local alias for p->zBuf */
char *z; /* Local alias for p->z */
p->isSpecial = 0;
p->z = p->zBuf;
assert( mxRound>0 );
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
@@ -1196,67 +1204,89 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
p->n = 0;
p->iDP = 0;
p->z = p->zBuf;
return;
}
v &= 0x000fffffffffffffULL;
if( e==0 ){
int n = countLeadingZeros(v);
v <<= n;
e = -1074 - n;
int nn = countLeadingZeros(v);
v <<= nn;
e = -1074 - nn;
}else{
v = (v<<11) | U64_BIT(63);
e -= 1086;
}
sqlite3Fp2Convert10(v, e, 17, &v, &exp);
sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp);
/* Extract significant digits. */
/* Extract significant digits, start at the right-most slot in p->zBuf
** and working back to the right. "i" keeps track of the next slot in
** which to store a digit. */
i = sizeof(p->zBuf)-1;
zBuf = p->zBuf;
assert( v>0 );
while( v>=10 ){
static const union {
char a[200];
short int forAlignment;
} dig = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
int kk = (v%100)*2;
assert( TWO_BYTE_ALIGNMENT(&dig.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&p->zBuf[i-1]) );
*(u16*)(&p->zBuf[i-1]) = *(u16*)&dig.a[kk];
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) );
*(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
v /= 100;
}
if( v ){
assert( v<10 );
p->zBuf[i--] = v + '0';
zBuf[i--] = v + '0';
}
assert( i>=0 && i<sizeof(p->zBuf)-1 );
p->n = sizeof(p->zBuf) - 1 - i;
assert( p->n>0 );
assert( p->n<sizeof(p->zBuf) );
p->iDP = p->n + exp;
n = sizeof(p->zBuf) - 1 - i; /* Total number of digits extracted */
assert( n>0 );
assert( n<sizeof(p->zBuf) );
testcase( n==sizeof(p->zBuf)-1 );
p->iDP = n + exp;
if( iRound<=0 ){
iRound = p->iDP - iRound;
if( iRound==0 && p->zBuf[i+1]>='5' ){
if( iRound==0 && zBuf[i+1]>='5' ){
iRound = 1;
p->zBuf[i--] = '0';
p->n++;
zBuf[i--] = '0';
n++;
p->iDP++;
}
}
if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
char *z = &p->zBuf[i+1];
z = &zBuf[i+1]; /* z points to the first digit */
if( iRound>0 && (iRound<n || n>mxRound) ){
if( iRound>mxRound ) iRound = mxRound;
p->n = iRound;
if( iRound==17 ){
/* If the precision is exactly 17, which only happens with the "!"
** flag (ex: "%!.17g") then try to reduce the precision if that
** yields text that will round-trip to the original floating-point.
** value. Thus, for exaple, 49.47 will render as 49.47, rather than
** as 49.469999999999999. */
if( z[15]=='9' && z[14]=='9' ){
int jj, kk;
u64 v2;
for(jj=14; jj>0 && z[jj-1]=='9'; jj--){}
if( jj==0 ){
v2 = 1;
}else{
v2 = z[0] - '0';
for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0';
v2++;
}
if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){
iRound = jj+1;
}
}else if( p->iDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){
int jj, kk;
u64 v2;
assert( z[0]!='0' );
for(jj=14; z[jj-1]=='0'; jj--){}
v2 = z[0] - '0';
for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0';
if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){
iRound = jj+1;
}
}
}
n = iRound;
if( z[iRound]>='5' ){
int j = iRound-1;
while( 1 /*exit-by-break*/ ){
@@ -1264,8 +1294,9 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
if( z[j]<='9' ) break;
z[j] = '0';
if( j==0 ){
p->z[i--] = '1';
p->n++;
z--;
z[0] = '1';
n++;
p->iDP++;
break;
}else{
@@ -1274,13 +1305,13 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
}
}
}
p->z = &p->zBuf[i+1];
assert( i+p->n < sizeof(p->zBuf) );
assert( p->n>0 );
while( p->z[p->n-1]=='0' ){
p->n--;
assert( p->n>0 );
assert( n>0 );
while( z[n-1]=='0' ){
n--;
assert( n>0 );
}
p->n = n;
p->z = z;
}
/*
+5 -3
View File
@@ -353,10 +353,9 @@ static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue;
u8 enc = pRec->enc;
int rc;
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
rValue = sqlite3MemRealValueRC(pRec, &rc);
if( rc<=0 ) return;
if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
pRec->flags |= MEM_Int;
@@ -438,7 +437,10 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){
int eType = sqlite3_value_type(pVal);
if( eType==SQLITE_TEXT ){
Mem *pMem = (Mem*)pVal;
assert( pMem->db!=0 );
sqlite3_mutex_enter(pMem->db->mutex);
applyNumericAffinity(pMem, 0);
sqlite3_mutex_leave(pMem->db->mutex);
eType = sqlite3_value_type(pVal);
}
return eType;
@@ -471,7 +473,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
pMem->u.i = 0;
return MEM_Int;
}
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
pMem->u.r = sqlite3MemRealValueRC(pMem, &rc);
if( rc<=0 ){
if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
pMem->u.i = ix;
+2 -1
View File
@@ -649,13 +649,14 @@ int sqlite3VdbeMemSetZeroBlob(Mem*,int);
int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
int sqlite3VdbeMemSetRowSet(Mem*);
void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
int sqlite3VdbeMemZeroTerminateIfAble(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemStringify(Mem*, u8, u8);
int sqlite3IntFloatCompare(i64,double);
i64 sqlite3VdbeIntValue(const Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem*, int*);
int sqlite3VdbeBooleanValue(Mem*, int ifNull);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
+88 -23
View File
@@ -107,21 +107,27 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
StrAccum acc;
assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
assert( sz>22 );
if( p->flags & MEM_Int ){
#if GCC_VERSION>=7000000
/* Work-around for GCC bug
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
if( p->flags & (MEM_Int|MEM_IntReal) ){
#if GCC_VERSION>=7000000 && GCC_VERSION<15000000 && defined(__i386__)
/* Work-around for GCC bug or bugs:
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
** The problem appears to be fixed in GCC 15 */
i64 x;
assert( (p->flags&MEM_Int)*2==sizeof(x) );
memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
assert( (MEM_Str&~p->flags)*4==sizeof(x) );
memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4);
p->n = sqlite3Int64ToText(x, zBuf);
#else
p->n = sqlite3Int64ToText(p->u.i, zBuf);
#endif
if( p->flags & MEM_IntReal ){
memcpy(zBuf+p->n,".0", 3);
p->n += 2;
}
}else{
sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
sqlite3_str_appendf(&acc, "%!.15g",
(p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
sqlite3_str_appendf(&acc, "%!.*g",
(p->db ? p->db->nFpDigit : 17), p->u.r);
assert( acc.zText==zBuf && acc.mxAlloc<=0 );
zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
p->n = acc.nChar;
@@ -170,6 +176,9 @@ int sqlite3VdbeMemValidStrRep(Mem *p){
assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
}
if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
if( p->db==0 ){
return 1; /* db->nFpDigit required to validate p->z[] */
}
memcpy(&tmp, p, sizeof(tmp));
vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp);
z = p->z;
@@ -320,13 +329,16 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
**
** This is an optimization. Correct operation continues even if
** this routine is a no-op.
**
** Return true if the strig is zero-terminated after this routine is
** called and false if it is not.
*/
void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){
/* pMem must be a string, and it cannot be an ephemeral or static string */
return;
return 0;
}
if( pMem->enc!=SQLITE_UTF8 ) return;
if( pMem->enc!=SQLITE_UTF8 ) return 0;
assert( pMem->z!=0 );
if( pMem->flags & MEM_Dyn ){
if( pMem->xDel==sqlite3_free
@@ -334,18 +346,19 @@ void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
return;
return 1;
}
if( pMem->xDel==sqlite3RCStrUnref ){
/* Blindly assume that all RCStr objects are zero-terminated */
pMem->flags |= MEM_Term;
return;
return 1;
}
}else if( pMem->szMalloc >= pMem->n+1 ){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
return;
return 1;
}
return 0;
}
/*
@@ -643,18 +656,70 @@ i64 sqlite3VdbeIntValue(const Mem *pMem){
}
}
/*
** Invoke sqlite3AtoF() on the text value of pMem and return the
** double result. If sqlite3AtoF() returns an error code, write
** that code into *pRC if (*pRC)!=NULL.
**
** The caller must ensure that pMem->db!=0 and that pMem is in
** mode MEM_Str or MEM_Blob.
*/
SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem *pMem, int *pRC){
double val = (double)0;
int rc = 0;
assert( pMem->db!=0 );
assert( pMem->flags & (MEM_Str|MEM_Blob) );
if( pMem->z==0 ){
/* no-op */
}else if( pMem->enc==SQLITE_UTF8
&& ((pMem->flags & MEM_Term)!=0 || sqlite3VdbeMemZeroTerminateIfAble(pMem))
){
rc = sqlite3AtoF(pMem->z, &val);
}else if( pMem->n==0 ){
/* no-op */
}else if( pMem->enc==SQLITE_UTF8 ){
char *zCopy = sqlite3DbStrNDup(pMem->db, pMem->z, pMem->n);
if( zCopy ){
rc = sqlite3AtoF(zCopy, &val);
sqlite3DbFree(pMem->db, zCopy);
}
}else{
int n, i, j;
char *zCopy;
const char *z;
n = pMem->n & ~1;
zCopy = sqlite3DbMallocRaw(pMem->db, n/2 + 2);
if( zCopy ){
z = pMem->z;
if( pMem->enc==SQLITE_UTF16LE ){
for(i=j=0; i<n-1; i+=2, j++){
zCopy[j] = z[i];
if( z[i+1]!=0 ) break;
}
}else{
for(i=j=0; i<n-1; i+=2, j++){
if( z[i]!=0 ) break;
zCopy[j] = z[i+1];
}
}
assert( j<=n/2 );
zCopy[j] = 0;
rc = sqlite3AtoF(zCopy, &val);
if( i<n ) rc = -100;
sqlite3DbFree(pMem->db, zCopy);
}
}
if( pRC ) *pRC = rc;
return val;
}
/*
** Return the best representation of pMem that we can get into a
** double. If pMem is already a double or an integer, return its
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
static SQLITE_NOINLINE double memRealValue(Mem *pMem){
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
double val = (double)0;
sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
return val;
}
double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -665,7 +730,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
testcase( pMem->flags & MEM_IntReal );
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
return memRealValue(pMem);
return sqlite3MemRealValueRC(pMem, 0);
}else{
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return (double)0;
@@ -789,7 +854,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
pMem->u.r = sqlite3MemRealValueRC(pMem, &rc);
if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
|| sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
){
@@ -1760,7 +1825,7 @@ static int valueFromExpr(
if( affinity==SQLITE_AFF_BLOB ){
if( op==TK_FLOAT ){
assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) );
sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8);
sqlite3AtoF(pVal->z, &pVal->u.r);
pVal->flags = MEM_Real;
}else if( op==TK_INTEGER ){
/* This case is required by -9223372036854775808 and other strings
+76 -61
View File
@@ -2254,68 +2254,82 @@ static int walCheckpoint(
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
){
u32 nBackfill = pInfo->nBackfill;
pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
WalIndexHdr *pLive = (WalIndexHdr*)walIndexHdr(pWal);
/* Sync the WAL to disk */
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
/* If the database may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
*/
if( rc==SQLITE_OK ){
i64 nReq = ((i64)mxPage * szPage);
i64 nSize; /* Current size of database file */
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)<nReq ){
/* If the size of the final database is larger than the current
** database plus the amount of data in the wal file, plus the
** maximum size of the pending-byte page (65536 bytes), then
** must be corruption somewhere. */
rc = SQLITE_CORRUPT_BKPT;
}else{
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq);
}
}
}
/* Iterate through the contents of the WAL, copying data to the db file */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
SEH_INJECT_FAULT;
if( AtomicLoad(&db->u1.isInterrupted) ){
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
break;
}
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
continue;
}
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
iOffset = (iDbpage-1)*(i64)szPage;
testcase( IS_BIG_INT(iOffset) );
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
i64 szDb = pWal->hdr.nPage*(i64)szPage;
testcase( IS_BIG_INT(szDb) );
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
if( rc==SQLITE_OK ){
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
}
}
/* Now that read-lock slot 0 is locked, check that the wal has not been
** wrapped since the header was read for this checkpoint. If it was, then
** there was no work to do anyway. In this case the
** (pInfo->nBackfill<pWal->hdr.mxFrame) test above only passed because
** pInfo->nBackfill had already been set to 0 by the writer that wrapped
** the wal file. It would also be dangerous to proceed, as there may be
** fewer than pWal->hdr.mxFrame valid frames in the wal file. */
int bChg = memcmp(pLive->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt));
if( 0==bChg ){
pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
/* Sync the WAL to disk */
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
/* If the database may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
*/
if( rc==SQLITE_OK ){
AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
i64 nReq = ((i64)mxPage * szPage);
i64 nSize; /* Current size of database file */
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)<nReq ){
/* If the size of the final database is larger than the current
** database plus the amount of data in the wal file, plus the
** maximum size of the pending-byte page (65536 bytes), then
** must be corruption somewhere. */
rc = SQLITE_CORRUPT_BKPT;
}else{
sqlite3OsFileControlHint(
pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
}
}
}
/* Iterate through the contents of the WAL, copying data to the
** db file */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
SEH_INJECT_FAULT;
if( AtomicLoad(&db->u1.isInterrupted) ){
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
break;
}
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
continue;
}
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
iOffset = (iDbpage-1)*(i64)szPage;
testcase( IS_BIG_INT(iOffset) );
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
i64 szDb = pWal->hdr.nPage*(i64)szPage;
testcase( IS_BIG_INT(szDb) );
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
if( rc==SQLITE_OK ){
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
}
}
if( rc==SQLITE_OK ){
AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
}
}
}
@@ -4362,9 +4376,10 @@ int sqlite3WalCheckpoint(
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
}
}
/* Copy data from the log to the database file. */
if( rc==SQLITE_OK ){
sqlite3FaultSim(660);
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
}else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){
+1 -1
View File
@@ -3182,7 +3182,7 @@ static int whereRangeVectorLen(
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
if( aff!=idxaff ) break;
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
if( pColl==0 ) break;
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
}
+3 -2
View File
@@ -293,13 +293,14 @@ static int isLikeOrGlob(
){
int isNum;
double rDummy;
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
assert( zNew[iTo]==0 );
isNum = sqlite3AtoF(zNew, &rDummy);
if( isNum<=0 ){
if( iTo==1 && zNew[0]=='-' ){
isNum = +1;
}else{
zNew[iTo-1]++;
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
isNum = sqlite3AtoF(zNew, &rDummy);
zNew[iTo-1]--;
}
}
+35
View File
@@ -0,0 +1,35 @@
# 2026-02-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.
#
#***********************************************************************
#
# Tests of the sqlite3AtoF() function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Rounding cases:
#
do_execsql_test atof2-1.0 {
SELECT format('%g',192.496475);
} 192.496
do_execsql_test atof2-1.1 {
SELECT format('%g',192.496501);
} 192.497
load_static_extension db ieee754
do_execsql_test atof2-2.1 {
SELECT format('%!.30f',ieee754_inc(100.0,-1));
} 99.9999999999999858
do_execsql_test atof2-2.2 {
SELECT format('%!.30f',ieee754_inc(100.0,-2));
} 99.9999999999999716
finish_test
+1 -1
View File
@@ -34,7 +34,7 @@ proc vtab_command {method args} {
set orderby [$hdl orderby]
if {[info exists ::xbestindex_sql]} {
explain_i $::xbestindex_sql
# explain_i $::xbestindex_sql
set ::xbestindex_res [ execsql $::xbestindex_sql ]
}
+4 -4
View File
@@ -1744,10 +1744,10 @@ do_execsql_test e_expr-32.2.8 {
integer 9223372036854775807 \
integer 9223372036854775807 \
integer 9223372036854775807 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
real 9.2233720368547758e+18 \
real 9.2233720368547758e+18 \
real 9.2233720368547758e+18 \
real 9.2233720368547758e+18 \
integer -5 \
integer -5 \
]
+60 -6
View File
@@ -17,28 +17,82 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Unusual rendering cases:
#
do_execsql_test fpconv1-1.0 {
SELECT 1.23 - 2.34;
} {-1.1099999999999999}
# ^--- Not -1.11 as you would expect. -1.11 has a different bit pattern
do_execsql_test fpconv1-1.1 {
SELECT 1.23 * 2.34;
} {2.8781999999999996}
# ^--- Not 2.8782 as you would expect. 2.8782 has a different bit pattern
# Change significant digits to 15 and get a different result.
sqlite3_db_config db FP_DIGITS 15
do_execsql_test fpconv1-1.2 {
SELECT 1.23 - 2.34;
} {-1.11}
do_execsql_test fpconv1-1.3 {
SELECT 1.23 * 2.34;
} {2.8782}
sqlite3_db_config db FP_DIGITS 17
if {[catch {load_static_extension db decimal} error]} {
puts "Skipping decimal tests, hit load error: $error"
finish_test; return
}
sqlite3_create_function db
do_execsql_test fpconv1-1.0 {
do_execsql_test fpconv1-2.0 {
WITH RECURSIVE
/* Number of random floating-point values to try.
** On a circa 2016 x64 linux box, this test runs at
** about 80000 cases per second -------------------vvvvvv */
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100000),
** On a circa 2021 Ryzen 5950X running Mint Linux, and
** compiled with -O0 -DSQLITE_DEBUG, this test runs at
** about 150000 cases per second ------------------vvvvvvv */
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<500_000),
fp(y) AS MATERIALIZED (
SELECT CAST( format('%+d.%019d0e%+03d',
random()%10,abs(random()),random()%200) AS real)
FROM c
)
SELECT y FROM fp
WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<15.0;
WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<17.0;
/* Number of digits of accuracy required -------^^^^ */
} {}
# ^---- Expect a empty set as the result. The output is all tested numbers
# that fail to preserve at least 15 significant digits of accuracy.
# that fail to preserve at least 16 significant digits of accuracy.
########################################################################
# Random test to ensure that double -> text -> double conversions
# round-trip exactly.
#
load_static_extension db ieee754
do_execsql_test fpconv1-3.0 {
WITH RECURSIVE
c(x,s) AS MATERIALIZED (VALUES(1,random()&0xffefffffffffffff)
UNION ALL
SELECT x+1,random()&0xffefffffffffffff
FROM c WHERE x<1_000_000),
fp(y,s) AS (
SELECT ieee754_from_int(s),s FROM c
),
fp2(yt,y,s) AS (
SELECT y||'', y, s FROM fp
)
SELECT format('%#016x',s) aS 'orig-hex',
format('%#016x',ieee754_to_int(CAST(yt AS real))) AS 'full-roundtrip',
yt AS 'rendered-as',
decimal_exp(yt,30) AS 'text-decimal',
decimal_exp(ieee754_from_int(s),30) AS 'float-decimal'
FROM fp2
WHERE ieee754_to_int(CAST(yt AS real))<>s;
} {}
# ^---- Values that fail to round-trip will be reported
finish_test
+76
View File
@@ -0,0 +1,76 @@
#!sqlite3
#
# 2026-03-01
#
# 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.
#
#***********************************************************************
#
# Floating-point to text conversions
#
# Verify that binary64 -> text -> binary64 conversions round-trip
# successfully for 98,256 different edge-case binary64 values. The
# query result is all cases that do not round-trip without change,
# and so the query result should be an empty set.
#
.testcase 100
.mode list
WITH
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<15),
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
i3(k) AS (VALUES(0x0000000000000000),
(0x000ffffffffffff0),
(0x0008080808080800)),
fpint(n) AS (SELECT (j<<52)+i+k FROM i2, i1, i3),
fp(n,r) AS (SELECT n, ieee754_from_int(n) FROM fpint)
SELECT n, r FROM fp WHERE r<>(0.0 + (r||''));
.check ''
# Another batch of 106,444 edge cases: All postiive floating point
# values that have only a single bit set in the mantissa part of the
# number.
#
.testcase 110
WITH
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<51),
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
fpint(n) AS (SELECT (j<<52)+(1<<i) FROM i2, i1),
fp(n,r) AS (SELECT n, ieee754_from_int(n) FROM fpint)
SELECT n, r FROM fp WHERE r<>(0.0 + (r||''));
.check ''
# Verify that text -> binary64 conversions agree with system strtod().
# for 98,256 different edge-cases.
#
.testcase 200
.mode list
WITH
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<15),
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
i3(k) AS (VALUES(0x0000000000000000),
(0x000ffffffffffff0),
(0x0008080808080800)),
fpint(n) AS (SELECT (j<<52)+i+k FROM i2, i1, i3),
fp(r) AS (SELECT ieee754_from_int(n) FROM fpint)
SELECT r FROM fp WHERE r<>strtod(r||'');
.check ''
# Another batch of 106,444 edge cases: All postiive floating point
# values that have only a single bit set in the mantissa part of the
# number.
#
.testcase 210
WITH
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<51),
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
fpint(n) AS (SELECT (j<<52)+(1<<i) FROM i2, i1),
fp(r) AS (SELECT ieee754_from_int(n) FROM fpint)
SELECT r FROM fp WHERE r<>strtod(r||'');
.check ''
+23
View File
@@ -0,0 +1,23 @@
#!sqlite3
#
# 2026-03-01
#
# 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.
#
#***********************************************************************
#
# Bug report sqlite.org/forum/forumpost/efc9bc9cb3
#
.testcase 100
.mode quote
.intck 1
SELECT parse_create_index('CREATE IDEX i ON t("x',0);
.check <<END
1 steps, 0 errors
NULL
END
+47
View File
@@ -121,5 +121,52 @@ do_execsql_test 5.1 {
INNER JOIN child2 ON child2.child2key = parent1.child2key;
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
CREATE TABLE t5(a, d);
CREATE TABLE t6(a, e);
INSERT INTO t5 VALUES(1, 'red');
INSERT INTO t6 VALUES(0, 1000);
CREATE TABLE t7(x);
CREATE TABLE t8(y);
}
do_catchsql_test 6.1 {
SELECT * FROM t6 CROSS JOIN (t7 RIGHT JOIN t8 ON (t6.a));
} {1 {no such column: t6.a}}
do_catchsql_test 6.4 {
SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6;
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.5 {
SELECT * FROM
(SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6);
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.6 {
SELECT *, NOT EXISTS (
SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
) FROM t5;
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.7 {
SELECT *, NOT EXISTS (
SELECT 1
EXCEPT
SELECT 11 FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
) FROM t5;
} {1 {ON clause references tables to its right}}
do_catchsql_test 6.8 {
SELECT *, NOT EXISTS (
SELECT 11 FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
EXCEPT
SELECT 1
) FROM t5;
} {1 {ON clause references tables to its right}}
finish_test
+16 -10
View File
@@ -115,6 +115,10 @@ ifcapable threadsafe1&&shared_cache {
}
} {
ifcapable thread_misuse_warnings {
if {$mode ne "serialized"} continue
}
# For journal_mode=memory, the static_prng mutex is not required. This
# is because the header of an in-memory journal does not contain
# any random bytes, and so no call to sqlite3_randomness() is made.
@@ -177,16 +181,18 @@ ifcapable threadsafe1&&shared_cache {
# Open and use a connection in "nomutex" mode. Test that no recursive
# mutexes are obtained.
do_test mutex1.3.1 {
catch {db close}
clear_mutex_counters
sqlite3 db test.db -nomutex 1
execsql { SELECT * FROM abc }
} {1 2 3 1 2 3 1 2 3}
do_test mutex1.3.2 {
mutex_counters counters
set counters(recursive)
} {0}
ifcapable !thread_misuse_warnings {
do_test mutex1.3.1 {
catch {db close}
clear_mutex_counters
sqlite3 db test.db -nomutex 1
execsql { SELECT * FROM abc }
} {1 2 3 1 2 3 1 2 3}
do_test mutex1.3.2 {
mutex_counters counters
set counters(recursive)
} {0}
}
}
# Test the sqlite3_db_mutex() function.
+8 -8
View File
@@ -697,13 +697,13 @@ do_test 5.2b {
mtime: 1333101221
datetime(...: 2012-03-30 09:53:41
value: x'cc7c57616c706861b535332e31313638383732334762
657461c73071726657696474685072696e7428702c2070
2d3e704f75742c202d702d3e752e734c696e652e6d7843
...
657461c73071726657696474685072696e7428702c2070
2d3e704f75742c202d702d3e752e734c696e652e6d7843
...
name: one
two
three
two
three
mtime: 1333206973
datetime(...: 2012-03-31 15:16:13
value:
@@ -712,9 +712,9 @@ datetime(...: 2012-03-31 15:16:13
mtime: 1708791504
datetime(...: 2024-02-24 16:18:24
value: x'00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000
...
0000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000
...
}
set sql "SELECT name, mtime, datetime(mtime,'unixepoch') AS time,\
value FROM t1 ORDER BY mtime"
+25
View File
@@ -73,4 +73,29 @@ do_catchsql_test 2.3 {
SELECT 2 IN ( (1, 2), (3, 4), (5, 6) )
} {1 {row value misused}}
#-------------------------------------------------------------------------
# Test the fix for forum post https://sqlite.org/forum/forumpost/6ceca07fc3
#
do_execsql_test 3.0 {
CREATE TABLE x2 (x, y);
INSERT INTO x2 VALUES (1234, 'abc');
CREATE TABLE x1 (a, b PRIMARY KEY COLLATE NOCASE) WITHOUT ROWID;
INSERT INTO x1 VALUES (1234, 'ABCD');
}
do_execsql_test 3.1 {
SELECT * FROM x2 CROSS JOIN x1 WHERE (1234, x2.y) > (x1.a, x1.b);
} {1234 abc 1234 ABCD}
do_execsql_test 3.2 {
CREATE INDEX x1a ON x1(a);
}
do_execsql_test 3.3 {
SELECT * FROM x2 CROSS JOIN x1 WHERE (1234, x2.y) > (x1.a, x1.b);
} {1234 abc 1234 ABCD}
finish_test
+2
View File
@@ -1121,6 +1121,7 @@ do_test shell1-4.7 {
# Test using arbitrary byte data with the shell via standard input/output.
#
if 0 { # Causes a valgrind error in TCL. Seems to be a TCL problem.
do_test shell1-5.0 {
#
# NOTE: Skip NUL byte because it appears to be incompatible with command
@@ -1187,6 +1188,7 @@ do_test shell1-5.0 {
}
}
} {}
}
# These test cases do not work on MinGW
if 0 {
+40
View File
@@ -217,6 +217,46 @@ if {$tcl_platform(platform)=="unix"} {
do_test 3.3 {
catchcmd shell8.db {.ar -x}
} {0 {}}
# Test defenses against using symlinks to write outside
# of the destination directory. See forum thread at
# sqlite.org/forum/forumpost/2026-02-21T11:04:36z
#
forcedelete shell8.db
forcedelete ar1
forcedelete ar2
forcedelete ar3
file mkdir ar2
file mkdir ar3
set pwd [pwd]
sqlite3 db shell8.db
db eval {
CREATE TABLE sqlar(
name TEXT PRIMARY KEY, -- name of the file
mode INT, -- access permissions
mtime INT, -- last modification time
sz INT, -- original file size
data BLOB -- compressed content
);
INSERT INTO sqlar VALUES
('abc',33188,0,-1,'content for abc'),
('escape',40960,0,-1,$pwd||'/ar3'),
('escape/def',33188,0,-1,'content for escape/def'),
('ghi',33188,0,-1,'content for ghi');
}
do_test 3.4.1 {
catchcmd shell8.db {.ar -x --directory ar2}
lsort [glob -tails -directory ar2 -nocomplain *]
} {abc escape ghi}
do_test 3.4.2 {
lsort [glob -tails -directory ar3 -nocomplain *]
} {}
# ^^--- An extraction into ar2 should not leak any files into ar3
forcedelete shell8.db
forcedelete ar2
forcedelete ar3
}
finish_test
+2
View File
@@ -46,6 +46,8 @@ do_clitest imposter1.sql
do_clitest dotcmd01.sql
ifcapable vtab {
do_clitest import01.sql
do_clitest intck01.sql
}
do_clitest fptest01.sql
finish_test
+1
View File
@@ -192,6 +192,7 @@ namespace eval trd {
-DSQLITE_ENABLE_HIDDEN_COLUMNS
-DSQLITE_MAX_ATTACHED=125
-DSQLITE_MUTATION_TEST
-DSQLITE_THREAD_MISUSE_ABORT
--enable-fts5
}
set build(Debug-Two) {
+3 -3
View File
@@ -21,9 +21,9 @@ do_execsql_test 1.0 {
}
explain_i {
INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
}
#explain_i {
# INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
#}
do_execsql_test 1.1.1 {
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
}
+87
View File
@@ -0,0 +1,87 @@
# 2026-03-03
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing a race condition in WAL restart.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$::tcl_platform(platform) ne "unix"} {
# This test only works on unix
finish_test
return
}
set testprefix walrestart
if {[permutation]=="memsubsys1"} {
# memsubsys1 configures a very small page-cache, which causes different
# numbers of frames to be written to the wal file for some transactions,
# which causes some of the tests in this file to fail.
finish_test
return
}
db close
sqlite3_shutdown
proc faultsim {n} { return 0 }
sqlite3_test_control_fault_install faultsim
# Populate database. Create a large wal file and checkpoint it.
#
reset_db
do_execsql_test 1.0 {
PRAGMA auto_vacuum = 0;
PRAGMA journal_mode = wal;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<20
)
INSERT INTO t1 SELECT NULL, randomblob(600) FROM s;
CREATE INDEX i1 ON t1(b);
PRAGMA wal_checkpoint;
} {wal 0 49 49}
do_execsql_test 1.1 {
UPDATE t1 SET b=randomblob(600);
PRAGMA wal_checkpoint;
} {0 45 45}
# We have a completely checkpointed wal file on disk. mxFrame=$large,
# nBackfill=$large. Do another checkpoint with [db]. This time, after [db]
# reads mxFrame but before it reads nBackfill, write to the db such
# that 0 < mxFrame < large.
#
proc faultsim {n} {
if {$n==660} {
db2 eval { UPDATE t1 SET b=randomblob(600) WHERE a<5 }
}
return 0
}
sqlite3 db2 test.db
do_execsql_test 1.2 {
PRAGMA wal_checkpoint;
} {0 45 0}
# Now write another big update to the wal file and checkpoint it.
#
do_execsql_test -db db2 1.3 {
UPDATE t1 SET b=randomblob(600);
}
proc faultsim {n} { return 0 }
do_execsql_test 1.4 {
PRAGMA wal_checkpoint;
} {0 58 58}
do_catchsql_test 1.5 {
PRAGMA integrity_check
} {0 ok}
finish_test
+15
View File
@@ -302,4 +302,19 @@ do_execsql_test 7.1 {
SELECT length(name) FROM t1;
} {60000}
# https://sqlite.org/forum/forumpost/721a05d2c5
#
if {[catch { load_static_extension db fileio }]==0} {
forcedelete test.zip
set fd [open test.zip wb]
fconfigure $fd -translation binary
puts -nonewline $fd [db one {SELECT X'504b0506000000000100010030000000160000000000504b01021400140000000000000000000000000000000000000000000100010000000000000000000000000000006100'}]
close $fd
do_catchsql_test 8.0 {
SELECT name,sz FROM zipfile(readfile('test.zip'));
} {1 {failed to read LFH at offset 0}}
}
finish_test
+1 -1
View File
@@ -123,7 +123,6 @@ set CompileOptionsToTest {
SQLITE_ENABLE_MEMSYS
SQLITE_ENABLE_MODULE_COMMENTS
SQLITE_ENABLE_MULTIPLEX
SQLITE_ENABLE_MULTITHREADED_CHECKS
SQLITE_ENABLE_NORMALIZE
SQLITE_ENABLE_NULL_TRIM
SQLITE_ENABLE_OFFSET_SQL_FUNC
@@ -152,6 +151,7 @@ set CompileOptionsToTest {
SQLITE_ENABLE_VFSTRACE
SQLITE_ENABLE_WHERETRACE
SQLITE_ENABLE_ZIPVFS
SQLITE_THREAD_MISUSE_WARNINGS
}
# Parse command-line options.
+20 -17
View File
@@ -28,6 +28,9 @@
#include "sqlite3.h"
#include "sqlite3_stdio.h"
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
/*
** All global variables are gathered into the "g" singleton.
*/
@@ -202,12 +205,12 @@ static char **columnNames(
int *pbRowid /* OUT: True if PK is an implicit rowid */
){
char **az = 0; /* List of column names to be returned */
int naz = 0; /* Number of entries in az[] */
i64 naz = 0; /* Number of entries in az[] */
sqlite3_stmt *pStmt; /* SQL statement being run */
char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */
int truePk = 0; /* PRAGMA table_info identifies the PK to use */
int nPK = 0; /* Number of PRIMARY KEY columns */
int i, j; /* Loop counters */
i64 nPK = 0; /* Number of PRIMARY KEY columns */
i64 i, j; /* Loop counters */
if( g.bSchemaPK==0 ){
/* Normal case: Figure out what the true primary key is for the table.
@@ -271,7 +274,7 @@ static char **columnNames(
}
*pnPKey = nPK;
naz = nPK;
az = sqlite3_malloc( sizeof(char*)*(nPK+1) );
az = sqlite3_malloc64( sizeof(char*)*(nPK+1) );
if( az==0 ) runtimeError("out of memory");
memset(az, 0, sizeof(char*)*(nPK+1));
if( g.bSchemaCompare ){
@@ -288,7 +291,7 @@ static char **columnNames(
|| !(strcmp(sid,"rootpage")==0
||strcmp(sid,"name")==0
||strcmp(sid,"type")==0)){
az = sqlite3_realloc(az, sizeof(char*)*(naz+2) );
az = sqlite3_realloc64(az, sizeof(char*)*(naz+2) );
if( az==0 ) runtimeError("out of memory");
az[naz++] = sid;
}
@@ -954,7 +957,7 @@ static int rbuDeltaCreate(
unsigned int i, base;
char *zOrigDelta = zDelta;
hash h;
int nHash; /* Number of hash table entries */
i64 nHash; /* Number of hash table entries */
int *landmark; /* Primary hash table */
int *collide; /* Collision chain */
int lastRead = -1; /* Last byte of zSrc read by a COPY command */
@@ -982,7 +985,7 @@ static int rbuDeltaCreate(
** source file.
*/
nHash = lenSrc/NHASH;
collide = sqlite3_malloc( nHash*2*sizeof(int) );
collide = sqlite3_malloc64( nHash*2*sizeof(int) );
landmark = &collide[nHash];
memset(landmark, -1, nHash*sizeof(int));
memset(collide, -1, nHash*sizeof(int));
@@ -1286,9 +1289,9 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
}
}else{
char *zOtaControl;
int nOtaControl = sqlite3_column_bytes(pStmt, nCol);
i64 nOtaControl = sqlite3_column_bytes(pStmt, nCol);
zOtaControl = (char*)sqlite3_malloc(nOtaControl+1);
zOtaControl = (char*)sqlite3_malloc64(nOtaControl+1);
memcpy(zOtaControl, sqlite3_column_text(pStmt, nCol), nOtaControl+1);
for(i=0; i<nCol; i++){
@@ -1300,11 +1303,11 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
const char *aSrc = sqlite3_column_blob(pStmt, nCol+1+i);
int nSrc = sqlite3_column_bytes(pStmt, nCol+1+i);
const char *aFinal = sqlite3_column_blob(pStmt, i);
int nFinal = sqlite3_column_bytes(pStmt, i);
i64 nFinal = sqlite3_column_bytes(pStmt, i);
char *aDelta;
int nDelta;
aDelta = sqlite3_malloc(nFinal + 60);
aDelta = sqlite3_malloc64(nFinal + 60);
nDelta = rbuDeltaCreate(aSrc, nSrc, aFinal, nFinal, aDelta);
if( nDelta<nFinal ){
int j;
@@ -1549,10 +1552,10 @@ static void changeset_one_table(const char *zTab, FILE *out){
sqlite3_stmt *pStmt; /* SQL statment */
char *zId = safeId(zTab); /* Escaped name of the table */
char **azCol = 0; /* List of escaped column names */
int nCol = 0; /* Number of columns */
i64 nCol = 0; /* Number of columns */
int *aiFlg = 0; /* 0 if column is not part of PK */
int *aiPk = 0; /* Column numbers for each PK column */
int nPk = 0; /* Number of PRIMARY KEY columns */
i64 nPk = 0; /* Number of PRIMARY KEY columns */
sqlite3_str *pSql; /* SQL for the diff query */
int i, k; /* Loop counters */
const char *zSep; /* List separator */
@@ -1564,16 +1567,16 @@ static void changeset_one_table(const char *zTab, FILE *out){
pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
nCol++;
azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol);
azCol = sqlite3_realloc64(azCol, sizeof(char*)*nCol);
if( azCol==0 ) runtimeError("out of memory");
aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol);
aiFlg = sqlite3_realloc64(aiFlg, sizeof(int)*nCol);
if( aiFlg==0 ) runtimeError("out of memory");
azCol[nCol-1] = safeId((const char*)sqlite3_column_text(pStmt,1));
aiFlg[nCol-1] = i = sqlite3_column_int(pStmt,5);
if( i>0 ){
if( i>nPk ){
nPk = i;
aiPk = sqlite3_realloc(aiPk, sizeof(int)*nPk);
aiPk = sqlite3_realloc64(aiPk, sizeof(int)*nPk);
if( aiPk==0 ) runtimeError("out of memory");
}
aiPk[i-1] = nCol-1;
@@ -1913,7 +1916,7 @@ int main(int argc, char **argv){
FILE *out = stdout;
void (*xDiff)(const char*,FILE*) = diff_one_table;
#ifndef SQLITE_OMIT_LOAD_EXTENSION
int nExt = 0;
i64 nExt = 0;
char **azExt = 0;
#endif
int useTransaction = 0;