Compare commits

...

221 Commits

Author SHA1 Message Date
drh 55bcaf6829 Version 3.13.0
FossilOrigin-Name: fc49f556e48970561d7ab6a2f24fdd7d9eb81ff2
2016-05-18 10:57:30 +00:00
dan ee7de914d4 Do not run snapshot_fault.test as part of the inmemory_journal permutation.
FossilOrigin-Name: 995c084bde44e678facc5f5d95a2335ce61e57b0
2016-05-16 14:35:15 +00:00
drh 697c9eaa90 Disable shell.exe test cases for UTF8 filenames as they do not work on MinGW.
FossilOrigin-Name: 386bcbba8ed733ee84958e6bd6e9d33c150e6c18
2016-05-16 11:55:09 +00:00
drh 3b02a07e7d Improvements to a comment in the pcache.c file. No changes to code.
FossilOrigin-Name: b369980f0c4550a9034833caa2c7c85d6030f5ff
2016-05-13 17:22:33 +00:00
drh a0f6b124ad Remove the unused PGHDR_NEED_READ flag. Add invariant checking (during
SQLITE_DEBUG builds only) for the PgHdr object.

FossilOrigin-Name: 771c5411e9ebcad00fb4b97556b519488284b87b
2016-05-13 15:22:06 +00:00
drh 4bf7d21f56 Clarification of the pagerFlushOnCommit() logic.
FossilOrigin-Name: 3401d9dcdbec390564574e8d2972c944c204e025
2016-05-13 12:12:38 +00:00
drh 935c4d8484 Fix pager_end_transaction() to ensure that a ROLLBACK does not clobber
unwritten pages in a TEMP file pcache.

FossilOrigin-Name: 9495d33879221c1821331dc72c61a6a3d182f526
2016-05-13 11:50:00 +00:00
drh 7aeb216a19 Additional debugging and tracing logic for pcache.c, turned off by default
using an "#if 0".

FossilOrigin-Name: 32a62e3bd46cf58586617d3f8b1a971c91df205e
2016-05-13 04:24:25 +00:00
drh 5f65ff277d Disable ALWAYS and NEVER when compiled with SQLITE_MUTATION_TEST.
FossilOrigin-Name: 24d9fbc1d0f99b90577ecd6edcd3bc1abc76633f
2016-05-12 19:17:09 +00:00
drh a7a45973e9 Simplification of the sqlite3FaultSim() call inside of
sqlite3PagerCommitPhaseOne().

FossilOrigin-Name: 1b0f4cc362cda1dc175aa363ae4e612b7d1164c3
2016-05-12 19:05:35 +00:00
drh d22f5099b5 Add an assert in pager.c to confirm that pPager->tempFile is always true
for in-memory databases.

FossilOrigin-Name: 3fd71092063bf1d30e03cf2497ea9c57b3ec82eb
2016-05-12 18:38:45 +00:00
dan 82c0447701 Add extra OPTIMIZATION-IF-FALSE comments where required to pcache.c.
FossilOrigin-Name: 9d55b8f541de43deb82d460d32005fd62f5430b2
2016-05-12 17:06:04 +00:00
drh 91ef8ad42c For in-memory databases, it does not matter if pcache entries are marked
"clean" or "writable".

FossilOrigin-Name: 06c1e27ca868f247f8c27b03eb19aac004f28650
2016-05-12 12:08:48 +00:00
drh 42bee5f4d6 Remove an unnecessary call to sqlite3PcacheMakeClean() inside of the ROLLBACK
logic.

FossilOrigin-Name: 0dc50d9915cd88916229ca5c3834de82fa16f017
2016-05-12 12:01:20 +00:00
dan 613723d9fd Add a missing OPTIMIZATION-IF-FALSE comment to pcache.c.
FossilOrigin-Name: bc202e5b418d5a57bfc766883c4417c94829d96e
2016-05-12 09:48:23 +00:00
drh 72e6a39907 For in-memory databases, it does not matter if pcache entries are marked
"clean" or "writable".

FossilOrigin-Name: ad601c7962a60a11699cf31f1faee09b95d5c710
2016-05-11 23:54:14 +00:00
dan 401907e3ff Remove a redundant condition from pcache.c. Add an OPTIMIZATION-IF-TRUE comment to another condition that requires it.
FossilOrigin-Name: 3bfd2621d13b4f842f3af6d35519653f4eb8cad7
2016-05-11 20:03:23 +00:00
dan b2ef900ade Remove some a small amount of redundant code related to PCache.pSynced from pcache.c.
FossilOrigin-Name: 9cc8cad78fdfe044ad6726ebfe6909c1e242fa55
2016-05-11 15:41:15 +00:00
drh a37e0cfb22 Do not reset the page cache when a rollback journal truncate fails, as doing
so can cause loss of information for an in-memory TEMP file.

FossilOrigin-Name: 345ce1c9f64f2a424663b4dfcbe4586d9df7bff6
2016-05-11 12:47:46 +00:00
drh 65c6420335 Always truncate, rather than persist, the rollback journal of a TEMP database.
FossilOrigin-Name: 42fb6f1e99a6c31889819a0302679d598dc0ab1b
2016-05-11 11:04:17 +00:00
drh 5c8e092804 Add pcache tracing macros. Off by default. Requires changing an "#if 0"
and recompiling to enable.

FossilOrigin-Name: d9313d19c75a62f558b3df6b15595b15bbfa0b62
2016-05-11 10:57:04 +00:00
dan 78d1c90567 Add another test case to temptable3.test.
FossilOrigin-Name: 223640243efc52c14bb2bb540833a2a624eaa41a
2016-05-10 20:16:43 +00:00
drh d12bc6022b Fix a problem in sqlite3PagerMovepage() when working on a temp table for which
pages have been spilled.

FossilOrigin-Name: 20cf8811caf705b482be100baecb3ef72aee2d5a
2016-05-10 20:03:08 +00:00
drh 3791c9c288 Fixes to requirements marks. No changes to code.
FossilOrigin-Name: 79ecd0ef20c12198e950a730871444a980a0f1b2
2016-05-09 23:11:47 +00:00
drh 83561932a5 Enhancements to test/sort5.test so that it works with SEE.
FossilOrigin-Name: 8a39c8ee49e6e80c83613546cf328801c80b7c4d
2016-05-09 22:35:06 +00:00
drh f52a697e04 Remove some forgotten debugging lines from test/sort5.test.
FossilOrigin-Name: f5875489810101c13a7917bde86e6a23b088e386
2016-05-09 22:32:18 +00:00
dan ba1079ba2a Update a comment in fts5.h. No changes to code.
FossilOrigin-Name: 14e53d0e2f62d82ae1d64a72fd9711548e3bf5ea
2016-05-09 19:03:42 +00:00
dan 170b66493d Fix the FTS5 xQueryPhrase() API function so that it recognizes column filters.
FossilOrigin-Name: 48505cde05d74748454dc135d4ec25954ecf020e
2016-05-09 18:05:44 +00:00
drh e8da01c189 Make the sqlite3DeleteTable() routine smaller and faster.
FossilOrigin-Name: d75140b851a34a5eb66041e294e421628efbc5ba
2016-05-07 12:15:34 +00:00
drh 3eead27022 Fix typo in the intpkey-17.2 test.
FossilOrigin-Name: a45fda657d987f5c923d141584841a6c62dfb504
2016-05-07 12:15:15 +00:00
drh f09c48233a Simplification to the logic used to decide between OP_Seek and OP_NotExists.
Use OP_NotExists for both DELETE and UPDATE.

FossilOrigin-Name: 3a695263183303e3f64eb2320752d0fdef53eaf2
2016-05-06 20:23:12 +00:00
drh a3fd75d426 Corrections to comments on the whereScanInit() interface.
FossilOrigin-Name: ab7ab415d19524f6c3901e474d3a154f55d28530
2016-05-06 18:47:23 +00:00
drh 87f8f1ac69 For DELETE operations, make sure that seeks on the main table are not
deferred, since if they are and none of the indexes reference columns of
the table, the seek might never occur until the OP_Delete opcode, which is
too late.  Fix for ticket [16c9801ceba49].

FossilOrigin-Name: 93a2bace5704f7ecad56541a6b3e06a88f7f393f
2016-05-06 16:49:54 +00:00
dan 39332fb0f7 Fix an error in main.mk causing testfixture to use individual fts5 source code files instead of fts5.c.
FossilOrigin-Name: 933a1c818c1d1ccec8680e1ba87f2cbe37cc9f7d
2016-05-06 16:30:34 +00:00
drh bcf6884afd In the WHERE generator, when building code for a DELETE operation, make sure
that seeks to the main table are not deferred.
This is a better fix for the [16c9801ceba49] bug than the previous.

FossilOrigin-Name: 150dd09ebd7b17234a79e1811a0fae8b0a7a40d5
2016-05-06 16:06:59 +00:00
dan d49c6930b1 Fix a bug in sqlite_analyzer causing it report (slightly) incorrect values for the number of entries in indexes or WITHOUT ROWID tables.
FossilOrigin-Name: dc37750d4e87d0c529785adceeebd838b8f8591d
2016-05-06 15:16:02 +00:00
drh 70077d1733 Do not scan indexes that have the integer primary key as their left-most
column.  This fixes the crash of ticket [16c9801ceba] but it seems like
the wrong fix.  More investigation needed.

FossilOrigin-Name: 50312273ffaf1bd4bfdc73865fa0b19166968429
2016-05-06 11:31:10 +00:00
drh ad5a9d715f Renumber internal constants in the printf() implemention for a small
performance improvement.

FossilOrigin-Name: 69d11447f4b1a8c536c3b6573d2a3419da870412
2016-05-05 11:53:12 +00:00
drh 4e80d5fcf1 Disable the session extension API if SQLITE_ENABLE_SESSION is not defined.
FossilOrigin-Name: 71af9ac165ac02272f4886f69bd9ab4770fd7bb6
2016-05-04 21:06:21 +00:00
mistachkin 9fe3fbbc35 Fix typo in comment. No changes to code.
FossilOrigin-Name: 6c43ba1c8753a4029e127078652f265c408a01c0
2016-05-04 19:04:20 +00:00
drh 91da707280 Only disable the one-pass DELETE optimization if the WHERE clause contains
a correlated subquery.  Uncorrelated subqueries are allowed.  This is a
refinement of check-in [3f221f592a9a1] that is the fix for
ticket [dc6ebeda9396087].

FossilOrigin-Name: aae389692a2ed2cc92151d51fb2cd5a16921c469
2016-05-04 14:45:30 +00:00
drh 582c080289 Portability enhancements to the configure script on the amalgamation tarball.
FossilOrigin-Name: 7184c4b8869ffc00944abdd8d2c521cb11ea5824
2016-05-04 14:20:15 +00:00
dan c88ae52d86 Disable the PagerDontWrite() optimization for temp tables. It can cause database corruption if a page passed to PagerDontWrite() is dirty at the start of a transaction that is subsequently rolled back.
FossilOrigin-Name: 6341ab2ffef298ca16b323358afbea4a4c1fb0e1
2016-05-04 11:28:03 +00:00
mistachkin 12b35ea980 Minor style tweaks in the MSVC makefile.
FossilOrigin-Name: 1b43358f8979c4f18519e824e0d5f6ef2250107c
2016-05-03 19:40:54 +00:00
drh 799730bf81 The session extension is disabled by default. To enable it using
--enable-session on ./configure on unix and add SESSION=1 to the nmake
on Windows.  Or add -DSQLITE_ENABLE_SESSION and
-DSQLITE_ENABLE_PREUPDATE_HOOK to build manually.

FossilOrigin-Name: bcaa650e8796984b275eceba0ed477f360295d01
2016-05-03 14:57:07 +00:00
drh 5e18d40200 Turn the session extension off by default. Enable using --enable-session on
configure scripts, or using the SESSION=1 argument to nmake on Windows.

FossilOrigin-Name: e462cde2a50c39cc2f8d8624aada19280b8226eb
2016-05-03 13:14:18 +00:00
drh 48cd59a57d Avoid left-shifts of signed integers.
FossilOrigin-Name: 0715ce164333e27671efbec8796f238df98cc287
2016-05-03 00:04:55 +00:00
dan 39f98c52d0 Remove some randomness from test script temptable2.test.
FossilOrigin-Name: 5830cf72e9e870830d088399f1ccb03ed6522582
2016-05-02 19:05:05 +00:00
drh b1c6995c58 Fix a test case in temptable2.test so that it works on systems that
lack a coherient cache (ex: OpenBSD) and thus do not support the
"PRAGMA mmap_size" command.

FossilOrigin-Name: 088cf83872f6477c3b297c58d6f8a5def7025daf
2016-05-02 16:59:49 +00:00
drh cf7e7557b5 Fix harmless LLVM compiler warnings in the srcck1.c utility program used
during the build process.

FossilOrigin-Name: e4af967533f290862dfba1d9ef44d4c9ddd8a01b
2016-05-02 13:57:19 +00:00
drh 57a07ba9a9 Disable the multi-row one-pass DELETE optimization when the WHERE clause
contains a subquery.  Fix for ticket [dc6ebeda9396087].

FossilOrigin-Name: 3f221f592a9a19009076e568566c59801cd3fc32
2016-05-02 12:18:56 +00:00
drh 44aebff246 Improvements to the way the LIKE optimization is implemented, resulting in
slightly smaller and faster code that is easier to test.

FossilOrigin-Name: 54c63b329288729031f45b7778752552cd90e226
2016-05-02 10:25:42 +00:00
dan 40cf36ff17 Change the way tester.tcl handes $argv so that in "permutations.test <permutation> <filename>" <filename> may be the name of any file in the test/ directory.
FossilOrigin-Name: 820c57bb24ad3d8663ca512e4022268b940bb2ee
2016-04-30 19:23:10 +00:00
drh 2f55511dfa Remove an unnecessary branch from the OP_String8 opcode.
FossilOrigin-Name: 459a0b456da69112605b37adc9af27d79e35a4d7
2016-04-30 18:10:34 +00:00
drh 2e55b04da4 More bug fixes to Lemon identified by Kelvin Sherlock. None of these
have any impact on SQLite.

FossilOrigin-Name: 762bdc55f8878ee2ef65af2165a8e7fdbddf0160
2016-04-30 17:19:30 +00:00
drh 99f5de771f Simplifications to the OP_Halt opcode implementation.
FossilOrigin-Name: daf4630f96f13133664908045e279da9d5a40bb5
2016-04-30 02:59:15 +00:00
drh 2aab11fa5a Fix the temporary directory search algorithm for unix so that it fails
gracefully even if all candidate directories are inaccessible.  This fixes
a bug that was introduced by check-in [9b8fec60d8e].

FossilOrigin-Name: 614bb709d34e11488da88861243023cc5de4b409
2016-04-29 20:30:56 +00:00
drh 54606bbc14 Postpone I/O associated with TEMP files for as long as possible, with the
hope that the I/O can ultimately be avoided completely.

FossilOrigin-Name: 9d0a5ae00273686ea35b43bc2ffaa8775c176363
2016-04-29 15:39:48 +00:00
dan 4a030c6430 Fix test script temptable2.test so that it works with the "inmemory_journal" and "journaltest" permutations.
FossilOrigin-Name: b7bec7f2d3d08d0c14f77654be2c5cedf1619e58
2016-04-29 14:12:48 +00:00
dan 20ae3264b8 Merge latest trunk changes, including test case fixes, with this branch.
FossilOrigin-Name: 99794aca7b6cb40f08ce4db9889a989fc597eac9
2016-04-29 11:35:28 +00:00
dan 288327ed81 Modify the permutations.test script so as to set any permutation specific configuration values before running each individual test script. Fix a mostly harmless buffer overread in the sessions module.
FossilOrigin-Name: 4cbd50245440e714935399a5c285cf32d8bfc424
2016-04-29 11:33:58 +00:00
drh afb8cd977d Lemon bug fix: Do not merge action routines unless their destructors are
also identical.  Problem and suggested fix reported on the mailing list
by Kelvin Sherlock.

FossilOrigin-Name: 4792d6dbba6857f74d27332dcc1468e39c767c71
2016-04-29 11:28:35 +00:00
dan 14faa061fd Fix an almost entirely harmless buffer overread in the sessions module.
FossilOrigin-Name: 89b0ee3351381f7bc666cb206f77a56f2e0d4a0e
2016-04-29 10:13:22 +00:00
drh a3fa140fb4 Some optimization comments added to vdbe.c. No functional changes to code.
FossilOrigin-Name: e7c22e3bffce63f3b47fa3683be8c00c42b2a7d3
2016-04-29 02:55:05 +00:00
drh aa50271a24 Further simplifications and improved commentting on the rowset.c module,
including several optimization comments.

FossilOrigin-Name: 9f15a520deb9f1d4ecaa3bfff82bd57ef122aadb
2016-04-28 22:29:31 +00:00
drh 396794f0ee Comment changes only: Add several optimization marks in rowset.c. Add
a header comment that explains what the various special comments mean.

FossilOrigin-Name: 8cdbe89ac6c22d632f677eb293111b3dbae7d6c1
2016-04-28 20:11:12 +00:00
mistachkin 2075fb08e6 Fix typo in comment. No changes to code.
FossilOrigin-Name: 9f6f17b5c97c9576c340173d068485fdbfd53253
2016-04-28 19:23:10 +00:00
drh cb6d66becc Rearrange some code in the RowSet logic for clarity of presentation, while
adding an /*OPTIMIZATION-IF-TRUE*/ comment.  It should operate identically.

FossilOrigin-Name: 5748e64376c1c2be5154a632d1527cfebbb9ec74
2016-04-28 18:53:08 +00:00
dan 8443533178 Merge latest changes from trunk with this branch.
FossilOrigin-Name: 45467ee49872f495d5276cf830f10c3cf4ac8e3c
2016-04-28 14:59:05 +00:00
dan 14cee38be8 Avoid running sessionfault.test and sessionfault2.test as part of the "inmemory_journal" permutation.
FossilOrigin-Name: 5973d3bf2e5aa979ccc9a4a3a0eb08b67098b499
2016-04-28 14:54:54 +00:00
drh 75ab50ce8f Use comments to mark several branches as optimizations. No changes to code.
FossilOrigin-Name: 33e627472780b872716c504f2d585cc057c390a5
2016-04-28 14:15:12 +00:00
dan 3104c4d6f4 Ensure that quota.test deletes the directory named "test.db" that it creates.
FossilOrigin-Name: 045edd4b17c6b76079ac90773c035d8c1f8d525d
2016-04-28 09:53:14 +00:00
drh 10c0a2a7c9 Remove an unnecessary conditional from the sqlite3DecOrHexToI64() routine.
FossilOrigin-Name: fcf85bfe50b254e825ee63a4cd0aa0b333b06eed
2016-04-28 03:52:18 +00:00
drh 609d5846ba Change the sqlite3Atoi64() routine so that it returns failure if not all of
the input characters are consumed, even if it consumed all characters up to
the first 0x00.  This has no impact on external APIs as far as I can tell.

FossilOrigin-Name: 46d4ffff3bd33d7e901e76cfac1cbde38d4f61d0
2016-04-28 00:32:16 +00:00
dan 05accd2216 Modify the permutations.test script so as to set any permutation specific configuration values before running each individual test script.
FossilOrigin-Name: 2662d8fef791f7b8b3b14f9c27dfedec84620dee
2016-04-27 18:54:49 +00:00
drh ad975d539e More simplification of the sqlite3AtoF() routine. Add special comments
to indicate branches that are for optimization purposes only and that give
the correct answer even if always or never taken.

FossilOrigin-Name: 0065fe97cb8e5076acae1bf1560fd2f69dab9014
2016-04-27 15:24:13 +00:00
dan 9bf0136384 Fix a couple of test script problems on this branch. Both related to the fact that temp database page sizes can no longer be changed by VACUUM or the backup API after the temp db is populated.
FossilOrigin-Name: 6bb5aa2be2a6c5ca66a98a9387b2845507a6bdd2
2016-04-27 11:24:42 +00:00
drh c6daa01c05 Remove still more unnecessary branches from sqlite3AtoF().
FossilOrigin-Name: 3adfe9f3e6ce7cc09fcb570d9b65e830a96cac15
2016-04-27 02:35:03 +00:00
drh 15af62acff Further simplifications to sqlite3AtoF() to remove unneeded branches.
FossilOrigin-Name: dd69e53cb077873171af5312c633ca185595bf31
2016-04-26 23:14:45 +00:00
drh e5f06fdc87 Remove an unnecessary line from the sqlite3AtoF() routine.
FossilOrigin-Name: a9d007494cfe30a26dca5352655dc7702351476e
2016-04-26 21:02:53 +00:00
drh 97a7e5e68c The pcache and the built-in VFSes should not use mutexes when
SQLITE_CONFIG_SINGLETHREAD is set.

FossilOrigin-Name: 12418b100196abbfbfb85e0ab4bb6b1cbf335df7
2016-04-26 18:58:54 +00:00
dan 45164826b7 Fix an issue in temptable2.test preventing it from working with SQLITE_DEFAULT_AUTOVACUUM=1 builds.
FossilOrigin-Name: e790aac02e4b427b4891b514a050699d159b03b1
2016-04-26 17:10:03 +00:00
dan 0a5ced4c1e Merge the checksymbols fix from trunk into this branch.
FossilOrigin-Name: 04911cee0cd5467ee99744b774d692219e5e1425
2016-04-26 16:03:58 +00:00
drh b283a0cde9 Fix the "checksymbols" target in Makefile.in to be able to deal with the
sqlite3changegroup family of interfaces.

FossilOrigin-Name: d819bfbd46dc7f065d2a3ab0ef9f8322d8394e11
2016-04-26 13:13:53 +00:00
drh ead01fd272 Add an sqlite3FaultSim() all to make it easier to simulate IO errors in
a VACUUM commit.

FossilOrigin-Name: 8bfde416c51f4e087275aebf652a73985515e810
2016-04-25 22:39:42 +00:00
drh 6c96358601 Remove an obsolete comment from the pager. No code changes.
FossilOrigin-Name: 36f97ca8874a03ac8699f44fe0da95b0be507cc7
2016-04-25 19:28:34 +00:00
dan ae20690e2c Update the RBU vacuum code so that databases that use custom collation sequences can be vacuumed.
FossilOrigin-Name: 7dd48c10790a7b9c4165214399c261a0aa701297
2016-04-25 19:25:12 +00:00
drh 835f22deda Fix some unreachable branches in the pager.
FossilOrigin-Name: 3ae44770fdecc40c8097f1de0b504f36585a2232
2016-04-25 19:20:56 +00:00
drh dc7adf20bb Merge bug fix from trunk.
FossilOrigin-Name: a905d5e08de3f3c60b667d840b5995911372647d
2016-04-25 15:03:49 +00:00
drh b1ec87afdb When checking for the WHERE-clause push-down optimization, verify that
all terms of the compound inner SELECT are non-aggregate, not just the
last term.  Fix for ticket [f7f8c97e97597].

FossilOrigin-Name: ec215f94ac9748c0acd82af0cc9e7a92249462f9
2016-04-25 02:20:10 +00:00
mistachkin 1de86ca17f Fix a typo in the Makefile.
FossilOrigin-Name: d0a579b35105810821bbfec6b50ecfebac7a17ee
2016-04-25 01:43:24 +00:00
drh d456e92ce0 Merge the temporary directory search algorithm fix from trunk.
FossilOrigin-Name: 9b8fec60d8e576cd09e1d075a59bfad1c6169d7a
2016-04-23 21:16:55 +00:00
drh 23ee893752 Fix the fix to the temporary directory search algorithm so that it continues
to return "." as a fallback if that directory has the correct permissions.

FossilOrigin-Name: b38fe522cfc971b37ca04e7b63a92bbb6e0b01e1
2016-04-23 20:59:23 +00:00
drh 7ff5d522bf Merge the latest trunk changes.
FossilOrigin-Name: 84da122dd6e70ed603fea781dca204ae2f668c53
2016-04-23 19:55:59 +00:00
dan 2d36f065e2 Fix a problem with mixing temp-files and mmap-mode.
FossilOrigin-Name: c80c5c62b2e2c5e47e0839f8e2d5b6341ca4a249
2016-04-23 17:24:16 +00:00
dan 6572c16ae1 Fix some problems to do with temp-file databases and recovering from IO and SQLITE_FULL errors.
FossilOrigin-Name: 3d61da4a76af8c9c2a293df085f3ed5a7bb447df
2016-04-23 14:55:28 +00:00
drh 7694e06461 Change the temporary directory search algorithm on unix so that directories
with only -wx permission are allowed.  And do not allow "." to be returned if
it lacks -wx permission.

FossilOrigin-Name: 67985761aa93fb613b87d340e75371fa55b0f778
2016-04-21 23:37:24 +00:00
dan 83b74f29c5 Add the sqlite3rbu_vacuum() API, to create an RBU handle that can be used to rebuild a database in the same way as the VACUUM command.
FossilOrigin-Name: bd4a6f8313eb71399a7141ebf7f2617d7b1464c3
2016-04-21 18:13:37 +00:00
dan b7a208686a If a call to sqlite3rbu_close() on an rbu handle opened by sqlite3rbu_vacuum() returns other than SQLITE_OK, delete the contents of the rbu_state table. This ensures that if an RBU vacuum operation either completes successfully or encounters an error, the next call to sqlite3rbu_vacuum() with the same parameters starts a new RBU vacuum operation.
FossilOrigin-Name: 6e4ac704f51bdd1e0b16814f6a45ab29f26400ee
2016-04-21 16:44:38 +00:00
dan 2e8bfb67d4 Fix a problem in rbu vacuum on tables with a large sqlite_master table.
FossilOrigin-Name: 23eac52e987996afe8db847921aef434cebd25b5
2016-04-21 15:26:26 +00:00
drh 6bcfe8b61f Add a function prototype in order to fix a compiler warning.
FossilOrigin-Name: 49aec9718d61c9f12aed96f530128666c3b01c81
2016-04-21 15:24:46 +00:00
drh 518aca114f Merge updates from trunk.
FossilOrigin-Name: cc28106e5c196c0a9678fbbd06f6afd49271a8e8
2016-04-21 15:03:37 +00:00
drh 26f7977c53 Add the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method for enabling
sqlite3_load_extension() while leaving the load_extension() SQL function
disabled.

FossilOrigin-Name: c4f165c460c4244ed434107feac005efa3c386cf
2016-04-21 02:27:56 +00:00
drh f602a16123 Test cases for SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION.
FossilOrigin-Name: debafa5efd37ac60e030d0963ce8e7c4f51a0f10
2016-04-21 01:58:21 +00:00
drh 191dd06195 Revert sqlite3_enable_load_extension() to its original long-standing behavior.
Add SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION which will enable only the C-API and
leave the SQL function disabled.

FossilOrigin-Name: b2ae5bfa32e608625bd177907596df3dbc2212e1
2016-04-21 01:30:09 +00:00
dan 94d49697b5 Add a documentation comment for sqlite3rbu_vacuum() to sqlite3rbu.h.
FossilOrigin-Name: da5c753ddac3cbfdf03710a82f5fd9fa2e29e819
2016-04-20 20:08:58 +00:00
drh cdce61e133 When an error occurs while transitioning out of WAL mode, make sure the
locking state is not left at EXCLUSIVE.

FossilOrigin-Name: 3340f086510b08ce5b42a8781f1df51bf7c27701
2016-04-20 19:30:47 +00:00
drh 333f80562b Fix a locking race condition in Windows 10 that can occur when two or more
processes attempt to recover the same hot journal at the same time.

FossilOrigin-Name: 38a4e9d92887898b779493c71e4500f777a4e2e7
2016-04-20 18:31:27 +00:00
dan 132dde5cdf Add fault injection tests for rbu vacuum. Fix some problems revealed by the same.
FossilOrigin-Name: f042fdd1ea7febec7228e51efc2b0281805e196a
2016-04-20 17:47:52 +00:00
drh 1a55dedf7b <b>API Change:</b> Modify sqlite3_enable_load_extension() so that it only
enables/disables the load_extension() SQL function, and leaves the C-APIs
enabled at all times.  In this way, applications can enable extension loading
for the C interface without having to expose that capability to the SQL.

FossilOrigin-Name: edb454e45ae008e051e2f48d704a855b0c3e4be9
2016-04-20 00:30:05 +00:00
dan 1aea63032a Updates to ensure the values of PRAGMA settings like "page_size", "auto_vacuum", "user_version" and "application_id" are not lost when a database is RBU vacuumed.
FossilOrigin-Name: 74ffea76b8c9ddd7699ce6ca77dce005bd7922ac
2016-04-19 19:27:09 +00:00
dan 46f0035b48 When an RBU vacuum is started on a db identified using a URI filename, pass the same URI parameters when creating the new version of the db. This ensures that RBU vacuum works with password protected databases.
FossilOrigin-Name: ca021ba88106500f347ed65199a4832bc9eb5ef8
2016-04-19 17:11:05 +00:00
dan bff4b6367c Detect attempts to use rbu vacuum on a wal mode database (not allowed). And attempts to write to a database in the middle of an rbu vacuum (which prevents the vacuum from resuming).
FossilOrigin-Name: 00b2f4b09ffca5156e43c4db2bfe0b2c979c49b0
2016-04-19 16:20:24 +00:00
dan 58e3812988 Another fix to rbu vacuum for a zipvfs case.
FossilOrigin-Name: 29407d70e44ad9ea5ddaf1011d0e212b602a3ddf
2016-04-18 21:00:01 +00:00
dan beccf1d16f Fix some zipvfs related problems in RBU vacuum.
FossilOrigin-Name: d76f4aaa4caab713460421bd27365a82ac986c20
2016-04-18 18:18:18 +00:00
drh a6dddd9bde Remove quotes from identifiers used as datatype names in a CREATE TABLE
statement.  Fix for ticket [7d7525cb01b68]

FossilOrigin-Name: eba27d4d17a76884292667d570d542e580ee3e77
2016-04-18 15:46:14 +00:00
drh 2c03652b45 Merge recent trunk changes.
FossilOrigin-Name: d9768de502e34da42f3ad955947c23da50f57bce
2016-04-18 13:36:17 +00:00
drh b5895e50f9 sqlite3PCachePerecentDirty() should return 0 if the pcache is empty.
FossilOrigin-Name: 85f3d80eb7319754792eef76996b2c740a2b0073
2016-04-18 13:30:50 +00:00
drh f9986d90d1 The last parameter to pread64() and pwrite64() should be off64_t, not off_t.
FossilOrigin-Name: 3a7d72986fabe9434ff5bd02c93169314f072b23
2016-04-18 13:09:55 +00:00
dan 303a094466 Add the -vacuum switch to the "rbu" demonstration program.
FossilOrigin-Name: 9a0078a538c7e73a009960347b8953c5af99fefd
2016-04-18 09:17:05 +00:00
dan 2bb5f4478e Changes so that rbu vacuum works with zipvfs databases.
FossilOrigin-Name: bae7f875f476f6e01112751cb404fef42ba0a01c
2016-04-16 19:02:53 +00:00
dan 977cbe78b3 Avoid creating any extra files ("<target>-vacuum") when running an RBU vacuum. Ensure that the OAL file created is "<target>-oal", not "<target>-vacuum-oal".
FossilOrigin-Name: dc19aacc7e99213edca9bb57b5c11a8a1ac99113
2016-04-16 17:53:14 +00:00
dan ee65eea4af Fix a couple of assert() statements that were failing with OOM error tests.
FossilOrigin-Name: 8eb3d7d8360530f364bbbebac53e1f0e6753d924
2016-04-16 15:03:20 +00:00
dan f89157653a Add the experimental sqlite3rbu_vacuum() API function. For opening an RBU handle that rebuilds a database from scratch.
FossilOrigin-Name: 0216b48f28042ad86711e00802c2da8ce9be3044
2016-04-15 20:46:41 +00:00
drh eacd29d484 CLI enhancement: Add the ".eqp full" option, that shows both the EXPLAIN
QUERY PLAN and the EXPLAIN output for each command run.  Also disable
any ".wheretrace" and ".selecttrace" when showing EQP output.

FossilOrigin-Name: 3e217d6265ecd16db783bed7ce1d9d0f9c4828bb
2016-04-15 15:03:27 +00:00
dan 5313f2e12e In the ICU extension toupper() and tolower() SQL functions, avoid calling u_strToUpper() or u_strToLower() a second time if the buffer passed to the first invocation turns out to be large enough.
FossilOrigin-Name: d23e581351fb8eea28e7b13b3dcadfc817c3a05f
2016-04-14 17:29:13 +00:00
drh 497116007e Add the SF_HasAgg constant (currently unused). Also enhance the comments on
many other constant definitions to detail constraints on their values.

