Compare commits

...

109 Commits

Author SHA1 Message Date
drh a72a15e45a Omit the unnecessary WHERE_REOPEN_IDX flag in the WHERE interface.
FossilOrigin-Name: da94a6e0ebacad8f235dcd653a25474327f26137
2016-05-09 19:58:56 +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
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
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 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
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 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
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 8a878f239c Merge enhancements from trunk.
FossilOrigin-Name: 9682c0433c04713c28bd9105a7e20af7372f873e
2016-04-12 16:10:10 +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
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
dan 67330a1224 Fixes for OOM and IO error handling with temp file databases.
FossilOrigin-Name: 4eb06e843af60d5e533793618c6e0e9b7ef7a1a6
2016-04-11 18:07:47 +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
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
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
82 changed files with 2704 additions and 709 deletions
+3 -3
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
+12
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
+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
+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;
+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
+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
+578 -178
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 {
+18 -14
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;
+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) */
+1 -2
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.
#
+88 -80
View File
@@ -1,8 +1,8 @@
C Test\scases\sfor\sSQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION.
D 2016-04-21T01:58:21.573
F Makefile.in eba680121821b8a60940a81454316f47a341487a
C Omit\sthe\sunnecessary\sWHERE_REOPEN_IDX\sflag\sin\sthe\sWHERE\sinterface.
D 2016-05-09T19:58:56.729
F Makefile.in 9eda6e1c90d05c199c3ec8a7069b0682ad307657
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
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
@@ -97,12 +97,12 @@ 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_expr.c da2b33c2aac91e96641c0a7cf2bbaa36eb2667f7
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c b429e23fabb57506f71e406997cc46b89190dc97
F ext/fts5/fts5_main.c b4a0fc5bf17f2f1f056ee76cdd7d2af08b360f55
@@ -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
@@ -222,7 +222,7 @@ 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 9097f1d95666dbef72ca61d5b6a13a84660735ac
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,10 +291,10 @@ 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 beb300cd1b5c5054062c8e6e807b10475e363410
F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d
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
@@ -300,7 +302,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk a283660f75c3c4b75d8c9d12a40fa38a066eee9d
F main.mk 86e6a8d79186ace5ff8b306093da1728d953f796
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -322,19 +324,19 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 3ae6aea66cc4e13d30162ff0d0d43c7088e34abf
F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 42e8ee74dfa3a4b99bfb2c201f8a66ab50688d95
F src/build.c d65be62254ca9df36e1e1c433324f0333f80009c
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b
F src/delete.c 78eb999114ec04fcf1b7d123ccedb4b5b734930e
F src/expr.c 17d4e745ef6a3fd2e4ef863f5f9a4912f1ba1198
F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f
F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb
F src/func.c ef4c18c8a66143413ce41a58d582d2c14ddf78e1
F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.c 55b5fb474100cee0b901edaf203e26c970940f36
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b
@@ -359,38 +361,38 @@ 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 d0b41a47eb5f0dc00e423a1723aadeab0e78c85f
F src/os_win.c b169437dff859e308b3726594094a2f8ca922941
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.c c512873311087cd22372f2b076fc869e090e8e16
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c c40cdb93586e21b5dd826b5e671240bd91c26b05
F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
F src/pcache.h 6b865be765d1ebd06145219550b10921c7da7cc9
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 30217121bdf6b587462150b8ee9e1467f7a6036b
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 ec538389481a3d093f07fb344c5a9dc988042304
F src/sqliteInt.h 47a90c85a42210a05387051aaaa661f5c307703d
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060
F src/test1.c abc10e3e81258835aeb59616685d7369ba99ad1e
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,14 +404,14 @@ 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 7e73009d5297b603c11c66d7c7d6723d4b5c73e1
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 da540964c675fde39487da2bc664096af97190d8
F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950
F src/test_multiplex.c eafc567ebe162e36f17b5062285dfe90461cf8e9
@@ -425,7 +427,7 @@ 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 4889d374f5a5856b7951f7a67c6401f7b938c6f5
F src/test_syscall.c 268c072541162564a882c57f54a6fee12ef4a4d2
F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
F src/test_vfs.c 4d02f38bfb8f7f273da7ba84bfe000f5babf206c
@@ -437,11 +439,11 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
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 187a0a2aaa3c5d2ccd2ab0143b2fd9e86d6bc816
F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52
F src/vdbe.c d3843a66d74a7696477ee5141e5eb9a7e5e2401c
F src/vdbe.c 4bad04212736526845fda9ca674afafb10078b2b
F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170
F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd
F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c
@@ -455,9 +457,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 4db22ed7e77bcf672b1a685d6ddeffba8d5be302
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
F src/where.c bae50f2f18f9e8584549a77363858623b07e4915
F src/whereInt.h 7de94b751f088fe3fdc8cc04a491376f0900a059
F src/wherecode.c 8fdad9fbba723df1c1e8d07e7ea8507572040340
F src/where.c ad8ad50ccf25795f6830b6b864bbfcd060ff08dd
F src/whereInt.h 3b1fc240e322613ba4e9dc857ca9c7c3390acc74
F src/wherecode.c d227fca7d766a10fe4ba4d812210f5631f5a98b3
F src/whereexpr.c eacc0e60d029a082b4fc0cc42ea98544add1319e
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -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
@@ -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 738044ee892ee0c84e0848e36ba92c55f907d52b
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 153b70e32d008f4f4b2dff8daf448a6110b62a9c
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
@@ -877,7 +879,7 @@ F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
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 dd5313eee9c6d9d4726593a68ede8768d3b50ccc
F test/permutations.test b6b3e165fdc1b8c82a820033646dbfc6a7a01746
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
@@ -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
@@ -1090,7 +1092,7 @@ 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,12 @@ 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/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 +1132,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 +1146,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 +1162,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
@@ -1396,7 +1401,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,7 +1417,7 @@ 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 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1442,7 +1447,7 @@ 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 +1455,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 +1487,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 b2ae5bfa32e608625bd177907596df3dbc2212e1
R 142ad50676c76bf1cd4debbac256d360
P 14e53d0e2f62d82ae1d64a72fd9711548e3bf5ea
R 91f64055039542194e221b2aa9a3eada
T *branch * dev
T *sym-dev *
T -sym-trunk *
U drh
Z d6546b0e1c5ecba4524ffa3ce100a1b6
Z 6a1a8543c69edff1da4c7cb6389abc41
+1 -1
View File
@@ -1 +1 @@
debafa5efd37ac60e030d0963ce8e7c4f51a0f10
da94a6e0ebacad8f235dcd653a25474327f26137
+9 -8
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
@@ -2221,7 +2222,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pTable->nCol = 0;
nErr++;
}
if( pSelTab ) sqlite3DeleteTable(db, pSelTab);
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
db->lookaside.bDisable--;
} else {
+4 -3
View File
@@ -239,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));
@@ -271,7 +272,6 @@ void sqlite3DeleteFrom(
#else
# define pTrigger 0
# define isView 0
# define bComplex 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
@@ -373,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 */
+2 -2
View File
@@ -2360,7 +2360,7 @@ static void cacheEntryClear(Parse *pParse, struct yColCache *p){
}
p->iReg = 0;
pParse->nColCache--;
assert( cacheIsValid(pParse) );
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
}
@@ -2405,7 +2405,7 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
pParse->nColCache++;
assert( cacheIsValid(pParse) );
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
return;
}
}
+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];
+20 -12
View File
@@ -4288,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 ){
@@ -5410,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;
}
/*
@@ -5439,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);
+10 -9
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();
@@ -3169,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,
@@ -3765,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,
+95 -46
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,25 @@ static int pager_error(Pager *pPager, int rc){
static int pager_truncate(Pager *pPager, Pgno nPage);
/*
** The write transaction open on the pager passed as the only argument is
** being committed. This function returns true if all dirty pages should
** be flushed to disk, or false otherwise. Pages should be flushed to disk
** unless one of the following is true:
**
** * The db is an in-memory database.
**
** * The db is a temporary database and the db file has not been opened.
**
** * The db is a temporary database and the cache contains less than
** C/4 dirty pages, where C is the configured cache-size.
*/
static int pagerFlushOnCommit(Pager *pPager){
if( pPager->tempFile==0 ) return 1;
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
@@ -2006,7 +2032,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
pPager->nRec = 0;
sqlite3PcacheCleanAll(pPager->pPCache);
if( MEMDB || pagerFlushOnCommit(pPager) ){
sqlite3PcacheCleanAll(pPager->pPCache);
}else{
sqlite3PcacheClearWritable(pPager->pPCache);
}
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
if( pagerUseWal(pPager) ){
@@ -2291,7 +2321,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")
@@ -2374,9 +2404,13 @@ static int pager_playback_one_page(
** 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.
**
** Update: Another exception is for temp files that are not
** in-memory databases. In this case the page may have been dirty
** at the start of the transaction.
*/
assert( !pagerUseWal(pPager) );
sqlite3PcacheMakeClean(pPg);
if( pPager->tempFile==0 ) sqlite3PcacheMakeClean(pPg);
}
pager_set_pagehash(pPg);
@@ -3168,6 +3202,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 +3211,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 +4291,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 +4961,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 +5054,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 +5150,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 +5246,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 +5379,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 +5446,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 +5589,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 +5977,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,10 +6008,16 @@ 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;
@@ -6173,17 +6216,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( (rc = sqlite3FaultSim(400))!=SQLITE_OK ) return rc;
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) ){
/* 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 +6569,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 +6852,7 @@ 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 ){
if( pPager->tempFile ){
rc = sqlite3PagerWrite(pPg);
if( rc ) return rc;
}
@@ -6862,7 +6909,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,7 +6926,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 ){
if( pPager->tempFile ){
assert( pPgOld );
sqlite3PcacheMove(pPgOld, origPgno);
sqlite3PagerUnrefNotNull(pPgOld);
@@ -7132,7 +7179,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 +7359,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;
+24 -2
View File
@@ -254,7 +254,7 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
/*
** 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
@@ -439,6 +439,17 @@ void sqlite3PcacheCleanAll(PCache *pCache){
}
}
/*
** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
*/
void sqlite3PcacheClearWritable(PCache *pCache){
PgHdr *p;
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.
*/
@@ -484,7 +495,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);
}
@@ -675,6 +686,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)
/*
+4
View File
@@ -99,6 +99,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);
@@ -173,4 +174,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){
+9 -5
View File
@@ -3785,14 +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 ){
testcase( pSubq->selFlags & SF_Aggregate );
testcase( pSubq->selFlags & SF_Recursive );
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);
+30 -1
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.
@@ -2513,9 +2540,10 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
/* 0x1000 not currently used */
#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()
*/
@@ -2570,6 +2598,7 @@ struct NameContext {
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
#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 */
/*
+10 -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;
}
@@ -5213,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 */
@@ -5222,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;
}
@@ -6698,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;
@@ -6726,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;
@@ -6735,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;
+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
+7
View File
@@ -396,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
+16 -11
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 */
};
@@ -285,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){
@@ -295,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;
}
@@ -517,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 ){
@@ -562,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;
}
@@ -576,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 ){
@@ -604,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 ){
@@ -730,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);
}
@@ -825,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.
*/
+9 -3
View File
@@ -722,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 -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);
+61 -50
View File
@@ -355,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 */
@@ -368,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);
}
@@ -384,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');
@@ -403,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;
@@ -416,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;
@@ -433,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 */
@@ -447,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
@@ -494,8 +505,6 @@ do_atof_calc:
result = s * scale;
}
}
} else {
result = (double)s;
}
}
@@ -503,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 */
@@ -565,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 );
@@ -576,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;
@@ -603,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;
@@ -646,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;
@@ -1408,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;
+26 -46
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;
@@ -946,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;
@@ -976,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 );
@@ -1069,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 );
@@ -1085,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 */
}
@@ -1097,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 );
@@ -1111,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;
@@ -5972,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])
**
+12 -13
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
@@ -4475,7 +4479,7 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->aiCurOnePass[1] = iIndexCur;
}else if( iAuxArg && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
iIndexCur = iAuxArg;
if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
op = OP_ReopenIdx;
}else{
iIndexCur = pParse->nTab++;
}
@@ -4607,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
+1 -1
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 */
+26 -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
@@ -1175,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
@@ -1320,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);
@@ -1516,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 ){
@@ -1624,7 +1629,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
){
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
pCov = pSubLoop->u.btree.pIndex;
wctrlFlags |= WHERE_REOPEN_IDX;
}else{
pCov = 0;
}
@@ -1696,11 +1700,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
}
+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 {
+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
+23
View File
@@ -161,4 +161,27 @@ do_execsql_test 5.0 {
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
+27 -1
View File
@@ -614,6 +614,32 @@ 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]
+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
+16 -14
View File
@@ -684,22 +684,24 @@ do_faultsim_test pagerfault-14a -prep {
# is not possible to change the page-size of an in-memory database. Even
# using the backup API.
#
if {$TEMP_STORE<2} {
do_faultsim_test pagerfault-14b -prep {
catch { db2 close }
faultsim_restore_and_reopen
# Update: It is no longer possible to change the page size of any temp
# database after it has been created.
#
do_faultsim_test pagerfault-14b -prep {
catch { db2 close }
faultsim_restore_and_reopen
sqlite3 db2 ""
db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
} -body {
sqlite3_backup B db2 main db main
B step 200
set rc [B finish]
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
set {} {}
} -test {
faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
}
} -body {
sqlite3_backup B db2 main db main
B step 200
set rc [B finish]
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
set {} {}
} -test {
faultsim_test_result {1 {attempt to write a readonly database}} \
{1 {sqlite3_backup_init() failed}}
}
do_faultsim_test pagerfault-14c -prep {
+6 -6
View File
@@ -728,7 +728,7 @@ test_suite "inmemory_journal" -description {
ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test
e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
fts3snippet.test mmapfault.test
fts3snippet.test mmapfault.test sessionfault.test sessionfault2.test
# Exclude test scripts that use tcl IO to access journal files or count
# the number of fsync() calls.
@@ -942,7 +942,9 @@ test_suite "journaltest" -description {
unregister_jt_vfs
} -files [test_set $::allquicktests -exclude {
wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test
async4.test bigfile.test backcompat.test
async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
pager2.test *fault* rowal* snapshot* superlock* symlink.test
}]
if {[info commands register_demovfs] != ""} {
@@ -1050,15 +1052,13 @@ proc run_tests {name args} {
set ::G(isquick) 1
set ::G(perm:dbconfig) $options(-dbconfig)
uplevel $options(-initialize)
foreach file [lsort $options(-files)] {
uplevel $options(-initialize)
if {[file tail $file] == $file} { set file [file join $::testdir $file] }
slave_test_file $file
uplevel $options(-shutdown)
}
uplevel $options(-shutdown)
unset ::G(perm:name)
unset ::G(perm:prefix)
unset ::G(perm:presql)
+14 -1
View File
@@ -1083,7 +1083,20 @@ do_test pragma-8.2.15 {
# "memory" or "disk" as appropriate.
#
proc check_temp_store {} {
db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)}
db eval {
PRAGMA temp.cache_size = 1;
CREATE TEMP TABLE IF NOT EXISTS a(b);
DELETE FROM a;
INSERT INTO a VALUES(randomblob(1000));
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
INSERT INTO a SELECT * FROM a;
}
db eval {PRAGMA database_list} {
if {$name=="temp"} {
set bt [btree_from_db db 1]
+1 -1
View File
@@ -221,7 +221,7 @@ ifcapable shared_cache {
# This will not work with the in-memory journal permutation, as opening
# [db2] switches the journal mode back to "memory"
#
ifcapable wal {
if {[wal_is_capable]} {
if {[permutation]!="inmemory_journal"} {
sqlite3 db test.db
+2
View File
@@ -527,4 +527,6 @@ do_faultsim_test quota-5.6 -prep {
}
catch { sqlite3_quota_shutdown }
catch { db close }
forcedelete test.db
finish_test
+5 -2
View File
@@ -51,10 +51,12 @@ array set ::Configs [strip_comments {
"Default" {
-O2
--disable-amalgamation --disable-shared
--enable-session
}
"Sanitize" {
CC=clang -fsanitize=undefined
-DSQLITE_ENABLE_STAT4
--enable-session
}
"Have-Not" {
# The "Have-Not" configuration sets all possible -UHAVE_feature options
@@ -106,7 +108,7 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_STMT_SCANSTATUS
--enable-json1 --enable-fts5
--enable-json1 --enable-fts5 --enable-session
}
"Debug-One" {
--disable-shared
@@ -132,6 +134,7 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_RBU
-DSQLITE_MAX_ATTACHED=125
-DLONGDOUBLE_TYPE=double
--enable-session
}
"Device-One" {
-O2
@@ -168,7 +171,7 @@ array set ::Configs [strip_comments {
-DSQLITE_OMIT_TRACE=1
-DSQLITE_TEMP_STORE=3
-DSQLITE_THREADSAFE=2
--enable-json1 --enable-fts5
--enable-json1 --enable-fts5 --enable-session
}
"Locking-Style" {
-O2
+36
View File
@@ -968,6 +968,42 @@ do_execsql_test select4-16.3 {
ORDER BY t3.a;
} {95 96 97 98 99}
# Ticket https://www.sqlite.org/src/tktview/f7f8c97e975978d45 on 2016-04-25
#
# The where push-down optimization from 2015-06-02 is suppose to disable
# on aggregate subqueries. But if the subquery is a compound where the
# last SELECT is non-aggregate but some other SELECT is an aggregate, the
# test is incomplete and the optimization is not properly disabled.
#
# The following test cases verify that the fix works.
#
do_execsql_test select4-17.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a int, b int);
INSERT INTO t1 VALUES(1,2),(1,18),(2,19);
SELECT x, y FROM (
SELECT 98 AS x, 99 AS y
UNION
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
) AS w WHERE y>=20
ORDER BY +x;
} {1 20 98 99}
do_execsql_test select4-17.2 {
SELECT x, y FROM (
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
UNION
SELECT 98 AS x, 99 AS y
) AS w WHERE y>=20
ORDER BY +x;
} {1 20 98 99}
do_catchsql_test select4-17.3 {
SELECT x, y FROM (
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a LIMIT 3
UNION
SELECT 98 AS x, 99 AS y
) AS w WHERE y>=20
ORDER BY +x;
} {1 {LIMIT clause should come after UNION not before}}
+1 -1
View File
@@ -37,7 +37,7 @@ do_execsql_test stat-0.0 {
SELECT * FROM stat;
} {}
ifcapable wal {
if {[wal_is_capable]} {
do_execsql_test stat-0.1 {
PRAGMA journal_mode = WAL;
PRAGMA journal_mode = delete;
+2
View File
@@ -81,6 +81,7 @@ do_test sync-1.3 {
set sqlite_sync_count
} 11
ifcapable pager_pragmas {
if {[permutation]!="journaltest"} {
do_test sync-1.4 {
set sqlite_sync_count 0
execsql {
@@ -94,6 +95,7 @@ ifcapable pager_pragmas {
set sqlite_sync_count
} 0
}
}
finish_test
+77
View File
@@ -0,0 +1,77 @@
# 2016 March 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tempdb2
db close
sqlite3 db ""
proc int2str {i} { string range [string repeat "$i." 450] 0 899 }
db func int2str int2str
#-------------------------------------------------------------------------
#
# 1.1: Write a big transaction to the db. One so large that it forces
# the file to be created and the cache flushed to disk on COMMIT.
#
# 1.2: Write a small transaction - one small enough that it remains in
# memory on COMMIT. All the pages of table [t1] are now dirty.
#
# 1.3: Delete the contents of [t1]. This moves all of its leaves to the
# free-list and causes the btree layer to call PagerDontWrite() on
# each of them.
#
# Then do a big update on table [t2]. So big that the former leaves
# of [t1] are forced out of the cache. Then roll back the transaction.
# If the PagerDontWrite() calls are honoured and the data is not written
# to disk, the update made in test 1.2 will be lost at this point. Or, if
# they are ignored (as they should be for temp databases), the update
# will be safely written out to disk before the cache entries are
# discarded.
#
do_execsql_test 1.1 {
PRAGMA page_size=1024;
PRAGMA cache_size=50;
BEGIN;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, int2str(1));
INSERT INTO t1 VALUES(2, int2str(1));
INSERT INTO t1 VALUES(3, int2str(1));
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 )
INSERT INTO t2 SELECT x, int2str(x) FROM c;
COMMIT;
PRAGMA lock_status;
} {main unlocked temp closed}
do_execsql_test 1.2 {
UPDATE t1 SET b=int2str(2);
SELECT b=int2str(2) FROM t1
} {1 1 1}
do_execsql_test 1.3 {
BEGIN;
DELETE FROM t1;
UPDATE t2 SET b=int2str(a+1);
ROLLBACK;
}
do_execsql_test 1.4 {
SELECT b=int2str(2) FROM t1
} {1 1 1}
finish_test
+134
View File
@@ -0,0 +1,134 @@
# 2016 April 11
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for fault-injection when SQLite is used with
# a temp file database.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix tempfault
# sqlite3_memdebug_vfs_oom_test 0
do_faultsim_test 1 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
}
} -body {
execsql { INSERT INTO t1 VALUES(5, 6) }
} -test {
faultsim_test_result {0 {}}
set rc [catch { execsql { SELECT * FROM t1 } } msg]
if {$rc==0 && $msg != "1 2 3 4 5 6" && $msg != "1 2 3 4"} {
error "data mismatch 1: $msg"
}
if {$testrc==0 && $msg != "1 2 3 4 5 6"} {
error "data mismatch 2: $msg"
}
faultsim_integrity_check
}
do_faultsim_test 2 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
} -body {
execsql { UPDATE t1 SET a = randomblob(99) }
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check db
}
catch { db close }
do_faultsim_test 2.1 -faults * -prep {
if {[info commands db]==""} {
sqlite3 db ""
execsql {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
}
} -body {
execsql { UPDATE t1 SET a = randomblob(99) }
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check db
}
do_faultsim_test 3 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
} -body {
execsql {
BEGIN;
UPDATE t1 SET a = randomblob(99);
SAVEPOINT abc;
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
ROLLBACK TO abc;
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
ROLLBACK TO abc;
COMMIT;
}
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check db
}
do_faultsim_test 4 -faults * -prep {
sqlite3 db ""
db eval {
PRAGMA page_size = 1024;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(b, a);
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
}
} -body {
execsql {
BEGIN;
UPDATE t1 SET a = randomblob(99);
SAVEPOINT abc;
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
ROLLBACK TO abc;
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
ROLLBACK TO abc;
COMMIT;
}
} -test {
faultsim_test_result {0 {}}
}
sqlite3_memdebug_vfs_oom_test 1
finish_test
+357
View File
@@ -0,0 +1,357 @@
# 2016 March 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix temptable2
do_execsql_test 1.1 {
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
}
do_execsql_test 1.2 {
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100000 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM X;
} {}
do_execsql_test 1.3 {
PRAGMA temp.integrity_check;
} {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.1 {
CREATE TEMP TABLE t2(a, b);
INSERT INTO t2 VALUES(1, 2);
} {}
do_execsql_test 2.2 {
BEGIN;
INSERT INTO t2 VALUES(3, 4);
SELECT * FROM t2;
} {1 2 3 4}
do_execsql_test 2.3 {
ROLLBACK;
SELECT * FROM t2;
} {1 2}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.1.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
SELECT count(*) FROM t1;
} {1000}
do_execsql_test 3.1.2 {
BEGIN;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
ROLLBACK;
}
do_execsql_test 3.1.3 {
SELECT count(*) FROM t1;
} {1000}
do_execsql_test 3.1.4 { PRAGMA temp.integrity_check } {ok}
do_execsql_test 3.2.1 {
BEGIN;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
SAVEPOINT abc;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==1;
ROLLBACK TO abc;
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==2;
COMMIT;
}
do_execsql_test 3.2.2 { PRAGMA temp.integrity_check } {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.1.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<10 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
SELECT count(*) FROM t1;
PRAGMA temp.page_count;
} {10 9}
do_execsql_test 4.1.2 {
BEGIN;
UPDATE t1 SET b=randomblob(100);
ROLLBACK;
}
do_execsql_test 4.1.3 {
CREATE TEMP TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
SELECT count(*) FROM t2;
SELECT count(*) FROM t1;
} {500 10}
do_test 4.1.4 {
set n [db one { PRAGMA temp.page_count }]
expr ($n >280 && $n < 300)
} 1
do_execsql_test 4.1.4 { PRAGMA temp.integrity_check } {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.1.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
CREATE TEMP TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
# Test that the temp database is now much bigger than the configured
# cache size (10 pages).
do_test 5.1.2 {
set n [db one { PRAGMA temp.page_count }]
expr ($n > 270 && $n < 290)
} {1}
do_execsql_test 5.1.3 {
BEGIN;
UPDATE t1 SET a=2;
UPDATE t2 SET a=randomblob(100);
SELECT count(*) FROM t1;
ROLLBACK;
} {1}
do_execsql_test 5.1.4 {
UPDATE t2 SET a=randomblob(100);
SELECT * FROM t1;
} {1 2}
do_execsql_test 5.1.5 { PRAGMA temp.integrity_check } {ok}
#-------------------------------------------------------------------------
# Test this:
#
# 1. Page is DIRTY at the start of a transaction.
# 2. Page is written out as part of the transaction.
# 3. Page is then read back in.
# 4. Transaction is rolled back. Is the page now clean or dirty?
#
# This actually does work. Step 4 marks the page as clean. But it also
# writes to the database file itself. So marking it clean is correct -
# the page does match the contents of the db file.
#
reset_db
do_execsql_test 6.1 {
PRAGMA main.cache_size = 10;
PRAGMA temp.cache_size = 10;
CREATE TEMP TABLE t1(x);
INSERT INTO t1 VALUES('one');
CREATE TEMP TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
}
do_execsql_test 6.2 {
UPDATE t1 SET x='two'; -- step 1
BEGIN;
UPDATE t2 SET a=randomblob(100); -- step 2
SELECT * FROM t1; -- step 3
ROLLBACK; -- step 4
SELECT count(*) FROM t2;
SELECT * FROM t1;
} {two 500 two}
#-------------------------------------------------------------------------
#
reset_db
sqlite3 db ""
do_execsql_test 7.1 {
PRAGMA auto_vacuum=INCREMENTAL;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(900));
INSERT INTO t1 VALUES(zeroblob(900));
INSERT INTO t1 SELECT x FROM t1;
INSERT INTO t1 SELECT x FROM t1;
INSERT INTO t1 SELECT x FROM t1;
INSERT INTO t1 SELECT x FROM t1;
BEGIN;
DELETE FROM t1 WHERE rowid%2;
PRAGMA incremental_vacuum(4);
ROLLBACK;
PRAGMA integrity_check;
} {ok}
#-------------------------------------------------------------------------
# Try changing the page size using a backup operation when pages are
# stored in main-memory only.
#
reset_db
do_execsql_test 8.1 {
PRAGMA auto_vacuum = OFF;
CREATE TABLE t2(a, b);
CREATE INDEX i2 ON t2(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<20 )
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x ORDER BY 1, 2;
PRAGMA page_count;
} {13}
do_test 8.2 {
sqlite3 tmp ""
execsql {
PRAGMA auto_vacuum = OFF;
PRAGMA page_size = 8192;
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x ORDER BY 1, 2;
PRAGMA page_count;
} tmp
} {10}
do_test 8.3 {
sqlite3_backup B tmp main db main
B step 5
B finish
} {SQLITE_READONLY}
do_test 8.4 {
execsql {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
PRAGMA page_size;
} tmp
} {100 ok 8192}
do_test 8.5 {
tmp eval { UPDATE t1 SET a=randomblob(100) }
} {}
do_test 8.6 {
sqlite3_backup B tmp main db main
B step 1000
B finish
} {SQLITE_READONLY}
tmp close
#-------------------------------------------------------------------------
# Try inserts and deletes with a large db in auto-vacuum mode. Check
#
foreach {tn mode} {
1 delete
2 wal
} {
reset_db
sqlite3 db ""
do_execsql_test 9.$tn.1.1 {
PRAGMA cache_size = 15;
PRAGMA auto_vacuum = 1;
}
execsql "PRAGMA journal_mode = $mode"
do_execsql_test 9.$tn.1.2 {
CREATE TABLE tx(a, b);
CREATE INDEX i1 ON tx(a);
CREATE INDEX i2 ON tx(b);
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
}
for {set i 2} {$i<20} {incr i} {
do_execsql_test 9.$tn.$i.1 { DELETE FROM tx WHERE (random()%3)==0 }
do_execsql_test 9.$tn.$i.2 { PRAGMA integrity_check } ok
do_execsql_test 9.$tn.$i.3 {
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<400 )
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
}
do_execsql_test 9.$tn.$i.4 { PRAGMA integrity_check } ok
do_execsql_test 9.$tn.$i.5 {
BEGIN;
DELETE FROM tx WHERE (random()%3)==0;
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
COMMIT;
}
do_execsql_test 9.$tn.$i.6 { PRAGMA integrity_check } ok
}
}
#-------------------------------------------------------------------------
# When using mmap mode with a temp file, SQLite must search the cache
# before using a mapped page even when there is no write transaction
# open. For a temp file, the on-disk version may not be up to date.
#
sqlite3 db ""
do_execsql_test 10.0 {
PRAGMA cache_size = 50;
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(a);
CREATE TABLE t2(x, y);
INSERT INTO t2 VALUES(1, 2);
}
do_execsql_test 10.1 {
BEGIN;
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
COMMIT;
INSERT INTO t2 VALUES(3, 4);
}
ifcapable mmap {
if {[permutation]!="journaltest"} {
# The journaltest permutation does not support mmap, so this part of
# the test is omitted.
do_execsql_test 10.2 { PRAGMA mmap_size = 512000 } 512000
}
}
do_execsql_test 10.3 { SELECT * FROM t2 } {1 2 3 4}
do_execsql_test 10.4 { PRAGMA integrity_check } ok
finish_test
+11 -1
View File
@@ -521,7 +521,11 @@ if {[info exists cmdlinearg]==0} {
}
default {
lappend leftover [file normalize $a]
if {[file tail $a]==$a} {
lappend leftover $a
} else {
lappend leftover [file normalize $a]
}
}
}
}
@@ -1944,6 +1948,12 @@ proc wal_check_journal_mode {testname {db db}} {
}
}
proc wal_is_capable {} {
ifcapable !wal { return 0 }
if {[permutation]=="journaltest"} { return 0 }
return 1
}
proc permutation {} {
set perm ""
catch {set perm $::G(perm:name)}
+2 -1
View File
@@ -19,7 +19,8 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-2d1a5c67d
ifcapable {!wal || !vtab} {finish_test; return}
ifcapable {!vtab} {finish_test; return}
if {[wal_is_capable]==0} {finish_test; return}
for {set ii 1} {$ii<=10} {incr ii} {
do_test tkt-2d1a5c67d.1.$ii {
+1 -1
View File
@@ -18,7 +18,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !wal { finish_test ; return }
if {![wal_is_capable]} { finish_test ; return }
do_execsql_test tkt-313723c356.1 {
PRAGMA page_size = 1024;
+1 -1
View File
@@ -18,7 +18,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix tkt-5d863f876e
ifcapable !wal {finish_test ; return }
if {![wal_is_capable]} {finish_test ; return }
do_multiclient_test tn {
do_test $tn.1 {
+2
View File
@@ -50,4 +50,6 @@ for {set i 0} {$i < 100} {incr i} {
} {ok}
}
catch { db close }
unregister_devsim
finish_test
+1 -1
View File
@@ -89,7 +89,7 @@ do_test zerodamage-2.1 {
concat [file_control_powersafe_overwrite db -1] [set ::max_journal_size]
} {0 0 24704}
ifcapable wal {
if {[wal_is_capable]} {
# Run a WAL-mode transaction with POWERSAFE_OVERWRITE on to verify that the
# WAL file does not get too big.
#
+18 -8
View File
@@ -3556,14 +3556,11 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
}
if( rp->lhsalias==0 ){
/* There is no LHS value symbol. */
lhsdirect = 1;
}else if( rp->nrhs==0 ){
if( rp->nrhs==0 ){
/* If there are no RHS symbols, then writing directly to the LHS is ok */
lhsdirect = 1;
}else if( rp->rhsalias[0]==0 ){
/* The left-most RHS symbol has not value. LHS direct is ok. But
/* The left-most RHS symbol has no value. LHS direct is ok. But
** we have to call the distructor on the RHS symbol first. */
lhsdirect = 1;
if( has_destructor(rp->rhs[0],lemp) ){
@@ -3572,6 +3569,9 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
rp->rhs[0]->index,1-rp->nrhs);
rp->codePrefix = Strsafe(append_str(0,0,0,0));
}
}else if( rp->lhsalias==0 ){
/* There is no LHS value symbol. */
lhsdirect = 1;
}else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
/* The LHS symbol and the left-most RHS symbol are the same, so
** direct writing is allowed */
@@ -3715,7 +3715,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
/* Suffix code generation complete */
cp = append_str(0,0,0,0);
if( cp ) rp->codeSuffix = Strsafe(cp);
if( cp && cp[0] ) rp->codeSuffix = Strsafe(cp);
return rc;
}
@@ -4397,12 +4397,20 @@ void ReportTable(
for(rp=lemp->rule; rp; rp=rp->next){
struct rule *rp2; /* Other rules with the same action */
if( rp->code==0 ) continue;
if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */
if( rp->code[0]=='\n'
&& rp->code[1]==0
&& rp->codePrefix==0
&& rp->codeSuffix==0
){
/* No actions, so this will be part of the "default:" rule */
continue;
}
fprintf(out," case %d: /* ", rp->iRule);
writeRuleText(out, rp);
fprintf(out, " */\n"); lineno++;
for(rp2=rp->next; rp2; rp2=rp2->next){
if( rp2->code==rp->code ){
if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
&& rp2->codeSuffix==rp->codeSuffix ){
fprintf(out," case %d: /* ", rp2->iRule);
writeRuleText(out, rp2);
fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
@@ -4419,6 +4427,8 @@ void ReportTable(
for(rp=lemp->rule; rp; rp=rp->next){
if( rp->code==0 ) continue;
assert( rp->code[0]=='\n' && rp->code[1]==0 );
assert( rp->codePrefix==0 );
assert( rp->codeSuffix==0 );
fprintf(out," /* (%d) ", rp->iRule);
writeRuleText(out, rp);
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
+13 -8
View File
@@ -152,6 +152,7 @@ set tabledef {CREATE TABLE space_used(
name clob, -- Name of a table or index in the database file
tblname clob, -- Name of associated table
is_index boolean, -- TRUE if it is an index, false for a table
is_without_rowid boolean, -- TRUE if WITHOUT ROWID table
nentry int, -- Number of entries in the BTree
leaf_entries int, -- Number of leaf entries
depth int, -- Depth of the b-tree
@@ -184,7 +185,7 @@ set sql { SELECT name, tbl_name FROM sqlite_master WHERE rootpage>0 }
foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
set is_index [expr {$name!=$tblname}]
set idx_btree [expr {$is_index || [is_without_rowid $name]}]
set is_without_rowid [is_without_rowid $name]
db eval {
SELECT
sum(ncell) AS nentry,
@@ -235,6 +236,7 @@ foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
$name,
$tblname,
$is_index,
$is_without_rowid,
$nentry,
$leaf_entries,
$depth,
@@ -330,12 +332,15 @@ proc subreport {title where showFrag} {
# following query returns exactly one row (because it is an aggregate).
#
# The results of the query are stored directly by SQLite into local
# variables (i.e. $nentry, $nleaf etc.).
# variables (i.e. $nentry, $payload etc.).
#
mem eval "
SELECT
int(sum(nentry)) AS nentry,
int(sum(leaf_entries)) AS nleaf,
int(sum(
CASE WHEN (is_without_rowid OR is_index) THEN nentry
ELSE leaf_entries
END
)) AS nentry,
int(sum(payload)) AS payload,
int(sum(ovfl_payload)) AS ovfl_payload,
max(mx_payload) AS mx_payload,
@@ -375,8 +380,8 @@ proc subreport {title where showFrag} {
set storage [expr {$total_pages*$pageSize}]
set payload_percent [percent $payload $storage {of storage consumed}]
set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}]
set avg_payload [divide $payload $nleaf]
set avg_unused [divide $total_unused $nleaf]
set avg_payload [divide $payload $nentry]
set avg_unused [divide $total_unused $nentry]
if {$int_pages>0} {
# TODO: Is this formula correct?
set nTab [mem eval "
@@ -390,12 +395,12 @@ proc subreport {title where showFrag} {
"]
set avg_fanout [format %.2f $avg_fanout]
}
set ovfl_cnt_percent [percent $ovfl_cnt $nleaf {of all entries}]
set ovfl_cnt_percent [percent $ovfl_cnt $nentry {of all entries}]
# Print out the sub-report statistics.
#
statline {Percentage of total database} $total_pages_percent
statline {Number of entries} $nleaf
statline {Number of entries} $nentry
statline {Bytes of storage consumed} $storage
if {$compressed_size!=$storage} {
set compressed_size [expr {$compressed_size+$compressOverhead*$total_pages}]
+4 -4
View File
@@ -111,11 +111,11 @@ static unsigned int findCloseParen(const char *z){
** Print error messages whenever a side effect is found. Return the number
** of problems seen.
*/
static unsigned int findAllSideEffects(const unsigned char *z){
static unsigned int findAllSideEffects(const char *z){
unsigned int lineno = 1; /* Line number */
unsigned int i;
unsigned int nErr = 0;
unsigned char c, prevC = 0;
char c, prevC = 0;
for(i=0; (c = z[i])!=0; prevC=c, i++){
if( c=='\n' ){ lineno++; continue; }
if( isalpha(c) && !isalpha(prevC) ){
@@ -125,7 +125,7 @@ static unsigned int findAllSideEffects(const unsigned char *z){
|| strncmp(&z[i],"testcase(",9)==0
){
unsigned int n;
unsigned const char *z2 = &z[i+5];
const char *z2 = &z[i+5];
while( z2[0]!='(' ){ z2++; }
z2++;
n = findCloseParen(z2);
@@ -141,7 +141,7 @@ static unsigned int findAllSideEffects(const unsigned char *z){
}
int main(int argc, char **argv){
unsigned char *z;
char *z;
unsigned int nErr = 0;
if( argc!=2 ){
fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);