FossilOrigin-Name: 7b7a69d098f7581a43b818c251717c2450b797de
2016-04-14 16:40:13 +00:00
dan fc26f7cfed Correctly interpret negative "PRAGMA cache_size" values when determining the cache-size used for sorting large amounts of data (i.e. the functionality in vdbesort.c).
FossilOrigin-Name: 79147dca87cfd7eb62d57baa3b70fa2a8542232a
2016-04-14 15:44:37 +00:00
drh 7111c93c40 Add some missing testcase() macros to the pushDownWhereTerms() routine.
FossilOrigin-Name: 67d7f79c5e5be41a18817c802b5c4d349e3a83a4
2016-04-14 15:38:33 +00:00
drh f1b5ff73cb Rename WhereInfo.pResultSet to pDistinctSet to more accurately reflect what
it represents.

FossilOrigin-Name: 5317961411695e107e8cefdeaba62280429979ca
2016-04-14 13:35:26 +00:00
drh 8f2ce91462 Since the return value of sqlite3OsClose() is always ignored, we might as
well make it "void" instead of "int", and thereby save 50 bytes in the
compiled binary.

FossilOrigin-Name: 7ee570e7a9a2159a8c0d41805c00f91ca0de00e3
2016-04-14 13:16:58 +00:00
drh 7512cb47e8 Additional ".selecttrace" debugging output when the query is transformed from a
DISTINCT into a GROUP BY.

FossilOrigin-Name: 5a46914510af4d5557b299db65c68d5df1070766
2016-04-14 13:06:49 +00:00
drh 07d683fdbc Fix compiler warnings by removing surplus local variables in the schema
pretty-printer logic of the command-line shell.

FossilOrigin-Name: 55a62483b9121a8b373d038a26fdebc4308661f6
2016-04-13 21:00:36 +00:00
drh 1454b26c17 Merge enhancements from trunk via tempfiles-lazy-open.
FossilOrigin-Name: ae16310c4e9a9b7e94874bd912fc6a4324cfaa2b
2016-04-13 19:20:23 +00:00
dan 0f52455a35 On commit, flush dirty temp-file pages only if the file is already open and 25% or more of the cache is dirty.
FossilOrigin-Name: f6babf2920340f25815c0a3c58de1e902c2f5542
2016-04-13 16:52:11 +00:00
drh 8ca7b177bb Merge enhancements from trunk.
FossilOrigin-Name: e2edd34e79af906e7069e3e837730b12de0b73fe
2016-04-13 16:02:28 +00:00
drh 0cb64edc95 Fixes for harmless compiler warnings.
FossilOrigin-Name: 68142dc541b7a0a36fcb075a26f10f03c1e7c422
2016-04-13 15:52:16 +00:00
drh 4926fec967 Add the --indent option to the .schema and .fullschema commands in the shell,
to enable simple but effective pretty-printing.

FossilOrigin-Name: 83cfe82cd6d31ec0a6193525fd92e63a2a43b142
2016-04-13 15:33:42 +00:00
mistachkin 02d436b1f6 A couple more compiler warning fixes.
FossilOrigin-Name: 929fa4c31e7c5b8c6cbb1412478ea91b15ad5529
2016-04-12 20:26:51 +00:00
mistachkin c5896b5cbb Even more compiler warning fixes.
FossilOrigin-Name: 7faec9ea335c53953338886398b85aef87348a1c
2016-04-12 20:15:12 +00:00
mistachkin 77fac879d2 More harmless compiler warning fixes.
FossilOrigin-Name: ab69527c1608da0b668f3b49e967661dd99cc3d4
2016-04-12 20:05:06 +00:00
mistachkin 02267cc213 Compilation fix for a C99-ism in the 'fts3view' tool.
FossilOrigin-Name: bedb88a4b9c808ea781ae69058399a1a3a3d15fa
2016-04-12 19:30:31 +00:00
mistachkin 74f598b677 Fix harmless compiler warnings in the 'session' module.
FossilOrigin-Name: a18a6ce2271865d04cd75a8a5baa63798b7393db
2016-04-12 19:20:22 +00:00
dan 199f56b984 Once a temporary database file has been opened, flush all dirty pages to disk when comitting a transaction.
FossilOrigin-Name: bbac71aa2aa2380d393cda3be64b0208b464b27e
2016-04-12 19:09:29 +00:00
drh 741c2772db Fix speedtest1 so that it automatically unlinks its test database prior
to startup.

FossilOrigin-Name: b65b69f6b686c6555876b6fc701da95cc49120b5
2016-04-12 17:13:33 +00:00
drh 2160ca5f8d Add the --temp option to the speedtest1.c performance test program.
FossilOrigin-Name: 8053a6e2bf616fc9326f0323962176e318d7d2a5
2016-04-12 16:59:39 +00:00
drh e11003d5ba Improved localtime() support for WindowsCE
FossilOrigin-Name: 662c32af0276a9ef4eea2d29e2523ccc44b6d128
2016-04-12 16:23:30 +00:00
mistachkin 8366ddf242 Add and adjust comments.
FossilOrigin-Name: 541c6da23850673f5d2a2e31c3967b796ee2effc
2016-04-12 16:11:52 +00:00
drh 8a878f239c Merge enhancements from trunk.
FossilOrigin-Name: 9682c0433c04713c28bd9105a7e20af7372f873e
2016-04-12 16:10:10 +00:00
drh 752b102e9b Add the sqlite3_snapshot_cmp() interface (available only with
SQLITE_ENABLE_SNAPSHOT).

FossilOrigin-Name: 7e7289655185e7643ead6d685922528bc4d9e0ae
2016-04-12 16:04:07 +00:00
dan 745be369c7 Update the documentation for sqlite3_snapshot_cmp() to make the circumstances under which the comparison is valid clearer. Add tests for the same.
FossilOrigin-Name: 8fc834741bf6c8a832a180795c3d6f5c3dcfcd62
2016-04-12 15:14:25 +00:00
drh 70b8d6bbcc Update the header comment on the memjournal.c file. No code changes.
FossilOrigin-Name: 07f10deabb0f4207408142541e3913d638dfcdeb
2016-04-12 11:58:18 +00:00
drh 6f07734349 Performance optimization the Vdbe allocator.
FossilOrigin-Name: e2c4995bf1099cc02bcb1dc4a4631f06a870d171
2016-04-12 00:26:59 +00:00
drh f3c57ff54c Avoid unnecessary calls to object destructors for a small performance gain.
FossilOrigin-Name: aec94b6ee68fe50e2cc14388281e2ef531e21d68
2016-04-12 00:16:54 +00:00
drh 926957f0a6 Performance improvements in sqlite3WhereExprUsage().
FossilOrigin-Name: fdf752394b48fb7b9afe7b8a7d83f859985cc2d2
2016-04-12 00:00:33 +00:00
mistachkin 0cedb963a3 Further refinements.
FossilOrigin-Name: b35bb928b25492f6dd71ccf9c250cb9f0cce09ff
2016-04-11 22:45:45 +00:00
mistachkin 9cdd401d37 Merge updates from trunk.
FossilOrigin-Name: b8094166b3c6a8ec7913b403e08b5e6790fb03c1
2016-04-11 22:24:03 +00:00
mistachkin 4f2c822cc5 Fix typo in the MSVC makefile.
FossilOrigin-Name: 3189a7f1851f823218d85a2455bf218d00d81543
2016-04-11 22:23:04 +00:00
mistachkin 0e188e1d1e Fix some compilation issues.
FossilOrigin-Name: 016481b39f8b23b4f0f851053068d8eaee6122e1
2016-04-11 22:10:26 +00:00
dan ad2d5baf1f Add the sqlite3_snapshot_cmp() API.
FossilOrigin-Name: c698a21af740ca1019c3a771fb83e569cd6bf23e
2016-04-11 19:59:52 +00:00
dan 0e55da2ef8 Fix a typo in temptable2.test.
FossilOrigin-Name: 04b1890fbc19eb3fa935083c1664fbbfb67dad93
2016-04-11 19:24:56 +00:00
dan b5a2592a9e Add tests for wal mode to temptable2.test.
FossilOrigin-Name: c6d0d441a1ab4873caedf2f23543444cea5d7f5a
2016-04-11 19:23:36 +00:00
drh 244b9d6ec6 Performance optimization to sqlite3Dequote() and its callers.
FossilOrigin-Name: 9efe2265b1e70172778d333c5b9d9a76095427ab
2016-04-11 19:01:08 +00:00
dan 7180de2aa4 Merge latest trunk changes with this branch.
FossilOrigin-Name: ffc62af1d503c6e7fc0059d9c2ee57a3bef9dd32
2016-04-11 18:50:25 +00:00
dan b9f11f932d Add extra tests to temptable2.test.
FossilOrigin-Name: 7dd9d4c15bb6b6ef9127dc7c80a189c55e714dc9
2016-04-11 18:49:37 +00:00
drh affa855c94 Performance optimization for the sqlite3ExprListDelete() routine.
FossilOrigin-Name: 2764aeaa11f38cf2ff4d6191e6d5466ddb203022
2016-04-11 18:25:05 +00:00
drh bea119cdeb Performance optimizations in the column cache of the code generator, and
especially the sqlite3ExprCacheRemove() routine.

FossilOrigin-Name: e35b345cf858018ae0c07f79725f8d58062168db
2016-04-11 18:15:37 +00:00
dan 67330a1224 Fixes for OOM and IO error handling with temp file databases.
FossilOrigin-Name: 4eb06e843af60d5e533793618c6e0e9b7ef7a1a6
2016-04-11 18:07:47 +00:00
drh 3c19469ca2 Simplification and performance improvements in sqlite3ExprDup() and its
subroutines.  More work is possible in this area.

FossilOrigin-Name: 476cc2838824e0667e80ce527b9caa551dee4a77
2016-04-11 16:43:43 +00:00
drh c310db39ff Rename the OP_MX_JUMP macro to SQLITE_MX_JUMP_OPCODE to avoid confusing the
opcode name generator.

FossilOrigin-Name: e554a4c38bda9c73bf129bb7c665c53ccc4d96a8
2016-04-11 16:35:05 +00:00
drh 4f0010b1bc Performance improvement in sqlite3ExprDelete().
FossilOrigin-Name: 60ad80e3af4bae9f5c74fedf09eec9689e2e3dbf
2016-04-11 14:49:39 +00:00
drh 7cc84c2cdd Remove the VdbeOp.opflags field and its associated initialization overhead.
Update mkopcodeh.tcl to reorder opcode numbers to help the resolveP2Values()
routine run faster.

FossilOrigin-Name: 099478fa7521ba52262ef2bf24dd8f0114ce92e1
2016-04-11 13:36:42 +00:00
dan 7082371de7 Update this branch with the latest changes from the trunk.
FossilOrigin-Name: 982b753d0b6a3ed9fba33ed41523b2cd42280276
2016-04-11 09:39:25 +00:00
drh 8679fbabaa Back off of the parser optimization in the previous check-in, slightly, to
preserve some backwards compatibility regarding some undocumented behavior
in the '#AAA' style query parameter.

FossilOrigin-Name: ef1966c2469a0f5dbdb31a0287bd37badb2b8f28
2016-04-11 01:43:33 +00:00
drh 8f3b137fa6 Small size reduction and performance improvement in the parser.
FossilOrigin-Name: 16df71284bf081c8b3d3aa57c129a07067ddbed3
2016-04-11 01:26:31 +00:00
drh 08de4f7933 Factor out the common operation of setting the Expr.x.pSelect field of an
Expr object into a subroutine.

FossilOrigin-Name: 6a5cceee486c5e3625556e4c7076ff90e9d8fa43
2016-04-11 01:06:47 +00:00
drh ba26faa33f Fix a problem in the code generator for joins on virtual tables where the
outer loop of the join uses the IN operator.

FossilOrigin-Name: 6c56b3a04778bc62ca50307ad838dd301cd91ac2
2016-04-09 18:04:28 +00:00
drh bfc7a8bb01 Fix the sqlite3BtreeDelete() routine so that it preserves the correct
key even when the row being deleted is not on a leaf page.
Fix for ticket [a306e56ff68b8fa56]

FossilOrigin-Name: ca2ef8a86cf806cbbcc64db03251b1df5b2c5501
2016-04-09 17:04:05 +00:00
drh 53801efcdf Limit the number of digits shown in the "prereq" mask for ".wheretrace"
debugging output.

FossilOrigin-Name: 3686ed7413ae6cdbc8020c0023205e0455e87467
2016-04-09 14:36:07 +00:00
drh 11b264019c Update documentation for sqlite3_snapshot_open(). No code changes.
FossilOrigin-Name: 1dfa5234d3ee38c6af2d18a6294afa93232821e7
2016-04-08 19:44:31 +00:00
drh dca595c4a3 Add test cases for ticket [7f7f8026eda387d544].
FossilOrigin-Name: 87aa9357fbe6749bae60e30af54ca16e48678802
2016-04-07 21:14:35 +00:00
drh 38b3dde00e Prevent the in-memory journal read cursor from entering an inconsistent state
when it reads the last few bytes out of the journal file.  Fix for
ticket [7f7f8026eda38].

FossilOrigin-Name: c4b9c611bdcd85f31d68aaf114ee34a9f27eba6d
2016-04-07 18:42:23 +00:00
drh 45c3c66385 Avoid decrementing a pointer off the front end of the buffer in OP_MakeRecord.
FossilOrigin-Name: 153135bfb3b8f7c407ccf36571e2d4d5afe28ea3
2016-04-07 14:16:16 +00:00
drh be5000d6bf Instead of just commenting out the unneeded code in the previous check-in,
remove it completely.

FossilOrigin-Name: 8415d4848ab36ca33b23d1fad6b063544de04a3b
2016-04-07 14:05:20 +00:00
drh 3b42be9178 Remove an unnecessary test for a NULL pointer in freeP4().
FossilOrigin-Name: e84e88e31b67afe42e2494d984ab1cafd107465a
2016-04-07 14:01:10 +00:00
drh f878e6e1a7 Update comments on the unix file locking protocol. No changes to code.
FossilOrigin-Name: 716b20de4306de1653ba5bcdbfb8d210d2d46e1a
2016-04-07 13:45:20 +00:00
dan 9131ab9386 For a pager backed by a temp file, store the main journal in memory until it is at least sqlite3_config.nStmtSpill bytes in size. Prevent the backup API from being used to change the page-size of a temp file.
FossilOrigin-Name: 84c557010c211595d2ec80b62c63af1c7f4714bd
2016-04-06 18:20:51 +00:00
dan 7f8def285e Fix a problem in test script lock.test. Fix minor issues in pager.c.
FossilOrigin-Name: 84de8813c3b4007e3c7c3a286ce13020f2065c7b
2016-04-06 16:27:50 +00:00
dan d87efd7221 Add tests to this branch. Fix a problem with temporary databases in auto-vacuum mode.
FossilOrigin-Name: afe9bd9b4b5dc98dccf1bced80567515ab5c0117
2016-04-06 15:39:03 +00:00
drh 40dc357a01 Remove an unnecessary branch in the sqlite3LogEstToInt() routine.
FossilOrigin-Name: da81d7afeb0566a09a505ba5fce901e991e4a029
2016-04-05 23:39:53 +00:00
dan 41113b6429 Defer opening the file used for the temp database (where CREATE TEMP TABLE tables are stored) until the database is too large to reside entirely within the cache. There are likely still problems on this branch.
FossilOrigin-Name: be5a549eba6cf8e29cb6b9824fd6d0db9d03ca7f
2016-04-05 21:07:58 +00:00
drh ed06a131da Carry table column types through into VIEW definitions, where possible.
FossilOrigin-Name: fb555c3c2af7f5e62ff839658f4fba7b645d3a68
2016-04-05 20:59:12 +00:00
mistachkin 18a1549322 Remove superfluous directories from the Makefile clean targets.
FossilOrigin-Name: 0bf9926c7a7865694edd48535777248e73d86bbf
2016-04-05 19:46:10 +00:00
mistachkin c0d10c8d4f Merge updates from trunk.
FossilOrigin-Name: 00990020d07d7c87b922cdbfa5373298a86bb4b3
2016-04-05 17:59:56 +00:00
drh 60de73e83d Incorrect version of build.c checked in at [87e5f5a6c60e3] (because I
neglected to press the "Save" button on the text editor).  There is no change
to the logic, just improved presentation.

FossilOrigin-Name: cf569f9f2fab1828e4bfced111fd9a6ee23ea8c0
2016-04-05 15:59:23 +00:00
drh aed11f2072 Make sure "0" intended as a NULL pointer is cast to a pointer when used
in a varargs functions parameter.

FossilOrigin-Name: ed128e8b826cd9620b7146d01d461ed28b9a672d
2016-04-05 14:02:16 +00:00
drh 868f0398e4 Remove an unnecessary conditional from the index builder.
FossilOrigin-Name: 87e5f5a6c60e37e943b3ce80617e81b09852515e
2016-04-05 14:01:34 +00:00
drh 1c715f67b9 Use SQLITE_WITHIN() for pointer range comparisons in some testing code.
FossilOrigin-Name: 7cacf4e954c8de5af5efb56d8271a5ac1edc1c04
2016-04-05 13:35:43 +00:00
drh cca6698408 Do not allow pointer arithmetic to move a pointer across a memory allocation
boundary.

FossilOrigin-Name: 85b979319bcb8ec301ae39b36ad60348e4515be7
2016-04-05 13:19:19 +00:00
drh 73a6bb5851 Fix documentation typos. Comment changes only. No changes to code.
FossilOrigin-Name: d5fc2f7f90f8cbd53810c7a445b0e9c9a0e39182
2016-04-04 18:04:56 +00:00
mistachkin 48dcf2b60b Improve error messages from the 'shell1-5.0' test.
FossilOrigin-Name: cefd36ff7b7f142bcebdb16b4d24ae274cdf2709
2016-04-04 17:59:37 +00:00
drh bdeb125741 Improved handling of UTF8 by the command-line shell.
FossilOrigin-Name: 4534ebf15fbcd6fe2028957b7aa591b6cd5da95f
2016-04-04 17:34:54 +00:00
drh de613c6d4a Add the ".auth ON|OFF" command to the command-line shell.
FossilOrigin-Name: 65c7bcc42786a254966c531ba9062abb8fc8c5bf
2016-04-04 17:23:10 +00:00
dan 455684a036 Test that the view name is passed to the authorization callback when a SELECT statement is run on a view.
FossilOrigin-Name: 8627a4cd6d64bd076b56c1e8ccc3b1dfc1b4c07d
2016-04-04 16:40:44 +00:00
mistachkin 49e1125b69 Add and enhance the new tests.
FossilOrigin-Name: f4cbd18db47af4af990d7891dcc831e92b3f17e0
2016-04-04 15:47:46 +00:00
drh ae0c84bd9e Enhance sqlite3session_apply() and sqlite3session_apply_strm() so that
conflicts are retried before the xConflict() callback is invoked, as long
as the "apply" operation is making forward progress.

FossilOrigin-Name: 42a219668413e18dae917b03b04a21d108cc44be
2016-04-04 14:57:25 +00:00
drh 5fd0c12049 Minor performance optimization in the comparison opcodes of the VDBE.
FossilOrigin-Name: e375fe52cea7903c11ecef71c3452c67a96b663e
2016-04-04 13:46:24 +00:00
drh 51b55a3ee6 Fix harmless compiler warnings.
FossilOrigin-Name: 0213d6af84965676626c2fb4d78b4c74675207cc
2016-04-04 12:38:05 +00:00
mistachkin 1810f22809 Refinements to the previous check-in.
FossilOrigin-Name: b36dfdff787dc4a107b2c3fcbb98bfc4922872d8
2016-04-04 02:33:34 +00:00
mistachkin 1fe36bb8a8 Experimental changes to the command line shell to make it work better with Unicode on Windows.
FossilOrigin-Name: 74183a5f803999e1d4e288851c72519c3c53f6b5
2016-04-04 02:16:44 +00:00
mistachkin 1293120345 More refactoring and cleanup work on the Win32 string conversion and utility routines.
FossilOrigin-Name: 02ccb444a3d0b9a52ffd04cae9d9b6f654128c35
2016-04-04 02:05:46 +00:00
mistachkin 5daed673b8 Revise and enhance the Win32 string conversion routines.
FossilOrigin-Name: 345860c92195544aad44ea9b0d14c9ebbd50adf2
2016-04-03 22:44:16 +00:00
mistachkin 899c5c9d34 Replace the new fprintf() calls.
FossilOrigin-Name: f76c3a0ca40989fe9401c3b6f662f8e6ef2a730c
2016-04-03 20:50:02 +00:00
mistachkin 0784f8a460 Merge updates from trunk.
FossilOrigin-Name: 566b551e5a81440a5c8ff865ceb4422c76d67cf7
2016-04-03 20:45:04 +00:00
drh 076b6468f5 Preupdate hook documentation fixes. No changes to code.
FossilOrigin-Name: 59814f35d13db1f6379b9ae218b5432bc03c6197
2016-04-01 17:54:07 +00:00
drh f6661a8896 When reading an sqlite_stat1 table with missing entries for some indexes,
set the default for the missing indexes after all other indexes are set
so that the default values are more in line with indexes that are actually
in the stat1 table.

FossilOrigin-Name: a62340dc0507e36f6dec05b1fda68d8399ec62ec
2016-04-01 12:35:22 +00:00
mistachkin 2779989110 Update the clean target in the MSVC makefile.
FossilOrigin-Name: 69f4d83210f6425b2c0d699b397ef4fa4422d438
2016-03-31 22:53:37 +00:00
drh 5996a77987 Enhance the query planner so that IS and IS NULL operators are able to drive
an index on a LEFT OUTER JOIN.

FossilOrigin-Name: c648539b52ca28c0b2cb61208e2c32b1d29626a1
2016-03-31 20:40:28 +00:00
mistachkin 6cc16fc070 Cleanup localtime() support for Windows CE.
FossilOrigin-Name: 39759a553208d8ef72964bdd539a0883e1d99cf6
2016-01-23 01:54:15 +00:00
mistachkin e787cbbe2a Merge updates from trunk.
FossilOrigin-Name: 5cbab63756f6f276996f39d16d70b178581f63cd
2016-01-06 20:50:02 +00:00
mistachkin 710b33b999 Alternative to [76f5efa6], move definition of utf8_printf up.
FossilOrigin-Name: 54c5522dda239cb9775709495ed7eb56a5dd8e11
2016-01-03 18:59:28 +00:00
131 changed files with 5044 additions and 1743 deletions
+3 -4
View File
@@ -82,7 +82,6 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
# The same set of OMIT and ENABLE flags should be passed to the
# LEMON parser generator and the mkkeywordhash tool as well.
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
OPT_FEATURE_FLAGS += -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK
TCC += $(OPT_FEATURE_FLAGS)
@@ -1032,7 +1031,7 @@ FTS5_SRC = \
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
cp $(TOP)/ext/fts5/fts5parse.y .
rm -f fts5parse.h
./lemon $(OPTS) fts5parse.y
./lemon$(BEXE) $(OPTS) fts5parse.y
fts5parse.h: fts5parse.c
@@ -1164,8 +1163,9 @@ loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
#
VALIDIDS=' sqlite3(changeset|changegroup|session)?_'
checksymbols: sqlite3.lo
nm -g --defined-only sqlite3.o | egrep -v ' sqlite3(changeset|session)?_' ; test $$? -ne 0
nm -g --defined-only sqlite3.o | egrep -v $(VALIDIDS); test $$? -ne 0
echo '0 errors out of 1 tests'
# Build the amalgamation-autoconf package. The amalamgation-tarball target builds
@@ -1228,7 +1228,6 @@ clean:
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
rm -f mkkeywordhash$(BEXE) keywordhash.h
rm -f *.da *.bb *.bbg gmon.out
rm -rf quota2a quota2b quota2c
rm -rf tsrc .target_source
rm -f tclsqlite3$(TEXE)
rm -f testfixture$(TEXE) test.db
+14 -5
View File
@@ -198,6 +198,12 @@ DEBUG = 0
OPTIMIZATIONS = 2
!ENDIF
# Set this to non-0 to enable support for the session extension.
#
!IFNDEF SESSION
SESSION = 0
!ENDIF
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
@@ -264,6 +270,12 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# Should the session extension be enabled? If so, add compilation options
# to enable it.
#
!IF $(SESSION)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
@@ -1882,7 +1894,7 @@ fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c
sqlite3session.lo: $(TOP)\ext\session\sqlite3sesion.c $(HDR) $(EXTHDR)
sqlite3session.lo: $(TOP)\ext\session\sqlite3session.c $(HDR) $(EXTHDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\session\sqlite3session.c
# FTS5 things
@@ -2075,9 +2087,6 @@ clean:
del /Q notasharedlib.* 2>NUL
-rmdir /Q/S .deps 2>NUL
-rmdir /Q/S .libs 2>NUL
-rmdir /Q/S quota2a 2>NUL
-rmdir /Q/S quota2b 2>NUL
-rmdir /Q/S quota2c 2>NUL
-rmdir /Q/S tsrc 2>NUL
del /Q .target_source 2>NUL
del /Q tclsqlite3.exe 2>NUL
@@ -2089,7 +2098,7 @@ clean:
del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
del /Q sqlite3.c sqlite3-*.c 2>NUL
del /Q sqlite3rc.h 2>NUL
del /Q shell.c sqlite3ext.h 2>NUL
del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL
+1 -1
View File
@@ -1,5 +1,5 @@
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
lib_LTLIBRARIES = libsqlite3.la
libsqlite3_la_SOURCES = sqlite3.c
+12
View File
@@ -183,6 +183,12 @@ DEBUG = 0
OPTIMIZATIONS = 2
!ENDIF
# Set this to non-0 to enable support for the session extension.
#
!IFNDEF SESSION
SESSION = 0
!ENDIF
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
@@ -249,6 +255,12 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# Should the session extension be enabled? If so, add compilation options
# to enable it.
#
!IF $(SESSION)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
+15 -3
View File
@@ -103,7 +103,7 @@ AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
[--enable-fts5], [include fts5 support [default=no]])],
[], [enable_fts5=no])
if test x"$enable_fts5" == "xyes"; then
if test x"$enable_fts5" = "xyes"; then
AC_SEARCH_LIBS(log, m)
FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
fi
@@ -116,12 +116,24 @@ AC_SUBST(FTS5_FLAGS)
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
[--enable-json1], [include json1 support [default=no]])],
[], [enable_json1=no])
if test x"$enable_json1" == "xyes"; then
if test x"$enable_json1" = "xyes"; then
JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
fi
AC_SUBST(JSON1_FLAGS)
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# --enable-session
#
AC_ARG_ENABLE(session, [AS_HELP_STRING(
[--enable-session], [enable the session extension [default=no]])],
[], [enable_session=no])
if test x"$enable_session" = "xyes"; then
SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
AC_SUBST(SESSION_FLAGS)
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# --enable-static-shell
#
@@ -129,7 +141,7 @@ AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
[--enable-static-shell],
[statically link libsqlite3 into shell tool [default=yes]])],
[], [enable_static_shell=yes])
if test x"$enable_static_shell" == "xyes"; then
if test x"$enable_static_shell" = "xyes"; then
EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT
else
EXTRA_SHELL_OBJ=libsqlite3.la
Vendored
+30 -14
View File
@@ -908,6 +908,7 @@ enable_fts4
enable_fts5
enable_json1
enable_rtree
enable_session
enable_gcov
'
ac_precious_vars='build_alias
@@ -1556,6 +1557,7 @@ Optional Features:
--enable-fts5 Enable the FTS5 extension
--enable-json1 Enable the JSON1 extension
--enable-rtree Enable the RTREE extension
--enable-session Enable the SESSION extension
--enable-gcov Enable coverage testing using gcov
Optional Packages:
@@ -3923,13 +3925,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3926: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3928: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3929: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3931: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3932: output\"" >&5)
(eval echo "\"\$as_me:3934: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5135,7 +5137,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5138 "configure"' > conftest.$ac_ext
echo '#line 5140 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6660,11 +6662,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6663: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6665: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6667: \$? = $ac_status" >&5
echo "$as_me:6669: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -6999,11 +7001,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7002: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7004: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7006: \$? = $ac_status" >&5
echo "$as_me:7008: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7104,11 +7106,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7107: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7109: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7111: \$? = $ac_status" >&5
echo "$as_me:7113: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7159,11 +7161,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7162: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7164: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7166: \$? = $ac_status" >&5
echo "$as_me:7168: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9539,7 +9541,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9542 "configure"
#line 9544 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9635,7 +9637,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9638 "configure"
#line 9640 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11494,6 +11496,20 @@ if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
fi
#########
# See whether we should enable the SESSION extension
# Check whether --enable-session was given.
if test "${enable_session+set}" = set; then :
enableval=$enable_session; enable_session=yes
else
enable_session=no
fi
if test "${enable_session}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#########
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
for option in $CFLAGS $CPPFLAGS
+10
View File
@@ -615,6 +615,16 @@ if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
fi
#########
# See whether we should enable the SESSION extension
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
[Enable the SESSION extension]),
[enable_session=yes],[enable_session=no])
if test "${enable_session}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#########
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
for option in $CFLAGS $CPPFLAGS
+1 -1
View File
@@ -458,7 +458,7 @@ static int testTokenizerNext(
if( pCsr->iLangid & 0x00000001 ){
for(i=0; i<nToken; i++) pCsr->aBuffer[i] = pToken[i];
}else{
for(i=0; i<nToken; i++) pCsr->aBuffer[i] = testTolower(pToken[i]);
for(i=0; i<nToken; i++) pCsr->aBuffer[i] = (char)testTolower(pToken[i]);
}
pCsr->iToken++;
pCsr->iInput = (int)(p - pCsr->aInput);
+1 -1
View File
@@ -398,8 +398,8 @@ static void showSegmentStats(sqlite3 *db, const char *zTab){
if( sqlite3_step(pStmt)==SQLITE_ROW
&& (nLeaf = sqlite3_column_int(pStmt, 0))>0
){
nIdx = sqlite3_column_int(pStmt, 5);
sqlite3_int64 sz;
nIdx = sqlite3_column_int(pStmt, 5);
printf("For level %d:\n", i);
printf(" Number of indexes...................... %9d\n", nIdx);
printf(" Number of leaf segments................ %9d\n", nLeaf);
+7 -5
View File
@@ -143,11 +143,13 @@ struct Fts5PhraseIter {
** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
**
** with $p set to a phrase equivalent to the phrase iPhrase of the
** current query is executed. For each row visited, the callback function
** passed as the fourth argument is invoked. The context and API objects
** passed to the callback function may be used to access the properties of
** each matched row. Invoking Api.xUserData() returns a copy of the pointer
** passed as the third argument to pUserData.
** current query is executed. Any column filter that applies to
** phrase iPhrase of the current query is included in $p. For each
** row visited, the callback function passed as the fourth argument
** is invoked. The context and API objects passed to the callback
** function may be used to access the properties of each matched row.
** Invoking Api.xUserData() returns a copy of the pointer passed as
** the third argument to pUserData.
**
** If the callback function returns any value other than SQLITE_OK, the
** query is abandoned and the xQueryPhrase function returns immediately.
+11
View File
@@ -1655,6 +1655,17 @@ int sqlite3Fts5ExprClonePhrase(
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
}
if( rc==SQLITE_OK ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
int nByte = sizeof(Fts5Colset) + pColsetOrig->nCol * sizeof(int);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, nByte);
}
pNew->pRoot->pNear->pColset = pColset;
}
}
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
+2 -2
View File
@@ -345,11 +345,11 @@ int sqlite3Fts5HashWrite(
if( pHash->eDetail==FTS5_DETAIL_FULL ){
pPtr[p->nData++] = 0x01;
p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
p->iCol = iCol;
p->iCol = (i16)iCol;
p->iPos = 0;
}else{
bNew = 1;
p->iCol = iPos = iCol;
p->iCol = (i16)(iPos = iCol);
}
}
+1 -1
View File
@@ -3244,7 +3244,7 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
if( aiCol==aiColEnd ) goto setoutputs_col_out;
}
if( *aiCol==iPrev ){
*aOut++ = (iPrev - iPrevOut) + 2;
*aOut++ = (u8)((iPrev - iPrevOut) + 2);
iPrevOut = iPrev;
}
}
+32
View File
@@ -246,5 +246,37 @@ foreach {tn lRow res} {
} $res
}
#-------------------------------------------------------------------------
# Test the built-in bm25() demo.
#
reset_db
do_execsql_test 9.1 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b);
INSERT INTO t1 VALUES('a', NULL); -- 1
INSERT INTO t1 VALUES('a', NULL); -- 2
INSERT INTO t1 VALUES('a', NULL); -- 3
INSERT INTO t1 VALUES('a', NULL); -- 4
INSERT INTO t1 VALUES('a', NULL); -- 5
INSERT INTO t1 VALUES('a', NULL); -- 6
INSERT INTO t1 VALUES('a', NULL); -- 7
INSERT INTO t1 VALUES('a', NULL); -- 8
INSERT INTO t1 VALUES(NULL, 'a a b'); -- 9
INSERT INTO t1 VALUES(NULL, 'b b a'); -- 10
}
do_execsql_test 9.2 {
SELECT rowid FROM t1('a AND b') ORDER BY rank;
} {
10 9
}
do_execsql_test 9.3 {
SELECT rowid FROM t1('b:a AND b:b') ORDER BY rank;
} {
9 10
}
finish_test
+17 -11
View File
@@ -354,15 +354,17 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
** http://www.icu-project.org/userguide/posix.html#case_mappings
*/
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
const UChar *zInput;
UChar *zOutput = 0;
int nInput;
int nOut;
const UChar *zInput; /* Pointer to input string */
UChar *zOutput = 0; /* Pointer to output buffer */
int nInput; /* Size of utf-16 input string in bytes */
int nOut; /* Size of output buffer in bytes */
int cnt;
int bToUpper; /* True for toupper(), false for tolower() */
UErrorCode status;
const char *zLocale = 0;
assert(nArg==1 || nArg==2);
bToUpper = (sqlite3_user_data(p)!=0);
if( nArg==2 ){
zLocale = (const char *)sqlite3_value_text(apArg[1]);
}
@@ -386,19 +388,23 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
}
zOutput = zNew;
status = U_ZERO_ERROR;
if( sqlite3_user_data(p) ){
if( bToUpper ){
nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
}else{
nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
}
if( !U_SUCCESS(status) ){
if( status==U_BUFFER_OVERFLOW_ERROR ) continue;
icuFunctionError(p,
sqlite3_user_data(p) ? "u_strToUpper" : "u_strToLower", status);
return;
if( U_SUCCESS(status) ){
sqlite3_result_text16(p, zOutput, nOut, xFree);
}else if( status==U_BUFFER_OVERFLOW_ERROR ){
assert( cnt==0 );
continue;
}else{
icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status);
}
return;
}
sqlite3_result_text16(p, zOutput, nOut, xFree);
assert( 0 ); /* Unreachable */
}
/*
+4 -4
View File
@@ -625,10 +625,10 @@ static int amatchLoadOneRule(
}else{
memset(pRule, 0, sizeof(*pRule));
pRule->zFrom = &pRule->zTo[nTo+1];
pRule->nFrom = nFrom;
pRule->nFrom = (amatch_len)nFrom;
memcpy(pRule->zFrom, zFrom, nFrom+1);
memcpy(pRule->zTo, zTo, nTo+1);
pRule->nTo = nTo;
pRule->nTo = (amatch_len)nTo;
pRule->rCost = rCost;
pRule->iLang = (int)iLang;
}
@@ -1081,7 +1081,7 @@ static void amatchAddWord(
pWord->rCost = rCost;
pWord->iSeq = pCur->nWord++;
amatchWriteCost(pWord);
pWord->nMatch = nMatch;
pWord->nMatch = (short)nMatch;
pWord->pNext = pCur->pAllWords;
pCur->pAllWords = pWord;
pWord->sCost.zKey = pWord->zCost;
@@ -1162,7 +1162,7 @@ static int amatchNext(sqlite3_vtab_cursor *cur){
#endif
nWord = (int)strlen(pWord->zWord+2);
if( nWord+20>nBuf ){
nBuf = nWord+100;
nBuf = (char)(nWord+100);
zBuf = sqlite3_realloc(zBuf, nBuf);
if( zBuf==0 ) return SQLITE_NOMEM;
}
+2 -2
View File
@@ -344,10 +344,10 @@ static int fuzzerLoadOneRule(
memset(pRule, 0, sizeof(*pRule));
pRule->zFrom = pRule->zTo;
pRule->zFrom += nTo + 1;
pRule->nFrom = nFrom;
pRule->nFrom = (fuzzer_len)nFrom;
memcpy(pRule->zFrom, zFrom, nFrom+1);
memcpy(pRule->zTo, zTo, nTo+1);
pRule->nTo = nTo;
pRule->nTo = (fuzzer_len)nTo;
pRule->rCost = nCost;
pRule->iRuleset = (int)iRuleset;
}
+5 -5
View File
@@ -136,7 +136,7 @@ struct ReCompiled {
static void re_add_state(ReStateSet *pSet, int newState){
unsigned i;
for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
pSet->aState[pSet->nState++] = newState;
pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}
/* Extract the next unicode character from *pzIn and return it. Advance
@@ -358,7 +358,7 @@ static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
p->aArg[i] = p->aArg[i-1];
}
p->nState++;
p->aOp[iBefore] = op;
p->aOp[iBefore] = (char)op;
p->aArg[iBefore] = arg;
return iBefore;
}
@@ -677,12 +677,12 @@ const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=127 ){
pRe->zInit[j++] = x;
pRe->zInit[j++] = (unsigned char)x;
}else if( x<=0xfff ){
pRe->zInit[j++] = 0xc0 | (x>>6);
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
pRe->zInit[j++] = 0xd0 | (x>>12);
pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else{
+10 -10
View File
@@ -390,7 +390,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
/* Special processing if either string is empty */
if( nA==0 ){
cBprev = dc;
cBprev = (char)dc;
for(xB=res=0; (cB = zB[xB])!=0; xB++){
res += insertOrDeleteCost(cBprev, cB, zB[xB+1])/FINAL_INS_COST_DIV;
cBprev = cB;
@@ -398,7 +398,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
return res;
}
if( nB==0 ){
cAprev = dc;
cAprev = (char)dc;
for(xA=res=0; (cA = zA[xA])!=0; xA++){
res += insertOrDeleteCost(cAprev, cA, zA[xA+1]);
cAprev = cA;
@@ -420,8 +420,8 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
/* Compute the Wagner edit distance */
m[0] = 0;
cx[0] = dc;
cBprev = dc;
cx[0] = (char)dc;
cBprev = (char)dc;
for(xB=1; xB<=nB; xB++){
cBnext = zB[xB];
cB = zB[xB-1];
@@ -429,7 +429,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
m[xB] = m[xB-1] + insertOrDeleteCost(cBprev, cB, cBnext);
cBprev = cB;
}
cAprev = dc;
cAprev = (char)dc;
for(xA=1; xA<=nA; xA++){
int lastA = (xA==nA);
cA = zA[xA-1];
@@ -476,7 +476,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
d = m[xB];
dc = cx[xB];
m[xB] = totalCost;
cx[xB] = ncx;
cx[xB] = (char)ncx;
cBprev = cB;
}
cAprev = cA;
@@ -711,9 +711,9 @@ static int editDist3ConfigLoad(
if( nExtra<0 ) nExtra = 0;
pCost = sqlite3_malloc64( sizeof(*pCost) + nExtra );
if( pCost==0 ){ rc = SQLITE_NOMEM; break; }
pCost->nFrom = nFrom;
pCost->nTo = nTo;
pCost->iCost = iCost;
pCost->nFrom = (u8)nFrom;
pCost->nTo = (u8)nTo;
pCost->iCost = (u16)iCost;
memcpy(pCost->a, zFrom, nFrom);
memcpy(pCost->a + nFrom, zTo, nTo);
pCost->pNext = pLang->pCost;
@@ -1616,7 +1616,7 @@ static unsigned char *transliterate(const unsigned char *zIn, int nIn){
zIn += sz;
nIn -= sz;
if( c<=127 ){
zOut[nOut++] = c;
zOut[nOut++] = (unsigned char)c;
}else{
int xTop, xBtm, x;
xTop = sizeof(translit)/sizeof(translit[0]) - 1;
+40 -16
View File
@@ -24,12 +24,22 @@
*/
void usage(const char *zArgv0){
fprintf(stderr,
"Usage: %s [-step NSTEP] TARGET-DB RBU-DB\n"
"Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n"
"\n"
" Argument RBU-DB must be an RBU database containing an update suitable for\n"
" target database TARGET-DB. If NSTEP is set to less than or equal to zero\n"
" (the default value), this program attempts to apply the entire update to\n"
" the target database.\n"
"Where options are:\n"
"\n"
" -step NSTEP\n"
" -vacuum\n"
"\n"
" If the -vacuum switch is not present, argument RBU-DB must be an RBU\n"
" database containing an update suitable for target database TARGET-DB.\n"
" Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n"
" RBU, and RBU-DB is used as the state database for the vacuum (refer to\n"
" API documentation for details).\n"
"\n"
" If NSTEP is set to less than or equal to zero (the default value), this \n"
" program attempts to perform the entire update or vacuum operation before\n"
" exiting\n"
"\n"
" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
" to sqlite3rbu_step(). If the RBU update has not been completely applied\n"
@@ -69,29 +79,43 @@ int main(int argc, char **argv){
char *zErrmsg; /* Error message, if any */
sqlite3rbu *pRbu; /* RBU handle */
int nStep = 0; /* Maximum number of step() calls */
int bVacuum = 0;
int rc;
sqlite3_int64 nProgress = 0;
int nArg = argc-2;
/* Process command line arguments. Following this block local variables
** zTarget, zRbu and nStep are all set. */
if( argc==5 ){
size_t nArg1 = strlen(argv[1]);
if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]);
nStep = atoi(argv[2]);
}else if( argc!=3 ){
usage(argv[0]);
if( argc<3 ) usage(argv[0]);
for(i=1; i<nArg; i++){
const char *zArg = argv[i];
int nArg = strlen(zArg);
if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){
bVacuum = 1;
}else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){
i++;
nStep = atoi(argv[i]);
}else{
usage(argv[0]);
}
}
zTarget = argv[argc-2];
zRbu = argv[argc-1];
report_default_vfs();
/* Open an RBU handle. If nStep is less than or equal to zero, call
/* Open an RBU handle. A vacuum handle if -vacuum was specified, or a
** regular RBU update handle otherwise. */
if( bVacuum ){
pRbu = sqlite3rbu_vacuum(zTarget, zRbu);
}else{
pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
}
report_rbu_vfs(pRbu);
/* If nStep is less than or equal to zero, call
** sqlite3rbu_step() until either the RBU has been completely applied
** or an error occurs. Or, if nStep is greater than zero, call
** sqlite3rbu_step() a maximum of nStep times. */
pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
report_rbu_vfs(pRbu);
for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++);
nProgress = sqlite3rbu_progress(pRbu);
rc = sqlite3rbu_close(pRbu, &zErrmsg);
+98
View File
@@ -0,0 +1,98 @@
# 2016 April 20
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains fault injection tests for RBU vacuum operations.
#
source [file join [file dirname [info script]] rbu_common.tcl]
source $testdir/malloc_common.tcl
set ::testprefix rbufault3
foreach {fault errlist} {
oom-* {
{1 SQLITE_NOMEM}
{1 SQLITE_IOERR_NOMEM}
{1 {SQLITE_NOMEM - out of memory}}
}
ioerr-* {
{1 {SQLITE_IOERR - disk I/O error}}
{1 SQLITE_IOERR}
{1 SQLITE_IOERR_WRITE}
{1 SQLITE_IOERR_FSYNC}
{1 SQLITE_IOERR_READ}
{1 {SQLITE_IOERR - unable to open database: test.db2}}
{1 {SQLITE_ERROR - unable to open database: test.db2}}
{1 {SQLITE_ERROR - SQL logic error or missing database}}
}
cantopen* {
{1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
{1 {SQLITE_CANTOPEN - unable to open database: test.db2}}
{1 {SQLITE_CANTOPEN - unable to open database file}}
{1 SQLITE_CANTOPEN}
}
} {
reset_db
do_execsql_test 0 {
CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
INSERT INTO target VALUES(1, 2, 3);
INSERT INTO target VALUES(4, 5, 6);
INSERT INTO target VALUES(7, 8, 9);
CREATE INDEX i1 ON target(z);
}
faultsim_save_and_close
do_faultsim_test 1 -faults $fault -prep {
faultsim_restore_and_reopen
forcedelete test.db2
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu step]=="SQLITE_OK"} {}
rbu close
} -test {
eval [list faultsim_test_result {0 SQLITE_DONE} {*}$::errlist]
}
do_faultsim_test 2 -faults $fault -prep {
faultsim_restore_and_reopen
forcedelete test.db2
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
rbu step
rbu close
} -test {
eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
}
forcedelete test.db2
sqlite3rbu_vacuum rbu test.db test.db2
rbu step
rbu close
faultsim_save_and_close
do_faultsim_test 3 -faults $fault -prep {
faultsim_restore_and_reopen
forcedelete test.db2
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
rbu step
rbu close
} -test {
eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
}
}
finish_test
+410
View File
@@ -0,0 +1,410 @@
# 2016 April 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#
source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbuvacuum
proc do_rbu_vacuum_test {tn step} {
uplevel [list do_test $tn.1 {
if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
while 1 {
if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
if {$step==1} { rbu close }
}
rbu close
} {SQLITE_DONE}]
uplevel [list do_execsql_test $tn.2 {
PRAGMA integrity_check
} ok]
}
foreach step {0 1} {
set ::testprefix rbuvacuum-step=$step
reset_db
# Simplest possible vacuum.
do_execsql_test 1.0 {
PRAGMA page_size = 1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9);
PRAGMA integrity_check;
} {ok}
do_rbu_vacuum_test 1.1 $step
# A vacuum that actually reclaims space.
do_execsql_test 1.2.1 {
INSERT INTO t1 VALUES(8, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(9, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(10, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(11, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(12, randomblob(900), randomblob(900));
PRAGMA page_count;
} {12}
do_execsql_test 1.2.2 {
DELETE FROM t1 WHERE rowid BETWEEN 8 AND 11;
PRAGMA page_count;
} {12}
do_rbu_vacuum_test 1.2.3 $step
do_execsql_test 1.2.4 {
PRAGMA page_count;
} {3}
# Add an index to the table.
do_execsql_test 1.3.1 {
CREATE INDEX t1b ON t1(b);
INSERT INTO t1 VALUES(13, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(14, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(15, randomblob(900), randomblob(900));
INSERT INTO t1 VALUES(16, randomblob(900), randomblob(900));
PRAGMA page_count;
} {18}
do_execsql_test 1.3.2 {
DELETE FROM t1 WHERE rowid BETWEEN 12 AND 15;
PRAGMA page_count;
} {18}
do_rbu_vacuum_test 1.3.3 $step
do_execsql_test 1.3.4 {
PRAGMA page_count;
} {5}
# WITHOUT ROWID table.
do_execsql_test 1.4.1 {
CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
INSERT INTO t2 VALUES(randomblob(900), 1, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 2, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 3, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 4, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 6, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 7, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 8, randomblob(900));
DELETE FROM t2 WHERE b BETWEEN 2 AND 7;
PRAGMA page_count;
} {20}
do_rbu_vacuum_test 1.4.2 $step
do_execsql_test 1.4.3 {
PRAGMA page_count;
} {10}
# WITHOUT ROWID table with an index.
do_execsql_test 1.4.1 {
CREATE INDEX t2c ON t2(c);
INSERT INTO t2 VALUES(randomblob(900), 9, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 10, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 11, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 12, randomblob(900));
INSERT INTO t2 VALUES(randomblob(900), 13, randomblob(900));
DELETE FROM t2 WHERE b BETWEEN 8 AND 12;
PRAGMA page_count;
} {35}
do_rbu_vacuum_test 1.4.2 $step
do_execsql_test 1.4.3 {
PRAGMA page_count;
} {15}
do_execsql_test 1.4.4 {
VACUUM;
PRAGMA page_count;
} {15}
do_execsql_test 1.5.1 {
CREATE TABLE t3(a, b, c);
INSERT INTO t3 VALUES('a', 'b', 'c');
INSERT INTO t3 VALUES('d', 'e', 'f');
INSERT INTO t3 VALUES('g', 'h', 'i');
}
do_rbu_vacuum_test 1.5.2 $step
do_execsql_test 1.5.3 {
SELECT * FROM t3
} {a b c d e f g h i}
do_execsql_test 1.5.4 {
CREATE INDEX t3a ON t3(a);
CREATE INDEX t3b ON t3(b);
CREATE INDEX t3c ON t3(c);
INSERT INTO t3 VALUES('j', 'k', 'l');
DELETE FROM t3 WHERE a = 'g';
}
do_rbu_vacuum_test 1.5.5 $step
do_execsql_test 1.5.6 {
SELECT rowid, * FROM t3 ORDER BY b
} {1 a b c 2 d e f 4 j k l}
do_execsql_test 1.6.1 {
CREATE TABLE t4(a PRIMARY KEY, b, c);
INSERT INTO t4 VALUES('a', 'b', 'c');
INSERT INTO t4 VALUES('d', 'e', 'f');
INSERT INTO t4 VALUES('g', 'h', 'i');
}
do_rbu_vacuum_test 1.6.2 $step
do_execsql_test 1.6.3 {
SELECT * FROM t4
} {a b c d e f g h i}
do_execsql_test 1.6.4 {
CREATE INDEX t4a ON t4(a);
CREATE INDEX t4b ON t4(b);
CREATE INDEX t4c ON t4(c);
INSERT INTO t4 VALUES('j', 'k', 'l');
DELETE FROM t4 WHERE a='g';
}
do_rbu_vacuum_test 1.6.5 $step
do_execsql_test 1.6.6 {
SELECT * FROM t4 ORDER BY b
} {a b c d e f j k l}
reset_db
do_execsql_test 1.7.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
INSERT INTO t1 VALUES(NULL, 'one');
INSERT INTO t1 VALUES(NULL, 'two');
DELETE FROM t1 WHERE a=2;
INSERT INTO t1 VALUES(NULL, 'three');
INSERT INTO t1 VALUES(NULL, 'four');
DELETE FROM t1 WHERE a=4;
INSERT INTO t1 VALUES(NULL, 'five');
INSERT INTO t1 VALUES(NULL, 'six');
DELETE FROM t1 WHERE a=6;
SELECT * FROM t1;
} {1 one 3 three 5 five}
do_rbu_vacuum_test 1.7.1 $step
do_execsql_test 1.7.2 {
INSERT INTO t1 VALUES(NULL, 'seven');
SELECT * FROM t1;
} {1 one 3 three 5 five 7 seven}
reset_db
do_execsql_test 1.8.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(NULL, 'one');
INSERT INTO t1 VALUES(NULL, 'two');
INSERT INTO t1 VALUES(NULL, 'three');
INSERT INTO t1 VALUES(NULL, 'four');
INSERT INTO t1 VALUES(NULL, 'five');
INSERT INTO t1 VALUES(NULL, 'six');
ANALYZE;
SELECT * FROM sqlite_stat1;
} {t1 i1 {6 1}}
do_rbu_vacuum_test 1.8.1 $step
do_execsql_test 1.7.2 {
SELECT * FROM sqlite_stat1;
} {t1 i1 {6 1}}
reset_db
do_execsql_test 1.9.0 {
PRAGMA page_size = 8192;
PRAGMA auto_vacuum = 2;
PRAGMA user_version = 412;
PRAGMA application_id = 413;
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(NULL, 'one');
INSERT INTO t1 VALUES(NULL, 'two');
INSERT INTO t1 VALUES(NULL, 'three');
INSERT INTO t1 VALUES(NULL, 'four');
INSERT INTO t1 VALUES(NULL, 'five');
INSERT INTO t1 VALUES(NULL, 'six');
PRAGMA main.page_size;
PRAGMA main.auto_vacuum;
PRAGMA main.user_version;
PRAGMA main.application_id;
} {8192 2 412 413}
do_rbu_vacuum_test 1.9.1 $step
do_execsql_test 1.9.2 {
PRAGMA main.page_size;
PRAGMA main.auto_vacuum;
PRAGMA main.user_version;
PRAGMA main.application_id;
} {8192 2 412 413}
# Vacuum a database with a large sqlite_master table.
#
reset_db
do_test 1.10.1 {
for {set i 1} {$i < 50} {incr i} {
execsql "PRAGMA page_size = 1024"
execsql "CREATE TABLE t$i (a, b, c, PRIMARY KEY(a, b));"
execsql "
INSERT INTO t$i VALUES(1, 2, 3);
INSERT INTO t$i VALUES(4, 5, 6);
"
}
} {}
do_rbu_vacuum_test 1.10.2 $step
# Database with empty tables.
#
reset_db
do_execsql_test 1.11.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
INSERT INTO t4 VALUES(1, 2);
}
do_rbu_vacuum_test 1.11.2 $step
do_execsql_test 1.11.3 {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
SELECT * FROM t4;
} {1 2}
reset_db
do_execsql_test 1.12.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 2);
}
do_rbu_vacuum_test 1.12.2 $step
do_execsql_test 1.12.3 {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
SELECT * FROM t4;
} {1 2}
}
set ::testprefix rbuvacuum
#-------------------------------------------------------------------------
# Test some error cases:
#
# 2.1.* the db being vacuumed being in wal mode already.
# 2.2.* database modified mid vacuum.
#
reset_db
do_execsql_test 2.1.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t1 VALUES(7, 8);
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(9, 10);
} wal
do_test 2.1.1 {
sqlite3rbu_vacuum rbu test.db state.db
rbu step
} {SQLITE_ERROR}
do_test 2.1.2 {
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
reset_db
do_execsql_test 2.2.0 {
CREATE TABLE tx(a PRIMARY KEY, b BLOB);
INSERT INTO tx VALUES(1, randomblob(900));
INSERT INTO tx SELECT a+1, randomblob(900) FROM tx;
INSERT INTO tx SELECT a+2, randomblob(900) FROM tx;
INSERT INTO tx SELECT a+4, randomblob(900) FROM tx;
INSERT INTO tx SELECT a+8, randomblob(900) FROM tx;
}
db_save_and_close
for {set i 1} 1 {incr i} {
db_restore_and_reopen
sqlite3rbu_vacuum rbu test.db state.db
for {set step 0} {$step<$i} {incr step} { rbu step }
rbu close
if {[file exists test.db-wal]} break
execsql { INSERT INTO tx VALUES(20, 20) }
do_test 2.2.$i.1 {
sqlite3rbu_vacuum rbu test.db state.db
rbu step
} {SQLITE_BUSY}
do_test 2.2.$i.2 {
list [catch { rbu close } msg] $msg
} {1 {SQLITE_BUSY - database modified during rbu vacuum}}
}
#-------------------------------------------------------------------------
# Test that a database that uses custom collation sequences can be RBU
# vacuumed.
#
reset_db
forcedelete state.db
proc noop {args} {}
proc length_cmp {x y} {
set n1 [string length $x]
set n2 [string length $y]
return [expr $n1 - $n2]
}
sqlite3_create_collation_v2 db length length_cmp noop
do_execsql_test 3.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 'i');
INSERT INTO t1 VALUES(2, 'iiii');
INSERT INTO t1 VALUES(3, 'ii');
INSERT INTO t1 VALUES(4, 'iii');
SELECT a FROM t1 ORDER BY b COLLATE length;
} {1 3 4 2}
do_execsql_test 3.1 {
CREATE INDEX i1 ON t1(b COLLATE length);
}
do_test 3.2 {
sqlite3rbu_vacuum rbu test.db state.db
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - no such collation sequence: length}}
do_test 3.3 {
sqlite3rbu_vacuum rbu test.db state.db
set db1 [rbu db 0]
sqlite3_create_collation_v2 $db1 length length_cmp noop
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - no such collation sequence: length}}
do_test 3.4 {
sqlite3rbu_vacuum rbu test.db state.db
set db1 [rbu db 1]
sqlite3_create_collation_v2 $db1 length length_cmp noop
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - no such collation sequence: length}}
do_test 3.5 {
sqlite3rbu_vacuum rbu test.db state.db
set db1 [rbu db 0]
set db2 [rbu db 1]
sqlite3_create_collation_v2 $db1 length length_cmp noop
sqlite3_create_collation_v2 $db2 length length_cmp noop
while {[rbu step]=="SQLITE_OK"} {}
list [catch { rbu close } msg] $msg
} {0 SQLITE_DONE}
catch { db close }
finish_test
+579 -179
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -314,6 +314,38 @@ sqlite3rbu *sqlite3rbu_open(
const char *zState
);
/*
** Open an RBU handle to perform an RBU vacuum on database file zTarget.
** An RBU vacuum is similar to SQLite's built-in VACUUM command, except
** that it can be suspended and resumed like an RBU update.
**
** The second argument to this function, which may not be NULL, identifies
** a database in which to store the state of the RBU vacuum operation if
** it is suspended. The first time sqlite3rbu_vacuum() is called, to start
** an RBU vacuum operation, the state database should either not exist or
** be empty (contain no tables). If an RBU vacuum is suspended by calling
** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has
** returned SQLITE_DONE, the vacuum state is stored in the state database.
** The vacuum can be resumed by calling this function to open a new RBU
** handle specifying the same target and state databases.
**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
** of the state tables within the state database are zeroed. This way,
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
** new RBU vacuum operation.
**
** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
** describing the sqlite3rbu_create_vfs() API function below for
** a description of the complications associated with using RBU with
** zipvfs databases.
*/
sqlite3rbu *sqlite3rbu_vacuum(
const char *zTarget,
const char *zState
);
/*
** Internally, each RBU connection uses a separate SQLite database
** connection to access the target and rbu update databases. This
+49 -2
View File
@@ -20,8 +20,9 @@
#include <tcl.h>
#include <assert.h>
/* From main.c (apparently...) */
/* From main.c */
extern const char *sqlite3ErrName(int);
extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
@@ -66,7 +67,8 @@ static int test_sqlite3rbu_cmd(
{"create_rbu_delta", 2, ""}, /* 2 */
{"savestate", 2, ""}, /* 3 */
{"dbMain_eval", 3, "SQL"}, /* 4 */
{"bp_progress", 2, ""}, /* 5 */
{"bp_progress", 2, ""}, /* 5 */
{"db", 3, "RBU"}, /* 6 */
{0,0,0}
};
int iCmd;
@@ -149,6 +151,22 @@ static int test_sqlite3rbu_cmd(
break;
}
case 6: /* db */ {
int bArg;
if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){
ret = TCL_ERROR;
}else{
char zBuf[50];
sqlite3 *db = sqlite3rbu_db(pRbu, bArg);
if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){
ret = TCL_ERROR;
}else{
Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
}
}
break;
}
default: /* seems unlikely */
assert( !"cannot happen" );
break;
@@ -187,6 +205,34 @@ static int test_sqlite3rbu(
return TCL_OK;
}
/*
** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db>
*/
static int test_sqlite3rbu_vacuum(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3rbu *pRbu = 0;
const char *zCmd;
const char *zTarget;
const char *zStateDb = 0;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB STATE-DB");
return TCL_ERROR;
}
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
zStateDb = Tcl_GetString(objv[3]);
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
/*
** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
*/
@@ -274,6 +320,7 @@ int SqliteRbu_Init(Tcl_Interp *interp){
Tcl_ObjCmdProc *xProc;
} aObjCmd[] = {
{ "sqlite3rbu", test_sqlite3rbu },
{ "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum },
{ "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
{ "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
{ "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },
+1
View File
@@ -17,6 +17,7 @@ if {![info exists testdir]} {
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionfault
+1
View File
@@ -17,6 +17,7 @@ if {![info exists testdir]} {
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionfault2
do_execsql_test 1.0.0 {
+24 -21
View File
@@ -278,19 +278,18 @@ static int sessionVarintGet(u8 *aBuf, int *piVal){
return getVarint32(aBuf, *piVal);
}
/* Load an unaligned and unsigned 32-bit integer */
#define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
/*
** Read a 64-bit big-endian integer value from buffer aRec[]. Return
** the value read.
*/
static sqlite3_int64 sessionGetI64(u8 *aRec){
return (((sqlite3_int64)aRec[0]) << 56)
+ (((sqlite3_int64)aRec[1]) << 48)
+ (((sqlite3_int64)aRec[2]) << 40)
+ (((sqlite3_int64)aRec[3]) << 32)
+ (((sqlite3_int64)aRec[4]) << 24)
+ (((sqlite3_int64)aRec[5]) << 16)
+ (((sqlite3_int64)aRec[6]) << 8)
+ (((sqlite3_int64)aRec[7]) << 0);
u64 x = SESSION_UINT32(aRec);
u32 y = SESSION_UINT32(aRec+4);
x = (x<<32) + y;
return (sqlite3_int64)x;
}
/*
@@ -592,14 +591,19 @@ static int sessionChangeEqual(
int iCol; /* Used to iterate through table columns */
for(iCol=0; iCol<pTab->nCol; iCol++){
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( pTab->abPK[iCol] ){
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){
return 0;
if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){
return 0;
}
a1 += n1;
a2 += n2;
}else{
if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1);
if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2);
}
if( pTab->abPK[iCol] || bLeftPkOnly==0 ) a1 += n1;
if( pTab->abPK[iCol] || bRightPkOnly==0 ) a2 += n2;
}
return 1;
@@ -935,9 +939,9 @@ static int sessionTableInfo(
int nDbCol = 0;
int nThis;
int i;
u8 *pAlloc;
u8 *pAlloc = 0;
char **azCol = 0;
u8 *abPK;
u8 *abPK = 0;
assert( pazCol && pabPK );
@@ -1593,9 +1597,9 @@ static void sessionDeleteTable(SessionTable *pList){
pNext = pTab->pNext;
for(i=0; i<pTab->nChange; i++){
SessionChange *p;
SessionChange *pNext;
for(p=pTab->apChange[i]; p; p=pNext){
pNext = p->pNext;
SessionChange *pNextChange;
for(p=pTab->apChange[i]; p; p=pNextChange){
pNextChange = p->pNext;
sqlite3_free(p);
}
}
@@ -2882,7 +2886,6 @@ static int sessionChangesetNext(
** modified fields are present in the new.* record. The old.* record
** is currently completely empty. This block shifts the PK fields from
** new.* to old.*, to accommodate the code that reads these arrays. */
int i;
for(i=0; i<p->nCol; i++){
assert( p->apValue[i]==0 );
assert( p->abPK[i]==0 || p->apValue[i+p->nCol] );
@@ -3655,7 +3658,7 @@ static int sessionConflictHandler(
void *pCtx, /* First argument for conflict handler */
int *pbReplace /* OUT: Set to true if PK row is found */
){
int res; /* Value returned by conflict handler */
int res = 0; /* Value returned by conflict handler */
int rc;
int nCol;
int op;
+2 -2
View File
@@ -1,5 +1,5 @@
#ifndef __SQLITESESSION_H_
#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION)
#define __SQLITESESSION_H_ 1
/*
@@ -1274,4 +1274,4 @@ int sqlite3changegroup_output_strm(sqlite3_changegroup*,
}
#endif
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */
+2 -3
View File
@@ -314,7 +314,8 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){
pObj = Tcl_NewStringObj(z, n);
break;
}
case SQLITE_BLOB:
default:
assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
Tcl_ListObjAppendElement(0, pList, Tcl_NewStringObj("b", 1));
pObj = Tcl_NewByteArrayObj(
sqlite3_value_blob(pVal),
@@ -871,7 +872,6 @@ static int test_sqlite3session_foreach(
pOld = Tcl_NewObj();
if( op!=SQLITE_INSERT ){
int i;
for(i=0; i<nCol; i++){
sqlite3_value *pVal;
sqlite3changeset_old(pIter, i, &pVal);
@@ -880,7 +880,6 @@ static int test_sqlite3session_foreach(
}
pNew = Tcl_NewObj();
if( op!=SQLITE_DELETE ){
int i;
for(i=0; i<nCol; i++){
sqlite3_value *pVal;
sqlite3changeset_new(pIter, i, &pVal);
+1 -3
View File
@@ -388,8 +388,7 @@ TESTSRC2 = \
$(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/session/test_session.c \
$(FTS5_SRC)
$(TOP)/ext/session/test_session.c
# Header files used by all library source files.
#
@@ -905,7 +904,6 @@ clean:
rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
rm -f $(PUBLISH)
rm -f *.da *.bb *.bbg gmon.out
rm -rf quota2a quota2b quota2c
rm -rf tsrc target_source
rm -f testloadext.dll libtestloadext.so
rm -f amalgamation-testfixture amalgamation-testfixture.exe
+138 -129
View File
@@ -1,8 +1,8 @@
C Add\sanother\sOOM\stest\sto\sthis\sbranch.
D 2016-03-31T15:08:10.284
F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449
C Version\s3.13.0
D 2016-05-18T10:57:30.274
F Makefile.in 9eda6e1c90d05c199c3ec8a7069b0682ad307657
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998
F Makefile.msc db82b35aef27f412fef14d8534afc022138bcdfd
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 5d234da9b5dae329fab75ff75884cfe0a9cb3fda
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -10,11 +10,11 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 42f7eb1fb2b06ddd6c6adab3e4388cc0a237ba40
F autoconf/Makefile.msc dc0d0500e4a827cb3891d08d846dd6dd40241b51
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
F autoconf/Makefile.msc 0eca137c12542bd76c253a2d24380f29ade59b95
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac d807b567f73a2b0986ccdd206b782cecb4d08fff
F autoconf/configure.ac ad7001cdde3d6ae6053bc0b66009869d7c5012a8
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -30,8 +30,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure dbd42c55ca6b65e0fb37ef54121755f26a890edf x
F configure.ac 89e4e02a83d8a1528011f8395621b8c3186b4089
F configure df9f793ad47eaeb3648a9090fbc0b96955e88b5a x
F configure.ac 02b972db825685b4b0cca0234b2aa97f71bd15a5
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html e2118945e5f07ed146b45c9cd2b2dd6eabb8ebf2
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
@@ -81,7 +81,7 @@ F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
F ext/fts3/fts3_test.c 11e36437b0f3f2266acea5b4787f615e4337a237
F ext/fts3/fts3_test.c a940cf104d545ad1abf926956ce65db2aa5af0cf
F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
F ext/fts3/fts3_tokenizer.c 3cf21cd2212db17a88d4ef7da0fd8a80275979a1
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
@@ -91,20 +91,20 @@ F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
F ext/fts3/fts3_write.c c3863f23b6b4623c8b9d5cf31c12ce4469f78ca9
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7
F ext/fts5/fts5.h b770c5e0a8d2ee071ddffc7ab722dbf3474a8abe
F ext/fts5/fts5Int.h 3677076aecbf645a7f2a019115c6a4ec3272dd78
F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c 5ca4bafe29aa3d27683c90e836192e4aefd20a3f
F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337
F ext/fts5/fts5_index.c fdd82bb421a5d1e64d004acb43f4dd9970c8d2b3
F ext/fts5/fts5_expr.c da2b33c2aac91e96641c0a7cf2bbaa36eb2667f7
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c b429e23fabb57506f71e406997cc46b89190dc97
F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55
F ext/fts5/fts5_storage.c 3309c6a8e34b974513016fd1ef47c83f5898f94c
F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966
@@ -131,7 +131,7 @@ F ext/fts5/test/fts5ak.test fb26389985407826f6076bb9f382c67d3db6b5d9
F ext/fts5/test/fts5al.test 18c277f5986df0a3d9071dfd7128afeb16fe9d5d
F ext/fts5/test/fts5alter.test 6022c61467a82aa11c70822ccad22b328dcf0d04
F ext/fts5/test/fts5auto.test 401c20e89f1114d733b94809be1e6f893e16c09e
F ext/fts5/test/fts5aux.test 8c687c948cc98e9a94be014df7d518acc1b3b74f
F ext/fts5/test/fts5aux.test 5dd158a1e7869e27e9762a2a452b189c728d1be3
F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
F ext/fts5/test/fts5bigtok.test 017a9397b14e7598883a6328ead4a6539b42d59a
@@ -201,28 +201,28 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 4bdf4c5daedabcd8e6eb6e6a377657f7b978f9f7
F ext/icu/icu.c 43df9d8ef2fae7a325100ebd713ab089dc829dd7
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c b9c88d5c3b6ecd8c731ffdd7f5b3d902857f8c96
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 598bbc45516227701558becdd38f4e6fe8e97cc2
F ext/misc/spellfix.c bf1b922c2750698e9a3d4c50cce6974adb7e93be
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rbu/rbu.c ba3983dceffa0938532e79142f391737513de023
F ext/rbu/rbu.c b2c0b5e6ae1a89affc0edfc127ebfa5f637a0ce4
F ext/rbu/rbu1.test 42bd835e019eff789ec241017965277baeb658b1
F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d
F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
@@ -243,12 +243,14 @@ F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695
F ext/rbu/rbudiff.test 2df0a8a7d998ecf81764c21eeda3cde5611c5091
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/sqlite3rbu.c 007fc4db8c0b95c7ef10162b5864921ef5cc8106
F ext/rbu/sqlite3rbu.h d7cc99350c10134f358fe1a8997d9225b3f712b2
F ext/rbu/test_rbu.c 3505641a78b723589b8780d5f9b2faeeb73e037d
F ext/rbu/rbuvacuum.test 66e02cf299836770e718e95c36686be0b26dbda3
F ext/rbu/sqlite3rbu.c bf36625990c6865ecf08bd844d8097ed2d0a6958
F ext/rbu/sqlite3rbu.h 2acd0a6344a6079de15c8dc9d84d3df83a665930
F ext/rbu/test_rbu.c 9bbdf6bd8efd58fbc4f192698df50569598fbb9e
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 0b870ccb7b58b734a2a8e1e2755a7c0ded070920
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@@ -289,18 +291,18 @@ F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596
F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40
F ext/session/sessionfault2.test ac1dfd77a0fb0ea310aee40a16645ef1b66d3f88
F ext/session/sqlite3session.c 2fc72bd989c424a15802da766c7ebd8eed47bcf6
F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d
F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
F ext/session/sqlite3session.c 37485891b4add26cf61495df193c419f36556a32
F ext/session/sqlite3session.h 69bf73cfd71e58f2ae5d2aa935b2c1a541aee555
F ext/session/test_session.c 464f2c8bf502795d95969387eb8e93f68c513c15
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 942e1fd30eb352492cf599aa7fcb5334783e4cbf
F main.mk 86e6a8d79186ace5ff8b306093da1728d953f796
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -313,41 +315,41 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b
F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188
F src/analyze.c 37fedc80ac966ce1745811746e68e4d8fa64c7fe
F src/attach.c 771153bd1f4ab0b97a44a13dde2c7e5e1efeba22
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce
F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0
F src/btree.c e53a01547d61a3d567daf7a7acc30122fe071aef
F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 39faaaeecb77eb3936d4bd5024e865e3836ca323
F src/build.c d65be62254ca9df36e1e1c433324f0333f80009c
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b
F src/delete.c eeac28b3d3d88e3541bdf93e91ea7492a7b67842
F src/expr.c 289ffac5240b60fee0a824d3d5ab2d7bd2630c94
F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f
F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb
F src/func.c 552d300265aed09eea21f68ac742a440550c0062
F src/global.c 884d4c7eba9f5fc25c96a23b21520da19b7713e2
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/func.c ef4c18c8a66143413ce41a58d582d2c14ddf78e1
F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015
F src/hash.c 55b5fb474100cee0b901edaf203e26c970940f36
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c e70f8f9e97624a232870ea5486e682c813ac3002
F src/main.c 5ac9dccc03faadd6f867f67b9018ff41eeeadb46
F src/loadext.c 8b3a73f0624c5f7cadbd5cb89940783bee1d39a6
F src/main.c 405d13e3a4f7c5add9fb27702ae70ed0a6e32cca
F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
F src/memjournal.c 5253fd4335a8d9c64e5df25cb9da6329af5242c7
F src/memjournal.c 95752936c11dc6995672d1dd783cd633eea0cc95
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
@@ -355,42 +357,42 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
F src/os.c ca10edb445ad2c5fdc7285b49d72bcdf261fa23e
F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1
F src/os.c 4d83917f072ad958fba9235136fa2ed43df47905
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c b1ccb273771f41dbdbe0ba7c1ad63c38ad5972ec
F src/os_win.c ff870d89f4cb088a04cbf5ea0cbd9ff1b089ff4a
F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234
F src/os_win.c 852fc2ff6084296348ed3739c548b2cf32df394e
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d
F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56
F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05
F src/pager.c 3910579bfbe323dfabed2b95d201159b61b8ef42
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
F src/pcache.c f398c0084399e7481482cbc6a578a3cc4c3675f3
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c 7f51d2b541aab57596adf62db2c4bb025d34f04d
F src/pragma.c faf42922bb7ab2f6672cb550356c1967abae3c84
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e
F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e
F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143
F src/shell.c cd3f82fdc5c895b817a375b7ab8319cb41f447ce
F src/sqlite.h.in 843a0dfcf8c5e961cfafa62009fed0867b88241e
F src/resolve.c cca3aa77b95706df5d635a2141a4d1de60ae6598
F src/rowset.c 49eb91c588a2bab36647368e031dc5b66928149d
F src/select.c fd4a7ce2937497181063cfedb92058ac89491a5d
F src/shell.c 14ff7f660530a52b117d110ba3390b7b2eb719b6
F src/sqlite.h.in 9984129d86243424b765fcb3f147c697bd20bb54
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2
F src/sqliteInt.h 594bf31a7a0cc788688ca947e562576e23bd7904
F src/sqliteInt.h 4fe51e4e26d9d576040198cef4f78df3d987387d
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/tclsqlite.c 56569acc73d36e836b64aefecbbb709a92ba0077
F src/test1.c 7187b7e924bfc97780e6fd2a40dad94a32bddca0
F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060
F src/test1.c c0e5b69f99e95a2c9f55fdb6e46b44f1a15292d8
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
F src/test3.c 0df6f8dbb4cbaa7106397c70a271fa6a43659042
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
F src/test6.c 2c014d4977efd6107ec9eef3dfdec56ac516f824
F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3
F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
@@ -402,21 +404,21 @@ F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 7003f6f35134de6f19c6588f44783e43390ea277
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b
F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c 96df9381a1ff1f6d3805ff7231b9baf1386aaabf
F src/test_multiplex.c 6a9de820fcaaf506c59aa14bc8693822333cea48
F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950
F src/test_multiplex.c eafc567ebe162e36f17b5062285dfe90461cf8e9
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
F src/test_osinst.c 5423dc1d355f594371f27dd292ca54bd320b8196
F src/test_onefile.c 416f87a28d6d673352d33fc4b1c7d39db878e50f
F src/test_osinst.c ad0233b1dabb0390e25edded4ebd79a2a61538c6
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
@@ -425,40 +427,40 @@ F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_syscall.c 268c072541162564a882c57f54a6fee12ef4a4d2
F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
F src/test_vfs.c 4d02f38bfb8f7f273da7ba84bfe000f5babf206c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61
F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c
F src/tokenize.c 3b29883b0ce4a6c6f643965b66b5ca6613178e59
F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373
F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280
F src/update.c 3e67ab3c0814635f355fb1f8ab010a2b9e016e7d
F src/update.c 4f05ea8cddfa367d045e03589756c02199e8f9bd
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c 8873d696c9ccc4206058c402e09e101f1b81561a
F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52
F src/vdbe.c 0f0e4a6255f9a5272857a818314d081db26bcd90
F src/vdbe.h c16ba943d407baa1c7085eefea73a063fc631863
F src/vdbe.c 4bad04212736526845fda9ca674afafb10078b2b
F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170
F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd
F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c
F src/vdbeaux.c fa06ba5441714160ab5f64422660ee286968672f
F src/vdbeaux.c ace1875da40b7185e604586768d5ac90de7e4f7f
F src/vdbeblob.c c9f2f494b911c6fa34efd9803f0a10807da80f77
F src/vdbemem.c 5cfef60e60e19cab6275d1b975bf4c791d575beb
F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062
F src/vdbesort.c 0a8f98366ae794442e6d1ef71d9553226d885d19
F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
F src/vtab.c 23b6cdfa996152d43b390504ed4a942c8caf3a00
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b
F src/wal.c 4db22ed7e77bcf672b1a685d6ddeffba8d5be302
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
F src/where.c fe7925faafbe9a458972035c0bb4753d672f04ed
F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34
F src/wherecode.c 863aedf086131743763c1960637fde904eadc442
F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a
F src/where.c fd321cc2c5ee346a2e146b93892ed01bb7a839c0
F src/whereInt.h 3b1fc240e322613ba4e9dc857ca9c7c3390acc74
F src/wherecode.c 23fc19ca546ce323ba5c4be96b88e3ba08cf6b8f
F src/whereexpr.c eacc0e60d029a082b4fc0cc42ea98544add1319e
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -497,7 +499,7 @@ F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360
F test/auth.test 872a122b3977c1d1bb9fd637dc20016e5c01880f
F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa
F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
@@ -510,7 +512,7 @@ F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
F test/backup.test b79299a536a4c6d919094786595b95be56d02014
F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
@@ -519,7 +521,7 @@ F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
F test/bestindex1.test d5ba89a7941a941476d8d69be39b146aaed3614c
F test/bestindex1.test 0cf1bd2d7b97d3a3a8c10736125274f64765c4ee
F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
@@ -551,7 +553,7 @@ F test/capi3c.test 0b9edb0c2156a964b9271cd5ea7ae56736cc2fcb
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
@@ -610,12 +612,12 @@ F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
F test/delete4.test 3ac0b8d23689ba764c2e8b78c1b56b8f1b942fa2
F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
@@ -642,7 +644,7 @@ F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519
F test/e_vacuum.test 4d5b391384bb7d56bb9337d956f08035332421fc
F test/e_vacuum.test 120f29ea56bdce4d43279527ece894ab5d1729d3
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
@@ -657,7 +659,7 @@ F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
@@ -806,7 +808,7 @@ F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test 40523db3aa76d62bda71c26f824fa0eabc420f0e
F test/hook.test 3b7b99d0eece6d279812c2aef6fa08bdfabc633e
F test/icu.test 73956798bace8982909c00476b216714a6d0559a
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
@@ -823,7 +825,7 @@ F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
@@ -845,7 +847,7 @@ F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/intpkey.test 70aab09756b9bd3bcb6b0358f971d7bbace46522
F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
@@ -860,7 +862,7 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 8a5c0be6f0c260a5c7177c3b8f07c7856141038a
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
@@ -875,9 +877,9 @@ F test/like.test 81632c437a947bf1f7130b19537da6a1a844806a
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
F test/loadext.test 42a3b8166dfcadcb0e0c8710dc520d97c31a8b98
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
@@ -966,7 +968,7 @@ F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
F test/pagerfault.test 42ff797b1e6426c141cc7ee8b7417c9f27427950
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
@@ -975,10 +977,10 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test cd1fa041074ed08eeaa563e4d1bacb0c69337ec1
F test/pragma.test afbf028be1c35b68f57db8eb015c4a3c59d8f28e
F test/permutations.test 544a2f317fc5045bc512ae432f89eae303c0d640
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 3f1984a04657331f838df5c519b443c2088df922
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -986,7 +988,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
F test/quota.test 36cd78b178c4eb0401d4f25754ef410fbd9df2a7
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
@@ -996,7 +998,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl f2519836bebefcc7db36b4946e8028d4885baa59
F test/releasetest.tcl 7d80014d0245b3f9d02d393d420bf03ca155aec0
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
@@ -1011,7 +1013,7 @@ F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test db3db281486c925095f305aad09fe806e5188ff3
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
@@ -1024,7 +1026,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test d926792a5e4d88fef0ddcddeb45d27ce75f7296c
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61
@@ -1051,7 +1053,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test dff5b20ad989770aface6d714491121172dfe8b0
F test/shell1.test c90b0415cea6eeefb86b4ab1651b06247922ca52
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd
F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9
@@ -1065,7 +1067,7 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
F test/snapshot.test 9ed24c792fb05382814258daf68b2256f23de57f
F test/snapshot.test a19465046168b4420b5afeed37c3214e42a49f4a
F test/snapshot_fault.test 062ff0438a074978d45e9f9a92e7ad459b74ee73
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1073,7 +1075,7 @@ F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b
F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5
F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c
F test/sort5.test d3041ce3c475aa04142a959ae56ef6593f98a99f
F test/sort5.test 30cc17768e0c06ecb048e08efec59c11811fd186
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
@@ -1083,14 +1085,14 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 21af8db2492a903835b654517ac8d90aed0af91f
F test/speedtest1.c 4476f7030775507f060d27b789e1f4123c5a5866
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
F test/stat.test b65bad7120c52583b8f0054d99eff80718119a77
F test/stat.test 66e95f97b9f724f9ab921d054ee0db3c2689f1ee
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
@@ -1100,7 +1102,7 @@ F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906
@@ -1109,9 +1111,13 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
F test/tempdb2.test 4fc92055f2a3f7626c0f2eabbb637dc021b311d5
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl 7b740ee852c55e1e72b6ebe5044acee7aa4e5553
F test/tester.tcl 3ace46dee55f07e28a1e3ab03258b929fefcee5b
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1127,10 +1133,10 @@ F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
F test/tkt-2d1a5c67d.test d371279946622698ab393ff88cad9f5f6d82960b
F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
F test/tkt-385a5b56b9.test c0a06ada41d7f06b1686da0e718553f853771d1e
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
@@ -1141,7 +1147,7 @@ F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa
F test/tkt-5d863f876e.test 726e76d725f6fe0eb2fc8a522b721b79807380ee
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
@@ -1157,7 +1163,7 @@ F test/tkt-8c63ff0ec.test 258b7fc8d7e4e1cb5362c7d65c143528b9c4cbed
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6
F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
@@ -1308,7 +1314,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test f6c3a39e0c819891265e1d0754e99960d81ef6c9
F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab
F test/vtab1.test 7c4b81abd88361ada9cbe414c459efca26be6bda
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
@@ -1396,7 +1402,7 @@ F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test 2d725c214b883e25ae6bb85ef228ecdfa03c6a7b
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
@@ -1412,15 +1418,15 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c cfbfe061a4b2766512f6b484882eee2c86a14506
F tool/lemon.c f38a55106d79b7a4c063abb958517d6c47dc6ac7
F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22
F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1436,13 +1442,13 @@ F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
F tool/showdb.c 82dca79a999b2701c62417636345e9974151fdad
F tool/showdb.c c695a5d5c8110640e0d9fadf5e254da90c79c36e
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
F tool/showstat4.c bda40d6e395df7edb6e9ea630784d3d762c35b4b
F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl 93c1fdc9733c525b17a2024c7df193daa002e037
F tool/spaceanal.tcl 85d90e6674d8298e3eaf82dbcef3abc2d5317f3e
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -1450,7 +1456,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/sqldiff.c ca315aca4e2d24233e8f2000edea5880c53d1875
F tool/srcck1.c 4f65e1a6748e42f24c0ea629dddc934d821c729a
F tool/srcck1.c 4c39bdfa9a92edd20233ee720df84dbeb2417602
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
@@ -1482,7 +1488,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 195f3340ee4d870420e4f58d44300bab5436b920
R 553c882c4eb73691c7e02bdd576b9d70
U dan
Z 5ef40d72349254975dc55c844d6daff8
P 995c084bde44e678facc5f5d95a2335ce61e57b0
R 0e39e66ffd1d7cd6d62e8fa571ff36a1
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.13.0 *
U drh
Z ecdfa0c32602745fc488e92155fa5f0d
+1 -1
View File
@@ -1 +1 @@
49763fc3ae2fb6117b0443ea28661568467f9bf2
fc49f556e48970561d7ab6a2f24fdd7d9eb81ff2
+17 -14
View File
@@ -1826,7 +1826,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
analysisInfo sInfo;
HashElem *i;
char *zSql;
int rc;
int rc = SQLITE_OK;
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
@@ -1835,31 +1835,34 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3DefaultRowEst(pIdx);
pIdx->aiRowLogEst[0] = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
#endif
}
/* Check to make sure the sqlite_stat1 table exists */
/* Load new statistics out of the sqlite_stat1 table */
sInfo.db = db;
sInfo.zDatabase = db->aDb[iDb].zName;
if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
return SQLITE_ERROR;
if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
zSql = sqlite3MPrintf(db,
"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
sqlite3DbFree(db, zSql);
}
}
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf(db,
"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
sqlite3DbFree(db, zSql);
/* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx);
}
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
+32 -32
View File
@@ -1676,11 +1676,11 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->xCellSize = cellSizePtr;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
/* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior
** table b-tree page. */
/* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an
** interior table b-tree page. */
assert( (PTF_LEAFDATA|PTF_INTKEY)==5 );
/* EVIDENCE-OF: R-20501-61796 A value of 13 means the page is a leaf
** table b-tree page. */
/* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a
** leaf table b-tree page. */
assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
pPage->intKey = 1;
if( pPage->leaf ){
@@ -1694,11 +1694,11 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->maxLocal = pBt->maxLeaf;
pPage->minLocal = pBt->minLeaf;
}else if( flagByte==PTF_ZERODATA ){
/* EVIDENCE-OF: R-27225-53936 A value of 2 means the page is an interior
** index b-tree page. */
/* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an
** interior index b-tree page. */
assert( (PTF_ZERODATA)==2 );
/* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf
** index b-tree page. */
/* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a
** leaf index b-tree page. */
assert( (PTF_ZERODATA|PTF_LEAF)==10 );
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
@@ -6545,8 +6545,8 @@ static int pageInsertArray(
u8 *pSlot;
sz = cachedCellSize(pCArray, i);
if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
if( (pData - pBegin)<sz ) return 1;
pData -= sz;
if( pData<pBegin ) return 1;
pSlot = pData;
}
/* pSlot and pCArray->apCell[i] will never overlap on a well-formed
@@ -6708,7 +6708,7 @@ static int editPage(
for(i=0; i<nNew && !CORRUPT_DB; i++){
u8 *pCell = pCArray->apCell[i+iNew];
int iOff = get2byteAligned(&pPg->aCellIdx[i*2]);
if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){
if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){
pCell = &pTmp[pCell - aData];
}
assert( 0==memcmp(pCell, &aData[iOff],
@@ -8140,6 +8140,28 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
pPage = pCur->apPage[iCellDepth];
pCell = findCell(pPage, iCellIdx);
/* If the bPreserve flag is set to true, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
** returning.
**
** Or, if the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
** before or after the deleted entry. In this case set bSkipnext to true. */
if( bPreserve ){
if( !pPage->leaf
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
){
/* A b-tree rebalance will be required after deleting this entry.
** Save the cursor key. */
rc = saveCursorKey(pCur);
if( rc ) return rc;
}else{
bSkipnext = 1;
}
}
/* If the page containing the entry to delete is not a leaf page, move
** the cursor to the largest entry in the tree that is smaller than
** the entry being deleted. This cell will replace the cell being deleted
@@ -8166,28 +8188,6 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
invalidateIncrblobCursors(p, pCur->info.nKey, 0);
}
/* If the bPreserve flag is set to true, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
** returning.
**
** Or, if the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
** before or after the deleted entry. In this case set bSkipnext to true. */
if( bPreserve ){
if( !pPage->leaf
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
){
/* A b-tree rebalance will be required after deleting this entry.
** Save the cursor key. */
rc = saveCursorKey(pCur);
if( rc ) return rc;
}else{
bSkipnext = 1;
}
}
/* Make the page containing the entry to be deleted writable. Then free any
** overflow pages associated with the entry and finally remove the cell
** itself from within the page. */
+53 -40
View File
@@ -592,16 +592,10 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
** db parameter can be used with db->pnBytesFreed to measure the memory
** used by the Table object.
*/
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
Index *pIndex, *pNext;
TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */
assert( !pTable || pTable->nRef>0 );
/* Do not delete the table until the reference count reaches zero. */
if( !pTable ) return;
if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
/* Record the number of outstanding lookaside allocations in schema Tables
** prior to doing any free() operations. Since schema Tables do not use
** lookaside, this number should not change. */
@@ -641,6 +635,13 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Verify that no lookaside memory was used by schema tables */
assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
}
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
if( !pTable ) return;
if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
deleteTable(db, pTable);
}
/*
** Unlink the given table from the hash tables and the delete the
@@ -1086,6 +1087,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
zType = z + sqlite3Strlen30(z) + 1;
memcpy(zType, pType->z, pType->n);
zType[pType->n] = 0;
sqlite3Dequote(zType);
pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst);
pCol->colFlags |= COLFLAG_HASTYPE;
}
@@ -2176,44 +2178,55 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** statement that defines the view.
*/
assert( pTable->pSelect );
if( pTable->pCheck ){
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
db->lookaside.bDisable++;
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
db->lookaside.bDisable--;
}else{
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
db->lookaside.bDisable++;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
db->xAuth = xAuth;
xAuth = db->xAuth;
db->xAuth = 0;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
db->xAuth = xAuth;
#else
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
#endif
db->lookaside.bDisable--;
pParse->nTab = n;
if( pSelTab ){
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(db, pSelTab);
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
}else{
pTable->nCol = 0;
nErr++;
pParse->nTab = n;
if( pTable->pCheck ){
/* CREATE VIEW name(arglist) AS ...
** The names of the columns in the table are taken from
** arglist which is stored in pTable->pCheck. The pCheck field
** normally holds CHECK constraints on an ordinary table, but for
** a VIEW it holds the list of column names.
*/
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
if( db->mallocFailed==0
&& pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel);
}
sqlite3SelectDelete(db, pSel);
} else {
}else if( pSelTab ){
/* CREATE VIEW name AS... without an argument list. Construct
** the column names from the SELECT statement that defines the view.
*/
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
}else{
pTable->nCol = 0;
nErr++;
}
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
db->lookaside.bDisable--;
} else {
nErr++;
}
pTable->pSchema->schemaFlags |= DB_UnresetViews;
#endif /* SQLITE_OMIT_VIEW */
@@ -2762,6 +2775,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
tnum = pIndex->tnum;
}
pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
@@ -2785,8 +2799,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
if( IsUniqueIndex(pIndex) && pKey!=0 ){
if( IsUniqueIndex(pIndex) ){
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
sqlite3VdbeGoto(v, j2);
addr2 = sqlite3VdbeCurrentAddr(v);
+10 -1
View File
@@ -50,6 +50,15 @@
#ifndef SQLITE_OMIT_DATETIME_FUNCS
/*
** The MSVC CRT on Windows CE may not have a localtime() function.
** So declare a substitute. The substitute function itself is
** defined in "os_win.c".
*/
#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
(!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
struct tm *__cdecl localtime(const time_t *);
#endif
/*
** A structure for holding a single date and time.
@@ -418,6 +427,7 @@ static void clearYMD_HMS_TZ(DateTime *p){
p->validTZ = 0;
}
#ifndef SQLITE_OMIT_LOCALTIME
/*
** On recent Windows platforms, the localtime_s() function is available
** as part of the "Secure CRT". It is essentially equivalent to
@@ -436,7 +446,6 @@ static void clearYMD_HMS_TZ(DateTime *p){
#define HAVE_LOCALTIME_S 1
#endif
#ifndef SQLITE_OMIT_LOCALTIME
/*
** The following routine implements the rough equivalent of localtime_r()
** using whatever operating-system specific localtime facility that
+11 -20
View File
@@ -143,7 +143,7 @@ Expr *sqlite3LimitWhere(
*/
if( pOrderBy && (pLimit == 0) ) {
sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
goto limit_where_cleanup_2;
goto limit_where_cleanup;
}
/* We only need to generate a select expression if there
@@ -165,16 +165,16 @@ Expr *sqlite3LimitWhere(
*/
pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
if( pSelectRowid == 0 ) goto limit_where_cleanup;
pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
if( pEList == 0 ) goto limit_where_cleanup_2;
if( pEList == 0 ) goto limit_where_cleanup;
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
if( pSelectSrc == 0 ) {
sqlite3ExprListDelete(pParse->db, pEList);
goto limit_where_cleanup_2;
goto limit_where_cleanup;
}
/* generate the SELECT expression tree. */
@@ -184,21 +184,11 @@ Expr *sqlite3LimitWhere(
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
if( pInClause == 0 ) goto limit_where_cleanup_1;
pInClause->x.pSelect = pSelect;
pInClause->flags |= EP_xIsSelect;
sqlite3ExprSetHeightAndFlags(pParse, pInClause);
pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0;
sqlite3PExprAddSelect(pParse, pInClause, pSelect);
return pInClause;
/* something went wrong. clean up anything allocated. */
limit_where_cleanup_1:
sqlite3SelectDelete(pParse->db, pSelect);
return 0;
limit_where_cleanup_2:
limit_where_cleanup:
sqlite3ExprDelete(pParse->db, pWhere);
sqlite3ExprListDelete(pParse->db, pOrderBy);
sqlite3ExprDelete(pParse->db, pLimit);
@@ -249,11 +239,12 @@ void sqlite3DeleteFrom(
int addrBypass = 0; /* Address of jump over the delete logic */
int addrLoop = 0; /* Top of the delete loop */
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */
int bComplex; /* True if there are triggers or FKs or
** subqueries in the WHERE clause */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
Trigger *pTrigger; /* List of table triggers, if required */
int bComplex; /* True if there are either triggers or FKs */
#endif
memset(&sContext, 0, sizeof(sContext));
@@ -281,7 +272,6 @@ void sqlite3DeleteFrom(
#else
# define pTrigger 0
# define isView 0
# define bComplex 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
@@ -383,7 +373,8 @@ void sqlite3DeleteFrom(
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
if( HasRowid(pTab) ){
/* For a rowid table, initialize the RowSet to an empty set */
+127 -92
View File
@@ -471,15 +471,13 @@ Expr *sqlite3ExprAlloc(
pNew->flags |= EP_IntValue;
pNew->u.iValue = iValue;
}else{
int c;
pNew->u.zToken = (char*)&pNew[1];
assert( pToken->z!=0 || pToken->n==0 );
if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
if( dequote && nExtra>=3
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted;
sqlite3Dequote(pNew->u.zToken);
if( c=='"' ) pNew->flags |= EP_DblQuoted;
}
}
}
@@ -562,6 +560,22 @@ Expr *sqlite3PExpr(
return p;
}
/*
** Add pSelect to the Expr.x.pSelect field. Or, if pExpr is NULL (due
** do a memory allocation failure) then delete the pSelect object.
*/
void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
if( pExpr ){
pExpr->x.pSelect = pSelect;
ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery);
sqlite3ExprSetHeightAndFlags(pParse, pExpr);
}else{
assert( pParse->db->mallocFailed );
sqlite3SelectDelete(pParse->db, pSelect);
}
}
/*
** If the expression is always either TRUE or FALSE (respectively),
** then return 1. If one cannot determine the truth value of the
@@ -722,8 +736,8 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
/*
** Recursively delete an expression tree.
*/
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
if( !ExprHasProperty(p, EP_TokenOnly) ){
@@ -742,6 +756,9 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
sqlite3DbFree(db, p);
}
}
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/*
** Return the number of bytes allocated for the expression structure
@@ -793,7 +810,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==(flags&EXPRDUP_REDUCE) ){
if( 0==flags ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -855,88 +872,88 @@ static int dupedExprSize(Expr *p, int flags){
** if any. Before returning, *pzBuffer is set to the first byte past the
** portion of the buffer copied into by this function.
*/
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
Expr *pNew = 0; /* Value to return */
assert( flags==0 || flags==EXPRDUP_REDUCE );
static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
Expr *pNew; /* Value to return */
u8 *zAlloc; /* Memory space from which to build Expr object */
u32 staticFlag; /* EP_Static if space not obtained from malloc */
assert( db!=0 );
if( p ){
const int isReduced = (flags&EXPRDUP_REDUCE);
u8 *zAlloc;
u32 staticFlag = 0;
assert( p );
assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE );
assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE );
assert( pzBuffer==0 || isReduced );
/* Figure out where to write the new Expr structure. */
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
}else{
zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
staticFlag = 0;
}
pNew = (Expr *)zAlloc;
/* Figure out where to write the new Expr structure. */
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
if( pNew ){
/* Set nNewSize to the size allocated for the structure pointed to
** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
** by the copy of the p->u.zToken string (if any).
*/
const unsigned nStructSize = dupedExprStructSize(p, dupFlags);
const int nNewSize = nStructSize & 0xfff;
int nToken;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
nToken = sqlite3Strlen30(p->u.zToken) + 1;
}else{
zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags));
nToken = 0;
}
if( dupFlags ){
assert( ExprHasProperty(p, EP_Reduced)==0 );
memcpy(zAlloc, p, nNewSize);
}else{
u32 nSize = (u32)exprStructSize(p);
memcpy(zAlloc, p, nSize);
if( nSize<EXPR_FULLSIZE ){
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
}
}
pNew = (Expr *)zAlloc;
if( pNew ){
/* Set nNewSize to the size allocated for the structure pointed to
** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
** by the copy of the p->u.zToken string (if any).
*/
const unsigned nStructSize = dupedExprStructSize(p, flags);
const int nNewSize = nStructSize & 0xfff;
int nToken;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
nToken = sqlite3Strlen30(p->u.zToken) + 1;
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag;
/* Copy the p->u.zToken string, if any. */
if( nToken ){
char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
memcpy(zToken, p->u.zToken, nToken);
}
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
if( ExprHasProperty(p, EP_xIsSelect) ){
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
}else{
nToken = 0;
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
}
if( isReduced ){
assert( ExprHasProperty(p, EP_Reduced)==0 );
memcpy(zAlloc, p, nNewSize);
}else{
u32 nSize = (u32)exprStructSize(p);
memcpy(zAlloc, p, nSize);
if( nSize<EXPR_FULLSIZE ){
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
}
}
/* Fill in pNew->pLeft and pNew->pRight. */
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
zAlloc += dupedExprNodeSize(p, dupFlags);
if( ExprHasProperty(pNew, EP_Reduced) ){
pNew->pLeft = p->pLeft ?
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
}
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag;
/* Copy the p->u.zToken string, if any. */
if( nToken ){
char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
memcpy(zToken, p->u.zToken, nToken);
if( pzBuffer ){
*pzBuffer = zAlloc;
}
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
if( ExprHasProperty(p, EP_xIsSelect) ){
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
}else{
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced);
}
}else{
if( !ExprHasProperty(p, EP_TokenOnly) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
/* Fill in pNew->pLeft and pNew->pRight. */
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
zAlloc += dupedExprNodeSize(p, flags);
if( ExprHasProperty(pNew, EP_Reduced) ){
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc);
}
if( pzBuffer ){
*pzBuffer = zAlloc;
}
}else{
if( !ExprHasProperty(p, EP_TokenOnly) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
}
}
return pNew;
@@ -988,7 +1005,7 @@ static With *withDup(sqlite3 *db, With *p){
*/
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
assert( flags==0 || flags==EXPRDUP_REDUCE );
return exprDup(db, p, flags, 0);
return p ? exprDup(db, p, flags, 0) : 0;
}
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
ExprList *pNew;
@@ -1210,7 +1227,7 @@ void sqlite3ExprListSetName(
pItem = &pList->a[pList->nExpr-1];
assert( pItem->zName==0 );
pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName);
if( dequote ) sqlite3Dequote(pItem->zName);
}
}
@@ -1259,10 +1276,9 @@ void sqlite3ExprListCheckLength(
/*
** Delete an entire expression list.
*/
void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
int i;
struct ExprList_item *pItem;
if( pList==0 ) return;
assert( pList->a!=0 || pList->nExpr==0 );
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
sqlite3ExprDelete(db, pItem->pExpr);
@@ -1272,6 +1288,9 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
sqlite3DbFree(db, pList->a);
sqlite3DbFree(db, pList);
}
void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
}
/*
** Return the bitwise-OR of all Expr.flags fields in the given
@@ -2316,6 +2335,19 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
}
}
#if defined(SQLITE_DEBUG)
/*
** Verify the consistency of the column cache
*/
static int cacheIsValid(Parse *pParse){
int i, n;
for(i=n=0; i<SQLITE_N_COLCACHE; i++){
if( pParse->aColCache[i].iReg>0 ) n++;
}
return n==pParse->nColCache;
}
#endif
/*
** Clear a cache entry.
*/
@@ -2326,6 +2358,9 @@ static void cacheEntryClear(Parse *pParse, struct yColCache *p){
}
p->tempReg = 0;
}
p->iReg = 0;
pParse->nColCache--;
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
}
@@ -2369,6 +2404,8 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->iReg = iReg;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
pParse->nColCache++;
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
return;
}
}
@@ -2390,6 +2427,7 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->iReg = iReg;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
assert( cacheIsValid(pParse) );
return;
}
}
@@ -2399,15 +2437,13 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
** Purge the range of registers from the column cache.
*/
void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
int i;
int iLast = iReg + nReg - 1;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
int r = p->iReg;
if( r>=iReg && r<=iLast ){
cacheEntryClear(pParse, p);
p->iReg = 0;
}
if( iReg<=0 || pParse->nColCache==0 ) return;
p = &pParse->aColCache[SQLITE_N_COLCACHE-1];
while(1){
if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p);
if( p==pParse->aColCache ) break;
p--;
}
}
@@ -2443,7 +2479,6 @@ void sqlite3ExprCachePop(Parse *pParse){
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
if( p->iReg && p->iLevel>pParse->iCacheLevel ){
cacheEntryClear(pParse, p);
p->iReg = 0;
}
}
}
@@ -2578,7 +2613,6 @@ void sqlite3ExprCacheClear(Parse *pParse){
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
if( p->iReg ){
cacheEntryClear(pParse, p);
p->iReg = 0;
}
}
}
@@ -2620,6 +2654,7 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
}
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
/*
** Convert an expression node to a TK_REGISTER
*/
+8
View File
@@ -1386,6 +1386,14 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3 *db = sqlite3_context_db_handle(context);
char *zErrMsg = 0;
/* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc
** flag is set. See the sqlite3_enable_load_extension() API.
*/
if( (db->flags & SQLITE_LoadExtFunc)==0 ){
sqlite3_result_error(context, "not authorized", -1);
return;
}
if( argc==2 ){
zProc = (const char *)sqlite3_value_text(argv[1]);
}else{
+4 -3
View File
@@ -70,6 +70,7 @@ const unsigned char sqlite3UpperToLower[] = {
** isxdigit() 0x08
** toupper() 0x20
** SQLite identifier character 0x40
** Quote character 0x80
**
** Bit 0x20 is set if the mapped character requires translation to upper
** case. i.e. if the character is a lower-case ASCII character.
@@ -95,7 +96,7 @@ const unsigned char sqlite3CtypeMap[256] = {
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, /* 20..27 !"#$%&' */
0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
@@ -103,8 +104,8 @@ const unsigned char sqlite3CtypeMap[256] = {
0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
+2 -2
View File
@@ -55,7 +55,7 @@ void sqlite3HashClear(Hash *pH){
static unsigned int strHash(const char *z){
unsigned int h = 0;
unsigned char c;
while( (c = (unsigned char)*z++)!=0 ){
while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
}
return h;
@@ -148,7 +148,7 @@ static HashElem *findElementWithHash(
int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */
if( pH->ht ){
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
h = strHash(pKey) % pH->htsize;
pEntry = &pH->ht[h];
+5 -4
View File
@@ -464,8 +464,9 @@ static int sqlite3LoadExtension(
/* Ticket #1863. To avoid a creating security problems for older
** applications that relink against newer versions of SQLite, the
** ability to run load_extension is turned off by default. One
** must call sqlite3_enable_load_extension() to turn on extension
** loading. Otherwise you get the following error.
** must call either sqlite3_enable_load_extension(db) or
** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0)
** to turn on extension loading.
*/
if( (db->flags & SQLITE_LoadExtension)==0 ){
if( pzErrMsg ){
@@ -604,9 +605,9 @@ void sqlite3CloseExtensions(sqlite3 *db){
int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
sqlite3_mutex_enter(db->mutex);
if( onoff ){
db->flags |= SQLITE_LoadExtension;
db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
}else{
db->flags &= ~SQLITE_LoadExtension;
db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
}
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
+1
View File
@@ -804,6 +804,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
+12 -1
View File
@@ -13,6 +13,15 @@
** This file contains code use to implement an in-memory rollback journal.
** The in-memory rollback journal is used to journal transactions for
** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
**
** Update: The in-memory journal is also used to temporarily cache
** smaller journals that are not critical for power-loss recovery.
** For example, statement journals that are not too big will be held
** entirely in memory, thus reducing the number of file I/O calls, and
** more importantly, reducing temporary file creation events. If these
** journals become too large for memory, they are spilled to disk. But
** in the common case, they are usually small and no file I/O needs to
** occur.
*/
#include "sqliteInt.h"
@@ -94,6 +103,7 @@ static int memjrnlRead(
#endif
assert( (iAmt+iOfst)<=p->endpoint.iOffset );
assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 );
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
sqlite3_int64 iOff = 0;
for(pChunk=p->pFirst;
@@ -104,6 +114,7 @@ static int memjrnlRead(
}
}else{
pChunk = p->readpoint.pChunk;
assert( pChunk!=0 );
}
iChunkOffset = (int)(iOfst%p->nChunkSize);
@@ -115,7 +126,7 @@ static int memjrnlRead(
nRead -= iSpace;
iChunkOffset = 0;
} while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
p->readpoint.iOffset = iOfst+iAmt;
p->readpoint.iOffset = pChunk ? iOfst+iAmt : 0;
p->readpoint.pChunk = pChunk;
return SQLITE_OK;
+4 -8
View File
@@ -81,13 +81,11 @@ int sqlite3_memdebug_vfs_oom_test = 1;
** of this would be completely automatic if SQLite were coded using
** C++ instead of plain old C.
*/
int sqlite3OsClose(sqlite3_file *pId){
int rc = SQLITE_OK;
void sqlite3OsClose(sqlite3_file *pId){
if( pId->pMethods ){
rc = pId->pMethods->xClose(pId);
pId->pMethods->xClose(pId);
pId->pMethods = 0;
}
return rc;
}
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
DO_OS_MALLOC_TEST(id);
@@ -305,12 +303,10 @@ int sqlite3OsOpenMalloc(
}
return rc;
}
int sqlite3OsCloseFree(sqlite3_file *pFile){
int rc = SQLITE_OK;
void sqlite3OsCloseFree(sqlite3_file *pFile){
assert( pFile );
rc = sqlite3OsClose(pFile);
sqlite3OsClose(pFile);
sqlite3_free(pFile);
return rc;
}
/*
+2 -2
View File
@@ -160,7 +160,7 @@ int sqlite3OsInit(void);
/*
** Functions for accessing sqlite3_file methods
*/
int sqlite3OsClose(sqlite3_file*);
void sqlite3OsClose(sqlite3_file*);
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
int sqlite3OsTruncate(sqlite3_file*, i64 size);
@@ -205,6 +205,6 @@ int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
** sqlite3_malloc() to obtain space for the file-handle structure.
*/
int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
int sqlite3OsCloseFree(sqlite3_file *);
void sqlite3OsCloseFree(sqlite3_file *);
#endif /* _SQLITE_OS_H_ */
+31 -22
View File
@@ -405,7 +405,7 @@ static struct unix_syscall {
#else
{ "pread64", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent)
{ "write", (sqlite3_syscall_ptr)write, 0 },
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
@@ -423,7 +423,7 @@ static struct unix_syscall {
#else
{ "pwrite64", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\
aSyscall[13].pCurrent)
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
@@ -1502,7 +1502,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** lock transitions in terms of the POSIX advisory shared and exclusive
** lock primitives (called read-locks and write-locks below, to avoid
** confusion with SQLite lock names). The algorithms are complicated
** slightly in order to be compatible with windows systems simultaneously
** slightly in order to be compatible with Windows95 systems simultaneously
** accessing the same database file, in case that is ever required.
**
** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
@@ -1510,8 +1510,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** range', a range of 510 bytes at a well known offset.
**
** To obtain a SHARED lock, a read-lock is obtained on the 'pending
** byte'. If this is successful, a random byte from the 'shared byte
** range' is read-locked and the lock on the 'pending byte' released.
** byte'. If this is successful, 'shared byte range' is read-locked
** and the lock on the 'pending byte' released. (Legacy note: When
** SQLite was first developed, Windows95 systems were still very common,
** and Widnows95 lacks a shared-lock capability. So on Windows95, a
** single randomly selected by from the 'shared byte range' is locked.
** Windows95 is now pretty much extinct, but this work-around for the
** lack of shared-locks on Windows95 lives on, for backwards
** compatibility.)
**
** A process may only obtain a RESERVED lock after it has a SHARED lock.
** A RESERVED lock is implemented by grabbing a write-lock on the
@@ -1530,11 +1536,6 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** range'. Since all other locks require a read-lock on one of the bytes
** within this range, this ensures that no other locks are held on the
** database.
**
** The reason a single byte cannot be used instead of the 'shared byte
** range' is that some versions of windows do not support read-locks. By
** locking a random byte from a range, concurrent SHARED locks may exist
** even if the locking primitive used is always a write-lock.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
@@ -4287,10 +4288,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
pShmNode->h = -1;
pDbFd->pInode->pShmNode = pShmNode;
pShmNode->pInode = pDbFd->pInode;
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->mutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->mutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
}
if( pInode->bProcessLock==0 ){
@@ -5409,20 +5412,24 @@ static const char *unixTempFileDir(void){
"/tmp",
"."
};
unsigned int i;
unsigned int i = 0;
struct stat buf;
const char *zDir = sqlite3_temp_directory;
if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
if( zDir==0 ) continue;
if( osStat(zDir, &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
if( osAccess(zDir, 07) ) continue;
break;
while(1){
if( zDir!=0
&& osStat(zDir, &buf)==0
&& S_ISDIR(buf.st_mode)
&& osAccess(zDir, 03)==0
){
return zDir;
}
if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
zDir = azDirs[i++];
}
return zDir;
return 0;
}
/*
@@ -5438,9 +5445,11 @@ static int unixGetTempname(int nBuf, char *zBuf){
** using the io-error infrastructure to test that SQLite handles this
** function failing.
*/
zBuf[0] = 0;
SimulateIOError( return SQLITE_IOERR );
zDir = unixTempFileDir();
if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
do{
u64 r;
sqlite3_randomness(sizeof(r), &r);
+195 -86
View File
@@ -1260,8 +1260,8 @@ int sqlite3_win32_reset_heap(){
int rc;
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); )
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
sqlite3_mutex_enter(pMaster);
sqlite3_mutex_enter(pMem);
winMemAssertMagic();
@@ -1306,6 +1306,12 @@ void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zBuf ){
(void)SQLITE_MISUSE_BKPT;
return;
}
#endif
#if defined(SQLITE_WIN32_HAS_ANSI)
if( nMin>0 ){
memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
@@ -1631,147 +1637,244 @@ void sqlite3MemSetDefault(void){
#endif /* SQLITE_WIN32_MALLOC */
/*
** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
** Convert a UTF-8 string to Microsoft Unicode.
**
** Space to hold the returned string is obtained from malloc.
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static LPWSTR winUtf8ToUnicode(const char *zFilename){
static LPWSTR winUtf8ToUnicode(const char *zText){
int nChar;
LPWSTR zWideFilename;
LPWSTR zWideText;
nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
if( nChar==0 ){
return 0;
}
zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
if( zWideFilename==0 ){
zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) );
if( zWideText==0 ){
return 0;
}
nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
nChar);
if( nChar==0 ){
sqlite3_free(zWideFilename);
zWideFilename = 0;
sqlite3_free(zWideText);
zWideText = 0;
}
return zWideFilename;
return zWideText;
}
/*
** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is
** obtained from sqlite3_malloc().
** Convert a Microsoft Unicode string to UTF-8.
**
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static char *winUnicodeToUtf8(LPCWSTR zWideFilename){
static char *winUnicodeToUtf8(LPCWSTR zWideText){
int nByte;
char *zFilename;
char *zText;
nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
if( nByte == 0 ){
return 0;
}
zFilename = sqlite3MallocZero( nByte );
if( zFilename==0 ){
zText = sqlite3MallocZero( nByte );
if( zText==0 ){
return 0;
}
nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
0, 0);
if( nByte == 0 ){
sqlite3_free(zFilename);
zFilename = 0;
sqlite3_free(zText);
zText = 0;
}
return zFilename;
return zText;
}
/*
** Convert an ANSI string to Microsoft Unicode, based on the
** current codepage settings for file apis.
** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM
** code page.
**
** Space to hold the returned string is obtained
** from sqlite3_malloc.
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static LPWSTR winMbcsToUnicode(const char *zFilename){
static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
int nByte;
LPWSTR zMbcsFilename;
int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
LPWSTR zMbcsText;
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
0)*sizeof(WCHAR);
if( nByte==0 ){
return 0;
}
zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
if( zMbcsFilename==0 ){
zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) );
if( zMbcsText==0 ){
return 0;
}
nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
nByte);
if( nByte==0 ){
sqlite3_free(zMbcsFilename);
zMbcsFilename = 0;
sqlite3_free(zMbcsText);
zMbcsText = 0;
}
return zMbcsFilename;
return zMbcsText;
}
/*
** Convert Microsoft Unicode to multi-byte character string, based on the
** user's ANSI codepage.
** Convert a Microsoft Unicode string to a multi-byte character string,
** using the ANSI or OEM code page.
**
** Space to hold the returned string is obtained from
** sqlite3_malloc().
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static char *winUnicodeToMbcs(LPCWSTR zWideFilename){
static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
int nByte;
char *zFilename;
int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
char *zText;
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0);
if( nByte == 0 ){
return 0;
}
zFilename = sqlite3MallocZero( nByte );
if( zFilename==0 ){
zText = sqlite3MallocZero( nByte );
if( zText==0 ){
return 0;
}
nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText,
nByte, 0, 0);
if( nByte == 0 ){
sqlite3_free(zFilename);
zFilename = 0;
sqlite3_free(zText);
zText = 0;
}
return zFilename;
return zText;
}
/*
** Convert multibyte character string to UTF-8. Space to hold the
** returned string is obtained from sqlite3_malloc().
** Convert a multi-byte character string to UTF-8.
**
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
char *zFilenameUtf8;
static char *winMbcsToUtf8(const char *zText, int useAnsi){
char *zTextUtf8;
LPWSTR zTmpWide;
zTmpWide = winMbcsToUnicode(zFilename);
zTmpWide = winMbcsToUnicode(zText, useAnsi);
if( zTmpWide==0 ){
return 0;
}
zFilenameUtf8 = winUnicodeToUtf8(zTmpWide);
zTextUtf8 = winUnicodeToUtf8(zTmpWide);
sqlite3_free(zTmpWide);
return zFilenameUtf8;
return zTextUtf8;
}
/*
** Convert UTF-8 to multibyte character string. Space to hold the
** returned string is obtained from sqlite3_malloc().
** Convert a UTF-8 string to a multi-byte character string.
**
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
char *zFilenameMbcs;
static char *winUtf8ToMbcs(const char *zText, int useAnsi){
char *zTextMbcs;
LPWSTR zTmpWide;
zTmpWide = winUtf8ToUnicode(zFilename);
zTmpWide = winUtf8ToUnicode(zText);
if( zTmpWide==0 ){
return 0;
}
zFilenameMbcs = winUnicodeToMbcs(zTmpWide);
zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi);
sqlite3_free(zTmpWide);
return zFilenameMbcs;
return zTextMbcs;
}
/*
** This is a public wrapper for the winUtf8ToUnicode() function.
*/
LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zText ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return winUtf8ToUnicode(zText);
}
/*
** This is a public wrapper for the winUnicodeToUtf8() function.
*/
char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zWideText ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return winUnicodeToUtf8(zWideText);
}
/*
** This is a public wrapper for the winMbcsToUtf8() function.
*/
char *sqlite3_win32_mbcs_to_utf8(const char *zText){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zText ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return winMbcsToUtf8(zText, osAreFileApisANSI());
}
/*
** This is a public wrapper for the winMbcsToUtf8() function.
*/
char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zText ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return winMbcsToUtf8(zText, useAnsi);
}
/*
** This is a public wrapper for the winUtf8ToMbcs() function.
*/
char *sqlite3_win32_utf8_to_mbcs(const char *zText){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zText ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return winUtf8ToMbcs(zText, osAreFileApisANSI());
}
/*
** This is a public wrapper for the winUtf8ToMbcs() function.
*/
char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !zText ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return winUtf8ToMbcs(zText, useAnsi);
}
/*
@@ -1873,7 +1976,7 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
if( dwLen > 0 ){
/* allocate a buffer and convert to UTF8 */
sqlite3BeginBenignMalloc();
zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
sqlite3EndBenignMalloc();
/* free the system buffer allocated by FormatMessage */
osLocalFree(zTemp);
@@ -2015,16 +2118,17 @@ static void winLogIoerr(int nRetry, int lineno){
}
}
#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/
#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
/*
** The MSVC CRT on Windows CE may not have a localtime() function. So
** create a substitute.
** This #if does not rely on the SQLITE_OS_WINCE define because the
** corresponding section in "date.c" cannot use it.
*/
#include <time.h>
#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
(!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
/*
** The MSVC CRT on Windows CE may not have a localtime() function.
** So define a substitute.
*/
# include <time.h>
struct tm *__cdecl localtime(const time_t *t)
{
static struct tm y;
@@ -2048,6 +2152,10 @@ struct tm *__cdecl localtime(const time_t *t)
}
#endif
#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/
#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
/*
@@ -3061,9 +3169,8 @@ static int winLock(sqlite3_file *id, int locktype){
** the PENDING_LOCK byte is temporary.
*/
newLocktype = pFile->locktype;
if( (pFile->locktype==NO_LOCK)
|| ( (locktype==EXCLUSIVE_LOCK)
&& (pFile->locktype==RESERVED_LOCK))
if( pFile->locktype==NO_LOCK
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
){
int cnt = 3;
while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
@@ -3657,10 +3764,12 @@ static int winOpenSharedMemory(winFile *pDbFd){
pShmNode->pNext = winShmNodeList;
winShmNodeList = pShmNode;
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->mutex==0 ){
rc = SQLITE_IOERR_NOMEM_BKPT;
goto shm_open_err;
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->mutex==0 ){
rc = SQLITE_IOERR_NOMEM_BKPT;
goto shm_open_err;
}
}
rc = winOpen(pDbFd->pVfs,
@@ -4318,7 +4427,7 @@ static char *winConvertToUtf8Filename(const void *zFilename){
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
zConverted = sqlite3_win32_mbcs_to_utf8(zFilename);
zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
}
#endif
/* caller will handle out of memory */
@@ -4339,7 +4448,7 @@ static void *winConvertFromUtf8Filename(const char *zFilename){
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
}
#endif
/* caller will handle out of memory */
@@ -4540,7 +4649,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
"winGetTempname3", 0);
}
zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
zUtf8 = winMbcsToUtf8(zMbcsPath, osAreFileApisANSI());
if( zUtf8 ){
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
sqlite3_free(zUtf8);
@@ -5318,7 +5427,7 @@ static int winFullPathname(
"winFullPathname4", zRelative);
}
sqlite3_free(zConverted);
zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
sqlite3_free(zTemp);
}
#endif
+104 -72
View File
@@ -872,6 +872,7 @@ static int assert_pager_state(Pager *p){
** state.
*/
if( MEMDB ){
assert( !isOpen(p->fd) );
assert( p->noSync );
assert( p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_MEMORY
@@ -958,7 +959,7 @@ static int assert_pager_state(Pager *p){
** back to OPEN state.
*/
assert( pPager->errCode!=SQLITE_OK );
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
break;
}
@@ -1170,6 +1171,8 @@ static int jrnlBufferSize(Pager *pPager){
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
}
#else
# define jrnlBufferSize(x) 0
#endif
/*
@@ -1818,13 +1821,17 @@ static void pager_unlock(Pager *pPager){
** it can safely move back to PAGER_OPEN state. This happens in both
** normal and exclusive-locking mode.
*/
assert( pPager->errCode==SQLITE_OK || !MEMDB );
if( pPager->errCode ){
assert( !MEMDB );
pager_reset(pPager);
pPager->changeCountDone = pPager->tempFile;
pPager->eState = PAGER_OPEN;
pPager->errCode = SQLITE_OK;
if( pPager->tempFile==0 ){
pager_reset(pPager);
pPager->changeCountDone = 0;
pPager->eState = PAGER_OPEN;
}else{
pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
}
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
pPager->errCode = SQLITE_OK;
}
pPager->journalOff = 0;
@@ -1868,6 +1875,29 @@ static int pager_error(Pager *pPager, int rc){
static int pager_truncate(Pager *pPager, Pgno nPage);
/*
** The write transaction open on pPager is being committed (bCommit==1)
** or rolled back (bCommit==0).
**
** Return TRUE if and only if all dirty pages should be flushed to disk.
**
** Rules:
**
** * For non-TEMP databases, always sync to disk. This is necessary
** for transactions to be durable.
**
** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing
** file has been created already (via a spill on pagerStress()) and
** when the number of dirty pages in memory exceeds 25% of the total
** cache size.
*/
static int pagerFlushOnCommit(Pager *pPager, int bCommit){
if( pPager->tempFile==0 ) return 1;
if( !bCommit ) return 0;
if( !isOpen(pPager->fd) ) return 0;
return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
}
/*
** This routine ends a transaction. A transaction is usually ended by
** either a COMMIT or a ROLLBACK operation. This routine may be called
@@ -1971,7 +2001,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
){
rc = zeroJournalHdr(pPager, hasMaster);
rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile);
pPager->journalOff = 0;
}else{
/* This branch may be executed with Pager.journalMode==MEMORY if
@@ -2006,8 +2036,14 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
pPager->nRec = 0;
sqlite3PcacheCleanAll(pPager->pPCache);
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
if( rc==SQLITE_OK ){
if( pagerFlushOnCommit(pPager, bCommit) ){
sqlite3PcacheCleanAll(pPager->pPCache);
}else{
sqlite3PcacheClearWritable(pPager->pPCache);
}
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
}
if( pagerUseWal(pPager) ){
/* Drop the WAL write-lock, if any. Also, if the connection was in
@@ -2291,7 +2327,7 @@ static int pager_playback_one_page(
pPg = sqlite3PagerLookup(pPager, pgno);
}
assert( pPg || !MEMDB );
assert( pPager->eState!=PAGER_OPEN || pPg==0 );
assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
(isMainJrnl?"main-journal":"sub-journal")
@@ -2341,7 +2377,6 @@ static int pager_playback_one_page(
assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
if( rc!=SQLITE_OK ) return rc;
pPg->flags &= ~PGHDR_NEED_READ;
sqlite3PcacheMakeDirty(pPg);
}
if( pPg ){
@@ -2355,29 +2390,10 @@ static int pager_playback_one_page(
pData = pPg->pData;
memcpy(pData, (u8*)aData, pPager->pageSize);
pPager->xReiniter(pPg);
if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
/* If the contents of this page were just restored from the main
** journal file, then its content must be as they were when the
** transaction was first opened. In this case we can mark the page
** as clean, since there will be no need to write it out to the
** database.
**
** There is one exception to this rule. If the page is being rolled
** back as part of a savepoint (or statement) rollback from an
** unsynced portion of the main journal file, then it is not safe
** to mark the page as clean. This is because marking the page as
** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
** already in the journal file (recorded in Pager.pInJournal) and
** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
** again within this transaction, it will be marked as dirty but
** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
** be written out into the database file before its journal file
** segment is synced. If a crash occurs during or following this,
** database corruption may ensue.
*/
assert( !pagerUseWal(pPager) );
sqlite3PcacheMakeClean(pPg);
}
/* It used to be that sqlite3PcacheMakeClean(pPg) was called here. But
** that call was dangerous and had no detectable benefit since the cache
** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so
** has been removed. */
pager_set_pagehash(pPg);
/* If this was page 1, then restore the value of Pager.dbFileVers.
@@ -3168,6 +3184,8 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
*/
assert( pPager->eState==PAGER_OPEN );
assert( pPager->eLock>=SHARED_LOCK );
assert( isOpen(pPager->fd) );
assert( pPager->tempFile==0 );
nPage = sqlite3WalDbsize(pPager->pWal);
/* If the number of pages in the database is not available from the
@@ -3175,14 +3193,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
** the database file. If the size of the database file is not an
** integer multiple of the page-size, round up the result.
*/
if( nPage==0 ){
if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
i64 n = 0; /* Size of db file in bytes */
assert( isOpen(pPager->fd) || pPager->tempFile );
if( isOpen(pPager->fd) ){
int rc = sqlite3OsFileSize(pPager->fd, &n);
if( rc!=SQLITE_OK ){
return rc;
}
int rc = sqlite3OsFileSize(pPager->fd, &n);
if( rc!=SQLITE_OK ){
return rc;
}
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
}
@@ -4258,8 +4273,9 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
/* This function is only called for rollback pagers in WRITER_DBMOD state. */
assert( !pagerUseWal(pPager) );
assert( pPager->eState==PAGER_WRITER_DBMOD );
assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD );
assert( pPager->eLock==EXCLUSIVE_LOCK );
assert( isOpen(pPager->fd) || pList->pDirty==0 );
/* If the file is a temp-file has not yet been opened, open it now. It
** is not possible for rc to be other than SQLITE_OK if this branch
@@ -4927,6 +4943,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
if( rc==SQLITE_OK && !locked ){
Pgno nPage; /* Number of pages in database file */
assert( pPager->tempFile==0 );
rc = pagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){
/* If the database is zero pages in size, that means that either (1) the
@@ -5019,17 +5036,17 @@ int sqlite3PagerSharedLock(Pager *pPager){
/* This routine is only called from b-tree and only when there are no
** outstanding pages. This implies that the pager state should either
** be OPEN or READER. READER is only possible if the pager is or was in
** exclusive access mode.
*/
** exclusive access mode. */
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
assert( assert_pager_state(pPager) );
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
assert( pPager->errCode==SQLITE_OK );
if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
int bHotJournal = 1; /* True if there exists a hot journal-file */
assert( !MEMDB );
assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
if( rc!=SQLITE_OK ){
@@ -5115,7 +5132,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
assert( rc==SQLITE_OK );
rc = pagerSyncHotJournal(pPager);
if( rc==SQLITE_OK ){
rc = pager_playback(pPager, 1);
rc = pager_playback(pPager, !pPager->tempFile);
pPager->eState = PAGER_OPEN;
}
}else if( !pPager->exclusiveMode ){
@@ -5211,7 +5228,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
rc = pagerBeginReadTransaction(pPager);
}
if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
rc = pagerPagecount(pPager, &pPager->dbSize);
}
@@ -5344,7 +5361,7 @@ int sqlite3PagerGet(
);
if( rc==SQLITE_OK && pData ){
if( pPager->eState>PAGER_READER ){
if( pPager->eState>PAGER_READER || pPager->tempFile ){
pPg = sqlite3PagerLookup(pPager, pgno);
}
if( pPg==0 ){
@@ -5411,7 +5428,8 @@ int sqlite3PagerGet(
goto pager_acquire_err;
}
if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
assert( !isOpen(pPager->fd) || !MEMDB );
if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
if( pgno>pPager->mxPgno ){
rc = SQLITE_FULL;
goto pager_acquire_err;
@@ -5553,24 +5571,24 @@ static int pager_open_journal(Pager *pPager){
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
sqlite3MemJournalOpen(pPager->jfd);
}else{
const int flags = /* VFS flags to open journal file */
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
(pPager->tempFile ?
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
(SQLITE_OPEN_MAIN_JOURNAL)
);
int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
int nSpill;
if( pPager->tempFile ){
flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
nSpill = sqlite3Config.nStmtSpill;
}else{
flags |= SQLITE_OPEN_MAIN_JOURNAL;
nSpill = jrnlBufferSize(pPager);
}
/* Verify that the database still has the same name as it did when
** it was originally opened. */
rc = databaseIsUnmoved(pPager);
if( rc==SQLITE_OK ){
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
rc = sqlite3JournalOpen(
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
rc = sqlite3JournalOpen (
pVfs, pPager->zJournal, pPager->jfd, flags, nSpill
);
#else
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
#endif
}
}
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
@@ -5941,6 +5959,7 @@ int sqlite3PagerWrite(PgHdr *pPg){
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
return SQLITE_OK;
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
assert( pPager->tempFile==0 );
return pagerWriteLargeSector(pPg);
}else{
return pager_write(pPg);
@@ -5971,14 +5990,21 @@ int sqlite3PagerIswriteable(DbPage *pPg){
**
** Tests show that this optimization can quadruple the speed of large
** DELETE operations.
**
** This optimization cannot be used with a temp-file, as the page may
** have been dirty at the start of the transaction. In that case, if
** memory pressure forces page pPg out of the cache, the data does need
** to be written out to disk so that it may be read back in if the
** current transaction is rolled back.
*/
void sqlite3PagerDontWrite(PgHdr *pPg){
Pager *pPager = pPg->pPager;
if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
pPg->flags |= PGHDR_DONT_WRITE;
pPg->flags &= ~PGHDR_WRITEABLE;
testcase( pPg->flags & PGHDR_NEED_SYNC );
pager_set_pagehash(pPg);
}
}
@@ -6173,17 +6199,21 @@ int sqlite3PagerCommitPhaseOne(
/* If a prior error occurred, report that error again. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
/* Provide the ability to easily simulate an I/O error during testing */
if( sqlite3FaultSim(400) ) return SQLITE_IOERR;
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
pPager->zFilename, zMaster, pPager->dbSize));
/* If no database changes have been made, return early. */
if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
if( MEMDB ){
assert( MEMDB==0 || pPager->tempFile );
assert( isOpen(pPager->fd) || pPager->tempFile );
if( 0==pagerFlushOnCommit(pPager, 1) ){
/* If this is an in-memory db, or no pages have been written to, or this
** function has already been called, it is mostly a no-op. However, any
** backup in progress needs to be restarted.
*/
** backup in progress needs to be restarted. */
sqlite3BackupRestart(pPager->pBackup);
}else{
if( pagerUseWal(pPager) ){
@@ -6522,10 +6552,10 @@ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
}
/*
** Return true if this is an in-memory pager.
** Return true if this is an in-memory or temp-file backed pager.
*/
int sqlite3PagerIsMemdb(Pager *pPager){
return MEMDB;
return pPager->tempFile;
}
/*
@@ -6805,7 +6835,8 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
/* In order to be able to rollback, an in-memory database must journal
** the page we are moving from.
*/
if( MEMDB ){
assert( pPager->tempFile || !MEMDB );
if( pPager->tempFile ){
rc = sqlite3PagerWrite(pPg);
if( rc ) return rc;
}
@@ -6862,7 +6893,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
assert( !pPgOld || pPgOld->nRef==1 );
if( pPgOld ){
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
if( MEMDB ){
if( pPager->tempFile ){
/* Do not discard pages from an in-memory database since we might
** need to rollback later. Just move the page out of the way. */
sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
@@ -6879,8 +6910,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
** to exist, in case the transaction needs to roll back. Use pPgOld
** as the original page since it has already been allocated.
*/
if( MEMDB ){
assert( pPgOld );
if( pPager->tempFile && pPgOld ){
sqlite3PcacheMove(pPgOld, origPgno);
sqlite3PagerUnrefNotNull(pPgOld);
}
@@ -7132,7 +7162,8 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
** Unless this is an in-memory or temporary database, clear the pager cache.
*/
void sqlite3PagerClearCache(Pager *pPager){
if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
assert( MEMDB==0 || pPager->tempFile );
if( pPager->tempFile==0 ) pager_reset(pPager);
}
#endif
@@ -7311,6 +7342,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0;
pagerFixMaplimit(pPager);
if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
}
}
return rc;
+10 -1
View File
@@ -68,7 +68,11 @@ typedef struct PgHdr DbPage;
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
/*
** Numeric constants that encode the journalmode.
** Numeric constants that encode the journalmode.
**
** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
** are exposed in the API via the "PRAGMA journal_mode" command and
** therefore cannot be changed without a compatibility break.
*/
#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
@@ -86,6 +90,11 @@ typedef struct PgHdr DbPage;
/*
** Flags for sqlite3PagerSetFlags()
**
** Value constraints (enforced via assert()):
** PAGER_FULLFSYNC == SQLITE_FullFSync
** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
** PAGER_CACHE_SPILL == SQLITE_CacheSpill
*/
#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
+34 -55
View File
@@ -194,28 +194,6 @@ columnlist ::= columnlist COMMA columnname carglist.
columnlist ::= columnname carglist.
columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
// An IDENTIFIER can be a generic identifier, or one of several
// keywords. Any non-standard keyword can also be an identifier.
//
%token_class id ID|INDEXED.
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
//
%fallback ID
ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
%ifdef SQLITE_OMIT_COMPOUND_SELECT
EXCEPT INTERSECT UNION
%endif SQLITE_OMIT_COMPOUND_SELECT
REINDEX RENAME CTIME_KW IF
.
%wildcard ANY.
// Define operator precedence early so that this is the first occurrence
// of the operator tokens in the grammer. Keeping the operators together
// causes them to be assigned integer values that are close together,
@@ -240,6 +218,29 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
%left COLLATE.
%right BITNOT.
// An IDENTIFIER can be a generic identifier, or one of several
// keywords. Any non-standard keyword can also be an identifier.
//
%token_class id ID|INDEXED.
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
//
%fallback ID
ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
%ifdef SQLITE_OMIT_COMPOUND_SELECT
EXCEPT INTERSECT UNION
%endif SQLITE_OMIT_COMPOUND_SELECT
REINDEX RENAME CTIME_KW IF
.
%wildcard ANY.
// And "ids" is an identifer-or-string.
//
%token_class ids ID|STRING.
@@ -871,11 +872,15 @@ expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
term(A) ::= STRING(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
expr(A) ::= VARIABLE(X). {
Token t = X; /*A-overwrites-X*/
if( t.n>=2 && t.z[0]=='#' && sqlite3Isdigit(t.z[1]) ){
if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){
spanExpr(&A, pParse, TK_VARIABLE, X);
sqlite3ExprAssignVarNumber(pParse, A.pExpr);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
** in the virtual machine. #N is the N-th register. */
Token t = X; /*A-overwrites-X*/
assert( t.n>=2 );
spanSet(&A, &t, &t);
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
@@ -884,9 +889,6 @@ expr(A) ::= VARIABLE(X). {
A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t);
if( A.pExpr ) sqlite3GetInt32(&t.z[1], &A.pExpr->iTable);
}
}else{
spanExpr(&A, pParse, TK_VARIABLE, t);
sqlite3ExprAssignVarNumber(pParse, A.pExpr);
}
}
expr(A) ::= expr(A) COLLATE ids(C). {
@@ -1122,36 +1124,19 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr(A) ::= LP(B) select(X) RP(E). {
spanSet(&A,&B,&E); /*A-overwrites-B*/
A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
if( A.pExpr ){
A.pExpr->x.pSelect = X;
ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
}else{
sqlite3SelectDelete(pParse->db, X);
}
sqlite3PExprAddSelect(pParse, A.pExpr, X);
}
expr(A) ::= expr(A) in_op(N) LP select(Y) RP(E). [IN] {
A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
if( A.pExpr ){
A.pExpr->x.pSelect = Y;
ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
}else{
sqlite3SelectDelete(pParse->db, Y);
}
sqlite3PExprAddSelect(pParse, A.pExpr, Y);
exprNot(pParse, N, &A);
A.zEnd = &E.z[E.n];
}
expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z). [IN] {
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
if( A.pExpr ){
A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
}else{
sqlite3SrcListDelete(pParse->db, pSrc);
}
sqlite3PExprAddSelect(pParse, A.pExpr, pSelect);
exprNot(pParse, N, &A);
A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
}
@@ -1159,13 +1144,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
Expr *p;
spanSet(&A,&B,&E); /*A-overwrites-B*/
p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
p->x.pSelect = Y;
ExprSetProperty(p, EP_xIsSelect|EP_Subquery);
sqlite3ExprSetHeightAndFlags(pParse, p);
}else{
sqlite3SelectDelete(pParse->db, Y);
}
sqlite3PExprAddSelect(pParse, p, Y);
}
%endif SQLITE_OMIT_SUBQUERY
+196 -17
View File
@@ -14,7 +14,29 @@
#include "sqliteInt.h"
/*
** A complete page cache is an instance of this structure.
** A complete page cache is an instance of this structure. Every
** entry in the cache holds a single page of the database file. The
** btree layer only operates on the cached copy of the database pages.
**
** A page cache entry is "clean" if it exactly matches what is currently
** on disk. A page is "dirty" if it has been modified and needs to be
** persisted to disk.
**
** pDirty, pDirtyTail, pSynced:
** All dirty pages are linked into the doubly linked list using
** PgHdr.pDirtyNext and pDirtyPrev. The list is maintained in LRU order
** such that p was added to the list more recently than p->pDirtyNext.
** PCache.pDirty points to the first (newest) element in the list and
** pDirtyTail to the last (oldest).
**
** The PCache.pSynced variable is used to optimize searching for a dirty
** page to eject from the cache mid-transaction. It is better to eject
** a page that does not require a journal sync than one that does.
** Therefore, pSynced is maintained to that it *almost* always points
** to either the oldest page in the pDirty/pDirtyTail list that has a
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
** (so that the right page to eject can be found by following pDirtyPrev
** pointers).
*/
struct PCache {
PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
@@ -31,6 +53,95 @@ struct PCache {
sqlite3_pcache *pCache; /* Pluggable cache module */
};
/********************************** Test and Debug Logic **********************/
/*
** Debug tracing macros. Enable by by changing the "0" to "1" and
** recompiling.
**
** When sqlite3PcacheTrace is 1, single line trace messages are issued.
** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries
** is displayed for many operations, resulting in a lot of output.
*/
#if defined(SQLITE_DEBUG) && 0
int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
void pcacheDump(PCache *pCache){
int N;
int i, j;
sqlite3_pcache_page *pLower;
PgHdr *pPg;
unsigned char *a;
if( sqlite3PcacheTrace<2 ) return;
if( pCache->pCache==0 ) return;
N = sqlite3PcachePagecount(pCache);
if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump;
for(i=1; i<=N; i++){
pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
if( pLower==0 ) continue;
pPg = (PgHdr*)pLower->pExtra;
printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
a = (unsigned char *)pLower->pBuf;
for(j=0; j<12; j++) printf("%02x", a[j]);
printf("\n");
if( pPg->pPage==0 ){
sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
}
}
}
#else
# define pcacheTrace(X)
# define pcacheDump(X)
#endif
/*
** Check invariants on a PgHdr entry. Return true if everything is OK.
** Return false if any invariant is violated.
**
** This routine is for use inside of assert() statements only. For
** example:
**
** assert( sqlite3PcachePageSanity(pPg) );
*/
#if SQLITE_DEBUG
int sqlite3PcachePageSanity(PgHdr *pPg){
PCache *pCache;
assert( pPg!=0 );
assert( pPg->pgno>0 ); /* Page number is 1 or more */
pCache = pPg->pCache;
assert( pCache!=0 ); /* Every page has an associated PCache */
if( pPg->flags & PGHDR_CLEAN ){
assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */
assert( pCache->pDirtyTail!=pPg );
}
/* WRITEABLE pages must also be DIRTY */
if( pPg->flags & PGHDR_WRITEABLE ){
assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */
}
/* NEED_SYNC can be set independently of WRITEABLE. This can happen,
** for example, when using the sqlite3PagerDontWrite() optimization:
** (1) Page X is journalled, and gets WRITEABLE and NEED_SEEK.
** (2) Page X moved to freelist, WRITEABLE is cleared
** (3) Page X reused, WRITEABLE is set again
** If NEED_SYNC had been cleared in step 2, then it would not be reset
** in step 3, and page might be written into the database without first
** syncing the rollback journal, which might cause corruption on a power
** loss.
**
** Another example is when the database page size is smaller than the
** disk sector size. When any page of a sector is journalled, all pages
** in that sector are marked NEED_SYNC even if they are still CLEAN, just
** in case they are later modified, since all pages in the same sector
** must be journalled and synced before any of those pages can be safely
** written.
*/
return 1;
}
#endif /* SQLITE_DEBUG */
/********************************** Linked List Management ********************/
/* Allowed values for second argument to pcacheManageDirtyList() */
@@ -47,17 +158,16 @@ struct PCache {
static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
PCache *p = pPage->pCache;
pcacheTrace(("%p.DIRTYLIST.%s %d\n", p,
addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT",
pPage->pgno));
if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
assert( pPage->pDirtyPrev || pPage==p->pDirty );
/* Update the PCache1.pSynced variable if necessary. */
if( p->pSynced==pPage ){
PgHdr *pSynced = pPage->pDirtyPrev;
while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
pSynced = pSynced->pDirtyPrev;
}
p->pSynced = pSynced;
p->pSynced = pPage->pDirtyPrev;
}
if( pPage->pDirtyNext ){
@@ -69,10 +179,15 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
if( pPage->pDirtyPrev ){
pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
}else{
/* If there are now no dirty pages in the cache, set eCreate to 2.
** This is an optimization that allows sqlite3PcacheFetch() to skip
** searching for a dirty page to eject from the cache when it might
** otherwise have to. */
assert( pPage==p->pDirty );
p->pDirty = pPage->pDirtyNext;
if( p->pDirty==0 && p->bPurgeable ){
assert( p->eCreate==1 );
assert( p->bPurgeable || p->eCreate==2 );
if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/
assert( p->bPurgeable==0 || p->eCreate==1 );
p->eCreate = 2;
}
}
@@ -94,10 +209,19 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
}
}
p->pDirty = pPage;
if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
/* If pSynced is NULL and this page has a clear NEED_SYNC flag, set
** pSynced to point to it. Checking the NEED_SYNC flag is an
** optimization, as if pSynced points to a page with the NEED_SYNC
** flag set sqlite3PcacheFetchStress() searches through all newer
** entries of the dirty-list for a page with NEED_SYNC clear anyway. */
if( !p->pSynced
&& 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/
){
p->pSynced = pPage;
}
}
pcacheDump(p);
}
/*
@@ -106,7 +230,9 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
*/
static void pcacheUnpin(PgHdr *p){
if( p->pCache->bPurgeable ){
pcacheTrace(("%p.UNPIN %d\n", p->pCache, p->pgno));
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
pcacheDump(p->pCache);
}
}
@@ -176,6 +302,7 @@ int sqlite3PcacheOpen(
p->pStress = pStress;
p->szCache = 100;
p->szSpill = 1;
pcacheTrace(("%p.OPEN szPage %d bPurgeable %d\n",p,szPage,bPurgeable));
return sqlite3PcacheSetPageSize(p, szPage);
}
@@ -198,6 +325,7 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
}
pCache->pCache = pNew;
pCache->szPage = szPage;
pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage));
}
return SQLITE_OK;
}
@@ -232,11 +360,13 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
int createFlag /* If true, create page if it does not exist already */
){
int eCreate;
sqlite3_pcache_page *pRes;
assert( pCache!=0 );
assert( pCache->pCache!=0 );
assert( createFlag==3 || createFlag==0 );
assert( pgno>0 );
assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );
/* eCreate defines what to do if the page does not exist.
** 0 Do not allocate a new page. (createFlag==0)
@@ -249,12 +379,15 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
assert( eCreate==0 || eCreate==1 || eCreate==2 );
assert( createFlag==0 || pCache->eCreate==eCreate );
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
return sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
createFlag?" create":"",pRes));
return pRes;
}
/*
** If the sqlite3PcacheFetch() routine is unable to allocate a new
** page because new clean pages are available for reuse and the cache
** page because no clean pages are available for reuse and the cache
** size limit has been reached, then this routine can be invoked to
** try harder to allocate a page. This routine might invoke the stress
** callback to spill dirty pages to the journal. It will then try to
@@ -276,7 +409,11 @@ int sqlite3PcacheFetchStress(
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
** cleared), but if that is not possible settle for any other
** unreferenced dirty page.
*/
**
** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC
** flag is currently referenced, then the following may leave pSynced
** set incorrectly (pointing to other than the LRU page with NEED_SYNC
** cleared). This is Ok, as pSynced is just an optimization. */
for(pPg=pCache->pSynced;
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
@@ -294,7 +431,9 @@ int sqlite3PcacheFetchStress(
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
numberOfCachePages(pCache));
#endif
pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
rc = pCache->xStress(pCache->pStress, pPg);
pcacheDump(pCache);
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
return rc;
}
@@ -354,6 +493,7 @@ PgHdr *sqlite3PcacheFetchFinish(
}
pCache->nRefSum++;
pPgHdr->nRef++;
assert( sqlite3PcachePageSanity(pPgHdr) );
return pPgHdr;
}
@@ -367,8 +507,11 @@ void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
if( (--p->nRef)==0 ){
if( p->flags&PGHDR_CLEAN ){
pcacheUnpin(p);
}else if( p->pDirtyPrev!=0 ){
/* Move the page to the head of the dirty list. */
}else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/
/* Move the page to the head of the dirty list. If p->pDirtyPrev==0,
** then page p is already at the head of the dirty list and the
** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE
** tag above. */
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
}
}
@@ -379,6 +522,7 @@ void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
*/
void sqlite3PcacheRef(PgHdr *p){
assert(p->nRef>0);
assert( sqlite3PcachePageSanity(p) );
p->nRef++;
p->pCache->nRefSum++;
}
@@ -390,6 +534,7 @@ void sqlite3PcacheRef(PgHdr *p){
*/
void sqlite3PcacheDrop(PgHdr *p){
assert( p->nRef==1 );
assert( sqlite3PcachePageSanity(p) );
if( p->flags&PGHDR_DIRTY ){
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
}
@@ -403,13 +548,16 @@ void sqlite3PcacheDrop(PgHdr *p){
*/
void sqlite3PcacheMakeDirty(PgHdr *p){
assert( p->nRef>0 );
if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){
assert( sqlite3PcachePageSanity(p) );
if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/
p->flags &= ~PGHDR_DONT_WRITE;
if( p->flags & PGHDR_CLEAN ){
p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN);
pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
}
assert( sqlite3PcachePageSanity(p) );
}
}
@@ -418,11 +566,14 @@ void sqlite3PcacheMakeDirty(PgHdr *p){
** make it so.
*/
void sqlite3PcacheMakeClean(PgHdr *p){
if( (p->flags & PGHDR_DIRTY) ){
assert( sqlite3PcachePageSanity(p) );
if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){
assert( (p->flags & PGHDR_CLEAN)==0 );
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
p->flags |= PGHDR_CLEAN;
pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
assert( sqlite3PcachePageSanity(p) );
if( p->nRef==0 ){
pcacheUnpin(p);
}
@@ -434,11 +585,24 @@ void sqlite3PcacheMakeClean(PgHdr *p){
*/
void sqlite3PcacheCleanAll(PCache *pCache){
PgHdr *p;
pcacheTrace(("%p.CLEAN-ALL\n",pCache));
while( (p = pCache->pDirty)!=0 ){
sqlite3PcacheMakeClean(p);
}
}
/*
** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
*/
void sqlite3PcacheClearWritable(PCache *pCache){
PgHdr *p;
pcacheTrace(("%p.CLEAR-WRITEABLE\n",pCache));
for(p=pCache->pDirty; p; p=p->pDirtyNext){
p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
}
pCache->pSynced = pCache->pDirtyTail;
}
/*
** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
*/
@@ -457,6 +621,8 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
PCache *pCache = p->pCache;
assert( p->nRef>0 );
assert( newPgno>0 );
assert( sqlite3PcachePageSanity(p) );
pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
p->pgno = newPgno;
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
@@ -477,6 +643,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
if( pCache->pCache ){
PgHdr *p;
PgHdr *pNext;
pcacheTrace(("%p.TRUNCATE %d\n",pCache,pgno));
for(p=pCache->pDirty; p; p=pNext){
pNext = p->pDirtyNext;
/* This routine never gets call with a positive pgno except right
@@ -484,7 +651,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
** it must be that pgno==0.
*/
assert( p->pgno>0 );
if( ALWAYS(p->pgno>pgno) ){
if( p->pgno>pgno ){
assert( p->flags&PGHDR_DIRTY );
sqlite3PcacheMakeClean(p);
}
@@ -507,6 +674,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
*/
void sqlite3PcacheClose(PCache *pCache){
assert( pCache->pCache!=0 );
pcacheTrace(("%p.CLOSE\n",pCache));
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
}
@@ -675,6 +843,17 @@ void sqlite3PcacheShrink(PCache *pCache){
*/
int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
/*
** Return the number of dirty pages currently in the cache, as a percentage
** of the configured cache size.
*/
int sqlite3PCachePercentDirty(PCache *pCache){
PgHdr *pDirty;
int nDirty = 0;
int nCache = numberOfCachePages(pCache);
for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++;
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
}
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/*
+13 -5
View File
@@ -26,7 +26,7 @@ struct PgHdr {
sqlite3_pcache_page *pPage; /* Pcache object page handle */
void *pData; /* Page data */
void *pExtra; /* Extra content */
PgHdr *pDirty; /* Transient list of dirty pages */
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
@@ -51,11 +51,10 @@ struct PgHdr {
#define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */
#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before
** writing this page to the database */
#define PGHDR_NEED_READ 0x010 /* Content is unread */
#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
#define PGHDR_MMAP 0x040 /* This is an mmap page object */
#define PGHDR_DONT_WRITE 0x010 /* Do not write content to disk */
#define PGHDR_MMAP 0x020 /* This is an mmap page object */
#define PGHDR_WAL_APPEND 0x080 /* Appended to wal file */
#define PGHDR_WAL_APPEND 0x040 /* Appended to wal file */
/* Initialize and shutdown the page cache subsystem */
int sqlite3PcacheInitialize(void);
@@ -99,6 +98,7 @@ void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
void sqlite3PcacheClearWritable(PCache*);
/* Change a page number. Used by incr-vacuum. */
void sqlite3PcacheMove(PgHdr*, Pgno);
@@ -137,6 +137,11 @@ int sqlite3PcachePagecount(PCache*);
void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
#endif
#if defined(SQLITE_DEBUG)
/* Check invariants on a PgHdr object */
int sqlite3PcachePageSanity(PgHdr*);
#endif
/* Set and get the suggested cache-size for the specified pager-cache.
**
** If no global maximum is configured, then the system attempts to limit
@@ -173,4 +178,7 @@ void sqlite3PCacheSetDefault(void);
int sqlite3HeaderSizePcache(void);
int sqlite3HeaderSizePcache1(void);
/* Number of dirty pages as a percentage of the configured cache size */
int sqlite3PCachePercentDirty(PCache*);
#endif /* _PCACHE_H_ */
+2 -2
View File
@@ -690,8 +690,8 @@ static int pcache1Init(void *NotUsed){
#if SQLITE_THREADSAFE
if( sqlite3GlobalConfig.bCoreMutex ){
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU);
pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM);
}
#endif
if( pcache1.separateCache
+18 -18
View File
@@ -15,26 +15,26 @@
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
#define etFLOAT 2 /* Floating point. %f */
#define etEXP 3 /* Exponentional notation. %e and %E */
#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
#define etSIZE 5 /* Return number of characters processed so far. %n */
#define etSTRING 6 /* Strings. %s */
#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
#define etPERCENT 8 /* Percent symbol. %% */
#define etCHARX 9 /* Characters. %c */
#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */
#define etFLOAT 1 /* Floating point. %f */
#define etEXP 2 /* Exponentional notation. %e and %E */
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
#define etSIZE 4 /* Return number of characters processed so far. %n */
#define etSTRING 5 /* Strings. %s */
#define etDYNSTRING 6 /* Dynamically allocated strings. %z */
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 12 /* a pointer to a Token structure */
#define etSRCLIST 13 /* a pointer to a SrcList */
#define etPOINTER 14 /* The %p conversion */
#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etTOKEN 11 /* a pointer to a Token structure */
#define etSRCLIST 12 /* a pointer to a SrcList */
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etINVALID 0 /* Any unrecognized conversion type */
#define etINVALID 16 /* Any unrecognized conversion type */
/*
@@ -189,7 +189,7 @@ void sqlite3VXPrintf(
etByte flag_long; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
etByte xtype = 0; /* Conversion paradigm */
etByte xtype = etINVALID; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
u8 useIntern; /* Ok to use internal conversions (ex: %T) */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
+1
View File
@@ -763,6 +763,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
pNC->ncFlags |= NC_VarSelect;
}
}
break;
+47 -56
View File
@@ -57,8 +57,9 @@
** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
** primitives are constant time. The cost of DESTROY is O(N).
**
** There is an added cost of O(N) when switching between TEST and
** SMALLEST primitives.
** TEST and SMALLEST may not be used by the same RowSet. This used to
** be possible, but the feature was not used, so it was removed in order
** to simplify the code.
*/
#include "sqliteInt.h"
@@ -179,7 +180,9 @@ void sqlite3RowSetClear(RowSet *p){
*/
static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
assert( p!=0 );
if( p->nFresh==0 ){
if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/
/* We could allocate a fresh RowSetEntry each time one is needed, but it
** is more efficient to pull a preallocated entry from the pool */
struct RowSetChunk *pNew;
pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew));
if( pNew==0 ){
@@ -213,7 +216,9 @@ void sqlite3RowSetInsert(RowSet *p, i64 rowid){
pEntry->pRight = 0;
pLast = p->pLast;
if( pLast ){
if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/
/* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags
** where possible */
p->rsFlags &= ~ROWSET_SORTED;
}
pLast->pRight = pEntry;
@@ -335,23 +340,29 @@ static struct RowSetEntry *rowSetNDeepTree(
){
struct RowSetEntry *p; /* Root of the new tree */
struct RowSetEntry *pLeft; /* Left subtree */
if( *ppList==0 ){
return 0;
if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/
/* Prevent unnecessary deep recursion when we run out of entries */
return 0;
}
if( iDepth==1 ){
if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/
/* This branch causes a *balanced* tree to be generated. A valid tree
** is still generated without this branch, but the tree is wildly
** unbalanced and inefficient. */
pLeft = rowSetNDeepTree(ppList, iDepth-1);
p = *ppList;
if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/
/* It is safe to always return here, but the resulting tree
** would be unbalanced */
return pLeft;
}
p->pLeft = pLeft;
*ppList = p->pRight;
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
}else{
p = *ppList;
*ppList = p->pRight;
p->pLeft = p->pRight = 0;
return p;
}
pLeft = rowSetNDeepTree(ppList, iDepth-1);
p = *ppList;
if( p==0 ){
return pLeft;
}
p->pLeft = pLeft;
*ppList = p->pRight;
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
return p;
}
@@ -378,59 +389,37 @@ static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
return p;
}
/*
** Take all the entries on p->pEntry and on the trees in p->pForest and
** sort them all together into one big ordered list on p->pEntry.
**
** This routine should only be called once in the life of a RowSet.
*/
static void rowSetToList(RowSet *p){
/* This routine is called only once */
assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
if( (p->rsFlags & ROWSET_SORTED)==0 ){
p->pEntry = rowSetEntrySort(p->pEntry);
}
/* While this module could theoretically support it, sqlite3RowSetNext()
** is never called after sqlite3RowSetText() for the same RowSet. So
** there is never a forest to deal with. Should this change, simply
** remove the assert() and the #if 0. */
assert( p->pForest==0 );
#if 0
while( p->pForest ){
struct RowSetEntry *pTree = p->pForest->pLeft;
if( pTree ){
struct RowSetEntry *pHead, *pTail;
rowSetTreeToList(pTree, &pHead, &pTail);
p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
}
p->pForest = p->pForest->pRight;
}
#endif
p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */
}
/*
** Extract the smallest element from the RowSet.
** Write the element into *pRowid. Return 1 on success. Return
** 0 if the RowSet is already empty.
**
** After this routine has been called, the sqlite3RowSetInsert()
** routine may not be called again.
** routine may not be called again.
**
** This routine may not be called after sqlite3RowSetTest() has
** been used. Older versions of RowSet allowed that, but as the
** capability was not used by the code generator, it was removed
** for code economy.
*/
int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
assert( p!=0 );
assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */
/* Merge the forest into a single sorted list on first call */
if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/
if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
p->pEntry = rowSetEntrySort(p->pEntry);
}
p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT;
}
/* Return the next entry on the list */
if( p->pEntry ){
*pRowid = p->pEntry->v;
p->pEntry = p->pEntry->pRight;
if( p->pEntry==0 ){
if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/
/* Free memory immediately, rather than waiting on sqlite3_finalize() */
sqlite3RowSetClear(p);
}
return 1;
@@ -453,13 +442,15 @@ int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
/* This routine is never called after sqlite3RowSetNext() */
assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
/* Sort entries into the forest on the first test of a new batch
/* Sort entries into the forest on the first test of a new batch.
** To save unnecessary work, only do this when the batch number changes.
*/
if( iBatch!=pRowSet->iBatch ){
if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/
p = pRowSet->pEntry;
if( p ){
struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
/* Only sort the current set of entiries if they need it */
p = rowSetEntrySort(p);
}
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
+43 -20
View File
@@ -74,7 +74,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pOffset);
sqlite3WithDelete(db, p->pWith);
if( p->pWith ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFree(db, p);
p = pPrior;
bFree = 1;
@@ -169,7 +169,7 @@ void sqlite3SelectSetName(Select *p, const char *zName){
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
clearSelect(db, p, 1);
if( p ) clearSelect(db, p, 1);
}
/*
@@ -1704,7 +1704,7 @@ int sqlite3ColumnsFromExprList(
** This routine requires that all identifiers in the SELECT
** statement be resolved.
*/
static void selectAddColumnTypeAndCollation(
void sqlite3SelectAddColumnTypeAndCollation(
Parse *pParse, /* Parsing contexts */
Table *pTab, /* Add column type information to this table */
Select *pSelect /* SELECT used to determine types and collations */
@@ -1726,10 +1726,20 @@ static void selectAddColumnTypeAndCollation(
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
int n, m;
p = a[i].pExpr;
columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
if( zType && (m = sqlite3Strlen30(zType))>0 ){
n = sqlite3Strlen30(pCol->zName);
pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
if( pCol->zName ){
memcpy(&pCol->zName[n+1], zType, m+1);
pCol->colFlags |= COLFLAG_HASTYPE;
}
}
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl && pCol->zColl==0 ){
@@ -1766,7 +1776,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
@@ -1779,20 +1789,20 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
** Get a VDBE for the given parser context. Create a new one if necessary.
** If an error occurs, return NULL and leave a message in pParse.
*/
Vdbe *sqlite3GetVdbe(Parse *pParse){
Vdbe *v = pParse->pVdbe;
if( v==0 ){
v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
if( v ) sqlite3VdbeAddOp0(v, OP_Init);
if( pParse->pToplevel==0
&& OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
){
pParse->okConstFactor = 1;
}
static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
if( v ) sqlite3VdbeAddOp0(v, OP_Init);
if( pParse->pToplevel==0
&& OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
){
pParse->okConstFactor = 1;
}
return v;
}
Vdbe *sqlite3GetVdbe(Parse *pParse){
Vdbe *v = pParse->pVdbe;
return v ? v : allocVdbe(pParse);
}
/*
@@ -3775,12 +3785,18 @@ static int pushDownWhereTerms(
){
Expr *pNew;
int nChng = 0;
Select *pX; /* For looping over compound SELECTs in pSubq */
if( pWhere==0 ) return 0;
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
return 0; /* restrictions (1) and (2) */
for(pX=pSubq; pX; pX=pX->pPrior){
if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
testcase( pX->selFlags & SF_Aggregate );
testcase( pX->selFlags & SF_Recursive );
testcase( pX!=pSubq );
return 0; /* restrictions (1) and (2) */
}
}
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
@@ -4550,7 +4566,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Select *pSel = pFrom->pSelect;
if( pSel ){
while( pSel->pPrior ) pSel = pSel->pPrior;
selectAddColumnTypeAndCollation(pParse, pTab, pSel);
sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
}
}
}
@@ -5082,6 +5098,13 @@ int sqlite3Select(
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
}
/* If there is an ORDER BY clause, then create an ephemeral index to
+500 -248
View File
File diff suppressed because it is too large Load Diff
+93 -18
View File
@@ -1932,12 +1932,30 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>
**
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
** There should be two additional arguments.
** When the first argument to this interface is 1, then only the C-API is
** enabled and the SQL function remains disabled. If the first argment to
** this interface is 0, then both the C-API and the SQL function are disabled.
** If the first argument is -1, then no changes are made to state of either the
** C-API or the SQL function.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
** is disabled or enabled following this call. The second parameter may
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
/*
@@ -5187,7 +5205,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
** to be invoked whenever a row is updated, inserted or deleted in
** a rowid table.
** a [rowid table].
** ^Any callback set by a previous call to this function
** for the same database connection is overridden.
**
@@ -5474,9 +5492,18 @@ int sqlite3_table_column_metadata(
** should free this memory by calling [sqlite3_free()].
**
** ^Extension loading must be enabled using
** [sqlite3_enable_load_extension()] prior to calling this API,
** [sqlite3_enable_load_extension()] or
** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL)
** prior to calling this API,
** otherwise an error will be returned.
**
** <b>Security warning:</b> It is recommended that the
** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
** interface. The use of the [sqlite3_enable_load_extension()] interface
** should be avoided. This will keep the SQL function [load_extension()]
** disabled and prevent SQL injections from giving attackers
** access to extension loading capabilities.
**
** See also the [load_extension() SQL function].
*/
int sqlite3_load_extension(
@@ -5499,6 +5526,17 @@ int sqlite3_load_extension(
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
**
** ^This interface enables or disables both the C-API
** [sqlite3_load_extension()] and the SQL function [load_extension()].
** Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
** to enable or disable only the C-API.
**
** <b>Security warning:</b> It is recommended that extension loading
** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
*/
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
@@ -6761,7 +6799,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** database file in rollback mode databases. Any pages written as part of
** transaction rollback or database recovery operations are not included.
** If an IO or other error occurs while writing a page to disk, the effect
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
**
@@ -7137,7 +7175,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
** an error.
**
** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if
** ^A call to sqlite3_backup_init() will fail, returning NULL, if
** there is already a read or read-write transaction open on the
** destination database.
**
@@ -7917,13 +7955,13 @@ int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
** EXPERIMENTAL
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_UPDATE_HOOK] compile-time option.
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation.
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
** on a [rowid table].
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
@@ -7932,8 +7970,9 @@ int sqlite3_db_cacheflush(sqlite3*);
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
** ^The preupdate hook only fires for changes to real tables; the preupdate
** hook is not invoked for changes to virtual tables.
** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate
** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID]
** tables.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
@@ -8080,20 +8119,29 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
** CAPI3REF: Start a read transaction on an historical snapshot
** EXPERIMENTAL
**
** ^The [sqlite3_snapshot_open(D,S,P)] interface attempts to move the
** read transaction that is currently open on schema S of
** [database connection] D so that it refers to historical [snapshot] P.
** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a
** read transaction for schema S of
** [database connection] D such that the read transaction
** refers to historical [snapshot] P, rather than the most
** recent change to the database.
** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
** or an appropriate [error code] if it fails.
**
** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
** the first operation, apart from other sqlite3_snapshot_open() calls,
** following the [BEGIN] that starts a new read transaction.
** ^A [snapshot] will fail to open if it has been overwritten by a
** the first operation following the [BEGIN] that takes the schema S
** out of [autocommit mode].
** ^In other words, schema S must not currently be in
** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the
** database connection D must be out of [autocommit mode].
** ^A [snapshot] will fail to open if it has been overwritten by a
** [checkpoint].
** ^A [snapshot] will fail to open if the database connection D has not
** previously completed at least one read operation against the database
** file. (Hint: Run "[PRAGMA application_id]" against a newly opened
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
** database connection D does not know that the database file for
** schema S is in [WAL mode]. A database connection might not know
** that the database file is in [WAL mode] if there has been no prior
** I/O on that database connection, or if the database entered [WAL mode]
** after the most recent I/O on the database connection.)^
** (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
@@ -8118,6 +8166,33 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
*/
SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
/*
** CAPI3REF: Compare the ages of two snapshot handles.
** EXPERIMENTAL
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.
**
** If the two snapshot handles are not associated with the same database
** file, the result of the comparison is undefined.
**
** Additionally, the result of the comparison is only valid if both of the
** snapshot handles were obtained by calling sqlite3_snapshot_get() since the
** last time the wal file was deleted. The wal file is deleted when the
** database is changed back to rollback mode or when the number of database
** clients drops to zero. If either snapshot handle was obtained before the
** wal file was last deleted, the value returned by this function
** is undefined.
**
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
*/
SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
sqlite3_snapshot *p2
);
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
+90 -24
View File
@@ -15,6 +15,33 @@
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
/* Special Comments:
**
** Some comments have special meaning to the tools that measure test
** coverage:
**
** NO_TEST - The branches on this line are not
** measured by branch coverage. This is
** used on lines of code that actually
** implement parts of coverage testing.
**
** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false
** and the correct answer is still obtained,
** though perhaps more slowly.
**
** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true
** and the correct answer is still obtained,
** though perhaps more slowly.
**
** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread
** that would be harmless and undetectable
** if it did occur.
**
** In all cases, the special comment must be enclosed in the usual
** slash-asterisk...asterisk-slash comment marks, with no spaces between the
** asterisks and the comment text.
*/
/*
** Make sure that rand_s() is available on Windows systems with MSVC 2005
** or higher.
@@ -384,7 +411,7 @@
** be true and false so that the unreachable code they specify will
** not be counted as untested code.
*/
#if defined(SQLITE_COVERAGE_TEST)
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define ALWAYS(X) (1)
# define NEVER(X) (0)
#elif !defined(NDEBUG)
@@ -1350,6 +1377,11 @@ struct sqlite3 {
/*
** Possible values for the sqlite3.flags.
**
** Value constraints (enforced via assert()):
** SQLITE_FullFSync == PAGER_FULLFSYNC
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
@@ -1377,13 +1409,14 @@ struct sqlite3 {
#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */
#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */
#define SQLITE_Fts3Tokenizer 0x20000000 /* Enable fts3_tokenizer(2) */
#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */
#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */
#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */
#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
/*
@@ -1484,6 +1517,13 @@ struct FuncDestructor {
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
** are assert() statements in the code to verify this.
**
** Value constraints (enforced via assert()):
** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
@@ -2483,6 +2523,9 @@ struct SrcList {
/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** and the WhereInfo.wctrlFlags member.
**
** Value constraints (enforced via assert()):
** WHERE_USE_LIMIT == SF_FixedLimit
*/
#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
@@ -2500,6 +2543,7 @@ struct SrcList {
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
#define WHERE_ONEPASS_MULTIROW 0x2000 /* ONEPASS is ok with multiple rows */
#define WHERE_USE_LIMIT 0x4000 /* There is a constant LIMIT clause */
#define WHERE_SEEK_TABLE 0x8000 /* Do not defer seeks on main table */
/* Allowed return values from sqlite3WhereIsDistinct()
*/
@@ -2543,16 +2587,18 @@ struct NameContext {
/*
** Allowed values for the NameContext, ncFlags field.
**
** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and
** SQLITE_FUNC_MINMAX.
** Value constraints (all checked via assert()):
** NC_HasAgg == SF_HasAgg
** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
**
*/
#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */
#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */
#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
/*
@@ -2600,24 +2646,30 @@ struct Select {
/*
** Allowed values for Select.selFlags. The "SF" prefix stands for
** "Select Flag".
**
** Value constraints (all checked via assert())
** SF_HasAgg == NC_HasAgg
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
** SF_FixedLimit == WHERE_USE_LIMIT
*/
#define SF_Distinct 0x00001 /* Output should be DISTINCT */
#define SF_All 0x00002 /* Includes the ALL keyword */
#define SF_Resolved 0x00004 /* Identifiers have been resolved */
#define SF_Aggregate 0x00008 /* Contains aggregate functions */
#define SF_UsesEphemeral 0x00010 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x00020 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x00040 /* FROM subqueries have Table metadata */
#define SF_Compound 0x00080 /* Part of a compound query */
#define SF_Values 0x00100 /* Synthesized from VALUES clause */
#define SF_MultiValue 0x00200 /* Single VALUES term with multiple rows */
#define SF_NestedFrom 0x00400 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x00800 /* Need convertCompoundSelectToSubquery() */
#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
#define SF_HasAgg 0x00010 /* Contains aggregate functions */
#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
#define SF_Compound 0x00100 /* Part of a compound query */
#define SF_Values 0x00200 /* Synthesized from VALUES clause */
#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
#define SF_Converted 0x08000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x10000 /* Include hidden columns in output */
#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
/*
@@ -2814,6 +2866,7 @@ struct Parse {
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 nColCache; /* Number of entries in aColCache[] */
int aTempReg[8]; /* Holding area for temporary registers */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
@@ -2927,6 +2980,15 @@ struct AuthContext {
/*
** Bitfield flags for P5 value in various opcodes.
**
** Value constraints (enforced via assert()):
** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH
** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF
** OPFLAG_BULKCSR == BTREE_BULKLOAD
** OPFLAG_SEEKEQ == BTREE_SEEK_EQ
** OPFLAG_FORDELETE == BTREE_FORDELETE
** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION
** OPFLAG_AUXDELETE == BTREE_AUXDELETE
*/
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
@@ -3301,6 +3363,7 @@ int sqlite3CantopenError(int);
# define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
#else
# define sqlite3Toupper(x) toupper((unsigned char)(x))
# define sqlite3Isspace(x) isspace((unsigned char)(x))
@@ -3309,6 +3372,7 @@ int sqlite3CantopenError(int);
# define sqlite3Isdigit(x) isdigit((unsigned char)(x))
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
# define sqlite3Tolower(x) tolower((unsigned char)(x))
# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`')
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
int sqlite3IsIdChar(u8);
@@ -3432,7 +3496,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3ErrorMsg(Parse*, const char*, ...);
int sqlite3Dequote(char*);
void sqlite3Dequote(char*);
void sqlite3TokenInit(Token*,char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
@@ -3449,6 +3513,7 @@ Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
Expr *sqlite3Expr(sqlite3*,int,const char*);
void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
@@ -3468,6 +3533,7 @@ void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
Table *sqlite3ResultSetOfSelect(Parse*,Select*);
void sqlite3OpenMasterTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
+1 -1
View File
@@ -3035,7 +3035,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
/* set ppHook to point at pUpdateHook or pRollbackHook, depending on
** whether [$db update_hook] or [$db rollback_hook] was invoked.
*/
Tcl_Obj **ppHook;
Tcl_Obj **ppHook = 0;
if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook;
if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook;
if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook;
+37 -8
View File
@@ -1271,7 +1271,7 @@ static int sqlite3_mprintf_int64(
return TCL_ERROR;
}
for(i=2; i<5; i++){
if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
return TCL_ERROR;
}
@@ -2359,6 +2359,31 @@ static int test_snapshot_free(
}
#endif /* SQLITE_ENABLE_SNAPSHOT */
#ifdef SQLITE_ENABLE_SNAPSHOT
/*
** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
*/
static int test_snapshot_cmp(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int res;
sqlite3_snapshot *p1;
sqlite3_snapshot *p2;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
return TCL_ERROR;
}
p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
res = sqlite3_snapshot_cmp(p1, p2);
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
return TCL_OK;
}
#endif /* SQLITE_ENABLE_SNAPSHOT */
/*
** Usage: sqlite3_next_stmt DB STMT
**
@@ -5188,7 +5213,9 @@ static int vfs_unregister_all(
/*
** tclcmd: vfs_reregister_all
**
** Restore all VFSes that were removed using vfs_unregister_all
** Restore all VFSes that were removed using vfs_unregister_all. Taking
** care to put the linked list back together in the same order as it was
** in before vfs_unregister_all was invoked.
*/
static int vfs_reregister_all(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
@@ -5197,8 +5224,8 @@ static int vfs_reregister_all(
Tcl_Obj *CONST objv[] /* Command arguments */
){
int i;
for(i=0; i<nVfs; i++){
sqlite3_vfs_register(apVfs[i], i==0);
for(i=nVfs-1; i>=0; i--){
sqlite3_vfs_register(apVfs[i], 1);
}
return TCL_OK;
}
@@ -6673,8 +6700,8 @@ static int sorter_test_sort4_helper(
const char *zSql2;
int nStep;
int iStep;
int iCksum1 = 0;
int iCksum2 = 0;
unsigned int iCksum1 = 0;
unsigned int iCksum2 = 0;
int rc;
int iB;
sqlite3 *db;
@@ -6701,7 +6728,7 @@ static int sorter_test_sort4_helper(
return TCL_ERROR;
}
iCksum1 += (iCksum1 << 3) + a;
iCksum1 += (iCksum1 << 3) + (unsigned int)a;
}
rc = sqlite3_finalize(pStmt);
if( rc!=SQLITE_OK ) goto sql_error;
@@ -6710,7 +6737,7 @@ static int sorter_test_sort4_helper(
if( rc!=SQLITE_OK ) goto sql_error;
for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
int a = sqlite3_column_int(pStmt, 0);
iCksum2 += (iCksum2 << 3) + a;
iCksum2 += (iCksum2 << 3) + (unsigned int)a;
}
rc = sqlite3_finalize(pStmt);
if( rc!=SQLITE_OK ) goto sql_error;
@@ -6963,6 +6990,7 @@ static int test_sqlite3_db_config(
{ "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
};
int i;
int v;
@@ -7249,6 +7277,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_snapshot_get", test_snapshot_get, 0 },
{ "sqlite3_snapshot_open", test_snapshot_open, 0 },
{ "sqlite3_snapshot_free", test_snapshot_free, 0 },
{ "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
#endif
};
static int bitmask_size = sizeof(Bitmask)*8;
+4 -2
View File
@@ -547,7 +547,7 @@ static int btree_from_db(
/*
** Usage: btree_ismemdb ID
**
** Return true if the B-Tree is in-memory.
** Return true if the B-Tree is currently stored entirely in memory.
*/
static int btree_ismemdb(
void *NotUsed,
@@ -557,6 +557,7 @@ static int btree_ismemdb(
){
Btree *pBt;
int res;
sqlite3_file *pFile;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -566,7 +567,8 @@ static int btree_ismemdb(
pBt = sqlite3TestTextToPtr(argv[1]);
sqlite3_mutex_enter(pBt->db->mutex);
sqlite3BtreeEnter(pBt);
res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt));
pFile = sqlite3PagerFile(sqlite3BtreePager(pBt));
res = (pFile->pMethods==0);
sqlite3BtreeLeave(pBt);
sqlite3_mutex_leave(pBt->db->mutex);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
+27 -1
View File
@@ -701,6 +701,10 @@ static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
return pVfs->xCurrentTime(pVfs, pTimeOut);
}
static int cfGetLastError(sqlite3_vfs *pCfVfs, int n, char *z){
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
return pVfs->xGetLastError(pVfs, n, z);
}
static int processDevSymArgs(
Tcl_Interp *interp,
@@ -827,7 +831,7 @@ static int crashEnableCmd(
cfRandomness, /* xRandomness */
cfSleep, /* xSleep */
cfCurrentTime, /* xCurrentTime */
0, /* xGetlastError */
cfGetLastError, /* xGetLastError */
0, /* xCurrentTimeInt64 */
};
@@ -940,6 +944,27 @@ static int devSymObjCmd(
devsym_register(iDc, iSectorSize);
return TCL_OK;
}
/*
** tclcmd: unregister_devsim
*/
static int dsUnregisterObjCmd(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
void devsym_unregister(void);
if( objc!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
devsym_unregister();
return TCL_OK;
}
/*
@@ -1010,6 +1035,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
#endif
+9 -1
View File
@@ -133,7 +133,8 @@ struct DevsymGlobal g = {0, 0, 512};
*/
static int devsymClose(sqlite3_file *pFile){
devsym_file *p = (devsym_file *)pFile;
return sqlite3OsClose(p->pReal);
sqlite3OsClose(p->pReal);
return SQLITE_OK;
}
/*
@@ -395,4 +396,11 @@ void devsym_register(int iDeviceChar, int iSectorSize){
}
}
void devsym_unregister(){
sqlite3_vfs_unregister(&devsym_vfs);
g.pVfs = 0;
g.iDeviceChar = 0;
g.iSectorSize = 0;
}
#endif
+18 -12
View File
@@ -160,6 +160,7 @@ static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int jtSleep(sqlite3_vfs*, int microseconds);
static int jtCurrentTime(sqlite3_vfs*, double*);
static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int jtGetLastError(sqlite3_vfs*, int, char*);
static sqlite3_vfs jt_vfs = {
2, /* iVersion */
@@ -179,7 +180,7 @@ static sqlite3_vfs jt_vfs = {
jtRandomness, /* xRandomness */
jtSleep, /* xSleep */
jtCurrentTime, /* xCurrentTime */
0, /* xGetLastError */
jtGetLastError, /* xGetLastError */
jtCurrentTimeInt64 /* xCurrentTimeInt64 */
};
@@ -256,7 +257,8 @@ static int jtClose(sqlite3_file *pFile){
*pp = p->pNext;
}
leaveJtMutex();
return sqlite3OsClose(p->pReal);
sqlite3OsClose(p->pReal);
return SQLITE_OK;
}
/*
@@ -284,9 +286,10 @@ static int jtRead(
** b) The file-name specified when the file was opened matches
** all but the final 8 characters of the journal file name.
**
** c) There is currently a reserved lock on the file.
** c) There is currently a reserved lock on the file. This
** condition is waived if the noLock argument is non-zero.
**/
static jt_file *locateDatabaseHandle(const char *zJournal){
static jt_file *locateDatabaseHandle(const char *zJournal, int noLock){
jt_file *pMain = 0;
enterJtMutex();
for(pMain=g.pList; pMain; pMain=pMain->pNext){
@@ -294,7 +297,7 @@ static jt_file *locateDatabaseHandle(const char *zJournal){
if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
&& ((int)strlen(pMain->zName)==nName)
&& 0==memcmp(pMain->zName, zJournal, nName)
&& (pMain->eLock>=SQLITE_LOCK_RESERVED)
&& ((pMain->eLock>=SQLITE_LOCK_RESERVED) || noLock)
){
break;
}
@@ -516,7 +519,7 @@ static int jtWrite(
jt_file *p = (jt_file *)pFile;
if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
if( iOfst==0 ){
jt_file *pMain = locateDatabaseHandle(p->zName);
jt_file *pMain = locateDatabaseHandle(p->zName, 0);
assert( pMain );
if( iAmt==28 ){
@@ -561,7 +564,7 @@ static int jtWrite(
rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){
jt_file *pMain = locateDatabaseHandle(p->zName);
jt_file *pMain = locateDatabaseHandle(p->zName, 0);
int rc2 = readJournalFile(p, pMain);
if( rc==SQLITE_OK ) rc = rc2;
}
@@ -575,7 +578,7 @@ static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){
jt_file *p = (jt_file *)pFile;
if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){
/* Truncating a journal file. This is the end of a transaction. */
jt_file *pMain = locateDatabaseHandle(p->zName);
jt_file *pMain = locateDatabaseHandle(p->zName, 0);
closeTransaction(pMain);
}
if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
@@ -603,11 +606,10 @@ static int jtSync(sqlite3_file *pFile, int flags){
** jt_file.pWritable bitvec of the main database file associated with
** this journal file.
*/
pMain = locateDatabaseHandle(p->zName);
assert(pMain);
pMain = locateDatabaseHandle(p->zName, 0);
/* Set the bitvec values */
if( pMain->pWritable ){
if( pMain && pMain->pWritable ){
pMain->nSync++;
rc = readJournalFile(p, pMain);
if( rc!=SQLITE_OK ){
@@ -729,7 +731,7 @@ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
int nPath = (int)strlen(zPath);
if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){
/* Deleting a journal file. The end of a transaction. */
jt_file *pMain = locateDatabaseHandle(zPath);
jt_file *pMain = locateDatabaseHandle(zPath, 0);
if( pMain ){
closeTransaction(pMain);
}
@@ -824,6 +826,10 @@ static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut);
}
static int jtGetLastError(sqlite3_vfs *pVfs, int n, char *z){
return g.pVfs->xGetLastError(g.pVfs, n, z);
}
/**************************************************************************
** Start of public API.
*/
+1 -1
View File
@@ -1093,7 +1093,7 @@ static int test_db_config_lookaside(
if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;
if( bufid==0 ){
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, 0, sz, cnt);
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt);
}else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);
}else{
+2 -2
View File
@@ -539,7 +539,7 @@ static int multiplexOpen(
memset(pGroup, 0, sz);
pMultiplexOpen->pGroup = pGroup;
pGroup->bEnabled = (unsigned char)-1;
pGroup->bTruncate = sqlite3_uri_boolean(zUri, "truncate",
pGroup->bTruncate = (unsigned char)sqlite3_uri_boolean(zUri, "truncate",
(flags & SQLITE_OPEN_MAIN_DB)==0);
pGroup->szChunk = (int)sqlite3_uri_int64(zUri, "chunksize",
SQLITE_MULTIPLEX_CHUNK_SIZE);
@@ -978,7 +978,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
case MULTIPLEX_CTRL_ENABLE:
if( pArg ) {
int bEnabled = *(int *)pArg;
pGroup->bEnabled = bEnabled;
pGroup->bEnabled = (unsigned char)bEnabled;
rc = SQLITE_OK;
}
break;
+1 -1
View File
@@ -508,7 +508,7 @@ static int fsSync(sqlite3_file *pFile, int flags){
if( p->eType==DATABASE_FILE ){
unsigned char zSize[4];
zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
zSize[1] = (unsigned char)((pReal->nDatabase&0x00FF0000)>>16);
zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
zSize[3] = (pReal->nDatabase&0x000000FF);
rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
+3 -3
View File
@@ -644,9 +644,9 @@ static void vfslog_flush(VfslogVfs *p){
static void put32bits(unsigned char *p, unsigned int v){
p[0] = v>>24;
p[1] = v>>16;
p[2] = v>>8;
p[3] = v;
p[1] = (unsigned char)(v>>16);
p[2] = (unsigned char)(v>>8);
p[3] = (unsigned char)v;
}
static void vfslog_call(
+18 -9
View File
@@ -108,10 +108,13 @@ static int ts_ftruncate(int fd, off_t n);
static int ts_fcntl(int fd, int cmd, ... );
static int ts_read(int fd, void *aBuf, size_t nBuf);
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off);
/* Note: pread64() and pwrite64() actually use off64_t as the type on their
** last parameter. But that datatype is not defined on many systems
** (ex: Mac, OpenBSD). So substitute a likely equivalent: sqlite3_uint64 */
static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off);
static int ts_write(int fd, const void *aBuf, size_t nBuf);
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off);
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off);
static int ts_fchmod(int fd, mode_t mode);
static int ts_fallocate(int fd, off_t off, off_t len);
static void *ts_mmap(void *, size_t, int, int, int, off_t);
@@ -155,11 +158,11 @@ struct TestSyscallArray {
#define orig_fcntl ((int(*)(int,int,...))aSyscall[7].xOrig)
#define orig_read ((ssize_t(*)(int,void*,size_t))aSyscall[8].xOrig)
#define orig_pread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].xOrig)
#define orig_pread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].xOrig)
#define orig_pread64 ((ssize_t(*)(int,void*,size_t,sqlite3_uint64))aSyscall[10].xOrig)
#define orig_write ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
#define orig_pwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
aSyscall[12].xOrig)
#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,sqlite3_uint64))\
aSyscall[13].xOrig)
#define orig_fchmod ((int(*)(int,mode_t))aSyscall[14].xOrig)
#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)
@@ -326,7 +329,7 @@ static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
/*
** A wrapper around pread64().
*/
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){
if( tsIsFailErrno("pread64") ){
return -1;
}
@@ -357,7 +360,7 @@ static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
/*
** A wrapper around pwrite64().
*/
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off){
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){
if( tsIsFailErrno("pwrite64") ){
return -1;
}
@@ -719,14 +722,20 @@ static int test_syscall(
};
int iCmd;
int rc;
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
if( objc<2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
return TCL_ERROR;
}
rc = Tcl_GetIndexFromObjStruct(interp,
objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd
);
if( pVfs->iVersion<3 || pVfs->xSetSystemCall==0 ){
Tcl_AppendResult(interp, "VFS does not support xSetSystemCall", 0);
rc = TCL_ERROR;
}else{
rc = Tcl_GetIndexFromObjStruct(interp,
objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd
);
}
if( rc!=TCL_OK ) return rc;
return aCmd[iCmd].xCmd(clientData, interp, objc, objv);
}
+2 -3
View File
@@ -306,7 +306,6 @@ static void tvfsExecTcl(
** Close an tvfs-file.
*/
static int tvfsClose(sqlite3_file *pFile){
int rc;
TestvfsFile *pTestfile = (TestvfsFile *)pFile;
TestvfsFd *pFd = pTestfile->pFd;
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
@@ -324,10 +323,10 @@ static int tvfsClose(sqlite3_file *pFile){
if( pFile->pMethods ){
ckfree((char *)pFile->pMethods);
}
rc = sqlite3OsClose(pFd->pReal);
sqlite3OsClose(pFd->pReal);
ckfree((char *)pFd);
pTestfile->pFd = 0;
return rc;
return SQLITE_OK;
}
/*
+1 -1
View File
@@ -583,7 +583,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
sqlite3DeleteTable(db, pParse->pNewTable);
}
sqlite3WithDelete(db, pParse->pWithToFree);
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
sqlite3DbFree(db, pParse->azVar);
+2 -1
View File
@@ -352,7 +352,8 @@ void sqlite3Update(
if( HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
pWInfo = sqlite3WhereBegin(
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
pParse, pTabList, pWhere, 0, 0,
WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE, iIdxCur
);
if( pWInfo==0 ) goto update_cleanup;
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+65 -61
View File
@@ -242,18 +242,13 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
** brackets from around identifiers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
int sqlite3Dequote(char *z){
void sqlite3Dequote(char *z){
char quote;
int i, j;
if( z==0 ) return -1;
if( z==0 ) return;
quote = z[0];
switch( quote ){
case '\'': break;
case '"': break;
case '`': break; /* For MySQL compatibility */
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
default: return -1;
}
if( !sqlite3Isquote(quote) ) return;
if( quote=='[' ) quote = ']';
for(i=1, j=0;; i++){
assert( z[i] );
if( z[i]==quote ){
@@ -268,7 +263,6 @@ int sqlite3Dequote(char *z){
}
}
z[j] = 0;
return j;
}
/*
@@ -361,7 +355,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
int eValid = 1; /* True exponent is either not used or is well-formed */
double result;
int nDigits = 0;
int nonNum = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
@@ -374,7 +368,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && z[i]==0; i+=2){}
nonNum = i<length;
zEnd = z+i+enc-3;
zEnd = &z[i^1];
z += (enc&1);
}
@@ -390,9 +384,6 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
z+=incr;
}
/* skip leading zeroes */
while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
/* copy max significant digits to significand */
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
@@ -409,12 +400,13 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
z+=incr;
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
z+=incr, nDigits++, d--;
while( z<zEnd && sqlite3Isdigit(*z) ){
if( s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
d--;
}
z+=incr, nDigits++;
}
/* skip non-significant digits */
while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
}
if( z>=zEnd ) goto do_atof_calc;
@@ -422,7 +414,12 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
if( *z=='e' || *z=='E' ){
z+=incr;
eValid = 0;
if( z>=zEnd ) goto do_atof_calc;
/* 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;
@@ -439,9 +436,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
}
/* skip trailing spaces */
if( nDigits && eValid ){
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
}
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
do_atof_calc:
/* adjust exponent by d, and update sign */
@@ -453,41 +448,51 @@ do_atof_calc:
esign = 1;
}
/* if 0 significand */
if( !s ) {
/* In the IEEE 754 standard, zero is signed.
** Add the sign if we've seen at least one digit */
result = (sign<0 && nDigits) ? -(double)0 : (double)0;
if( s==0 ) {
/* In the IEEE 754 standard, zero is signed. */
result = sign<0 ? -(double)0 : (double)0;
} else {
/* attempt to reduce exponent */
if( esign>0 ){
while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
}else{
while( !(s%10) && e>0 ) e--,s/=10;
/* Attempt to reduce exponent.
**
** Branches that are not required for the correct answer but which only
** help to obtain the correct answer faster are marked with special
** comments, as a hint to the mutation tester.
*/
while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/
if( esign>0 ){
if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
s *= 10;
}else{
if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
s /= 10;
}
e--;
}
/* adjust the sign of significand */
s = sign<0 ? -s : s;
/* if exponent, scale significand as appropriate
** and store in result. */
if( e ){
if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
result = (double)s;
}else{
LONGDOUBLE_TYPE scale = 1.0;
/* attempt to handle extremely small/large numbers better */
if( e>307 && e<342 ){
while( e%308 ) { scale *= 1.0e+1; e -= 1; }
if( esign<0 ){
result = s / scale;
result /= 1.0e+308;
}else{
result = s * scale;
result *= 1.0e+308;
}
}else if( e>=342 ){
if( esign<0 ){
result = 0.0*s;
}else{
result = 1e308*1e308*s; /* Infinity */
if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
while( e%308 ) { scale *= 1.0e+1; e -= 1; }
if( esign<0 ){
result = s / scale;
result /= 1.0e+308;
}else{
result = s * scale;
result *= 1.0e+308;
}
}else{ assert( e>=342 );
if( esign<0 ){
result = 0.0*s;
}else{
result = 1e308*1e308*s; /* Infinity */
}
}
}else{
/* 1.0e+22 is the largest power of 10 than can be
@@ -500,8 +505,6 @@ do_atof_calc:
result = s * scale;
}
}
} else {
result = (double)s;
}
}
@@ -509,7 +512,7 @@ do_atof_calc:
*pResult = result;
/* return true if number and no extra non-whitespace chracters after */
return z>=zEnd && nDigits>0 && eValid && nonNum==0;
return z==zEnd && nDigits>0 && eValid && nonNum==0;
#else
return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -571,7 +574,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
int neg = 0; /* assume positive */
int i;
int c = 0;
int nonNum = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
const char *zStart;
const char *zEnd = zNum + length;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
@@ -582,7 +585,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && zNum[i]==0; i+=2){}
nonNum = i<length;
zEnd = zNum+i+enc-3;
zEnd = &zNum[i^1];
zNum += (enc&1);
}
while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
@@ -609,8 +612,11 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
testcase( i==18 );
testcase( i==19 );
testcase( i==20 );
if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum)
|| i>19*incr || nonNum ){
if( &zNum[i]<zEnd /* Extra bytes at the end */
|| (i==0 && zStart==zNum) /* No digits */
|| i>19*incr /* Too many digits */
|| nonNum /* UTF16 with high-order bytes non-zero */
){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */
return 1;
@@ -652,7 +658,6 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
#ifndef SQLITE_OMIT_HEX_INTEGER
if( z[0]=='0'
&& (z[1]=='x' || z[1]=='X')
&& sqlite3Isxdigit(z[2])
){
u64 u = 0;
int i, k;
@@ -1414,7 +1419,7 @@ LogEst sqlite3LogEst(u64 x){
if( x<2 ) return 0;
while( x<8 ){ y -= 10; x <<= 1; }
}else{
while( x>255 ){ y += 40; x >>= 4; }
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
while( x>15 ){ y += 10; x >>= 1; }
}
return a[x&7] + y - 10;
@@ -1448,7 +1453,6 @@ LogEst sqlite3LogEstFromDouble(double x){
*/
u64 sqlite3LogEstToInt(LogEst x){
u64 n;
if( x<10 ) return 1;
n = x%10;
x /= 10;
if( n>=5 ) n -= 2;
+72 -85
View File
@@ -215,7 +215,7 @@ static VdbeCursor *allocateCursor(
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
@@ -292,7 +292,7 @@ static void applyAffinity(
if( affinity>=SQLITE_AFF_NUMERIC ){
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|| affinity==SQLITE_AFF_NUMERIC );
if( (pRec->flags & MEM_Int)==0 ){
if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/
if( (pRec->flags & MEM_Real)==0 ){
if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
}else{
@@ -302,10 +302,13 @@ static void applyAffinity(
}else if( affinity==SQLITE_AFF_TEXT ){
/* Only attempt the conversion to TEXT if there is an integer or real
** representation (blob and NULL do not get converted) but no string
** representation.
*/
if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
sqlite3VdbeMemStringify(pRec, enc, 1);
** representation. It would be harmless to repeat the conversion if
** there is already a string rep, but it is pointless to waste those
** CPU cycles. */
if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
if( (pRec->flags&(MEM_Real|MEM_Int)) ){
sqlite3VdbeMemStringify(pRec, enc, 1);
}
}
pRec->flags &= ~(MEM_Real|MEM_Int);
}
@@ -542,7 +545,7 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
pOut = &p->aMem[pOp->p2];
memAboutToChange(p, pOut);
if( VdbeMemDynamic(pOut) ){
if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
return out2PrereleaseWithClear(pOut);
}else{
pOut->flags = MEM_Int;
@@ -674,37 +677,39 @@ int sqlite3VdbeExec(
/* Sanity checking on other operands */
#ifdef SQLITE_DEBUG
assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
if( (pOp->opflags & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 );
assert( pOp->p1<=(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p1]) );
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
}
if( (pOp->opflags & OPFLG_IN2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p2]) );
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_IN3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p3]) );
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
}
if( (pOp->opflags & OPFLG_OUT2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
memAboutToChange(p, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_OUT3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
memAboutToChange(p, &aMem[pOp->p3]);
{
u8 opProperty = sqlite3OpcodeProperty[pOp->opcode];
if( (opProperty & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 );
assert( pOp->p1<=(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p1]) );
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
}
if( (opProperty & OPFLG_IN2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p2]) );
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
}
if( (opProperty & OPFLG_IN3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p3]) );
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
}
if( (opProperty & OPFLG_OUT2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
memAboutToChange(p, &aMem[pOp->p2]);
}
if( (opProperty & OPFLG_OUT3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
memAboutToChange(p, &aMem[pOp->p3]);
}
}
#endif
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
@@ -944,8 +949,6 @@ case OP_HaltIfNull: { /* in3 */
** is the same as executing Halt.
*/
case OP_Halt: {
const char *zType;
const char *zLogFmt;
VdbeFrame *pFrame;
int pcx;
@@ -974,34 +977,28 @@ case OP_Halt: {
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pcx;
assert( pOp->p5>=0 && pOp->p5<=4 );
if( p->rc ){
if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
"FOREIGN KEY" };
assert( pOp->p5>=1 && pOp->p5<=4 );
testcase( pOp->p5==1 );
testcase( pOp->p5==2 );
testcase( pOp->p5==3 );
testcase( pOp->p5==4 );
zType = azType[pOp->p5-1];
sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
if( pOp->p4.z ){
p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
}
}else{
zType = 0;
}
assert( zType!=0 || pOp->p4.z!=0 );
zLogFmt = "abort at %d in [%s]: %s";
if( zType && pOp->p4.z ){
sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z);
}else if( pOp->p4.z ){
sqlite3VdbeError(p, "%s", pOp->p4.z);
}else{
sqlite3VdbeError(p, "%s constraint failed", zType);
}
sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
p->rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
@@ -1067,10 +1064,7 @@ case OP_String8: { /* same as TK_STRING, out2 */
#ifndef SQLITE_OMIT_UTF16
if( encoding!=SQLITE_UTF8 ){
rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
if( rc ){
assert( rc==SQLITE_TOOBIG ); /* This is the only possible error here */
goto too_big;
}
assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
assert( VdbeMemDynamic(pOut)==0 );
@@ -1083,10 +1077,12 @@ case OP_String8: { /* same as TK_STRING, out2 */
pOp->p4.z = pOut->z;
pOp->p1 = pOut->n;
}
testcase( rc==SQLITE_TOOBIG );
#endif
if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
assert( rc==SQLITE_OK );
/* Fall through to the next case, OP_String */
}
@@ -1095,10 +1091,12 @@ case OP_String8: { /* same as TK_STRING, out2 */
**
** The string value P4 of length P1 (bytes) is stored in register P2.
**
** If P5!=0 and the content of register P3 is greater than zero, then
** If P3 is not zero and the content of register P3 is equal to P5, then
** the datatype of the register P2 is converted to BLOB. The content is
** the same sequence of bytes, it is merely interpreted as a BLOB instead
** of a string, as if it had been CAST.
** of a string, as if it had been CAST. In other words:
**
** if( P3!=0 and reg[P3]==P5 ) reg[P2] := CAST(reg[P2] as BLOB)
*/
case OP_String: { /* out2 */
assert( pOp->p4.z!=0 );
@@ -1109,12 +1107,11 @@ case OP_String: { /* out2 */
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
if( pOp->p5 ){
assert( pOp->p3>0 );
if( pOp->p3>0 ){
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
pIn3 = &aMem[pOp->p3];
assert( pIn3->flags & MEM_Int );
if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
}
#endif
break;
@@ -2016,11 +2013,13 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
/* Neither operand is NULL. Do a comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
}
if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3,0);
if( (flags1 | flags3)&MEM_Str ){
if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
}
if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3,0);
}
}
}else if( affinity==SQLITE_AFF_TEXT ){
if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
@@ -2753,7 +2752,9 @@ case OP_MakeRecord: {
testcase( serial_type==127 );
testcase( serial_type==128 );
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
}while( (--pRec)>=pData0 );
if( pRec==pData0 ) break;
pRec--;
}while(1);
/* EVIDENCE-OF: R-22564-11647 The header begins with a single varint
** which determines the total number of bytes in the header. The varint
@@ -5966,21 +5967,6 @@ case OP_DecrJumpZero: { /* jump, in1 */
}
/* Opcode: JumpZeroIncr P1 P2 * * *
** Synopsis: if (r[P1]++)==0 ) goto P2
**
** The register P1 must contain an integer. If register P1 is initially
** zero, then jump to P2. Increment register P1 regardless of whether or
** not the jump is taken.
*/
case OP_JumpZeroIncr: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
VdbeBranchTaken(pIn1->u.i==0, 2);
if( (pIn1->u.i++)==0 ) goto jump_to_p2;
break;
}
/* Opcode: AggStep0 * P2 P3 P4 P5
** Synopsis: accum=r[P3] step(r[P2@P5])
**
@@ -6873,11 +6859,12 @@ default: { /* This is really OP_Noop and OP_Explain */
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
u8 opProperty = sqlite3OpcodeProperty[pOrigOp->opcode];
if( rc!=0 ) printf("rc=%d\n",rc);
if( pOrigOp->opflags & (OPFLG_OUT2) ){
if( opProperty & (OPFLG_OUT2) ){
registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]);
}
if( pOrigOp->opflags & OPFLG_OUT3 ){
if( opProperty & OPFLG_OUT3 ){
registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
}
}
+1 -1
View File
@@ -41,7 +41,7 @@ typedef struct SubProgram SubProgram;
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */
u8 notUsed1;
u8 p5; /* Fifth parameter is an unsigned character */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
+103 -94
View File
@@ -545,73 +545,84 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
** (4) Initialize the p4.xAdvance pointer on opcodes that use it.
**
** (5) Reclaim the memory allocated for storing labels.
**
** This routine will only function correctly if the mkopcodeh.tcl generator
** script numbers the opcodes correctly. Changes to this routine must be
** coordinated with changes to mkopcodeh.tcl.
*/
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
int i;
int nMaxArgs = *pMaxFuncArgs;
Op *pOp;
Parse *pParse = p->pParse;
int *aLabel = pParse->aLabel;
p->readOnly = 1;
p->bIsReader = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
pOp = &p->aOp[p->nOp-1];
while(1){
/* NOTE: Be sure to update mkopcodeh.tcl when adding or removing
** cases from this switch! */
switch( opcode ){
case OP_Transaction: {
if( pOp->p2!=0 ) p->readOnly = 0;
/* fall thru */
}
case OP_AutoCommit:
case OP_Savepoint: {
p->bIsReader = 1;
break;
}
/* Only JUMP opcodes and the short list of special opcodes in the switch
** below need to be considered. The mkopcodeh.tcl generator script groups
** all these opcodes together near the front of the opcode list. Skip
** any opcode that does not need processing by virtual of the fact that
** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization.
*/
if( pOp->opcode<=SQLITE_MX_JUMP_OPCODE ){
/* NOTE: Be sure to update mkopcodeh.tcl when adding or removing
** cases from this switch! */
switch( pOp->opcode ){
case OP_Transaction: {
if( pOp->p2!=0 ) p->readOnly = 0;
/* fall thru */
}
case OP_AutoCommit:
case OP_Savepoint: {
p->bIsReader = 1;
break;
}
#ifndef SQLITE_OMIT_WAL
case OP_Checkpoint:
case OP_Checkpoint:
#endif
case OP_Vacuum:
case OP_JournalMode: {
p->readOnly = 0;
p->bIsReader = 1;
break;
}
case OP_Vacuum:
case OP_JournalMode: {
p->readOnly = 0;
p->bIsReader = 1;
break;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
case OP_VUpdate: {
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
break;
}
case OP_VFilter: {
int n;
assert( p->nOp - i >= 3 );
assert( pOp[-1].opcode==OP_Integer );
n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n;
break;
}
case OP_VUpdate: {
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
break;
}
case OP_VFilter: {
int n;
assert( (pOp - p->aOp) >= 3 );
assert( pOp[-1].opcode==OP_Integer );
n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n;
break;
}
#endif
case OP_Next:
case OP_NextIfOpen:
case OP_SorterNext: {
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
break;
case OP_Next:
case OP_NextIfOpen:
case OP_SorterNext: {
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
break;
}
case OP_Prev:
case OP_PrevIfOpen: {
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
break;
}
}
case OP_Prev:
case OP_PrevIfOpen: {
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
break;
if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){
assert( ADDR(pOp->p2)<pParse->nLabel );
pOp->p2 = aLabel[ADDR(pOp->p2)];
}
}
pOp->opflags = sqlite3OpcodeProperty[opcode];
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
assert( ADDR(pOp->p2)<pParse->nLabel );
pOp->p2 = aLabel[ADDR(pOp->p2)];
}
if( pOp==p->aOp ) break;
pOp--;
}
sqlite3DbFree(p->db, pParse->aLabel);
pParse->aLabel = 0;
@@ -791,52 +802,50 @@ static void vdbeFreeOpArray(sqlite3 *, Op *, int);
** Delete a P4 value if necessary.
*/
static void freeP4(sqlite3 *db, int p4type, void *p4){
if( p4 ){
assert( db );
switch( p4type ){
case P4_FUNCCTX: {
freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc);
/* Fall through into the next case */
}
case P4_REAL:
case P4_INT64:
case P4_DYNAMIC:
case P4_INTARRAY: {
sqlite3DbFree(db, p4);
break;
}
case P4_KEYINFO: {
if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
break;
}
assert( db );
switch( p4type ){
case P4_FUNCCTX: {
freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc);
/* Fall through into the next case */
}
case P4_REAL:
case P4_INT64:
case P4_DYNAMIC:
case P4_INTARRAY: {
sqlite3DbFree(db, p4);
break;
}
case P4_KEYINFO: {
if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
break;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
case P4_EXPR: {
sqlite3ExprDelete(db, (Expr*)p4);
break;
}
case P4_EXPR: {
sqlite3ExprDelete(db, (Expr*)p4);
break;
}
#endif
case P4_MPRINTF: {
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
break;
}
case P4_FUNCDEF: {
freeEphemeralFunction(db, (FuncDef*)p4);
break;
}
case P4_MEM: {
if( db->pnBytesFreed==0 ){
sqlite3ValueFree((sqlite3_value*)p4);
}else{
Mem *p = (Mem*)p4;
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
sqlite3DbFree(db, p);
}
break;
}
case P4_VTAB : {
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
case P4_MPRINTF: {
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
break;
}
case P4_FUNCDEF: {
freeEphemeralFunction(db, (FuncDef*)p4);
break;
}
case P4_MEM: {
if( db->pnBytesFreed==0 ){
sqlite3ValueFree((sqlite3_value*)p4);
}else{
Mem *p = (Mem*)p4;
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
sqlite3DbFree(db, p);
}
break;
}
case P4_VTAB : {
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
}
}
}
+11 -3
View File
@@ -931,7 +931,6 @@ int sqlite3VdbeSorterInit(
){
int pgsz; /* Page size of main database */
int i; /* Used to iterate through aTask[] */
int mxCache; /* Cache size */
VdbeSorter *pSorter; /* The new sorter */
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
@@ -988,11 +987,20 @@ int sqlite3VdbeSorterInit(
}
if( !sqlite3TempInMemory(db) ){
i64 mxCache; /* Cache size in bytes*/
u32 szPma = sqlite3GlobalConfig.szPma;
pSorter->mnPmaSize = szPma * pgsz;
mxCache = db->aDb[0].pSchema->cache_size;
if( mxCache<(int)szPma ) mxCache = (int)szPma;
pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
if( mxCache<0 ){
/* A negative cache-size value C indicates that the cache is abs(C)
** KiB in size. */
mxCache = mxCache * -1024;
}else{
mxCache = mxCache * pgsz;
}
mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
+17
View File
@@ -3399,6 +3399,23 @@ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
}
/*
** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
** p1 is older than p2 and zero if p1 and p2 are the same snapshot.
*/
int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
WalIndexHdr *pHdr1 = (WalIndexHdr*)p1;
WalIndexHdr *pHdr2 = (WalIndexHdr*)p2;
/* aSalt[0] is a copy of the value stored in the wal file header. It
** is incremented each time the wal file is restarted. */
if( pHdr1->aSalt[0]<pHdr2->aSalt[0] ) return -1;
if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1;
if( pHdr1->mxFrame<pHdr2->mxFrame ) return -1;
if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1;
return 0;
}
#endif /* SQLITE_ENABLE_SNAPSHOT */
#ifdef SQLITE_ENABLE_ZIPVFS
+41 -31
View File
@@ -261,7 +261,10 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
**
** The scanner will be searching the WHERE clause pWC. It will look
** for terms of the form "X <op> <expr>" where X is column iColumn of table
** iCur. The <op> must be one of the operators described by opMask.
** iCur. Or if pIdx!=0 then X is column iColumn of index pIdx. pIdx
** must be one of the indexes of table iCur.
**
** The <op> must be one of the operators described by opMask.
**
** If the search is for X and the WHERE clause contains terms of the
** form X=Y then this routine might also return terms of the form
@@ -309,11 +312,12 @@ static WhereTerm *whereScanInit(
/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur and <op> is one of
** the WO_xx operator codes specified by the op parameter.
** Return a pointer to the term. Return 0 if not found.
** where X is a reference to the iColumn of table iCur or of index pIdx
** if pIdx!=0 and <op> is one of the WO_xx operator codes specified by
** the op parameter. Return a pointer to the term. Return 0 if not found.
**
** If pIdx!=0 then search for terms matching the iColumn-th column of pIdx
** If pIdx!=0 then it must be one of the indexes of table iCur.
** Search for terms matching the iColumn-th column of pIdx
** rather than the iColumn-th column of table iCur.
**
** The term returned might by Y=<expr> if there is another constraint in
@@ -1651,11 +1655,12 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
*/
static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
WhereInfo *pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+7)/8;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
Table *pTab = pItem->pTab;
Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
p->iTab, nb, p->maskSelf, nb, p->prereq);
p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
sqlite3DebugPrintf(" %12s",
pItem->zAlias ? pItem->zAlias : pTab->zName);
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
@@ -2201,8 +2206,6 @@ static int whereLoopAddBtreeIndex(
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
if( pNew->wsFlags & WHERE_BTM_LIMIT ){
opMask = WO_LT|WO_LE;
}else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
}else{
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
}
@@ -2240,6 +2243,18 @@ static int whereLoopAddBtreeIndex(
** to mix with a lower range bound from some other source */
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
/* Do not allow IS constraints from the WHERE clause to be used by the
** right table of a LEFT JOIN. Only constraints in the ON clause are
** allowed */
if( (pSrc->fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
&& (eOp & (WO_IS|WO_ISNULL))!=0
){
testcase( eOp & WO_IS );
testcase( eOp & WO_ISNULL );
continue;
}
pNew->wsFlags = saved_wsFlags;
pNew->u.btree.nEq = saved_nEq;
pNew->nLTerm = saved_nLTerm;
@@ -3870,9 +3885,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
&& nRowEst
){
Bitmask notUsed;
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom,
WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
if( rc==pWInfo->pResultSet->nExpr ){
if( rc==pWInfo->pDistinctSet->nExpr ){
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
}
}
@@ -4087,14 +4102,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
** used.
*/
WhereInfo *sqlite3WhereBegin(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
ExprList *pResultSet, /* Result set of the query */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number,
** If WHERE_USE_LIMIT, then the limit amount */
Parse *pParse, /* The parser context */
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number
** If WHERE_USE_LIMIT, then the limit amount */
){
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
int nTabList; /* Number of elements in pTabList */
@@ -4169,7 +4184,7 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->pOrderBy = pOrderBy;
pWInfo->pResultSet = pResultSet;
pWInfo->pDistinctSet = pDistinctSet;
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->iLimit = iAuxArg;
@@ -4242,13 +4257,13 @@ WhereInfo *sqlite3WhereBegin(
if( db->mallocFailed ) goto whereBeginError;
if( wctrlFlags & WHERE_WANT_DISTINCT ){
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){
/* The DISTINCT marking is pointless. Ignore it. */
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}else if( pOrderBy==0 ){
/* Try to ORDER BY the result set to make distinct processing easier */
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
pWInfo->pOrderBy = pResultSet;
pWInfo->pOrderBy = pDistinctSet;
}
}
@@ -4327,10 +4342,10 @@ WhereInfo *sqlite3WhereBegin(
#endif
/* Attempt to omit tables from the join that do not effect the result */
if( pWInfo->nLevel>=2
&& pResultSet!=0
&& pDistinctSet!=0
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet);
if( sWLB.pOrderBy ){
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
}
@@ -4596,13 +4611,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
if( pLevel->addrLikeRep ){
int op;
if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
op = OP_DecrJumpZero;
}else{
op = OP_JumpZeroIncr;
}
sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1),
pLevel->addrLikeRep);
VdbeCoverage(v);
}
#endif
+10 -2
View File
@@ -70,7 +70,7 @@ struct WhereLevel {
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
int iLikeRepCntr; /* LIKE range processing counter register */
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
u8 iFrom; /* Which entry in the FROM clause */
@@ -408,7 +408,7 @@ struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */
SrcList *pTabList; /* List of tables in the join */
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
ExprList *pDistinctSet; /* DISTINCT over all these values */
WhereLoop *pLoops; /* List of all WhereLoop objects */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
LogEst nRowOut; /* Estimated number of output rows */
@@ -492,6 +492,14 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
** operators that are of interest to the query planner. An
** OR-ed combination of these values can be used when searching for
** particular WhereTerms within a WhereClause.
**
** Value constraints:
** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ
** WO_LT == SQLITE_INDEX_CONSTRAINT_LT
** WO_LE == SQLITE_INDEX_CONSTRAINT_LE
** WO_GT == SQLITE_INDEX_CONSTRAINT_GT
** WO_GE == SQLITE_INDEX_CONSTRAINT_GE
** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH
*/
#define WO_IN 0x0001
#define WO_EQ 0x0002
+33 -16
View File
@@ -560,9 +560,10 @@ static int codeAllEqualityTerms(
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
/*
** If the most recently coded instruction is a constant range contraint
** that originated from the LIKE optimization, then change the P3 to be
** pLoop->iLikeRepCntr and set P5.
** If the most recently coded instruction is a constant range constraint
** (a string literal) that originated from the LIKE optimization, then
** set P3 and P5 on the OP_String opcode so that the string will be cast
** to a BLOB at appropriate times.
**
** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
** expression: "x>='ABC' AND x<'abd'". But this requires that the range
@@ -587,8 +588,8 @@ static void whereLikeOptimizationStringFixup(
assert( pOp!=0 );
assert( pOp->opcode==OP_String8
|| pTerm->pWC->pWInfo->pParse->db->mallocFailed );
pOp->p3 = pLevel->iLikeRepCntr;
pOp->p5 = 1;
pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */
pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */
}
}
#else
@@ -941,7 +942,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
}
}
sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
/* These registers need to be preserved in case there is an IN operator
** loop. So we could deallocate the registers here (and potentially
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
** simpler and safer to simply not reuse the registers.
**
** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
*/
sqlite3ExprCachePop(pParse);
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -1169,14 +1176,17 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
assert( pRangeStart!=0 ); /* LIKE opt constraints */
assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
pLevel->iLikeRepCntr = ++pParse->nMem;
testcase( bRev );
testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
sqlite3VdbeAddOp2(v, OP_Integer,
bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC),
pLevel->iLikeRepCntr);
pLevel->iLikeRepCntr = (u32)++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr);
VdbeComment((v, "LIKE loop counter"));
pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
/* iLikeRepCntr actually stores 2x the counter register number. The
** bottom bit indicates whether the search order is ASC or DESC. */
testcase( bRev );
testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
assert( (bRev & ~1)==0 );
pLevel->iLikeRepCntr <<=1;
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
}
#endif
if( pRangeStart==0
@@ -1314,7 +1324,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
if( pWInfo->eOnePass!=ONEPASS_OFF ){
if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
@@ -1510,7 +1520,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
wctrlFlags = WHERE_OMIT_OPEN_CLOSE
| WHERE_FORCE_TABLE
| WHERE_ONETABLE_ONLY
| WHERE_NO_AUTOINDEX;
| WHERE_NO_AUTOINDEX
| (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
@@ -1690,11 +1701,17 @@ Bitmask sqlite3WhereCodeOneLoopStart(
continue;
}
if( pTerm->wtFlags & TERM_LIKECOND ){
/* If the TERM_LIKECOND flag is set, that means that the range search
** is sufficient to guarantee that the LIKE operator is true, so we
** can skip the call to the like(A,B) function. But this only works
** for strings. So do not skip the call to the function on the pass
** that compares BLOBs. */
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
continue;
#else
assert( pLevel->iLikeRepCntr>0 );
skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
u32 x = pLevel->iLikeRepCntr;
assert( x>0 );
skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)? OP_IfNot : OP_If, (int)(x>>1));
VdbeCoverage(v);
#endif
}
+2 -2
View File
@@ -1282,10 +1282,10 @@ Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
return mask;
}
mask = sqlite3WhereExprUsage(pMaskSet, p->pRight);
mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
if( ExprHasProperty(p, EP_xIsSelect) ){
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
}else{
}else if( p->x.pList ){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
}
return mask;
+47 -2
View File
@@ -2432,8 +2432,53 @@ do_test auth-6.3 {
execsql {SELECT rowid, * FROM t6}
} {101 1 2 3 4 5 6 7 8}
#-------------------------------------------------------------------------
# Test that view names are included as zArg4.
#
do_execsql_test auth-7.1 {
CREATE TABLE t7(a, b, c);
CREATE VIEW v7 AS SELECT * FROM t7;
} {}
set ::authargs [list]
proc auth {args} {
eval lappend ::authargs [lrange $args 0 4]
return SQLITE_OK
}
do_test auth-7.2 {
execsql {SELECT a, c FROM v7}
set ::authargs
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t7 a main v7 \
SQLITE_READ t7 b main v7 \
SQLITE_READ t7 c main v7 \
SQLITE_READ v7 a main {} \
SQLITE_READ v7 c main {} \
SQLITE_SELECT {} {} {} v7 \
]
set ::authargs [list]
do_test auth-7.3 {
execsql {SELECT a, c FROM t7}
set ::authargs
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t7 a main {} \
SQLITE_READ t7 c main {} \
]
set ::authargs [list]
do_test auth-7.4 {
execsql {SELECT a, c FROM t7 AS v7}
set ::authargs
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t7 a main {} \
SQLITE_READ t7 c main {} \
]
rename proc {}
rename proc_real proc
finish_test
+10 -11
View File
@@ -164,7 +164,7 @@ foreach zOpenScript [list {
set file_dest temp
}] {
foreach rows_dest {0 3 10} {
foreach pgsz_dest {512 1024 2048} {
foreach pgsz_dest {512 1024 2048 4096} {
foreach nPagePerStep {1 200} {
# Open the databases.
@@ -176,17 +176,16 @@ foreach nPagePerStep {1 200} {
# in-memory destination is only possible if the initial destination
# page size is the same as the source page size (in this case 1024 bytes).
#
set isMemDest [expr {
$zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2
}]
set isMemDest [expr { $zDestFile eq ":memory:" || $file_dest eq "temp" }]
if { $isMemDest==0 || $pgsz_dest == 1024 } {
if 0 {
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
puts -nonewline " (as $db_dest.$file_dest)"
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
puts ""
}
if 0 {
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
puts -nonewline " (as $db_dest.$file_dest)"
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
puts ""
}
if { $isMemDest==0 || $pgsz_dest==1024 || $rows_dest==0 } {
# Set up the content of the source database.
execsql {
+107
View File
@@ -165,4 +165,111 @@ foreach {tn mode} {
} $plan($mode)
}
# 2016-04-09.
# Demonstrate a register overwrite problem when using two virtual
# tables where the outer loop uses the IN operator.
#
set G(collist) [list PrimaryKey flagA columnA]
set G(cols) [join $G(collist) ,]
set G(nulls) "NULL"
proc vtab_command {method args} {
global G
switch -- $method {
xConnect {
return "CREATE TABLE t1($G(cols))"
}
xBestIndex {
set clist [lindex $args 0]
#puts $clist
set W [list]
set U [list]
set i 0
for {set idx 0} {$idx < [llength $clist]} {incr idx} {
array set c [lindex $clist $idx]
if {$c(op)=="eq" && $c(usable)} {
lappend W "[lindex $G(collist) $c(column)] = %$i%"
lappend U use $idx
incr i
}
}
if {$W==""} {
set sql "SELECT rowid, * FROM t1"
} else {
set sql "SELECT rowid, * FROM t1 WHERE [join $W { AND }]"
}
return [concat [list idxstr $sql] $U]
}
xFilter {
foreach {idxnum idxstr vals} $args {}
set map [list]
for {set i 0} {$i < [llength $vals]} {incr i} {
lappend map "%$i%"
set v [lindex $vals $i]
if {[string is integer $v]} {
lappend map $v
} else {
lappend map "'$v'"
}
}
set sql [string map $map $idxstr]
#puts "SQL: $sql"
return [list sql $sql]
}
}
return {}
}
db close
forcedelete test.db
sqlite3 db test.db
register_tcl_module db
do_execsql_test 3.1 "
CREATE TABLE t1($G(cols));
INSERT INTO t1 VALUES(1, 0, 'ValueA');
INSERT INTO t1 VALUES(2, 0, 'ValueA');
INSERT INTO t1 VALUES(3, 0, 'ValueB');
INSERT INTO t1 VALUES(4, 0, 'ValueB');
"
do_execsql_test 3.2 {
CREATE VIRTUAL TABLE VirtualTableA USING tcl(vtab_command);
CREATE VIRTUAL TABLE VirtualTableB USING tcl(vtab_command);
}
do_execsql_test 3.3 { SELECT primarykey FROM VirtualTableA } {1 2 3 4}
do_execsql_test 3.4 {
SELECT * FROM
VirtualTableA a CROSS JOIN VirtualTableB b ON b.PrimaryKey=a.PrimaryKey
WHERE a.ColumnA IN ('ValueA', 'ValueB') AND a.FlagA=0
} {
1 0 ValueA 1 0 ValueA
2 0 ValueA 2 0 ValueA
3 0 ValueB 3 0 ValueB
4 0 ValueB 4 0 ValueB
}
do_execsql_test 3.5 {
SELECT * FROM
VirtualTableA a CROSS JOIN VirtualTableB b ON b.PrimaryKey=a.PrimaryKey
WHERE a.FlagA=0 AND a.ColumnA IN ('ValueA', 'ValueB')
} {
1 0 ValueA 1 0 ValueA
2 0 ValueA 2 0 ValueA
3 0 ValueB 3 0 ValueB
4 0 ValueB 4 0 ValueB
}
finish_test
+1 -1
View File
@@ -15,7 +15,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cacheflush
set testprefix cffault
source $testdir/malloc_common.tcl
# Run the supplied SQL on a copy of the database currently stored on
+1 -1
View File
@@ -86,7 +86,7 @@ do_test 2.3 { db_write db 1 } {0 4 0}
do_test 2.4 { db_write db 0 } {0 0 0}
do_test 2.5 { db_write db 1 } {0 0 0}
ifcapable wal {
if {[wal_is_capable]} {
do_test 2.6 {
execsql { PRAGMA journal_mode = WAL }
db_write db 1
+42
View File
@@ -139,7 +139,49 @@ do_execsql_test 4.12 {
PRAGMA integrity_check;
} {ok}
# 2016-04-09
# Ticket https://sqlite.org/src/info/a306e56ff68b8fa5
# Failure to completely delete when reverse_unordered_selects is
# engaged.
#
db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 5.0 {
PRAGMA page_size=1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX x1 ON t1(b, c);
INSERT INTO t1(a,b,c) VALUES(1, 1, zeroblob(80));
INSERT INTO t1(a,b,c) SELECT a+1, 1, c FROM t1;
INSERT INTO t1(a,b,c) SELECT a+2, 1, c FROM t1;
INSERT INTO t1(a,b,c) SELECT a+10, 2, c FROM t1 WHERE b=1;
INSERT INTO t1(a,b,c) SELECT a+20, 3, c FROM t1 WHERE b=1;
PRAGMA reverse_unordered_selects = ON;
DELETE FROM t1 WHERE b=2;
SELECT a FROM t1 WHERE b=2;
} {}
# 2016-05-02
# Ticket https://www.sqlite.org/src/tktview/dc6ebeda93960877
# A subquery in the WHERE clause of a one-pass DELETE can cause an
# incorrect answer.
#
db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 6.0 {
CREATE TABLE t2(x INT);
INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x-1);
SELECT x FROM t2;
} {1}
do_execsql_test 6.1 {
DROP TABLE IF EXISTS t2;
CREATE TABLE t2(x INT);
INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x+1);
SELECT x FROM t2;
} {5}
finish_test
+1 -1
View File
@@ -176,7 +176,7 @@ if {![nonzero_reserved_bytes]} {
# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
# auto_vacuum support property can be changed using VACUUM.
#
ifcapable wal {
if {[wal_is_capable]} {
do_test e_vacuum-1.3.3.1 {
execsql { PRAGMA journal_mode = wal }
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
+1
View File
@@ -19,6 +19,7 @@ source $testdir/lock_common.tcl
foreach jm {rollback wal} {
if {![wal_is_capable] && $jm=="wal"} continue
set testprefix exists-$jm
+1 -1
View File
@@ -704,7 +704,7 @@ do_execsql_test 7.5.2.0 {
ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
}
ifcapable !session {
if 0 {
# At time of writing, these two are broken. They demonstrate that the
# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
# has been used to add a column with a default value other than NULL.
+1 -1
View File
@@ -134,7 +134,7 @@ do_test incrvacuum2-3.2 {
integrity_check incrvacuum2-3.3
ifcapable wal {
if {[wal_is_capable]} {
# At one point, when a specific page was being extracted from the b-tree
# free-list (e.g. during an incremental-vacuum), all trunk pages that
# occurred before the specific page in the free-list trunk were being
+37
View File
@@ -604,5 +604,42 @@ do_test intpkey-15.7 {
}
} {}
# 2016-04-18 ticket https://www.sqlite.org/src/tktview/7d7525cb01b68712495d3a
# Be sure to escape quoted typenames.
#
do_execsql_test intpkey-16.0 {
CREATE TABLE t16a(id "INTEGER" PRIMARY KEY AUTOINCREMENT, b [TEXT], c `INT`);
} {}
do_execsql_test intpkey-16.1 {
PRAGMA table_info=t16a;
} {0 id INTEGER 0 {} 1 1 b TEXT 0 {} 0 2 c INT 0 {} 0}
# 2016-05-06 ticket https://www.sqlite.org/src/tktview/16c9801ceba4923939085
# When the schema contains an index on the IPK and no other index
# and a WHERE clause on a delete uses an OR where both sides referencing
# the IPK, then it is possible that the OP_Delete will fail because there
# deferred seek of the OP_Seek is not resolved prior to reaching the OP_Delete.
#
do_execsql_test intpkey-17.0 {
CREATE TABLE t17(x INTEGER PRIMARY KEY, y TEXT);
INSERT INTO t17(x,y) VALUES(123,'elephant'),(248,'giraffe');
CREATE INDEX t17x ON t17(x);
DELETE FROM t17 WHERE x=99 OR x<130;
SELECT * FROM t17;
} {248 giraffe}
do_execsql_test intpkey-17.1 {
DROP INDEX t17x;
DELETE FROM t17;
INSERT INTO t17(x,y) VALUES(123,'elephant'),(248,'giraffe');
CREATE UNIQUE INDEX t17x ON t17(abs(x));
DELETE FROM t17 WHERE abs(x) IS NULL OR abs(x)<130;
SELECT * FROM t17;
} {248 giraffe}
do_execsql_test intpkey-17.2 {
DELETE FROM t17;
INSERT INTO t17(x,y) VALUES(123,'elephant'),(248,'giraffe');
UPDATE t17 SET y='ostrich' WHERE abs(x)=248;
SELECT * FROM t17 ORDER BY +x;
} {123 elephant 248 ostrich}
finish_test
+1 -1
View File
@@ -204,7 +204,7 @@ db close
# delete the journal file when committing the transaction that switches
# the system to WAL mode.
#
ifcapable wal {
if {[wal_is_capable]} {
do_test journal2-2.1 {
faultsim_delete_and_reopen
set ::oplog [list]
+11 -1
View File
@@ -111,7 +111,7 @@ do_test loadext-1.2 {
#
do_test loadext-1.3 {
sqlite3 db2 test.db
sqlite3_enable_load_extension db2 1
sqlite3_db_config db2 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
catchsql {
SELECT half(1.0);
} db2
@@ -256,6 +256,7 @@ do_test loadext-4.2 {
}
} {0 {{}}}
# disable all extension loading
do_test loadext-4.3 {
sqlite3_enable_load_extension db 0
catchsql {
@@ -263,6 +264,15 @@ do_test loadext-4.3 {
}
} {1 {not authorized}}
# enable C-api extension loading only. Show that the SQL function
# still does not work.
do_test loadext-4.4 {
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
catchsql {
SELECT load_extension($::testextension,'testloadext_init')
}
} {1 {not authorized}}
source $testdir/malloc_common.tcl
+3 -2
View File
@@ -423,8 +423,9 @@ do_test lock-6.5 {
# * there exists one or more active read-only statements, and
# * a transaction that modified zero database pages is committed.
#
set temp_status unlocked
if {$TEMP_STORE>=2} {set temp_status unknown}
#set temp_status unlocked
#if {$TEMP_STORE>=2} {set temp_status unknown}
set temp_status unknown
do_test lock-7.1 {
set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
sqlite3_step $STMT

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