Compare commits

...

87 Commits

Author SHA1 Message Date
drh 365852a6bc SQLite version 3.7.5 release candidate 2
FossilOrigin-Name: ed759d5a9edb3bba5f48f243df47be29e3fe8cd7
2011-01-28 17:03:50 +00:00
dan 1af5e9a494 Add test script pagerfault3.test. No changes to code or existing tests.
FossilOrigin-Name: 682fe41efd3578e8c9abc7138b61f361c3adbe95
2011-01-28 16:45:42 +00:00
drh bd1334dfd9 Change pager_truncate() to a different method for extending files while
also ensuring that writes are page-size and page-aligned.

FossilOrigin-Name: 874bc8844f6494cdbf700bd884dee67d40f11fc0
2011-01-28 15:46:14 +00:00
dan fb3828c25f When extending a database file, do so by writing one or more page-size chunks of data to the file, instead of just a single byte to the end.
FossilOrigin-Name: 58577135a81d3f19667b1de6167d2e3f1b74cd53
2011-01-28 15:07:55 +00:00
drh 10431c306b SQLite version 3.7.5 release candidate 1
FossilOrigin-Name: 35ac78f55159705af140b949ee33852aedd62816
2011-01-27 14:35:01 +00:00
drh 0b52b7d0cd Update all built-in VFSes to return SQLITE_OK for the
SQLITE_FCNTL_SYNC_OMITTED file-control operation.  Also change the 
xFileControl methods to return SQLITE_NOTFOUND for unrecognized
operation codes.

FossilOrigin-Name: 6f2c72a0f6579db3f40c079436ca40e3e52bd6d9
2011-01-26 19:46:22 +00:00
dan b69577d3b8 Update test file mutex1.test to account for [e3b500fb5d].
FossilOrigin-Name: c86e46f4fd8f485fa1d34c70e17ea3aa1b334ce3
2011-01-26 15:23:22 +00:00
drh 15ad92f2ae More mutexes around another sqlite3StatusAdd() call.
FossilOrigin-Name: e3b500fb5d93d98e6e1ddf6d494a841274d1b68d
2011-01-26 13:28:06 +00:00
drh 9bf3da8eab Add a mutex around an sqlite3StatusAdd() call to prevent the pagecount
overflow measurements from getting off in multithreaded applications.

FossilOrigin-Name: 3d8b298dc24fe13a3f390da41f79b8613a6f25a7
2011-01-26 13:24:40 +00:00
dan 6d4fb833b7 Update mutex1.test so that it works with the memsubsys1 permutation (pagecache memory). Change a few instances of SQLITE_MUTEX_STATIC_LRU2 in comments and test code to STATIC_PMEM.
FossilOrigin-Name: 456bd5c63b41bae8e389df81e318b830aa314000
2011-01-26 07:25:32 +00:00
dan 7cfbeb7fb5 Changes to exclusive2.test to make it more deterministic.
FossilOrigin-Name: 84b0c2bc7125623be2ee526b5ca75e1b72debb93
2011-01-26 06:13:14 +00:00
drh 25ca568251 Rename the PCache1.mxPinned field to n90pct (since it is 90% of nMax) in order
to distinguish it from PGroup.mxPinned.  Fix the computation of n90pct so that
it does not overflow adversely on excessively large cache sizes.

FossilOrigin-Name: c85202baac49b22a4be36b9733d44f01d83edb28
2011-01-26 00:07:03 +00:00
drh 1e4040a4b4 Fix new compiler warnings in pcache1.c that were introduced by the recent
performance enhancement patches of [e14649301138b684].

FossilOrigin-Name: c17703ec1e604934f8bd5b1f66f34b19d17a6d1f
2011-01-25 18:30:51 +00:00
dan 4d26d585d6 Add a missing call to sqlite3PagerSync() removed by [ce552d975] to the backup code.
FossilOrigin-Name: 1965b85318c1fac62fae9691059021b298c17dde
2011-01-25 18:19:24 +00:00
drh 534a58a76d Make sure the return code from doing an xSync is correctly initialized
so that a valid return code is produced regardless of the path taken through
the logic.

FossilOrigin-Name: f12b5d76854c2f294ac60afe38a6dac37eb5b174
2011-01-25 16:48:56 +00:00
drh 951596cdef Change the name of SQLITE_FCNTL_SYNC to SQLITE_FCNTL_SYNC_OMITTED and only
send it when PRAGMA synchronous=OFF.  Add better documentation to explain
what that file-control opcode is used for.

FossilOrigin-Name: 64914980855dbbf19512642836ca962a507b3ddb
2011-01-25 16:20:16 +00:00
dan 0ecdeb2414 Fix a couple of typos in comments. No changes to actual code.
FossilOrigin-Name: 9167fdb3560b1567a0bdc9a1906a87ec98e161f1
2011-01-25 13:43:35 +00:00
dan d1cf7e2972 Fix a broken assert() in pager.c.
FossilOrigin-Name: 13108ce13c281f31aa60b403567710ae3d925797
2011-01-25 11:33:01 +00:00
dan ff07ccadee Fix a problem in memsubsys1.test. Modifications to test code only.
FossilOrigin-Name: 7ef3f7cba768ef0c4782a6c80424833b4df6a059
2011-01-25 09:54:53 +00:00
drh 41692e9d7c Shave a few cycles so that performance is better than 3.7.4 in speed tests.
FossilOrigin-Name: e14649301138b6840e24a4bbd2cf5205c0f72409
2011-01-25 04:34:51 +00:00
drh 3778ac15dd Modify the test_quote.c demonstration shim so that it works when
SQLITE_THREADSAFE=0 is defined.

FossilOrigin-Name: b70bcccaf5597c8a59cccb64fb997523f7b8fe4f
2011-01-24 20:18:05 +00:00
drh 2afc704ad8 Fix a typo in the documentation for sqlite3_snprintf(). No changes to code.
FossilOrigin-Name: 8d1065411aadf189880606c48ab63dd2a56b9793
2011-01-24 19:45:07 +00:00
drh 906b662060 Fix a harmless compiler warning (a shadowed local variable) in analyze.c.
FossilOrigin-Name: a1ad7fb38bb38909ca2fddee31c7a8001f10686f
2011-01-24 19:14:06 +00:00
dan 27381bd519 Modify the trace callback mechanism so that SQL commands executed from within virtual table or user function callbacks are passed to the trace callback without parameter expansion and enclosed in SQL comments.
FossilOrigin-Name: a764915b87564fa91ee68e9b1f41394ce0f1fc7e
2011-01-22 13:32:29 +00:00
dan a9ef7097c7 Change sqlite3StrAccumAppend() to use realloc instead of malloc.
FossilOrigin-Name: 380f61df0754ceec6b3f6a758d04e951cce8c3d9
2011-01-21 18:25:29 +00:00
dan f3aef49cbd Add options to test command [do_faultsim_test] to support testing VFS implementations.
FossilOrigin-Name: 503ad889da675b3dd83da7338e2902e42f69acac
2011-01-21 15:52:02 +00:00
drh 3a5676ce26 Comment improvements in pcache1.c. No changes to code.
FossilOrigin-Name: 9660a0a22547656cc3765b673d0cee9e1dd829ef
2011-01-19 21:58:56 +00:00
drh bee29f4ac1 Do not use mutexes in the pcache implementation unless
SQLITE_ENABLE_MEMORY_MANAGMENT is defined.  This is a performance enhancement.
A side effect is that pcaches will not steal pages from one another unless
ENABLE_MEMORY_MANAGEMENT is set, or unless SQLITE_THREADSAFE=0.

FossilOrigin-Name: e5ca59e63b18ac45a8c82ca39dc8cce1c4ce903c
2011-01-18 17:03:26 +00:00
drh 986d3b95bb Get all test cases working with the mutex-free-pcache implementation.
FossilOrigin-Name: 2dc98d29995bef51108e99aa8f7a56427cf9e1d7
2011-01-18 16:13:27 +00:00
drh 40f9837ff6 Do not use SQLITE_MUTEX_STATIC_MEM2 since it has been reused as STATIC_OPEN.
Instead, create a new static mutex STATIC_PMEM which is an alias for the
unused STATIC_LRU2.

FossilOrigin-Name: f1cf02efcb3a871fef49f8b5f41bcf07622a6d29
2011-01-18 15:17:57 +00:00
drh 9f8cf9da27 Here is a completely new implementation of the mutex-free-pcache. This
one uses a common code base and automatically selects whether or not to 
use mutexes depending on compile-time and start-time options.

FossilOrigin-Name: d094a1bfb7569a52b637fe9ba5d3fa6ce5ea6d94
2011-01-17 21:32:24 +00:00
drh eee50ca5a7 Fix a typo in the documentation for sqlite3_stmt_readonly().
FossilOrigin-Name: 56417a3386fc84dd36bf1488e88149b1ac6a0d02
2011-01-17 18:30:10 +00:00
drh 602acb4871 Add the SQLITE_OMIT_AUTORESET compile-time option which if enabled causes
the sqlite3_step() routine to return SQLITE_MISUSE if it is called after
it has previously returned anything other than SQLITE_ROW, SQLITE_BUSY, or
SQLITE_LOCKED.

FossilOrigin-Name: 053ce76deb356d31358454507ba94947142e20ca
2011-01-17 17:42:37 +00:00
drh c5aae5c90b Add back an ALWAYS() to regain full test coverage.
FossilOrigin-Name: b93f6f3e679c7710f42580a8dd9ce43136376c1d
2011-01-17 02:24:12 +00:00
drh c6aed5424b On a backup from a smaller to a larger page size, do not begin committing
the transaction until the source pages after the pending byte have been
copied.

FossilOrigin-Name: 612e2599d3e1a17c268402fce018a53dee6dffe1
2011-01-16 22:37:09 +00:00
drh d40d7ec78b Make sure the change-counter and SQLite-version fields of the header are
set correctly even when doing a VACUUM with locking_mode=EXCLUSIVE.
Ticket [5d863f876ee9561b].

FossilOrigin-Name: 04fa1e16905183b948ee6456675799a873d5f97d
2011-01-16 00:56:19 +00:00
drh 0bf1f496b8 Make sure the change counter and SQLite version numbers in the header are
set correctly, even when running in WAL mode and when VACUUMing in WAL mode.
Ticket [5d863f876ee9561b9].

FossilOrigin-Name: 0be92a75769dbafbc08c3b229089aaac03a9a907
2011-01-15 21:42:23 +00:00
drh 54a7347aa1 Fix the change-counter increment for WAL pages so that it works even when
invoked from xStress.  Ticket [5d863f876ee9561b95e2].

FossilOrigin-Name: 228e7c34c64114670fe015747d47fdaa3b7e1270
2011-01-15 18:11:12 +00:00
drh 104a7bba8c Increment the change counter and update the SQLite version number whenever
page 1 is added to the WAL.  Ticket [5d863f876ee9561b9]

FossilOrigin-Name: c1e0d09cd3f5feae123468a35f147021d839641c
2011-01-15 17:12:59 +00:00
dan 39210bdaa6 Add a test case demonstrating the problem described by ticket [5d863f876e].
FossilOrigin-Name: af54963f0fa0afafbc2d0847f30543c041b182ec
2011-01-15 16:52:10 +00:00
drh a5657d710b Rerun autoconf to bring the configure script up-to-date.
FossilOrigin-Name: 142174640d60e834cae27ccaa78b02ecef8bcfe5
2011-01-14 16:43:29 +00:00
drh 94e7bd55bd Fix comments, including some documentation comments, in the page cache
logic.  No code changes.

FossilOrigin-Name: c80e9c1a0dc0e501b209874e147e1cb1348cb4a4
2011-01-14 15:17:55 +00:00
dan 47e909bb15 Fix a bug in test code (test_vfs.c).
FossilOrigin-Name: 772a3845f8ef5cd3131992c45f6ce607977820f3
2011-01-14 11:51:28 +00:00
drh 5b3696e8a6 Fix a typo on the sqlite3_open_v2() documentation.
FossilOrigin-Name: b0add45abc9929c5b8d1124879bc3e8acf2ab7c7
2011-01-13 16:10:58 +00:00
dan a8ab60c648 Fix a couple of crashes in fts3 that can occur if the database contents are inconsistent.
FossilOrigin-Name: 811e12cddfb3246c6cf3d5085bd9b72b12e05550
2011-01-13 11:20:04 +00:00
dan 86596e552e Fix a segfault that can occur in matchinfo if an fts4 table contains mostly zero-length documents. Specifically, if the table contains more rows than it does bytes of text.
FossilOrigin-Name: fe9047668eaaf76e7aa1ef1f32dec7c7c4226e45
2011-01-13 10:58:26 +00:00
drh efd95a7aca Do not raise an SQLITE_CORRUPT error in Recoverymode
if the database size in the header is larger than the physical file
size.  This facilitates recovery of a database in which the database size
field has been corrupted.

FossilOrigin-Name: 114640d920e16c85de90b19d53c485135875de5b
2011-01-12 17:56:26 +00:00
dan da56b15e95 Merge accidentally created fork.
FossilOrigin-Name: b7d080b8e850bd262f53f29ba4687a62cf76d4ef
2011-01-11 17:40:30 +00:00
dan 354bfe0363 Add the SQLITE_FCNTL_SYNC file-control.
FossilOrigin-Name: b3f2f465c310a2cfef8731a0dae3453593b68de9
2011-01-11 17:39:37 +00:00
drh ca94d8bf82 Change the page size of the destination database in a backup, if it is
changeable, prior to starting the backup.

FossilOrigin-Name: a5e4e0caad788318bc973e2550488a3b83128b8b
2011-01-11 17:38:03 +00:00
dan 9f4beedb6f If a rollback is attempted in journal_mode=off mode, force SQLite to discard the contents of the pager cache before processing any subsequent queries.
FossilOrigin-Name: ece7efce2733b4fdd71db385abebbde464ac8f30
2011-01-11 16:09:55 +00:00
drh bbd91944dd Fix the sqlite3.h generator script so that it generates the correct
SQLITE_SOURCE_ID string with the latest versions of Fossil that 
include fractional seconds on the date/time stamp.

FossilOrigin-Name: 3513bf6ee090d9be97f60e12a4b39f4361ee17b7
2011-01-11 12:46:05 +00:00
drh 444d26065e Update pager requirements to accound for the ZIPVFS extension.
FossilOrigin-Name: d94e59b514c16c5f7ea506e0af1c6e2ffecc13be
2011-01-10 21:01:10 +00:00
drh 2e5de2f2b3 Reorder the fields in private structures in an effort to reduce alignment
gaps and thus make the structures smaller, and to put frequently accessed
fields first.  Also update some obsolete comments.  Valgrind shows a very
slight performance improvement.

FossilOrigin-Name: 378a1d13af4a6f4cb2bfa65944b3b0d444b9f21c
2011-01-07 02:50:40 +00:00
drh b7787eef7a Enhance the showdb tool to show overflow page pointers at the end of
overflow cells.

FossilOrigin-Name: cda5eab18f48d3836dfd3e1f8c76e5f83b43485f
2011-01-06 15:51:18 +00:00
drh 5240aebdd8 Enhance the showdb tool to show a btree page layout. Add limit checks so that
overflow content does not overflow the buffer.

FossilOrigin-Name: 57ffa07e26a26d2f4527c8e6d7a9c1f48f380bf7
2011-01-06 01:26:38 +00:00
drh b2c062df71 Fix a bug in the showdb utility: the serial types for BLOB and TEXT where
reversed.

FossilOrigin-Name: 65a13faf1e3cd18f3459cd410f65d334cfa7c376
2011-01-05 21:46:52 +00:00
drh 100335be77 Enhancements to the "showdb" debugging tool. Add the ability to display
the content of a cell.

FossilOrigin-Name: e9023a4e1edd552a81dcb2dcd5a996edfa167709
2011-01-05 21:20:52 +00:00
drh 8a3d62224c Increment the version number to 3.7.5.
FossilOrigin-Name: 9ec3896e2fda5b04e609300463dc5b6e79d6cff1
2011-01-05 13:43:23 +00:00
drh db26d4c9e1 Add the sqlite3_vsnprintf() interface.
FossilOrigin-Name: fc67adea414320e0c0b24054f76070cfaeebb401
2011-01-05 12:20:09 +00:00
drh 65a0ce16aa Fix a null-pointer dereference that can occur on an OOM error while running
ANALYZE with SQLITE_ENABLE_STAT2.

FossilOrigin-Name: 73128d4ef5d7703bf7af0553c307b55dc1b783f6
2011-01-04 20:06:33 +00:00
drh 4856698fa5 Fix the ANALYZE command so that it takes collating sequences into account
when gathering index statistics.

FossilOrigin-Name: a5867cfc4c9b9155fa345247dec29e38fffa8002
2011-01-04 19:01:26 +00:00
drh 8e93b10a4e The ANALYZE command now counts at all rows of an index, even those containing
NULL values.  A valid sqlite_stat1 entry is created even if the index contains
nothing but NULLs.

FossilOrigin-Name: 824c8dd3015bbd5c8a1dd661cfe09fe5bf7a80d3
2011-01-04 17:57:53 +00:00
dan b29010cd4f Have testfixture invoke C routine Zipvfs_Init() when creating a new interpreter if SQLITE_ENABLE_ZIPVFS is defined.
FossilOrigin-Name: 430635dacfa818e8266a88214aaf60c77862de1c
2010-12-29 18:24:38 +00:00
dan 72903821e3 Fix some off-by-one errors in the comments for API functions create_function() and value_blob(). No changes to code or tests.
FossilOrigin-Name: 7ded90baeb75db5af83345cd2c31211cbee1e91b
2010-12-29 10:49:46 +00:00
dan b9a93d70b8 Reduce the number of calls to sqlite3_realloc() made by fts3 when querying for position information of a term prefix.
FossilOrigin-Name: 7088d9450f403f12f67eed558e368573101245d6
2010-12-24 15:49:27 +00:00
drh b469f46083 Do not include <sys/mmap.h> if SQLITE_OMIT_WAL is defined.
FossilOrigin-Name: b82e85ece94c8e25c1dc3251f5444a295fbf8c89
2010-12-22 21:48:50 +00:00
drh 2a58e9cc32 Add test cases for the new lookaside hit and miss status outputs. Add
the output of lookaside hit and miss to the command-line shell statistics.

FossilOrigin-Name: b0888047bb6d9ac55e29b9224df2ff650728bb78
2010-12-21 21:28:38 +00:00
drh e0a55f443b Merge into the trunk the experimental enhancements to sqlite3_db_status()
for measuring lookaside memory allocator performance.

FossilOrigin-Name: 8c3b06c299554759b67437e09ee7ef6420dacafc
2010-12-21 20:36:45 +00:00
drh 697e965299 Remove the obsolete compile-time option SQLITE_THREAD_OVERRIDE_LOCK
from the autoconf makefile.  Needed only for LinuxThreads, which we no
longer support.

FossilOrigin-Name: 09f6c053ff9239c22ecf527ae579446c6e21e550
2010-12-21 00:20:53 +00:00
drh 29ecd8a077 Rearrange a variable declaration in the proxy locking code to avoid a harmless
compiler warning on recent MacOS versions.

FossilOrigin-Name: 39bbd35599e735b32f7ed18143073165b805dd98
2010-12-21 00:16:40 +00:00
drh 08bd9f83ce Clarify the documentation of the SQLITE_STATUS_MALLOC_COUNT parameter to
sqlite3_status().

FossilOrigin-Name: 3b41bcc3e36a9ef0146bc2f6ae86377bd1700afd
2010-12-20 17:00:27 +00:00
drh 0b12e7f860 Add additional DBSTATUS options for measuring the hit and miss rates against
the lookaside memory pool - information useful in tuning the lookaside size.
Currently experimental pending analysis of performance impact.

FossilOrigin-Name: 34613f1dc54c638531ca2f5907b71fbe8841233e
2010-12-20 15:51:58 +00:00
drh 9c88d68988 Add the "-heap" option to the command-line shell - to allocate a fixed heap
for use with SQLITE_ENABLE_MEMSYS5.

FossilOrigin-Name: 74fff692345fed4b247e2b34c1e63b4d50cddfd4
2010-12-17 14:03:01 +00:00
drh cd2f58b374 Fix minor typos in the sqlite3_backup documentation.
FossilOrigin-Name: df430be59d0766a34a94ab85fec9aa3c3baeb740
2010-12-17 00:59:59 +00:00
drh 230bd63011 Improvements to the documentation for sqlite3_backup. No code changes.
FossilOrigin-Name: f83609f4703b5e74a91bca071a4ac2843189f463
2010-12-16 20:35:09 +00:00
drh 4278d53efa Fix an assertion fault that can only occur if SQLITE_ENABLE_STAT2 is defined
and the constant folding optimization is disabled using sqlite3_test_control().
Problem introduced by [ad8bc68197f2b4] but we missed it prior to the 3.7.4
release due to taking shortcuts and skipping tests in the release checklist.

FossilOrigin-Name: 70a3d81742fcd481f83ccc8f7ff6af58bc29c4fa
2010-12-16 19:52:52 +00:00
drh 7d20844542 Make wal_checkpoint a no-op if a prior checkpoint has already copied all
WAL content into the database.  This prevents a concurrent write to the
database from resetting the wal-index out from under the WalIterator of
the checkpoint as it is initializing.

FossilOrigin-Name: cf86affcb7d3089496e9849cbf43a211097e4f64
2010-12-16 02:06:29 +00:00
drh d9c9b78e6c Enhanced comments in wal.c and declare some procedure parameters "const".
No changes to the generated code.

FossilOrigin-Name: d0e4375b8a784d4e4ae66caababac919edd61883
2010-12-15 21:02:06 +00:00
drh 901e994b8b When registering the built-in LIKE and GLOB functions, make sure that they
are tagged with SQLITE_UTF8 so that if other application-defined LIKE and
GLOB implementations are provided for UTF16, then the appropriate function
will be selected.

FossilOrigin-Name: e1660764f20fed3fe92156d2b7f06075ff6ac145
2010-12-15 18:54:37 +00:00
dan d3842765ae Fix a performance regression in matchinfo().
FossilOrigin-Name: fa37d8eb7cd8049689068af2a80fe2cbb4a603f1
2010-12-10 17:06:48 +00:00
drh a4bfd7fde8 Add support for the SQLITE_DEFAULT_FOREIGN_KEYS compile-time option.
FossilOrigin-Name: c959945ab7129b67eb2364befb9bf5cc88a8b0bf
2010-12-09 19:15:17 +00:00
drh 7f322e791c Mention the SQLITE_DEFAULT_WAL_AUTOCHECKPOINT compile-time option in the
documentation for the sqlite3_wal_autocheckpoint() interface.

FossilOrigin-Name: 5a52dd59ff577b071b4ed9316dc3bc753a18c8da
2010-12-09 18:55:09 +00:00
drh 10fc727d35 Update the sqlite3_stmt_readonly() interface so that its output is
well-defined for all prepared statements, and so that it gives the 
correct result for VACUUM.

FossilOrigin-Name: 9c19b7ae3542fd1fac692b4471f1839b22685c76
2010-12-08 18:30:19 +00:00
drh e14cd93f2e The command-line shell ignore errors in sqlite3_close() when shutting down.
FossilOrigin-Name: 925332c3d79f6252895ff1a367f795630619247e
2010-12-08 03:28:17 +00:00
drh 81d7fd13e4 Changes to the shell which should, in theory, allow it to work with
libeditline as an alternative to libreadline.

FossilOrigin-Name: e474fd9e7f89644a7840e33e9df03dbaa4dd28bd
2010-12-08 00:02:26 +00:00
drh 91412b2446 Improved documentation for SQLITE_FCNTL_FILE_POINTER.
FossilOrigin-Name: 43935548ae79d4d1a71549820a77368cda77104a
2010-12-07 23:24:00 +00:00
63 changed files with 1667 additions and 667 deletions
-4
View File
@@ -59,10 +59,6 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
#
TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
# Do threads override each others locks by default (1), or do we test (-1)
#
TCC += -DSQLITE_THREAD_OVERRIDE_LOCK=@THREADSOVERRIDELOCKS@
# Any target libraries which libsqlite must be linked against
#
TLIBS = @LIBS@
+1 -1
View File
@@ -1 +1 @@
3.7.4
3.7.5
Vendored
+23 -53
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.7.4.
# Generated by GNU Autoconf 2.62 for sqlite 3.7.5.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.7.4'
PACKAGE_STRING='sqlite 3.7.4'
PACKAGE_VERSION='3.7.5'
PACKAGE_STRING='sqlite 3.7.5'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -869,7 +869,6 @@ VERSION_NUMBER
BUILD_CC
SQLITE_THREADSAFE
XTHREADCONNECT
THREADSOVERRIDELOCKS
ALLOWRELEASE
TEMP_STORE
BUILD_EXEEXT
@@ -912,7 +911,6 @@ enable_largefile
with_hints
enable_threadsafe
enable_cross_thread_connections
enable_threads_override_locks
enable_releasemode
enable_tempstore
enable_tcl
@@ -1487,7 +1485,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.7.4 to adapt to many kinds of systems.
\`configure' configures sqlite 3.7.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1552,7 +1550,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.7.4:";;
short | recursive ) echo "Configuration of sqlite 3.7.5:";;
esac
cat <<\_ACEOF
@@ -1569,8 +1567,6 @@ Optional Features:
--enable-threadsafe Support threadsafe operation
--enable-cross-thread-connections
Allow connection sharing across threads
--enable-threads-override-locks
Threads can override each others locks
--enable-releasemode Support libtool link to release mode
--enable-tempstore Use an in-ram database for temporary tables
(never,no,yes,always)
@@ -1670,7 +1666,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.7.4
sqlite configure 3.7.5
generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1684,7 +1680,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.7.4, which was
It was created by sqlite $as_me 3.7.5, which was
generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@
@@ -3738,13 +3734,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3741: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3737: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3744: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3740: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3747: output\"" >&5)
(eval echo "\"\$as_me:3743: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -4966,7 +4962,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 4969 "configure"' > conftest.$ac_ext
echo '#line 4965 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6835,11 +6831,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:6838: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6834: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6842: \$? = $ac_status" >&5
echo "$as_me:6838: \$? = $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.
@@ -7174,11 +7170,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:7177: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7173: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7181: \$? = $ac_status" >&5
echo "$as_me:7177: \$? = $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.
@@ -7279,11 +7275,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:7282: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7278: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7286: \$? = $ac_status" >&5
echo "$as_me:7282: \$? = $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
@@ -7334,11 +7330,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:7337: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7333: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7341: \$? = $ac_status" >&5
echo "$as_me:7337: \$? = $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
@@ -10147,7 +10143,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 10150 "configure"
#line 10146 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10243,7 +10239,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 10246 "configure"
#line 10242 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12580,32 +12576,6 @@ $as_echo "yes" >&6; }
fi
##########
# Do we want to set threadsOverrideEachOthersLocks variable to be 1 (true) by
# default. Normally, a test at runtime is performed to determine the
# appropriate value of this variable. Use this option only if you're sure that
# threads can safely override each others locks in all runtime situations.
#
# Check whether --enable-threads-override-locks was given.
if test "${enable_threads_override_locks+set}" = set; then
enableval=$enable_threads_override_locks;
else
enable_threads_override_locks=no
fi
{ $as_echo "$as_me:$LINENO: checking whether threads can override each others locks" >&5
$as_echo_n "checking whether threads can override each others locks... " >&6; }
if test "$enable_threads_override_locks" = "no"; then
THREADSOVERRIDELOCKS='-1'
{ $as_echo "$as_me:$LINENO: result: no" >&5
$as_echo "no" >&6; }
else
THREADSOVERRIDELOCKS='1'
{ $as_echo "$as_me:$LINENO: result: yes" >&5
$as_echo "yes" >&6; }
fi
##########
# Do we want to support release
#
@@ -13972,7 +13942,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.7.4, which was
This file was extended by sqlite $as_me 3.7.5, which was
generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14025,7 +13995,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
sqlite config.status 3.7.4
sqlite config.status 3.7.5
configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
-18
View File
@@ -268,24 +268,6 @@ else
fi
AC_SUBST(XTHREADCONNECT)
##########
# Do we want to set threadsOverrideEachOthersLocks variable to be 1 (true) by
# default. Normally, a test at runtime is performed to determine the
# appropriate value of this variable. Use this option only if you're sure that
# threads can safely override each others locks in all runtime situations.
#
AC_ARG_ENABLE(threads-override-locks,
AC_HELP_STRING([--enable-threads-override-locks],[Threads can override each others locks]),,enable_threads_override_locks=no)
AC_MSG_CHECKING([whether threads can override each others locks])
if test "$enable_threads_override_locks" = "no"; then
THREADSOVERRIDELOCKS='-1'
AC_MSG_RESULT([no])
else
THREADSOVERRIDELOCKS='1'
AC_MSG_RESULT([yes])
fi
AC_SUBST(THREADSOVERRIDELOCKS)
##########
# Do we want to support release
#
+8 -1
View File
@@ -3106,9 +3106,16 @@ char *sqlite3Fts3FindPositions(
assert( pExpr->isLoaded );
if( pExpr->aDoclist ){
char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
char *pCsr = pExpr->pCurrent;
char *pCsr;
if( pExpr->pCurrent==0 ){
pExpr->pCurrent = pExpr->aDoclist;
pExpr->iCurrent = 0;
pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent);
}
pCsr = pExpr->pCurrent;
assert( pCsr );
while( pCsr<pEnd ){
if( pExpr->iCurrent<iDocid ){
fts3PoslistCopy(0, &pCsr);
+3 -21
View File
@@ -226,7 +226,7 @@ static int fts3ExprNearTrim(Fts3Expr *pExpr){
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){
static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
int rc = SQLITE_OK;
LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
@@ -246,22 +246,6 @@ static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){
return rc;
}
/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb2(Fts3Expr *pExpr, int iPhrase, void *ctx){
UNUSED_PARAMETER(iPhrase);
UNUSED_PARAMETER(ctx);
if( pExpr->aDoclist ){
pExpr->pCurrent = pExpr->aDoclist;
pExpr->iCurrent = 0;
pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent, &pExpr->iCurrent);
}
return SQLITE_OK;
}
/*
** Load the doclists for each phrase in the query associated with FTS3 cursor
** pCsr.
@@ -280,10 +264,7 @@ static int fts3ExprLoadDoclists(
int rc; /* Return Code */
LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */
sCtx.pCsr = pCsr;
rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb1, (void *)&sCtx);
if( rc==SQLITE_OK ){
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb2, 0);
}
rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx);
if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
if( pnToken ) *pnToken = sCtx.nToken;
return rc;
@@ -975,6 +956,7 @@ static int fts3MatchinfoSelectDoctotal(
if( rc!=SQLITE_OK ) return rc;
}
pStmt = *ppStmt;
assert( sqlite3_data_count(pStmt)==1 );
a = sqlite3_column_blob(pStmt, 0);
a += sqlite3Fts3GetVarint(a, &nDoc);
+19 -15
View File
@@ -1102,24 +1102,28 @@ int sqlite3Fts3SegReaderCost(
** to right.
*/
sqlite3_stmt *pStmt;
rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
sqlite3_int64 nDoc = 0;
sqlite3_int64 nByte = 0;
const char *a;
rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
if( rc ) return rc;
if( sqlite3_step(pStmt)==SQLITE_ROW ){
sqlite3_int64 nDoc = 0;
sqlite3_int64 nByte = 0;
const char *a = sqlite3_column_blob(pStmt, 0);
if( a ){
const char *pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
a += sqlite3Fts3GetVarint(a, &nDoc);
while( a<pEnd ){
a += sqlite3Fts3GetVarint(a, &nByte);
}
a = sqlite3_column_blob(pStmt, 0);
if( a ){
const char *pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
a += sqlite3Fts3GetVarint(a, &nDoc);
while( a<pEnd ){
a += sqlite3Fts3GetVarint(a, &nByte);
}
pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz - 1) / pgsz);
}
if( nDoc==0 || nByte==0 ){
sqlite3_reset(pStmt);
return SQLITE_CORRUPT;
}
pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
assert( pCsr->nRowAvg>0 );
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK || pCsr->nRowAvg==0 ) return rc;
if( rc!=SQLITE_OK ) return rc;
}
/* Assume that a blob flows over onto overflow pages if it is larger
@@ -2240,7 +2244,7 @@ int sqlite3Fts3SegReaderIterate(
nByte = sqlite3Fts3VarintLen(iDocid-iPrev) + (isRequirePos?nList+1:0);
if( nDoclist+nByte>nAlloc ){
char *aNew;
nAlloc = nDoclist+nByte*2;
nAlloc = (nDoclist+nByte)*2;
aNew = sqlite3_realloc(aBuffer, nAlloc);
if( !aNew ){
rc = SQLITE_NOMEM;
+69 -65
View File
@@ -1,14 +1,14 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Version\s3.7.4\srelease\scandidate\s4
D 2010-12-07T20:14:09
C SQLite\sversion\s3.7.5\srelease\scandidate\s2
D 2011-01-28T17:03:50.592
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0
F Makefile.in de6498556d536ae60bb8bb10e8c1ba011448658c
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION 3466c92381170cedd7c04fc6ac2760b53a61cde9
F VERSION de8d3477dbf0d6cc226ccc6e046273627eb55fc5
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
@@ -25,8 +25,8 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure daed6cfdb4c1449a4335b3eeddc0d836e33fb54e x
F configure.ac 699040cc9abb7465dca5a2972bc89d227fd8f734
F configure 0eb10c03a6536d8e5ce52ab70fda0a152d8a3262 x
F configure.ac 87a3c71bbe9c925381c154413eea7f3cdc397244
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
F doc/pager-invariants.txt 870107036470d7c419e93768676fae2f8749cf9e
@@ -64,7 +64,7 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 44f998657ec849362484bb389c5728e821fc8c59
F ext/fts3/fts3.c 28ada7d1c700e57b072b2c95d70565b05925fa46
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h a6c69c1c5e2c8c19172ddff42d262c087dcd7337
F ext/fts3/fts3_expr.c 5f49e0deaf723724b08100bb3ff40aab02ad0c93
@@ -72,11 +72,11 @@ F ext/fts3/fts3_hash.c 3c8f6387a4a7f5305588b203fa7c887d753e1f1c
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295
F ext/fts3/fts3_porter.c d61cfd81fb0fd8fbcb25adcaee0ba671aefaa5c2
F ext/fts3/fts3_snippet.c 6c87b55965124920d6461d79ea44b22cc3f307aa
F ext/fts3/fts3_snippet.c 196c5e6cde57bfc1907c2d60e9c29590e4f93fb6
F ext/fts3/fts3_tokenizer.c 055f3dc7369585350b28db1ee0f3b214dca6724d
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
F ext/fts3/fts3_tokenizer1.c 6e5cbaa588924ac578263a598e4fb9f5c9bb179d
F ext/fts3/fts3_write.c 13012755d59e5d4f09a41fd3b5ad17de7dafe3e7
F ext/fts3/fts3_write.c 3eea26b9ca4219e1711b0db74fd5a9d448a6afbb
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
@@ -116,25 +116,25 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 6a0c176e64a34929a4436048066a84ef4f1445b3
F src/analyze.c 1ea594a912a14138e20a05db09d9065e46f29a2a
F src/analyze.c a038162344265ac21dfb24b3fcc06c666ebb9c07
F src/attach.c 252c4f7e36cc219349451ed63e278c60e80b26f3
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c d5b0137bc20327af08c14772227cc35134839c30
F src/backup.c 6728d6d48d55b449af76a3e51c0808849cb32a2e
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
F src/btree.c b70bf1dc563ec532851715ce51aa1ea0c0c592b9
F src/btree.c 9004c98fc576306eee4fc0562ffeb362ef53912c
F src/btree.h 10f9296bf4edf034f5adce921b7b4383a56a1c90
F src/btreeInt.h c424f2f131cc61ddf130f9bd736b3df12c8a51f0
F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4
F src/build.c 00a327120d81ace6267e714ae8010c997d55de5d
F src/callback.c a1d1b1c9c85415dff013af033e2fed9c8382d33b
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 4f3aadad62c6c9f0d4e5a96718516ac4e3c598df
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd
F src/expr.c 1810f3056b11de99cc10e24629edf00e5fbd3a75
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 17950a28f28b23e8ad3feaac5fc88c324d2f600a
F src/func.c 2b7cf54d2569c2eba42fe81165d1932b546681a3
F src/func.c cb41f614edc43b00bfeb030f9768e80eaff47edd
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
@@ -144,8 +144,8 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e
F src/main.c 721e5530b14b91a1fb6aead279af8b8729fa9a20
F src/malloc.c 3d7284cd9346ab6e3945535761e68c23c6cf40ef
F src/main.c 6653e46db7ecb5a7449d8a12900147192f748b97
F src/malloc.c 92d59a007d7a42857d4e9454aa25b6b703286be1
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
@@ -156,37 +156,37 @@ F src/mutex.c 6949180803ff05a7d0e2b9334a95b4fb5a00e23f
F src/mutex.h fe2ef5e1c4dae531d5a544f9241f19c56d26803d
F src/mutex_noop.c d5cfbca87168c661a0b118cd8e329a908e453151
F src/mutex_os2.c 6a62583e374ba3ac1a3fcc0da2bfdac7d3942689
F src/mutex_unix.c abb8c98a6c27c57280e71522d059e929c708d019
F src/mutex_w32.c b7ed3366a1d44a62a17d4eaefdaa2e7c25f944c2
F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
F src/mutex_w32.c 3ade5ae71449d1d023f0ebb3184c2ae6aa9307e4
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
F src/os_unix.c 0240c5b547b4cf585c8cac351a95c3e85ce00772
F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad
F src/pager.c c0aca5c733c15a16fe158c3215d857841a4e5381
F src/os_os2.c 2e452c9f2ca507623ad351c33a8a8b27849b1863
F src/os_unix.c 1be46a35bad4bec5171e4de88aaff817260eb378
F src/os_win.c 9abdcdd925416d854eabb0996c96debd92abfef5
F src/pager.c b0fcbe3038fd08b111e1cf1deddd5f42418004d8
F src/pager.h 0ea59db2a33bc6c2c02cae34de33367e1effdf76
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c e9578a3beac26f229ee558a4e16c863f2498185f
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
F src/pragma.c 8a6cd3c787f882fa44f6490d2411fc26839ce8f3
F src/prepare.c c8b877b80721d70b68053fd9ae30ec6d63eeeadc
F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506
F src/prepare.c 395b3fab1b93f45b6aa194b23ebc201221c47b99
F src/printf.c df2ff3bb5409e8958136933342c46464fbd017e7
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 8a7ba246b0b4bb45df7fbc52681728a0e3deaaa7
F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056
F src/sqlite.h.in b7e8a4e4749cfae9c99e1fbe3f9f87763cbbf7a2
F src/shell.c 83c6f0cc5a79a081c7b9ddfe4f557b47e0bad976
F src/sqlite.h.in 76955fcd1c5371268ecc8afe0ce6c49ea750ae38
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h b96d5ddb8b419a2ed7cf69a7778b53872d73e8a7
F src/sqliteInt.h 45926deaf59b1ce3f55d21d5f91a8cecb6a7eb4c
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 77c5c4b8ac7b2d94ee480e1ad626fbd921d948e4
F src/test1.c 397809a3069c171a507a49b6f6edfc4255b0afbc
F src/tclsqlite.c 549859dc2c143f3deb6a92636a2d27973652c164
F src/test1.c 771407a49ae199241f0efb7055634e4a1899c026
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee
@@ -199,7 +199,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
F src/test_config.c 55918873f0a2ebbd5b52417319987f9f99c401fa
F src/test_config.c 9f025a7f3686c94e82dc6d6bd3cbf0f89cd67487
F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c 13b582345fb1185a93e46c53310fae8547dcce20
@@ -209,13 +209,13 @@ F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c 09a88f0c111201dc4f8c20470aa1b5f611d59200
F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d
F src/test_multiplex.c 5990431a852aa21c9a67da748f23d2cf1e21f8fc
F src/test_mutex.c ce06b59aca168cd8c520b77159a24352a7469bd3
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
F src/test_quota.c 6d32dd5885777f432db91e3a6c9e39008dd67d86
F src/test_quota.c b5576f17d701af461effd7ca1e71f0d100071192
F src/test_rtree.c 30c981837445a4e187ee850a49c4760d9642f7c3
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
@@ -223,7 +223,7 @@ F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
F src/test_vfs.c e10fcca756cafa89438311b31522ac1f95bf784b
F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852
@@ -233,17 +233,17 @@ F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1
F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
F src/vdbe.c 5d310eaf1a4d8383602126fa82e01291ab7d3cf3
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
F src/vdbeInt.h 1f2137b905969f4de0648256aeb73abdf88f9213
F src/vdbeapi.c fb0036185b3c56e15916a5ee96309cd4acf6818f
F src/vdbeaux.c b810a66902ee40c71cdb9c64f43760da516c91df
F src/vdbeInt.h 6e6f28e9bccc6c703dca1372fd661c57b5c15fb0
F src/vdbeapi.c 8e9324fd35eb70d0b5904bd1af40f2598744dc4d
F src/vdbeaux.c 33448d23b857654dd69ed2103611f5c733606f68
F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c
F src/vdbemem.c 411649a35686f54268ccabeda175322c4697f5a6
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
F src/wal.c dbca424f71678f663a286ab2a98f947af1d412a7
F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c fa22d45b2577c77146f2e894d58011d472d64103
F src/where.c af069e6b53234118014dabfece96a9515b69d76b
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
@@ -255,6 +255,7 @@ F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/analyze.test c1eb87067fc16ece7c07e823d6395fd831b270c5
F test/analyze2.test 3bde8f0879d9c1f2df3af21fcf42e706d8ee1e43
F test/analyze3.test 820ddfb7591b49607fbaf77240c7955ac3cabb04
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@@ -295,7 +296,7 @@ F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 754baab2f18089fc9bcba7afaeb4dc907c6c6de2
F test/capi2.test 00032d7504b9c14f1b36331670c5e7b0f73e3c5d
F test/capi2.test 835d4cee9f542ea50fa8d01f3fe6de80b0627360
F test/capi3.test 1945a2ba75e3f4c49d5beb8fc092115b6292d471
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test bea67403a5e37a4b33230ee4723e315a2ffb31e7
@@ -376,14 +377,14 @@ F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de
F test/eqp.test 69670e7919030f21de29fb99bf1d68f97aedcbdb
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
F test/exclusive2.test 76e63c05349cb70d09d60b99d2ae625525ff5155
F test/exclusive2.test b65264c3e76e1db6c6eda15c02000a40743f6541
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
F test/filefmt.test f77c92141960b7933bc6691631d2ad62257ef40a
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
F test/fkey2.test e028cd80aa0bd38541c99214e3ba2dfccadffe6f
F test/fkey2.test 080969fe219b3b082b0e097ac18c6af2e5b0631f
F test/fkey3.test 42f88d6048d8dc079e2a8cf7baad1cc1483a7620
F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -452,7 +453,7 @@ F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3fault.test f83e556465bb69dc8bc676339eca408dce4ca246
F test/fts3malloc.test 9c8cc3f885bb4dfc66d0460c52f68f45e4710d1b
F test/fts3matchinfo.test ae910aa666285e14743a80799214bfb3f1aab8f2
F test/fts3matchinfo.test cc0b009edbbf575283d5fdb53271179e0d8019ba
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
F test/fts3query.test ef79d31fdb355d094baec1c1b24b60439a1fb8a2
F test/fts3rnd.test 2b1a579be557ab8ac54a51b39caa4aa8043cc4ad
@@ -511,7 +512,7 @@ F test/journal2.test 50a3604768494d4a337f194f0a9480e7c57dcb72
F test/journal3.test ff175219be1b02d2f7e54297ad7e491b7533edb6
F test/jrnlmode.test e3fe6c4a2c3213d285650dc8e33aab7eaaa5ce53
F test/jrnlmode2.test a19e28de1a6ec898067e46a122f1b71c9323bf00
F test/jrnlmode3.test cfcdb12b90e640a23b92785a002d96c0624c8710
F test/jrnlmode3.test c6522b276ba315fd1416198de6fc1da9e72409fb
F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05
F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
@@ -528,7 +529,7 @@ F test/lock5.test b2abb5e711bc59b0eae00f6c97a36ec9f458fada
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
F test/lock_common.tcl d279887a0ab16cdb6d935c1203e64113c5a000e9
F test/lookaside.test 382e7bc2fab23d902c8eafb1b9ed7ababfff75a6
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
F test/main.test 9d7bbfcc1b52c88ba7b2ba6554068ecf9939f252
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 927e6c8668a1d48c23aa6189bda02aff5a1b83de
@@ -551,11 +552,11 @@ F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9
F test/malloc_common.tcl 27087a2bfad8f695ca6f8b463ecac5d71b9b0712
F test/malloc_common.tcl 660b82ab528521cc4a48ff6df05ca3b6a00d47c5
F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c
F test/memdb.test 0825155b2290e900264daaaf0334b6dfe69ea498
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 4cbec6f202c91504bfc4717bfc2ffd6160316c4c
F test/memsubsys1.test 679db68394a5692791737b150852173b3e2fea10
F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
@@ -569,7 +570,7 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/multiplex.test 92a4839213fd8cba8b59f86d42b7a1da1857db39
F test/mutex1.test 5b71777fc127509cd257910c8db799de557a02de
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723
F test/notify1.test 8433bc74bd952fb8a6e3f8d7a4c2b28dfd69e310
@@ -578,14 +579,15 @@ F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
F test/pager1.test e066fb2e2dc1ac1cd9ef2b44a28ae3cc79a9150f
F test/pager2.test 0fbb6b6dc40ce1fecfe758c555a748ad2e9beaa3
F test/pager1.test 7006a8b5dd3df1fe0d51d7da014333d7dc099778
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test 9de4d3e0c59970b4c6cb8dac511fa242f335d8a7
F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401
F test/pagerfault3.test 9b413f48a3e9a9a8c26968118f8db19fd7bfb8c7
F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
F test/permutations.test c0ce0f3b741dd92a6d4c2671dbacba4b92dd81eb
F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
@@ -606,7 +608,7 @@ F test/rollback.test 1a83118ea6db4e7d8c10eaa63871b5e90502ffdc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/savepoint.test d3dd00e0137fc4b4659bde378a4d8f2cd07238a3
F test/savepoint.test a1bef7ace82cc7922975fa96b06176e9bd5114cf
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
@@ -686,6 +688,7 @@ F test/tkt-38cb5df375.test 9e9b19857dba0896a8efdaf334d405ba423492f2
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
F test/tkt-5d863f876e.test 884072c2de496ddbb90c387c9ebc0d4f44a91b8e
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 3581260f2a71e51db94e1506ba6b0f7311d002a9
F test/tkt-78e04e52ea.test ab52f0c1e2de6e46c910f4cc16b086bba05952b7
@@ -787,6 +790,7 @@ F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
F test/trace2.test 092bc2c5776272700450d60a36919921095bdc21
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97
@@ -875,17 +879,17 @@ F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c.tcl e0db70c2c52b0e3d0867ca931229e5b90ffe7837
F tool/mksqlite3h.tcl 03b6ca938c833814923674d8a160e91fcedb4571
F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/shell1.test 6c66ada564076681d38cba7eb00468e72a4764f4
F tool/shell1.test c31b0814a9c543db51ca0cc63edb5e77ea532303
F tool/shell2.test 5dc76b8005b465f420fed8241621da7513060ff3
F tool/shell3.test 4fad469e8003938426355afdf34155f08c587836
F tool/shell4.test 35f9c3d452b4e76d5013c63e1fd07478a62f14ce
F tool/shell5.test 62bfaf9267296da1b91e4b1c03e44e7b393f6a94
F tool/showdb.c c7a978cf525ef0f8bc2fd29cd52108dd1dfa605a
F tool/showdb.c 471c0f8fa472e71bb7654500096a5bdb4ea1fb2a
F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02
F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
@@ -897,14 +901,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P fe441df9ba447d97571e919099846efa3ec87427
R 6bbeb99b0a61f7ea1af21c5b74072ff6
P 682fe41efd3578e8c9abc7138b61f361c3adbe95
R 7fccaf9f7c013ddef8926255f6aeb773
U drh
Z 584aed3667b20c0c4d105810047e9fd4
Z 4223173e58f25d45d236e232b9c90989
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFM/pWUoxKgR168RlERAuOQAJ9BLHxhysfzWC+psYkAVcf2xDsyTgCeIRqp
FF5a9ESJ6yucR80Re9sEWmU=
=ZPd3
iD8DBQFNQvb6oxKgR168RlERAtOTAJ9BaewewKXL3RGZUy5ycaHwjeEmJACeOPbw
/JKqOugR+37RH7HnLCo9DBk=
=kgPx
-----END PGP SIGNATURE-----
+1 -1
View File
@@ -1 +1 @@
a586a4deeb25330037a49df295b36aaf624d0f45
ed759d5a9edb3bba5f48f243df47be29e3fe8cd7
+21 -8
View File
@@ -233,9 +233,10 @@ static void analyzeOneTable(
sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1);
for(i=0; i<nCol; i++){
CollSeq *pColl;
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
#ifdef SQLITE_ENABLE_STAT2
if( i==0 ){
#ifdef SQLITE_ENABLE_STAT2
/* Check if the record that cursor iIdxCur points to contains a
** value that should be stored in the sqlite_stat2 table. If so,
** store it. */
@@ -264,12 +265,17 @@ static void analyzeOneTable(
sqlite3VdbeJumpHere(v, ne);
sqlite3VdbeAddOp2(v, OP_AddImm, regRecno, 1);
}
#endif
sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1);
/**** TODO: add collating sequence *****/
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
/* Always record the very first row */
sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
}
assert( pIdx->azColl!=0 );
assert( pIdx->azColl[i]!=0 );
pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
(char*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
}
if( db->mallocFailed ){
/* If a malloc failure has occurred, then the result of the expression
@@ -280,7 +286,11 @@ static void analyzeOneTable(
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
for(i=0; i<nCol; i++){
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-(nCol*2));
int addr2 = sqlite3VdbeCurrentAddr(v) - (nCol*2);
if( i==0 ){
sqlite3VdbeJumpHere(v, addr2-1); /* Set jump dest for the OP_IfNot */
}
sqlite3VdbeJumpHere(v, addr2); /* Set jump dest for the OP_Ne */
sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
}
@@ -626,8 +636,11 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( rc==SQLITE_OK ){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char *zIndex = (char *)sqlite3_column_text(pStmt, 0);
Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
char *zIndex; /* Index name */
Index *pIdx; /* Pointer to the index object */
zIndex = (char *)sqlite3_column_text(pStmt, 0);
pIdx = zIndex ? sqlite3FindIndex(db, zIndex, sInfo.zDatabase) : 0;
if( pIdx ){
int iSample = sqlite3_column_int(pStmt, 1);
if( iSample<SQLITE_INDEX_SAMPLES && iSample>=0 ){
+47 -22
View File
@@ -117,6 +117,16 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
return pDb->aDb[i].pBt;
}
/*
** Attempt to set the page size of the destination to match the page size
** of the source.
*/
static int setDestPgsz(sqlite3_backup *p){
int rc;
rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
return rc;
}
/*
** Create an sqlite3_backup process to copy the contents of zSrcDb from
** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
@@ -170,10 +180,11 @@ sqlite3_backup *sqlite3_backup_init(
p->iNext = 1;
p->isAttached = 0;
if( 0==p->pSrc || 0==p->pDest ){
/* One (or both) of the named databases did not exist. An error has
** already been written into the pDestDb handle. All that is left
** to do here is free the sqlite3_backup structure.
if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. The error has already been written into the
** pDestDb handle. All that is left to do here is free the
** sqlite3_backup structure.
*/
sqlite3_free(p);
p = 0;
@@ -430,32 +441,46 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
*/
const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
i64 iOff;
i64 iEnd;
assert( pFile );
assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
));
if( SQLITE_OK==(rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1))
&& SQLITE_OK==(rc = backupTruncateFile(pFile, iSize))
&& SQLITE_OK==(rc = sqlite3PagerSync(pDestPager))
/* This call ensures that all data required to recreate the original
** database has been stored in the journal for pDestPager and the
** journal synced to disk. So at this point we may safely modify
** the database file in any way, knowing that if a power failure
** occurs, the original database will be reconstructed from the
** journal file. */
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
/* Write the extra pages and truncate the database file as required. */
iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
for(
iOff=PENDING_BYTE+pgszSrc;
rc==SQLITE_OK && iOff<iEnd;
iOff+=pgszSrc
){
i64 iOff;
i64 iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
for(
iOff=PENDING_BYTE+pgszSrc;
rc==SQLITE_OK && iOff<iEnd;
iOff+=pgszSrc
){
PgHdr *pSrcPg = 0;
const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){
u8 *zData = sqlite3PagerGetData(pSrcPg);
rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
}
sqlite3PagerUnref(pSrcPg);
PgHdr *pSrcPg = 0;
const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){
u8 *zData = sqlite3PagerGetData(pSrcPg);
rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
}
sqlite3PagerUnref(pSrcPg);
}
if( rc==SQLITE_OK ){
rc = backupTruncateFile(pFile, iSize);
}
/* Sync the database file to disk. */
if( rc==SQLITE_OK ){
rc = sqlite3PagerSync(pDestPager);
}
}else{
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
+2 -7
View File
@@ -918,14 +918,9 @@ static void btreeParseCellPtr(
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
int nSize; /* Total size of cell content in bytes */
nSize = nPayload + n;
if( (pInfo->nSize = (u16)(n+nPayload))<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
pInfo->iOverflow = 0;
if( (nSize & ~3)==0 ){
nSize = 4; /* Minimum cell size is 4 */
}
pInfo->nSize = (u16)nSize;
}else{
/* If the payload will not fit completely on the local page, we have
** to decide how much to store locally and how much to spill onto
@@ -2386,7 +2381,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
if( nPageHeader>nPageFile ){
if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPageHeader>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
+8 -8
View File
@@ -414,12 +414,12 @@ struct BtShared {
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
#endif
u8 inTransaction; /* Transaction state */
u8 doNotUseWAL; /* If true, do not open write-ahead-log file */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
u8 inTransaction; /* Transaction state */
u8 doNotUseWAL; /* If true, do not open write-ahead-log file */
u32 pageSize; /* Total number of bytes on a page */
u32 usableSize; /* Number of usable bytes on each page */
int nTransaction; /* Number of open transactions (read + write) */
@@ -446,8 +446,8 @@ struct BtShared {
*/
typedef struct CellInfo CellInfo;
struct CellInfo {
u8 *pCell; /* Pointer to the start of cell content */
i64 nKey; /* The key for INTKEY tables, or number of bytes in key */
u8 *pCell; /* Pointer to the start of cell content */
u32 nData; /* Number of bytes of data */
u32 nPayload; /* Total amount of payload */
u16 nHeader; /* Size of the cell content header in bytes */
@@ -489,20 +489,20 @@ struct BtCursor {
Pgno pgnoRoot; /* The root page of this tree */
sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */
CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor's last known position */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
u8 wrFlag; /* True if writable */
u8 atLast; /* Cursor pointing to the last entry */
u8 validNKey; /* True if info.nKey is valid */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
void *pKey; /* Saved key that was cursor's last known position */
i64 nKey; /* Size of pKey, or last integer key */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
#ifndef SQLITE_OMIT_INCRBLOB
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
Pgno *aOverflow; /* Cache of overflow page locations */
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
#endif
i16 iPage; /* Index of current page in apPage */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
};
/*
+3
View File
@@ -174,6 +174,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
"OMIT_AUTOMATIC_INDEX",
#endif
#ifdef SQLITE_OMIT_AUTORESET
"OMIT_AUTORESET",
#endif
#ifdef SQLITE_OMIT_AUTOVACUUM
"OMIT_AUTOVACUUM",
#endif
+3 -3
View File
@@ -1450,9 +1450,9 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
}else{
pInfo = (struct compareInfo*)&likeInfoNorm;
}
sqlite3CreateFunc(db, "like", 2, SQLITE_ANY, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "like", 3, SQLITE_ANY, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "glob", 2, SQLITE_ANY,
sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
(struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
setLikeOptFlag(db, "like",
+6 -1
View File
@@ -816,7 +816,7 @@ const char *sqlite3ErrStr(int rc){
/* SQLITE_INTERRUPT */ "interrupted",
/* SQLITE_IOERR */ "disk I/O error",
/* SQLITE_CORRUPT */ "database disk image is malformed",
/* SQLITE_NOTFOUND */ 0,
/* SQLITE_NOTFOUND */ "unknown operation",
/* SQLITE_FULL */ "database or disk is full",
/* SQLITE_CANTOPEN */ "unable to open database file",
/* SQLITE_PROTOCOL */ "locking protocol",
@@ -1821,6 +1821,9 @@ static int openDatabase(
#endif
#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
| SQLITE_RecTriggers
#endif
#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
| SQLITE_ForeignKeys
#endif
;
sqlite3HashInit(&db->aCollSeq);
@@ -2361,6 +2364,8 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
rc = SQLITE_OK;
}else if( fd->pMethods ){
rc = sqlite3OsFileControl(fd, op, pArg);
}else{
rc = SQLITE_NOTFOUND;
}
sqlite3BtreeLeave(pBtree);
}
+13 -7
View File
@@ -616,14 +616,20 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
if( db->mallocFailed ){
return 0;
}
if( db->lookaside.bEnabled && n<=db->lookaside.sz
&& (pBuf = db->lookaside.pFree)!=0 ){
db->lookaside.pFree = pBuf->pNext;
db->lookaside.nOut++;
if( db->lookaside.nOut>db->lookaside.mxOut ){
db->lookaside.mxOut = db->lookaside.nOut;
if( db->lookaside.bEnabled ){
if( n>db->lookaside.sz ){
db->lookaside.anStat[1]++;
}else if( (pBuf = db->lookaside.pFree)==0 ){
db->lookaside.anStat[2]++;
}else{
db->lookaside.pFree = pBuf->pNext;
db->lookaside.nOut++;
db->lookaside.anStat[0]++;
if( db->lookaside.nOut>db->lookaside.mxOut ){
db->lookaside.mxOut = db->lookaside.nOut;
}
return (void*)pBuf;
}
return (void*)pBuf;
}
}
#else
+1 -1
View File
@@ -99,7 +99,7 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
** <li> SQLITE_MUTEX_STATIC_LRU2
** <li> SQLITE_MUTEX_STATIC_PMEM
** </ul>
**
** The first two constants cause sqlite3_mutex_alloc() to create
+1 -1
View File
@@ -156,7 +156,7 @@ static int winMutexEnd(void){
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
** <li> SQLITE_MUTEX_STATIC_LRU2
** <li> SQLITE_MUTEX_STATIC_PMEM
** </ul>
**
** The first two constants cause sqlite3_mutex_alloc() to create
+1 -1
View File
@@ -533,7 +533,7 @@ static int os2FileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
}
return SQLITE_ERROR;
return SQLITE_NOTFOUND;
}
/*
+14 -8
View File
@@ -119,7 +119,9 @@
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#ifndef SQLITE_OMIT_WAL
#include <sys/mman.h>
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
@@ -3133,8 +3135,11 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
case SQLITE_FCNTL_SYNC_OMITTED: {
return SQLITE_OK; /* A no-op */
}
}
return SQLITE_ERROR;
return SQLITE_NOTFOUND;
}
/*
@@ -5403,18 +5408,19 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait);
** bytes of writable memory.
*/
static int proxyGetHostID(unsigned char *pHostID, int *pError){
struct timespec timeout = {1, 0}; /* 1 sec timeout */
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
memset(pHostID, 0, PROXY_HOSTIDLEN);
#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\
&& __MAC_OS_X_VERSION_MIN_REQUIRED<1050
if( gethostuuid(pHostID, &timeout) ){
int err = errno;
if( pError ){
*pError = err;
{
static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
if( gethostuuid(pHostID, &timeout) ){
int err = errno;
if( pError ){
*pError = err;
}
return SQLITE_IOERR;
}
return SQLITE_IOERR;
}
#endif
#ifdef SQLITE_TEST
+4 -1
View File
@@ -1183,8 +1183,11 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
SimulateIOErrorBenign(0);
return SQLITE_OK;
}
case SQLITE_FCNTL_SYNC_OMITTED: {
return SQLITE_OK;
}
}
return SQLITE_ERROR;
return SQLITE_NOTFOUND;
}
/*
+78 -27
View File
@@ -2477,15 +2477,21 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
i64 currentSize, newSize;
int szPage = pPager->pageSize;
assert( pPager->eLock==EXCLUSIVE_LOCK );
/* TODO: Is it safe to use Pager.dbFileSize here? */
rc = sqlite3OsFileSize(pPager->fd, &currentSize);
newSize = pPager->pageSize*(i64)nPage;
newSize = szPage*(i64)nPage;
if( rc==SQLITE_OK && currentSize!=newSize ){
if( currentSize>newSize ){
rc = sqlite3OsTruncate(pPager->fd, newSize);
}else{
rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1);
char *pTmp = pPager->pTmpSpace;
memset(pTmp, 0, szPage);
testcase( (newSize-szPage) < currentSize );
testcase( (newSize-szPage) == currentSize );
testcase( (newSize-szPage) > currentSize );
rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
}
if( rc==SQLITE_OK ){
pPager->dbFileSize = nPage;
@@ -2749,10 +2755,10 @@ end_playback:
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && !pPager->noSync
if( rc==SQLITE_OK
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
rc = sqlite3PagerSync(pPager);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
@@ -2915,11 +2921,37 @@ static int pagerRollbackWal(Pager *pPager){
return rc;
}
/*
** Update the value of the change-counter at offsets 24 and 92 in
** the header and the sqlite version number at offset 96.
**
** This is an unconditional update. See also the pager_incr_changecounter()
** routine which only updates the change-counter if the update is actually
** needed, as determined by the pPager->changeCountDone state variable.
*/
static void pager_write_changecounter(PgHdr *pPg){
u32 change_counter;
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
put32bits(((char*)pPg->pData)+24, change_counter);
/* Also store the SQLite version number in bytes 96..99 and in
** bytes 92..95 store the change counter for which the version number
** is valid. */
put32bits(((char*)pPg->pData)+92, change_counter);
put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
}
/*
** This function is a wrapper around sqlite3WalFrames(). As well as logging
** the contents of the list of pages headed by pList (connected by pDirty),
** this function notifies any active backup processes that the pages have
** changed.
** changed.
**
** The list of pages passed into this routine is always sorted by page number.
** Hence, if page 1 appears anywhere on the list, it will be the first page.
*/
static int pagerWalFrames(
Pager *pPager, /* Pager object */
@@ -2929,8 +2961,19 @@ static int pagerWalFrames(
int syncFlags /* Flags to pass to OsSync() (or 0) */
){
int rc; /* Return code */
#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
PgHdr *p; /* For looping over pages */
#endif
assert( pPager->pWal );
#ifdef SQLITE_DEBUG
/* Verify that the page list is in accending order */
for(p=pList; p && p->pDirty; p=p->pDirty){
assert( p->pgno < p->pDirty->pgno );
}
#endif
if( pList->pgno==1 ) pager_write_changecounter(pList);
rc = sqlite3WalFrames(pPager->pWal,
pPager->pageSize, pList, nTruncate, isCommit, syncFlags
);
@@ -2942,9 +2985,8 @@ static int pagerWalFrames(
}
#ifdef SQLITE_CHECK_PAGES
{
PgHdr *p;
for(p=pList; p; p=p->pDirty) pager_set_pagehash(p);
for(p=pList; p; p=p->pDirty){
pager_set_pagehash(p);
}
#endif
@@ -3969,6 +4011,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
char *pData; /* Data to write */
assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
if( pList->pgno==1 ) pager_write_changecounter(pList);
/* Encode the database */
CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
@@ -5489,7 +5532,13 @@ void sqlite3PagerDontWrite(PgHdr *pPg){
/*
** This routine is called to increment the value of the database file
** change-counter, stored as a 4-byte big-endian integer starting at
** byte offset 24 of the pager file.
** byte offset 24 of the pager file. The secondary change counter at
** 92 is also updated, as is the SQLite version number at offset 96.
**
** But this only happens if the pPager->changeCountDone flag is false.
** To avoid excess churning of page 1, the update only happens once.
** See also the pager_write_changecounter() routine that does an
** unconditional update of the change counters.
**
** If the isDirectMode flag is zero, then this is done by calling
** sqlite3PagerWrite() on page 1, then modifying the contents of the
@@ -5530,7 +5579,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
if( !pPager->changeCountDone && pPager->dbSize>0 ){
PgHdr *pPgHdr; /* Reference to page 1 */
u32 change_counter; /* Initial value of change-counter field */
assert( !pPager->tempFile && isOpen(pPager->fd) );
@@ -5548,16 +5596,8 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
}
if( rc==SQLITE_OK ){
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
change_counter++;
put32bits(((char*)pPgHdr->pData)+24, change_counter);
/* Also store the SQLite version number in bytes 96..99 and in
** bytes 92..95 store the change counter for which the version number
** is valid. */
put32bits(((char*)pPgHdr->pData)+92, change_counter);
put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);
/* Actually do the update of the change counter */
pager_write_changecounter(pPgHdr);
/* If running in direct mode, write the contents of page 1 to the file. */
if( DIRECT_MODE ){
@@ -5589,12 +5629,13 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
*/
int sqlite3PagerSync(Pager *pPager){
int rc; /* Return code */
assert( !MEMDB );
if( pPager->noSync ){
rc = SQLITE_OK;
}else{
int rc = SQLITE_OK;
if( !pPager->noSync ){
assert( !MEMDB );
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
}else if( isOpen(pPager->fd) ){
assert( !MEMDB );
sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, (void *)&rc);
}
return rc;
}
@@ -5813,8 +5854,8 @@ int sqlite3PagerCommitPhaseOne(
}
/* Finally, sync the database file. */
if( !pPager->noSync && !noSync ){
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
if( !noSync ){
rc = sqlite3PagerSync(pPager);
}
IOTRACE(("DBSYNC %p\n", pPager))
}
@@ -5926,7 +5967,17 @@ int sqlite3PagerRollback(Pager *pPager){
rc2 = pager_end_transaction(pPager, pPager->setMaster);
if( rc==SQLITE_OK ) rc = rc2;
}else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
int eState = pPager->eState;
rc = pager_end_transaction(pPager, 0);
if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
/* This can happen using journal_mode=off. Move the pager to the error
** state to indicate that the contents of the cache may not be trusted.
** Any active readers will get SQLITE_ABORT.
*/
pPager->errCode = SQLITE_ABORT;
pPager->eState = PAGER_ERROR;
return rc;
}
}else{
rc = pager_playback(pPager, 0);
}
+250 -136
View File
@@ -22,6 +22,38 @@
typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure. A PGroup is an instance of
** the following object.
**
** This page cache implementation works in one of two modes:
**
** (1) Every PCache is the sole member of its own PGroup. There is
** one PGroup per PCache.
**
** (2) There is a single global PGroup that all PCaches are a member
** of.
**
** Mode 1 uses more memory (since PCache instances are not able to rob
** unused pages from other PCaches) but it also operates without a mutex,
** and is therefore often faster. Mode 2 requires a mutex in order to be
** threadsafe, but is able recycle pages more efficient.
**
** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
** PGroup which is the pcache1.grp global variable and its mutex is
** SQLITE_MUTEX_STATIC_LRU.
*/
struct PGroup {
sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
int nMaxPage; /* Sum of nMax for purgeable caches */
int nMinPage; /* Sum of nMin for purgeable caches */
int mxPinned; /* nMaxpage + 10 - nMinPage */
int nCurrentPage; /* Number of purgeable pages allocated */
PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
};
/* Each page cache is an instance of the following object. Every
** open database file (including each in-memory database and each
@@ -35,16 +67,17 @@ struct PCache1 {
/* Cache configuration parameters. Page size (szPage) and the purgeable
** flag (bPurgeable) are set when the cache is created. nMax may be
** modified at any time by a call to the pcache1CacheSize() method.
** The global mutex must be held when accessing nMax.
** The PGroup mutex must be held when accessing nMax.
*/
PGroup *pGroup; /* PGroup this cache belongs to */
int szPage; /* Size of allocated pages in bytes */
int bPurgeable; /* True if cache is purgeable */
unsigned int nMin; /* Minimum number of pages reserved */
unsigned int nMax; /* Configured "cache_size" value */
unsigned int n90pct; /* nMax*9/10 */
/* Hash table of all pages. The following variables may only be accessed
** when the accessor is holding the global mutex (see pcache1EnterMutex()
** and pcache1LeaveMutex()).
** when the accessor is holding the PGroup mutex.
*/
unsigned int nRecyclable; /* Number of pages in the LRU list */
unsigned int nPage; /* Total number of pages in apHash */
@@ -80,21 +113,27 @@ struct PgFreeslot {
** Global data used by this cache.
*/
static SQLITE_WSD struct PCacheGlobal {
sqlite3_mutex *mutex; /* static mutex MUTEX_STATIC_LRU */
PGroup grp; /* The global PGroup for mode (2) */
int nMaxPage; /* Sum of nMaxPage for purgeable caches */
int nMinPage; /* Sum of nMinPage for purgeable caches */
int nCurrentPage; /* Number of purgeable pages allocated */
PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
/* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
int szSlot; /* Size of each free slot */
int nSlot; /* The number of pcache slots */
int nFreeSlot; /* Number of unused pcache slots */
int nReserve; /* Try to keep nFreeSlot above this */
void *pStart, *pEnd; /* Bounds of pagecache malloc range */
PgFreeslot *pFree; /* Free page blocks */
int isInit; /* True if initialized */
/* Variables related to SQLITE_CONFIG_PAGECACHE settings. The
** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
** fixed at sqlite3_initialize() time and do not require mutex protection.
** The nFreeSlot and pFree values do require mutex protection.
*/
int isInit; /* True if initialized */
int szSlot; /* Size of each free slot */
int nSlot; /* The number of pcache slots */
int nReserve; /* Try to keep nFreeSlot above this */
void *pStart, *pEnd; /* Bounds of pagecache malloc range */
/* Above requires no mutex. Use mutex below for variable that follow. */
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
int nFreeSlot; /* Number of unused pcache slots */
PgFreeslot *pFree; /* Free page blocks */
/* The following value requires a mutex to change. We skip the mutex on
** reading because (1) most platforms read a 32-bit integer atomically and
** (2) even if an incorrect value is read, no great harm is done since this
** is really just an optimization. */
int bUnderPressure; /* True if low on PAGECACHE memory */
} pcache1_g;
/*
@@ -120,10 +159,10 @@ static SQLITE_WSD struct PCacheGlobal {
#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
/*
** Macros to enter and leave the global LRU mutex.
** Macros to enter and leave the PCache LRU mutex.
*/
#define pcache1EnterMutex() sqlite3_mutex_enter(pcache1.mutex)
#define pcache1LeaveMutex() sqlite3_mutex_leave(pcache1.mutex)
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
/******************************************************************************/
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
@@ -133,6 +172,9 @@ static SQLITE_WSD struct PCacheGlobal {
** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
** verb to sqlite3_config(). Parameter pBuf points to an allocation large
** enough to contain 'n' buffers of 'sz' bytes each.
**
** This routine is called from sqlite3_initialize() and so it is guaranteed
** to be serialized already. There is no need for further mutexing.
*/
void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
if( pcache1.isInit ){
@@ -143,6 +185,7 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
pcache1.pStart = pBuf;
pcache1.pFree = 0;
pcache1.bUnderPressure = 0;
while( n-- ){
p = (PgFreeslot*)pBuf;
p->pNext = pcache1.pFree;
@@ -158,32 +201,36 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
** such buffer exists or there is no space left in it, this function falls
** back to sqlite3Malloc().
**
** Multiple threads can run this routine at the same time. Global variables
** in pcache1 need to be protected via mutex.
*/
static void *pcache1Alloc(int nByte){
void *p;
assert( sqlite3_mutex_held(pcache1.mutex) );
void *p = 0;
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
if( nByte<=pcache1.szSlot && pcache1.pFree ){
assert( pcache1.isInit );
if( nByte<=pcache1.szSlot ){
sqlite3_mutex_enter(pcache1.mutex);
p = (PgHdr1 *)pcache1.pFree;
pcache1.pFree = pcache1.pFree->pNext;
pcache1.nFreeSlot--;
assert( pcache1.nFreeSlot>=0 );
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
}else{
/* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
** global pcache mutex and unlock the pager-cache object pCache. This is
** so that if the attempt to allocate a new buffer causes the the
** configured soft-heap-limit to be breached, it will be possible to
** reclaim memory from this pager-cache.
if( p ){
pcache1.pFree = pcache1.pFree->pNext;
pcache1.nFreeSlot--;
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
assert( pcache1.nFreeSlot>=0 );
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
}
sqlite3_mutex_leave(pcache1.mutex);
}
if( p==0 ){
/* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get
** it from sqlite3Malloc instead.
*/
pcache1LeaveMutex();
p = sqlite3Malloc(nByte);
pcache1EnterMutex();
if( p ){
int sz = sqlite3MallocSize(p);
sqlite3_mutex_enter(pcache1.mutex);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
sqlite3_mutex_leave(pcache1.mutex);
}
sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
}
@@ -194,22 +241,26 @@ static void *pcache1Alloc(int nByte){
** Free an allocated buffer obtained from pcache1Alloc().
*/
static void pcache1Free(void *p){
assert( sqlite3_mutex_held(pcache1.mutex) );
if( p==0 ) return;
if( p>=pcache1.pStart && p<pcache1.pEnd ){
PgFreeslot *pSlot;
sqlite3_mutex_enter(pcache1.mutex);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
pSlot = (PgFreeslot*)p;
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
pcache1.nFreeSlot++;
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
assert( pcache1.nFreeSlot<=pcache1.nSlot );
sqlite3_mutex_leave(pcache1.mutex);
}else{
int iSize;
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(pcache1.mutex);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
sqlite3_mutex_leave(pcache1.mutex);
sqlite3_free(p);
}
}
@@ -219,7 +270,6 @@ static void pcache1Free(void *p){
** Return the size of a pcache allocation
*/
static int pcache1MemSize(void *p){
assert( sqlite3_mutex_held(pcache1.mutex) );
if( p>=pcache1.pStart && p<pcache1.pEnd ){
return pcache1.szSlot;
}else{
@@ -243,7 +293,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
if( pPg ){
p = PAGE_TO_PGHDR1(pCache, pPg);
if( pCache->bPurgeable ){
pcache1.nCurrentPage++;
pCache->pGroup->nCurrentPage++;
}
}else{
p = 0;
@@ -260,8 +310,9 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
*/
static void pcache1FreePage(PgHdr1 *p){
if( ALWAYS(p) ){
if( p->pCache->bPurgeable ){
pcache1.nCurrentPage--;
PCache1 *pCache = p->pCache;
if( pCache->bPurgeable ){
pCache->pGroup->nCurrentPage--;
}
pcache1Free(PGHDR1_TO_PAGE(p));
}
@@ -273,20 +324,14 @@ static void pcache1FreePage(PgHdr1 *p){
** exists, this function falls back to sqlite3Malloc().
*/
void *sqlite3PageMalloc(int sz){
void *p;
pcache1EnterMutex();
p = pcache1Alloc(sz);
pcache1LeaveMutex();
return p;
return pcache1Alloc(sz);
}
/*
** Free an allocated buffer obtained from sqlite3PageMalloc().
*/
void sqlite3PageFree(void *p){
pcache1EnterMutex();
pcache1Free(p);
pcache1LeaveMutex();
}
@@ -307,9 +352,8 @@ void sqlite3PageFree(void *p){
** the heap even further.
*/
static int pcache1UnderMemoryPressure(PCache1 *pCache){
assert( sqlite3_mutex_held(pcache1.mutex) );
if( pcache1.nSlot && pCache->szPage<=pcache1.szSlot ){
return pcache1.nFreeSlot<pcache1.nReserve;
return pcache1.bUnderPressure;
}else{
return sqlite3HeapNearlyFull();
}
@@ -322,25 +366,25 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){
** This function is used to resize the hash table used by the cache passed
** as the first argument.
**
** The global mutex must be held when this function is called.
** The PCache mutex must be held when this function is called.
*/
static int pcache1ResizeHash(PCache1 *p){
PgHdr1 **apNew;
unsigned int nNew;
unsigned int i;
assert( sqlite3_mutex_held(pcache1.mutex) );
assert( sqlite3_mutex_held(p->pGroup->mutex) );
nNew = p->nHash*2;
if( nNew<256 ){
nNew = 256;
}
pcache1LeaveMutex();
pcache1LeaveMutex(p->pGroup);
if( p->nHash ){ sqlite3BeginBenignMalloc(); }
apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
if( p->nHash ){ sqlite3EndBenignMalloc(); }
pcache1EnterMutex();
pcache1EnterMutex(p->pGroup);
if( apNew ){
memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
for(i=0; i<p->nHash; i++){
@@ -363,25 +407,33 @@ static int pcache1ResizeHash(PCache1 *p){
/*
** This function is used internally to remove the page pPage from the
** global LRU list, if is part of it. If pPage is not part of the global
** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
** LRU list, then this function is a no-op.
**
** The global mutex must be held when this function is called.
** The PGroup mutex must be held when this function is called.
**
** If pPage is NULL then this routine is a no-op.
*/
static void pcache1PinPage(PgHdr1 *pPage){
assert( sqlite3_mutex_held(pcache1.mutex) );
if( pPage && (pPage->pLruNext || pPage==pcache1.pLruTail) ){
PCache1 *pCache;
PGroup *pGroup;
if( pPage==0 ) return;
pCache = pPage->pCache;
pGroup = pCache->pGroup;
assert( sqlite3_mutex_held(pGroup->mutex) );
if( pPage->pLruNext || pPage==pGroup->pLruTail ){
if( pPage->pLruPrev ){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
}
if( pPage->pLruNext ){
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
}
if( pcache1.pLruHead==pPage ){
pcache1.pLruHead = pPage->pLruNext;
if( pGroup->pLruHead==pPage ){
pGroup->pLruHead = pPage->pLruNext;
}
if( pcache1.pLruTail==pPage ){
pcache1.pLruTail = pPage->pLruPrev;
if( pGroup->pLruTail==pPage ){
pGroup->pLruTail = pPage->pLruPrev;
}
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
@@ -394,13 +446,14 @@ static void pcache1PinPage(PgHdr1 *pPage){
** Remove the page supplied as an argument from the hash table
** (PCache1.apHash structure) that it is currently stored in.
**
** The global mutex must be held when this function is called.
** The PGroup mutex must be held when this function is called.
*/
static void pcache1RemoveFromHash(PgHdr1 *pPage){
unsigned int h;
PCache1 *pCache = pPage->pCache;
PgHdr1 **pp;
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
h = pPage->iKey % pCache->nHash;
for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
*pp = (*pp)->pNext;
@@ -409,13 +462,14 @@ static void pcache1RemoveFromHash(PgHdr1 *pPage){
}
/*
** If there are currently more than pcache.nMaxPage pages allocated, try
** to recycle pages to reduce the number allocated to pcache.nMaxPage.
** If there are currently more than nMaxPage pages allocated, try
** to recycle pages to reduce the number allocated to nMaxPage.
*/
static void pcache1EnforceMaxPage(void){
assert( sqlite3_mutex_held(pcache1.mutex) );
while( pcache1.nCurrentPage>pcache1.nMaxPage && pcache1.pLruTail ){
PgHdr1 *p = pcache1.pLruTail;
static void pcache1EnforceMaxPage(PGroup *pGroup){
assert( sqlite3_mutex_held(pGroup->mutex) );
while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
PgHdr1 *p = pGroup->pLruTail;
assert( p->pCache->pGroup==pGroup );
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
@@ -427,15 +481,15 @@ static void pcache1EnforceMaxPage(void){
** greater than or equal to iLimit. Any pinned pages that meet this
** criteria are unpinned before they are discarded.
**
** The global mutex must be held when this function is called.
** The PCache mutex must be held when this function is called.
*/
static void pcache1TruncateUnsafe(
PCache1 *pCache,
unsigned int iLimit
PCache1 *pCache, /* The cache to truncate */
unsigned int iLimit /* Drop pages with this pgno or larger */
){
TESTONLY( unsigned int nPage = 0; ) /* Used to assert pCache->nPage is correct */
TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */
unsigned int h;
assert( sqlite3_mutex_held(pcache1.mutex) );
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
for(h=0; h<pCache->nHash; h++){
PgHdr1 **pp = &pCache->apHash[h];
PgHdr1 *pPage;
@@ -465,8 +519,10 @@ static int pcache1Init(void *NotUsed){
assert( pcache1.isInit==0 );
memset(&pcache1, 0, sizeof(pcache1));
if( sqlite3GlobalConfig.bCoreMutex ){
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
}
pcache1.grp.mxPinned = 10;
pcache1.isInit = 1;
return SQLITE_OK;
}
@@ -488,18 +544,47 @@ static void pcache1Shutdown(void *NotUsed){
** Allocate a new cache.
*/
static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
PCache1 *pCache;
PCache1 *pCache; /* The newly created page cache */
PGroup *pGroup; /* The group the new page cache will belong to */
int sz; /* Bytes of memory required to allocate the new cache */
pCache = (PCache1 *)sqlite3_malloc(sizeof(PCache1));
/*
** The seperateCache variable is true if each PCache has its own private
** PGroup. In other words, separateCache is true for mode (1) where no
** mutexing is required.
**
** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
**
** * Always use a unified cache in single-threaded applications
**
** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off)
** use separate caches (mode-1)
*/
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
const int separateCache = 0;
#else
int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
#endif
sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
pCache = (PCache1 *)sqlite3_malloc(sz);
if( pCache ){
memset(pCache, 0, sizeof(PCache1));
memset(pCache, 0, sz);
if( separateCache ){
pGroup = (PGroup*)&pCache[1];
pGroup->mxPinned = 10;
}else{
pGroup = &pcache1_g.grp;
}
pCache->pGroup = pGroup;
pCache->szPage = szPage;
pCache->bPurgeable = (bPurgeable ? 1 : 0);
if( bPurgeable ){
pCache->nMin = 10;
pcache1EnterMutex();
pcache1.nMinPage += pCache->nMin;
pcache1LeaveMutex();
pcache1EnterMutex(pGroup);
pGroup->nMinPage += pCache->nMin;
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pcache1LeaveMutex(pGroup);
}
}
return (sqlite3_pcache *)pCache;
@@ -513,11 +598,14 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
PCache1 *pCache = (PCache1 *)p;
if( pCache->bPurgeable ){
pcache1EnterMutex();
pcache1.nMaxPage += (nMax - pCache->nMax);
PGroup *pGroup = pCache->pGroup;
pcache1EnterMutex(pGroup);
pGroup->nMaxPage += (nMax - pCache->nMax);
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pCache->nMax = nMax;
pcache1EnforceMaxPage();
pcache1LeaveMutex();
pCache->n90pct = pCache->nMax*9/10;
pcache1EnforceMaxPage(pGroup);
pcache1LeaveMutex(pGroup);
}
}
@@ -526,9 +614,10 @@ static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
*/
static int pcache1Pagecount(sqlite3_pcache *p){
int n;
pcache1EnterMutex();
n = ((PCache1 *)p)->nPage;
pcache1LeaveMutex();
PCache1 *pCache = (PCache1*)p;
pcache1EnterMutex(pCache->pGroup);
n = pCache->nPage;
pcache1LeaveMutex(pCache->pGroup);
return n;
}
@@ -587,30 +676,49 @@ static int pcache1Pagecount(sqlite3_pcache *p){
** 5. Otherwise, allocate and return a new page buffer.
*/
static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
unsigned int nPinned;
int nPinned;
PCache1 *pCache = (PCache1 *)p;
PGroup *pGroup;
PgHdr1 *pPage = 0;
assert( pCache->bPurgeable || createFlag!=1 );
pcache1EnterMutex();
if( createFlag==1 ) sqlite3BeginBenignMalloc();
assert( pCache->bPurgeable || pCache->nMin==0 );
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
assert( pCache->nMin==0 || pCache->bPurgeable );
pcache1EnterMutex(pGroup = pCache->pGroup);
/* Search the hash table for an existing entry. */
/* Step 1: Search the hash table for an existing entry. */
if( pCache->nHash>0 ){
unsigned int h = iKey % pCache->nHash;
for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
}
/* Step 2: Abort if no existing page is found and createFlag is 0 */
if( pPage || createFlag==0 ){
pcache1PinPage(pPage);
goto fetch_out;
}
/* Step 3 of header comment. */
/* The pGroup local variable will normally be initialized by the
** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined,
** then pcache1EnterMutex() is a no-op, so we have to initialize the
** local variable here. Delaying the initialization of pGroup is an
** optimization: The common case is to exit the module before reaching
** this point.
*/
#ifdef SQLITE_MUTEX_OMIT
pGroup = pCache->pGroup;
#endif
/* Step 3: Abort if createFlag is 1 but the cache is nearly full */
nPinned = pCache->nPage - pCache->nRecyclable;
assert( nPinned>=0 );
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
assert( pCache->n90pct == pCache->nMax*9/10 );
if( createFlag==1 && (
nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage)
|| nPinned>=(pCache->nMax * 9 / 10)
nPinned>=pGroup->mxPinned
|| nPinned>=(int)pCache->n90pct
|| pcache1UnderMemoryPressure(pCache)
)){
goto fetch_out;
@@ -620,20 +728,22 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
goto fetch_out;
}
/* Step 4. Try to recycle a page buffer if appropriate. */
if( pCache->bPurgeable && pcache1.pLruTail && (
/* Step 4. Try to recycle a page. */
if( pCache->bPurgeable && pGroup->pLruTail && (
(pCache->nPage+1>=pCache->nMax)
|| pcache1.nCurrentPage>=pcache1.nMaxPage
|| pGroup->nCurrentPage>=pGroup->nMaxPage
|| pcache1UnderMemoryPressure(pCache)
)){
pPage = pcache1.pLruTail;
PCache1 *pOtherCache;
pPage = pGroup->pLruTail;
pcache1RemoveFromHash(pPage);
pcache1PinPage(pPage);
if( pPage->pCache->szPage!=pCache->szPage ){
if( (pOtherCache = pPage->pCache)->szPage!=pCache->szPage ){
pcache1FreePage(pPage);
pPage = 0;
}else{
pcache1.nCurrentPage -= (pPage->pCache->bPurgeable - pCache->bPurgeable);
pGroup->nCurrentPage -=
(pOtherCache->bPurgeable - pCache->bPurgeable);
}
}
@@ -641,7 +751,11 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
** attempt to allocate a new one.
*/
if( !pPage ){
if( createFlag==1 ) sqlite3BeginBenignMalloc();
pcache1LeaveMutex(pGroup);
pPage = pcache1AllocPage(pCache);
pcache1EnterMutex(pGroup);
if( createFlag==1 ) sqlite3EndBenignMalloc();
}
if( pPage ){
@@ -660,8 +774,7 @@ fetch_out:
if( pPage && iKey>pCache->iMaxKey ){
pCache->iMaxKey = iKey;
}
if( createFlag==1 ) sqlite3EndBenignMalloc();
pcache1LeaveMutex();
pcache1LeaveMutex(pGroup);
return (pPage ? PGHDR1_TO_PAGE(pPage) : 0);
}
@@ -674,37 +787,34 @@ fetch_out:
static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
PGroup *pGroup = pCache->pGroup;
assert( pPage->pCache==pCache );
pcache1EnterMutex();
pcache1EnterMutex(pGroup);
/* It is an error to call this function if the page is already
** part of the global LRU list.
** part of the PGroup LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
assert( pcache1.pLruHead!=pPage && pcache1.pLruTail!=pPage );
assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
if( reuseUnlikely || pcache1.nCurrentPage>pcache1.nMaxPage ){
if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
pcache1RemoveFromHash(pPage);
pcache1FreePage(pPage);
}else{
/* Add the page to the global LRU list. Normally, the page is added to
** the head of the list (last page to be recycled). However, if the
** reuseUnlikely flag passed to this function is true, the page is added
** to the tail of the list (first page to be recycled).
*/
if( pcache1.pLruHead ){
pcache1.pLruHead->pLruPrev = pPage;
pPage->pLruNext = pcache1.pLruHead;
pcache1.pLruHead = pPage;
/* Add the page to the PGroup LRU list. */
if( pGroup->pLruHead ){
pGroup->pLruHead->pLruPrev = pPage;
pPage->pLruNext = pGroup->pLruHead;
pGroup->pLruHead = pPage;
}else{
pcache1.pLruTail = pPage;
pcache1.pLruHead = pPage;
pGroup->pLruTail = pPage;
pGroup->pLruHead = pPage;
}
pCache->nRecyclable++;
}
pcache1LeaveMutex();
pcache1LeaveMutex(pCache->pGroup);
}
/*
@@ -723,7 +833,7 @@ static void pcache1Rekey(
assert( pPage->iKey==iOld );
assert( pPage->pCache==pCache );
pcache1EnterMutex();
pcache1EnterMutex(pCache->pGroup);
h = iOld%pCache->nHash;
pp = &pCache->apHash[h];
@@ -740,7 +850,7 @@ static void pcache1Rekey(
pCache->iMaxKey = iNew;
}
pcache1LeaveMutex();
pcache1LeaveMutex(pCache->pGroup);
}
/*
@@ -752,12 +862,12 @@ static void pcache1Rekey(
*/
static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
PCache1 *pCache = (PCache1 *)p;
pcache1EnterMutex();
pcache1EnterMutex(pCache->pGroup);
if( iLimit<=pCache->iMaxKey ){
pcache1TruncateUnsafe(pCache, iLimit);
pCache->iMaxKey = iLimit-1;
}
pcache1LeaveMutex();
pcache1LeaveMutex(pCache->pGroup);
}
/*
@@ -767,13 +877,15 @@ static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
*/
static void pcache1Destroy(sqlite3_pcache *p){
PCache1 *pCache = (PCache1 *)p;
PGroup *pGroup = pCache->pGroup;
assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
pcache1EnterMutex();
pcache1EnterMutex(pGroup);
pcache1TruncateUnsafe(pCache, 0);
pcache1.nMaxPage -= pCache->nMax;
pcache1.nMinPage -= pCache->nMin;
pcache1EnforceMaxPage();
pcache1LeaveMutex();
pGroup->nMaxPage -= pCache->nMax;
pGroup->nMinPage -= pCache->nMin;
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pcache1EnforceMaxPage(pGroup);
pcache1LeaveMutex(pGroup);
sqlite3_free(pCache->apHash);
sqlite3_free(pCache);
}
@@ -812,16 +924,18 @@ void sqlite3PCacheSetDefault(void){
*/
int sqlite3PcacheReleaseMemory(int nReq){
int nFree = 0;
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
assert( sqlite3_mutex_notheld(pcache1.mutex) );
if( pcache1.pStart==0 ){
PgHdr1 *p;
pcache1EnterMutex();
while( (nReq<0 || nFree<nReq) && ((p=pcache1.pLruTail)!=0) ){
pcache1EnterMutex(&pcache1.grp);
while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
nFree += pcache1MemSize(PGHDR1_TO_PAGE(p));
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
}
pcache1LeaveMutex();
pcache1LeaveMutex(&pcache1.grp);
}
return nFree;
}
@@ -840,12 +954,12 @@ void sqlite3PcacheStats(
){
PgHdr1 *p;
int nRecyclable = 0;
for(p=pcache1.pLruHead; p; p=p->pLruNext){
for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
nRecyclable++;
}
*pnCurrent = pcache1.nCurrentPage;
*pnMax = pcache1.nMaxPage;
*pnMin = pcache1.nMinPage;
*pnCurrent = pcache1.grp.nCurrentPage;
*pnMax = pcache1.grp.nMaxPage;
*pnMin = pcache1.grp.nMinPage;
*pnRecyclable = nRecyclable;
}
#endif
+3 -3
View File
@@ -784,7 +784,7 @@ int sqlite3_prepare_v2(
*/
static int sqlite3Prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
@@ -834,7 +834,7 @@ static int sqlite3Prepare16(
*/
int sqlite3_prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
@@ -846,7 +846,7 @@ int sqlite3_prepare16(
}
int sqlite3_prepare16_v2(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
+20 -13
View File
@@ -763,6 +763,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
return;
}
}else{
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
i64 szNew = p->nChar;
szNew += N + 1;
if( szNew > p->mxAlloc ){
@@ -773,13 +774,12 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
p->nAlloc = (int)szNew;
}
if( p->useMalloc==1 ){
zNew = sqlite3DbMallocRaw(p->db, p->nAlloc );
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
zNew = sqlite3_malloc(p->nAlloc);
zNew = sqlite3_realloc(zOld, p->nAlloc);
}
if( zNew ){
memcpy(zNew, p->zText, p->nChar);
sqlite3StrAccumReset(p);
if( zOld==0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
p->mallocFailed = 1;
@@ -934,21 +934,28 @@ char *sqlite3_mprintf(const char *zFormat, ...){
** current locale settings. This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
**
** Oops: The first two arguments of sqlite3_snprintf() are backwards
** from the snprintf() standard. Unfortunately, it is too late to change
** this without breaking compatibility, so we just have to live with the
** mistake.
**
** sqlite3_vsnprintf() is the varargs version.
*/
char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
StrAccum acc;
if( n<=0 ) return zBuf;
sqlite3StrAccumInit(&acc, zBuf, n, 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
return sqlite3StrAccumFinish(&acc);
}
char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
va_list ap;
StrAccum acc;
if( n<=0 ){
return zBuf;
}
sqlite3StrAccumInit(&acc, zBuf, n, 0);
acc.useMalloc = 0;
va_start(ap,zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
va_end(ap);
z = sqlite3StrAccumFinish(&acc);
return z;
}
+32 -7
View File
@@ -38,10 +38,14 @@
# include <unistd.h>
#endif
#ifdef HAVE_EDITLINE
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
#else
#endif
#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
# define readline(p) local_getline(p,stdin)
# define add_history(X)
# define read_history(X)
@@ -980,7 +984,7 @@ static int display_stats(
fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Allocations: %d (max %d)\n", iCur, iHiwtr);
fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.
** iHiwtr = iCur = -1;
@@ -1019,6 +1023,12 @@ static int display_stats(
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr);
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr);
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr);
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur);
@@ -2538,6 +2548,7 @@ int main(int argc, char **argv){
/* Do an initial pass through the command-line argument to locate
** the name of the database file, the name of the initialization file,
** the size of the alternative malloc heap,
** and the first command to execute.
*/
for(i=1; i<argc-1; i++){
@@ -2556,6 +2567,22 @@ int main(int argc, char **argv){
*/
}else if( strcmp(argv[i],"-batch")==0 ){
stdin_is_interactive = 0;
}else if( strcmp(argv[i],"-heap")==0 ){
int j, c;
const char *zSize;
sqlite3_int64 szHeap;
zSize = argv[++i];
szHeap = atoi(zSize);
for(j=0; (c = zSize[j])!=0; j++){
if( c=='M' ){ szHeap *= 1000000; break; }
if( c=='K' ){ szHeap *= 1000; break; }
if( c=='G' ){ szHeap *= 1000000000; break; }
}
if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
}
}
if( i<argc ){
@@ -2662,6 +2689,8 @@ int main(int argc, char **argv){
stdin_is_interactive = 1;
}else if( strcmp(z,"-batch")==0 ){
stdin_is_interactive = 0;
}else if( strcmp(z,"-heap")==0 ){
i++;
}else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
usage(1);
}else{
@@ -2723,11 +2752,7 @@ int main(int argc, char **argv){
}
set_table_name(&data, 0);
if( data.db ){
if( sqlite3_close(data.db)!=SQLITE_OK ){
fprintf(stderr,"Error: cannot close database \"%s\"\n",
sqlite3_errmsg(db));
rc++;
}
sqlite3_close(data.db);
}
return rc;
}
+115 -42
View File
@@ -385,7 +385,7 @@ int sqlite3_exec(
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
@@ -617,7 +617,9 @@ struct sqlite3_file {
** core reserves all opcodes less than 100 for its own use.
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
** Applications that define a custom xFileControl method should use opcodes
** greater than 100 to avoid conflicts.
** greater than 100 to avoid conflicts. VFS implementations should
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
** recognize.
**
** The xSectorSize() method returns the sector size of the
** device that underlies the file. The sector size is the
@@ -710,6 +712,21 @@ struct sqlite3_io_methods {
** for the nominated database. Allocating database file space in large
** chunks (say 1MB at a time), may reduce file-system fragmentation and
** improve performance on some systems.
**
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
** to the [sqlite3_file] object associated with a particular database
** connection. See the [sqlite3_file_control()] documentation for
** additional information.
**
** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
** SQLite and sent to all VFSes in place of a call to the xSync method
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specilized VFSes
** that do require it.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2
@@ -718,6 +735,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_SIZE_HINT 5
#define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7
#define SQLITE_FCNTL_SYNC_OMITTED 8
/*
@@ -1837,7 +1855,7 @@ void sqlite3_free_table(char **result);
** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
** memory to hold the resulting string.
**
** ^(In sqlite3_snprintf() routine is similar to "snprintf()" from
** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
** the standard C library. The result is written into the
** buffer supplied as the second parameter whose size is given by
** the first parameter. Note that the order of the
@@ -1856,6 +1874,8 @@ void sqlite3_free_table(char **result);
** the zero terminator. So the longest string that can be completely
** written will be n-1 characters.
**
** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
**
** These routines all implement some additional formatting
** options that are useful for constructing SQL statements.
** All of the usual printf() formatting options apply. In addition, there
@@ -1919,6 +1939,7 @@ void sqlite3_free_table(char **result);
char *sqlite3_mprintf(const char*,...);
char *sqlite3_vmprintf(const char*, va_list);
char *sqlite3_snprintf(int,char*,const char*, ...);
char *sqlite3_vsnprintf(int,char*,const char*, va_list);
/*
** CAPI3REF: Memory Allocation Subsystem
@@ -2296,7 +2317,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** case the database must already exist, otherwise an error is returned.</dd>)^
**
** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
** <dd>The database is opened for reading and writing, and is creates it if
** <dd>The database is opened for reading and writing, and is created if
** it does not already exist. This is the behavior that is always used for
** sqlite3_open() and sqlite3_open16().</dd>)^
** </dl>
@@ -2645,14 +2666,31 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
**
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** the [prepared statement] X is [SELECT] statement and false (zero) if
** X is an [INSERT], [UPDATE], [DELETE], CREATE, DROP, [ANALYZE],
** [ALTER], or [REINDEX] statement.
** If X is a NULL pointer or any other kind of statement, including but
** not limited to [ATTACH], [DETACH], [COMMIT], [ROLLBACK], [RELEASE],
** [SAVEPOINT], [PRAGMA], or [VACUUM] the result of sqlite3_stmt_readonly(X) is
** undefined.
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
** the content of the database file.
**
** Note that [application-defined SQL functions] or
** [virtual tables] might change the database indirectly as a side effect.
** ^(For example, if an application defines a function "eval()" that
** calls [sqlite3_exec()], then the following SQL statement would
** change the database file through side-effects:
**
** <blockquote><pre>
** SELECT eval('DELETE FROM t1') FROM t2;
** </pre></blockquote>
**
** But because the [SELECT] statement does not change the database file
** directly, sqlite3_stmt_readonly() would still return true.)^
**
** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
** since the statements themselves do not actually modify the database but
** rather they control the timing of when other statements modify the
** database. ^The [ATTACH] and [DETACH] statements also cause
** sqlite3_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -3046,13 +3084,17 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** be the case that the same database connection is being used by two or
** more threads at the same moment in time.
**
** For all versions of SQLite up to and including 3.6.23.1, it was required
** after sqlite3_step() returned anything other than [SQLITE_ROW] that
** [sqlite3_reset()] be called before any subsequent invocation of
** sqlite3_step(). Failure to invoke [sqlite3_reset()] in this way would
** result in an [SQLITE_MISUSE] return from sqlite3_step(). But after
** version 3.6.23.1, sqlite3_step() began calling [sqlite3_reset()]
** automatically in this circumstance rather than returning [SQLITE_MISUSE].
** For all versions of SQLite up to and including 3.6.23.1, a call to
** [sqlite3_reset()] was required after sqlite3_step() returned anything
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
** break because any application that ever receives an SQLITE_MISUSE error
** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
** can be used to restore the legacy behavior.
**
** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
** API always returns a generic error code, [SQLITE_ERROR], following any
@@ -3389,7 +3431,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
** ^The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are
** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
** pointers to C-language functions that implement the SQL function or
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
** callback only; NULL pointers must be passed as the xStep and xFinal
@@ -3398,7 +3440,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** SQL function or aggregate, pass NULL poiners for all three function
** callbacks.
**
** ^(If the tenth parameter to sqlite3_create_function_v2() is not NULL,
** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
** then it is destructor for the application data pointer.
** The destructor is invoked when the function is deleted, either by being
** overloaded or when the database connection closes.)^
@@ -3502,7 +3544,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void
** The xFunc (for scalar functions) or xStep (for aggregates) parameters
** to [sqlite3_create_function()] and [sqlite3_create_function16()]
** define callbacks that implement the SQL functions and aggregates.
** The 4th parameter to these callbacks is an array of pointers to
** The 3rd parameter to these callbacks is an array of pointers to
** [protected sqlite3_value] objects. There is one [sqlite3_value] object for
** each parameter to the SQL function. These routines are used to
** extract values from the [sqlite3_value] objects.
@@ -5230,7 +5272,8 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
/*
** CAPI3REF: Retrieve the mutex for a database connection
@@ -5381,7 +5424,8 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
** <dd>This parameter records the number of separate memory allocations.</dd>)^
** <dd>This parameter records the number of separate memory allocations
** currently checked out.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
@@ -5487,6 +5531,28 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.
** checked out.</dd>)^
**
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
** the current value is always zero.
** checked out.</dd>)^
**
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
** the current value is always zero.
** checked out.</dd>)^
**
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
@@ -5509,11 +5575,14 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
#define SQLITE_DBSTATUS_CACHE_USED 1
#define SQLITE_DBSTATUS_SCHEMA_USED 2
#define SQLITE_DBSTATUS_STMT_USED 3
#define SQLITE_DBSTATUS_MAX 3 /* Largest defined DBSTATUS */
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
#define SQLITE_DBSTATUS_CACHE_USED 1
#define SQLITE_DBSTATUS_SCHEMA_USED 2
#define SQLITE_DBSTATUS_STMT_USED 3
#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
#define SQLITE_DBSTATUS_MAX 6 /* Largest defined DBSTATUS */
/*
@@ -5641,11 +5710,13 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** first parameter, szPage, is the size in bytes of the pages that must
** be allocated by the cache. ^szPage will not be a power of two. ^szPage
** will the page size of the database file that is to be cached plus an
** increment (here called "R") of about 100 or 200. SQLite will use the
** increment (here called "R") of less than 250. SQLite will use the
** extra R bytes on each page to store metadata about the underlying
** database page on disk. The value of R depends
** on the SQLite version, the target platform, and how SQLite was compiled.
** ^R is constant for a particular build of SQLite. ^The second argument to
** ^(R is constant for a particular build of SQLite. Except, there are two
** distinct values of R when SQLite is compiled with the proprietary
** ZIPVFS extension.)^ ^The second argument to
** xCreate(), bPurgeable, is true if the cache being created will
** be used to cache database pages of a file stored on disk, or
** false if it is used for an in-memory database. The cache implementation
@@ -5677,7 +5748,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** If the requested page is already in the page cache, then the page cache
** implementation must return a pointer to the page buffer with its content
** intact. If the requested page is not already in the cache, then the
** behavior of the cache implementation should use the value of the createFlag
** cache implementation should use the value of the createFlag
** parameter to help it determined what action to take:
**
** <table border=1 width=85% align=center>
@@ -5761,11 +5832,12 @@ typedef struct sqlite3_backup sqlite3_backup;
**
** See Also: [Using the SQLite Online Backup API]
**
** ^Exclusive access is required to the destination database for the
** duration of the operation. ^However the source database is only
** read-locked while it is actually being read; it is not locked
** continuously for the entire backup operation. ^Thus, the backup may be
** performed on a live source database without preventing other users from
** ^SQLite holds a write transaction open on the destination database file
** for the duration of the backup operation.
** ^The source database is read-locked only while it is being read;
** it is not locked continuously for the entire backup operation.
** ^Thus, the backup may be performed on a live source database without
** preventing other database connections from
** reading or writing to the source database while the backup is underway.
**
** ^(To perform a backup operation:
@@ -5792,11 +5864,11 @@ typedef struct sqlite3_backup sqlite3_backup;
** sqlite3_backup_init(D,N,S,M) identify the [database connection]
** and database name of the source database, respectively.
** ^The source and destination [database connections] (parameters S and D)
** must be different or else sqlite3_backup_init(D,N,S,M) will file with
** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
** an error.
**
** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
** returned and an error code and error message are store3d in the
** returned and an error code and error message are stored in the
** destination [database connection] D.
** ^The error code and message for the failed call to sqlite3_backup_init()
** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or
@@ -5813,7 +5885,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** the source and destination databases specified by [sqlite3_backup] object B.
** ^If N is negative, all remaining source pages are copied.
** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
** are still more pages to be copied, then the function resturns [SQLITE_OK].
** are still more pages to be copied, then the function returns [SQLITE_OK].
** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
** from source to destination, then it returns [SQLITE_DONE].
** ^If an error occurs while running sqlite3_backup_step(B,N),
@@ -5827,7 +5899,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** <li> the destination database was opened read-only, or
** <li> the destination database is using write-ahead-log journaling
** and the destination and source page sizes differ, or
** <li> The destination database is an in-memory database and the
** <li> the destination database is an in-memory database and the
** destination and source page sizes differ.
** </ol>)^
**
@@ -6158,7 +6230,8 @@ void *sqlite3_wal_hook(
** from SQL.
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 pages. The use of this interface
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages. The use of this interface
** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
+2
View File
@@ -737,6 +737,7 @@ struct Lookaside {
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
int nOut; /* Number of buffers currently checked out */
int mxOut; /* Highwater mark for nOut */
int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
LookasideSlot *pFree; /* List of available buffers */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
@@ -815,6 +816,7 @@ struct sqlite3 {
struct Vdbe *pVdbe; /* List of active virtual machines */
int activeVdbeCnt; /* Number of VDBEs currently executing */
int writeVdbeCnt; /* Number of active VDBEs that are writing */
int vdbeExecCnt; /* Number of nested calls to VdbeExec() */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
void (*xProfile)(void*,const char*,u64); /* Profiling function */
+16
View File
@@ -116,6 +116,22 @@ int sqlite3_db_status(
break;
}
case SQLITE_DBSTATUS_LOOKASIDE_HIT:
case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
*pCurrent = 0;
*pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
if( resetFlag ){
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
}
break;
}
/*
** Return an approximation for the amount of memory currently used
** by all pagers associated with the given database connection. The
+5
View File
@@ -3582,6 +3582,11 @@ static void init_all(Tcl_Interp *interp){
extern int Sqlitemultiplex_Init(Tcl_Interp*);
extern int SqliteSuperlock_Init(Tcl_Interp*);
#ifdef SQLITE_ENABLE_ZIPVFS
extern int Zipvfs_Init(Tcl_Interp*);
Zipvfs_Init(interp);
#endif
Sqliteconfig_Init(interp);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
+3 -3
View File
@@ -4801,13 +4801,13 @@ static int file_control_test(
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
rc = sqlite3_file_control(db, 0, 0, &iArg);
assert( rc==SQLITE_ERROR );
assert( rc==SQLITE_NOTFOUND );
rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
assert( rc==SQLITE_ERROR );
rc = sqlite3_file_control(db, "main", -1, &iArg);
assert( rc==SQLITE_ERROR );
assert( rc==SQLITE_NOTFOUND );
rc = sqlite3_file_control(db, "temp", -1, &iArg);
assert( rc==SQLITE_ERROR );
assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
return TCL_OK;
}
+6
View File
@@ -133,6 +133,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "autoindex", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_AUTORESET
Tcl_SetVar2(interp, "sqlite_options", "autoreset", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "autoreset", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_AUTOVACUUM
Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
#else
+9 -4
View File
@@ -1290,10 +1290,13 @@ static int test_db_status(
const char *zName;
int op;
} aOp[] = {
{ "SQLITE_DBSTATUS_LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
{ "SQLITE_DBSTATUS_CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
{ "SQLITE_DBSTATUS_SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
{ "SQLITE_DBSTATUS_STMT_USED", SQLITE_DBSTATUS_STMT_USED }
{ "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
{ "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
{ "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
{ "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
{ "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
{ "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
{ "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }
};
Tcl_Obj *pResult;
if( objc!=4 ){
@@ -1302,6 +1305,8 @@ static int test_db_status(
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
zOpName = Tcl_GetString(objv[2]);
if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7;
if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9;
for(i=0; i<ArraySize(aOp); i++){
if( strcmp(aOp[i].zName, zOpName)==0 ){
op = aOp[i].op;
+1 -1
View File
@@ -247,7 +247,7 @@ static int test_read_mutex_counters(
int ii;
char *aName[8] = {
"fast", "recursive", "static_master", "static_mem",
"static_open", "static_prng", "static_lru", "static_lru2"
"static_open", "static_prng", "static_lru", "static_pmem"
};
if( objc!=1 ){
+14
View File
@@ -31,6 +31,20 @@
#include <string.h>
#include <assert.h>
/*
** For an build without mutexes, no-op the mutex calls.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)
#define sqlite3_mutex_try(X) SQLITE_OK
#define sqlite3_mutex_leave(X)
#define sqlite3_mutex_held(X) ((void)(X),1)
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#endif /* SQLITE_THREADSAFE==0 */
/************************ Object Definitions ******************************/
/* Forward declaration of all object types */
+1
View File
@@ -540,6 +540,7 @@ static int tvfsOpen(
pFd->zFilename = zName;
pFd->pVfs = pVfs;
pFd->pReal = (sqlite3_file *)&pFd[1];
memset(pTestfile, 0, sizeof(TestvfsFile));
pTestfile->pFd = pFd;
/* Evaluate the Tcl script:
+33 -57
View File
@@ -39,16 +39,14 @@ typedef unsigned char Bool;
**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
**
** If the VdbeCursor.isTriggerRow flag is set it means that this cursor is
** really a single row that represents the NEW or OLD pseudo-table of
** a row trigger. The data for the row is stored in VdbeCursor.pData and
** the rowid is in VdbeCursor.iKey.
*/
struct VdbeCursor {
BtCursor *pCursor; /* The cursor structure of the backend */
Btree *pBt; /* Separate file holding temporary table */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int iDb; /* Index of cursor database in db->aDb[] (or -1) */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
int pseudoTableReg; /* Register holding pseudotable content. */
int nField; /* Number of fields in the header */
Bool zeroed; /* True if zeroed out and ready for reuse */
Bool rowidIsValid; /* True if lastRowid is valid */
Bool atFirst; /* True if pointing to first entry */
@@ -58,14 +56,11 @@ struct VdbeCursor {
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
Btree *pBt; /* Separate file holding temporary table */
int pseudoTableReg; /* Register holding pseudotable content. */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
** OP_IsUnique opcode on this cursor. */
@@ -137,25 +132,19 @@ struct VdbeFrame {
/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value. A value (and therefore Mem structure)
** has the following properties:
**
** Each value has a manifest type. The manifest type of the value stored
** in a Mem struct is returned by the MemType(Mem*) macro. The type is
** one of SQLITE_NULL, SQLITE_INTEGER, SQLITE_REAL, SQLITE_TEXT or
** SQLITE_BLOB.
** integer etc.) of the same value.
*/
struct Mem {
sqlite3 *db; /* The associated database connection */
char *z; /* String or BLOB value */
double r; /* Real value */
union {
i64 i; /* Integer value. */
i64 i; /* Integer value used when MEM_Int is set in flags */
int nZero; /* Used when bit MEM_Zero is set in flags */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
} u;
double r; /* Real value */
sqlite3 *db; /* The associated database connection */
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
@@ -179,9 +168,6 @@ struct Mem {
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
**
** Multiple of these values can appear in Mem.flags. But only one
** at a time can appear in Mem.type.
*/
#define MEM_Null 0x0001 /* Value is NULL */
#define MEM_Str 0x0002 /* Value is a string */
@@ -264,23 +250,11 @@ struct sqlite3_context {
CollSeq *pColl; /* Collating sequence */
};
/*
** A Set structure is used for quick testing to see if a value
** is part of a small set. Sets are used to implement code like
** this:
** x.y IN ('hi','hoo','hum')
*/
typedef struct Set Set;
struct Set {
Hash hash; /* A set is just a hash table */
HashElem *prev; /* Previously accessed hash elemen */
};
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile()
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
** is really a pointer to an instance of this structure.
**
** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
@@ -293,31 +267,31 @@ struct Set {
*/
struct Vdbe {
sqlite3 *db; /* The database connection that owns this statement */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
int nOp; /* Number of instructions in the program */
int nOpAlloc; /* Number of slots allocated for aOp[] */
Op *aOp; /* Space to hold the virtual machine's program */
int nLabel; /* Number of labels used */
int nLabelAlloc; /* Number of slots allocated in aLabel[] */
int *aLabel; /* Space to hold the labels */
Mem *aMem; /* The memory locations */
Mem **apArg; /* Arguments to currently executing user function */
Mem *aColName; /* Column names to return */
Mem *pResultSet; /* Pointer to an array of results */
int nMem; /* Number of memory locations currently allocated */
int nOp; /* Number of instructions in the program */
int nOpAlloc; /* Number of slots allocated for aOp[] */
int nLabel; /* Number of labels used */
int nLabelAlloc; /* Number of slots allocated in aLabel[] */
int *aLabel; /* Space to hold the labels */
u16 nResColumn; /* Number of columns in one row of the result set */
u16 nCursor; /* Number of slots in apCsr[] */
u32 magic; /* Magic number for sanity checking */
char *zErrMsg; /* Error message written here */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
u8 errorAction; /* Recovery action to do in case of an error */
u8 okVar; /* True if azVar[] has been initialized */
ynVar nVar; /* Number of entries in aVar[] */
Mem *aVar; /* Values for the OP_Variable opcode. */
char **azVar; /* Name of variables */
u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
ynVar nVar; /* Number of entries in aVar[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
char *zErrMsg; /* Error message written here */
u8 errorAction; /* Recovery action to do in case of an error */
u8 okVar; /* True if azVar[] has been initialized */
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 expired; /* True if the VM needs to be recompiled */
@@ -329,14 +303,16 @@ struct Vdbe {
u8 isPrepareV2; /* True if prepared with prepare_v2() */
int nChange; /* Number of db changes made since last reset */
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
i64 startTime; /* Time when query started - used for profiling */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
int iStatement; /* Statement number (or 0 if has not opened stmt) */
int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
int iStatement; /* Statement number (or 0 if has not opened stmt) */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
#ifdef SQLITE_DEBUG
FILE *trace; /* Write an execution trace here, if not NULL */
#endif
+25 -4
View File
@@ -345,11 +345,30 @@ static int sqlite3Step(Vdbe *p){
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error. But after 3.6.23, we changed this
** so that sqlite3_reset() would be called automatically instead of
** throwing the error.
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
** be called automatically instead of throwing the SQLITE_MISUSE error.
** This "automatic-reset" change is not technically an incompatibility,
** since any application that receives an SQLITE_MISUSE is broken by
** definition.
**
** Nevertheless, some published applications that were originally written
** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
** returns, and the so were broken by the automatic-reset change. As a
** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
** legacy behavior of returning SQLITE_MISUSE for cases where the
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
#ifdef SQLITE_OMIT_AUTORESET
if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){
sqlite3_reset((sqlite3_stmt*)p);
}else{
return SQLITE_MISUSE_BKPT;
}
#else
sqlite3_reset((sqlite3_stmt*)p);
#endif
}
/* Check that malloc() has not failed. If it has, return early. */
@@ -391,7 +410,9 @@ static int sqlite3Step(Vdbe *p){
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
db->vdbeExecCnt++;
rc = sqlite3VdbeExec(p);
db->vdbeExecCnt--;
}
#ifndef SQLITE_OMIT_TRACE
@@ -685,7 +706,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
__attribute__((aligned(8)))
#endif
= {{0}, (double)0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 };
= {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0, 0, 0 };
if( pVm && ALWAYS(pVm->db) ){
sqlite3_mutex_enter(pVm->db->mutex);
+1 -1
View File
@@ -408,7 +408,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
pOp->opflags = sqlite3OpcodeProperty[opcode];
if( opcode==OP_Function || opcode==OP_AggStep ){
if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
}else if( opcode==OP_Transaction && pOp->p2!=0 ){
}else if( (opcode==OP_Transaction && pOp->p2!=0) || opcode==OP_Vacuum ){
p->readOnly = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( opcode==OP_VUpdate ){
+68 -56
View File
@@ -44,9 +44,12 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
}
/*
** Return a pointer to a string in memory obtained form sqlite3DbMalloc() which
** holds a copy of zRawSql but with host parameters expanded to their
** current bindings.
** This function returns a pointer to a nul-terminated string in memory
** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
** string contains a copy of zRawSql but with host parameters expanded to
** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
** The calling function is responsible for making sure the memory returned
** is eventually freed.
@@ -77,63 +80,72 @@ char *sqlite3VdbeExpandSql(
sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
while( zRawSql[0] ){
n = findNextHostParameter(zRawSql, &nToken);
assert( n>0 );
sqlite3StrAccumAppend(&out, zRawSql, n);
zRawSql += n;
assert( zRawSql[0] || nToken==0 );
if( nToken==0 ) break;
if( zRawSql[0]=='?' ){
if( nToken>1 ){
assert( sqlite3Isdigit(zRawSql[1]) );
sqlite3GetInt32(&zRawSql[1], &idx);
}else{
idx = nextIndex;
}
}else{
assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
testcase( zRawSql[0]==':' );
testcase( zRawSql[0]=='$' );
testcase( zRawSql[0]=='@' );
idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
assert( idx>0 );
if( db->vdbeExecCnt>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;
while( *(zRawSql++)!='\n' && *zRawSql );
sqlite3StrAccumAppend(&out, "-- ", 3);
sqlite3StrAccumAppend(&out, zStart, zRawSql-zStart);
}
zRawSql += nToken;
nextIndex = idx + 1;
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
sqlite3StrAccumAppend(&out, "NULL", 4);
}else if( pVar->flags & MEM_Int ){
sqlite3XPrintf(&out, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){
sqlite3XPrintf(&out, "%!.15g", pVar->r);
}else if( pVar->flags & MEM_Str ){
}else{
while( zRawSql[0] ){
n = findNextHostParameter(zRawSql, &nToken);
assert( n>0 );
sqlite3StrAccumAppend(&out, zRawSql, n);
zRawSql += n;
assert( zRawSql[0] || nToken==0 );
if( nToken==0 ) break;
if( zRawSql[0]=='?' ){
if( nToken>1 ){
assert( sqlite3Isdigit(zRawSql[1]) );
sqlite3GetInt32(&zRawSql[1], &idx);
}else{
idx = nextIndex;
}
}else{
assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
testcase( zRawSql[0]==':' );
testcase( zRawSql[0]=='$' );
testcase( zRawSql[0]=='@' );
idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
assert( idx>0 );
}
zRawSql += nToken;
nextIndex = idx + 1;
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
sqlite3StrAccumAppend(&out, "NULL", 4);
}else if( pVar->flags & MEM_Int ){
sqlite3XPrintf(&out, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){
sqlite3XPrintf(&out, "%!.15g", pVar->r);
}else if( pVar->flags & MEM_Str ){
#ifndef SQLITE_OMIT_UTF16
u8 enc = ENC(db);
if( enc!=SQLITE_UTF8 ){
Mem utf8;
memset(&utf8, 0, sizeof(utf8));
utf8.db = db;
sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
sqlite3VdbeMemRelease(&utf8);
}else
u8 enc = ENC(db);
if( enc!=SQLITE_UTF8 ){
Mem utf8;
memset(&utf8, 0, sizeof(utf8));
utf8.db = db;
sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
sqlite3VdbeMemRelease(&utf8);
}else
#endif
{
sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
{
sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
}
}else if( pVar->flags & MEM_Zero ){
sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
}else{
assert( pVar->flags & MEM_Blob );
sqlite3StrAccumAppend(&out, "x'", 2);
for(i=0; i<pVar->n; i++){
sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
}
sqlite3StrAccumAppend(&out, "'", 1);
}
}else if( pVar->flags & MEM_Zero ){
sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
}else{
assert( pVar->flags & MEM_Blob );
sqlite3StrAccumAppend(&out, "x'", 2);
for(i=0; i<pVar->n; i++){
sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
}
sqlite3StrAccumAppend(&out, "'", 1);
}
}
return sqlite3StrAccumFinish(&out);
+43 -8
View File
@@ -458,14 +458,14 @@ typedef u16 ht_slot;
*/
struct WalIterator {
int iPrior; /* Last result returned from the iterator */
int nSegment; /* Size of the aSegment[] array */
int nSegment; /* Number of entries in aSegment[] */
struct WalSegment {
int iNext; /* Next slot in aIndex[] not yet returned */
ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
u32 *aPgno; /* Array of page numbers. */
int nEntry; /* Max size of aPgno[] and aIndex[] arrays */
int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
int iZero; /* Frame number associated with aPgno[0] */
} aSegment[1]; /* One for every 32KB page in the WAL */
} aSegment[1]; /* One for every 32KB page in the wal-index */
};
/*
@@ -1329,9 +1329,29 @@ static int walIteratorNext(
/*
** This function merges two sorted lists into a single sorted list.
**
** aLeft[] and aRight[] are arrays of indices. The sort key is
** aContent[aLeft[]] and aContent[aRight[]]. Upon entry, the following
** is guaranteed for all J<K:
**
** aContent[aLeft[J]] < aContent[aLeft[K]]
** aContent[aRight[J]] < aContent[aRight[K]]
**
** This routine overwrites aRight[] with a new (probably longer) sequence
** of indices such that the aRight[] contains every index that appears in
** either aLeft[] or the old aRight[] and such that the second condition
** above is still met.
**
** The aContent[aLeft[X]] values will be unique for all X. And the
** aContent[aRight[X]] values will be unique too. But there might be
** one or more combinations of X and Y such that
**
** aLeft[X]!=aRight[Y] && aContent[aLeft[X]] == aContent[aRight[Y]]
**
** When that happens, omit the aLeft[X] and use the aRight[Y] index.
*/
static void walMerge(
u32 *aContent, /* Pages in wal */
const u32 *aContent, /* Pages in wal - keys for the sort */
ht_slot *aLeft, /* IN: Left hand input list */
int nLeft, /* IN: Elements in array *paLeft */
ht_slot **paRight, /* IN/OUT: Right hand input list */
@@ -1371,10 +1391,24 @@ static void walMerge(
}
/*
** Sort the elements in list aList, removing any duplicates.
** Sort the elements in list aList using aContent[] as the sort key.
** Remove elements with duplicate keys, preferring to keep the
** larger aList[] values.
**
** The aList[] entries are indices into aContent[]. The values in
** aList[] are to be sorted so that for all J<K:
**
** aContent[aList[J]] < aContent[aList[K]]
**
** For any X and Y such that
**
** aContent[aList[X]] == aContent[aList[Y]]
**
** Keep the larger of the two values aList[X] and aList[Y] and discard
** the smaller.
*/
static void walMergesort(
u32 *aContent, /* Pages in wal */
const u32 *aContent, /* Pages in wal */
ht_slot *aBuffer, /* Buffer of at least *pnList items to use */
ht_slot *aList, /* IN/OUT: List to sort */
int *pnList /* IN/OUT: Number of elements in aList[] */
@@ -1439,6 +1473,7 @@ static void walIteratorFree(WalIterator *p){
/*
** Construct a WalInterator object that can be used to loop over all
** pages in the WAL in ascending order. The caller must hold the checkpoint
** lock.
**
** On success, make *pp point to the newly allocated WalInterator object
** return SQLITE_OK. Otherwise, return an error code. If this routine
@@ -1573,7 +1608,8 @@ static int walCheckpoint(
szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
testcase( szPage<=32768 );
testcase( szPage>=65536 );
if( pWal->hdr.mxFrame==0 ) return SQLITE_OK;
pInfo = walCkptInfo(pWal);
if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
/* Allocate the iterator */
rc = walIteratorInit(pWal, &pIter);
@@ -1595,7 +1631,6 @@ static int walCheckpoint(
*/
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
pInfo = walCkptInfo(pWal);
for(i=1; i<WAL_NREADER; i++){
u32 y = pInfo->aReadMark[i];
if( mxSafeFrame>=y ){
+3 -4
View File
@@ -2315,10 +2315,9 @@ static int valueFromExpr(
u8 aff,
sqlite3_value **pp
){
/* The evalConstExpr() function will have already converted any TK_VARIABLE
** expression involved in an comparison into a TK_REGISTER. */
assert( pExpr->op!=TK_VARIABLE );
if( pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE ){
if( pExpr->op==TK_VARIABLE
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
){
int iVar = pExpr->iColumn;
sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); /* IMP: R-23257-02778 */
*pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
+111
View File
@@ -0,0 +1,111 @@
# 2011 January 04
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements regression tests for SQLite library. This file
# implements tests for ANALYZE to verify that multiple rows containing
# a NULL value count as distinct rows for the purposes of analyze
# statistics.
#
# Also include test cases for collating sequences on indices.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test analyze4-1.0 {
db eval {
CREATE TABLE t1(a,b);
CREATE INDEX t1a ON t1(a);
CREATE INDEX t1b ON t1(b);
INSERT INTO t1 VALUES(1,NULL);
INSERT INTO t1 SELECT a+1, b FROM t1;
INSERT INTO t1 SELECT a+2, b FROM t1;
INSERT INTO t1 SELECT a+4, b FROM t1;
INSERT INTO t1 SELECT a+8, b FROM t1;
INSERT INTO t1 SELECT a+16, b FROM t1;
INSERT INTO t1 SELECT a+32, b FROM t1;
INSERT INTO t1 SELECT a+64, b FROM t1;
ANALYZE;
}
# Should choose the t1a index since it is more specific than t1b.
db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
# Verify that the t1b index shows that it does not narrow down the
# search any at all.
#
do_test analyze4-1.1 {
db eval {
SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
}
} {t1a {128 1} t1b {128 128}}
# Change half of the b values from NULL to a constant. Verify
# that the number of rows selected in stat1 is half the total
# number of rows.
#
do_test analyze4-1.2 {
db eval {
UPDATE t1 SET b='x' WHERE a%2;
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
}
} {t1a {128 1} t1b {128 64}}
# Change the t1.b values all back to NULL. Add columns t1.c and t1.d.
# Create a multi-column indices using t1.b and verify that ANALYZE
# processes them correctly.
#
do_test analyze4-1.3 {
db eval {
UPDATE t1 SET b=NULL;
ALTER TABLE t1 ADD COLUMN c;
ALTER TABLE t1 ADD COLUMN d;
UPDATE t1 SET c=a/4, d=a/2;
CREATE INDEX t1bcd ON t1(b,c,d);
CREATE INDEX t1cdb ON t1(c,d,b);
CREATE INDEX t1cbd ON t1(c,b,d);
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
}
} {t1a {128 1} t1b {128 128} t1bcd {128 128 4 2} t1cbd {128 4 4 2} t1cdb {128 4 2 2}}
# Verify that collating sequences are taken into account when computing
# ANALYZE statistics.
#
do_test analyze4-2.0 {
db eval {
CREATE TABLE t2(
x INTEGER PRIMARY KEY,
a TEXT COLLATE nocase,
b TEXT COLLATE rtrim,
c TEXT COLLATE binary
);
CREATE INDEX t2a ON t2(a);
CREATE INDEX t2b ON t2(b);
CREATE INDEX t2c ON t2(c);
CREATE INDEX t2c2 ON t2(c COLLATE nocase);
CREATE INDEX t2c3 ON t2(c COLLATE rtrim);
INSERT INTO t2 VALUES(1, 'abc', 'abc', 'abc');
INSERT INTO t2 VALUES(2, 'abC', 'abC', 'abC');
INSERT INTO t2 VALUES(3, 'abc ', 'abc ', 'abc ');
INSERT INTO t2 VALUES(4, 'abC ', 'abC ', 'abC ');
INSERT INTO t2 VALUES(5, 'aBc', 'aBc', 'aBc');
INSERT INTO t2 VALUES(6, 'aBC', 'aBC', 'aBC');
INSERT INTO t2 VALUES(7, 'aBc ', 'aBc ', 'aBc ');
INSERT INTO t2 VALUES(8, 'aBC ', 'aBC ', 'aBC ');
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t2' ORDER BY idx;
}
} {t2a {8 4} t2b {8 2} t2c {8 1} t2c2 {8 4} t2c3 {8 2}}
finish_test
+9 -3
View File
@@ -74,9 +74,15 @@ do_test capi2-1.7 {
# This used to be SQLITE_MISUSE. But now we automatically reset prepared
# statements.
do_test capi2-1.8 {
sqlite3_step $VM
} {SQLITE_ROW}
ifcapable autoreset {
do_test capi2-1.8 {
sqlite3_step $VM
} {SQLITE_ROW}
} else {
do_test capi2-1.8 {
sqlite3_step $VM
} {SQLITE_MISUSE}
}
# Update: In v2, once SQLITE_MISUSE is returned the statement handle cannot
# be interrogated for more information. However in v3, since the column
+10 -9
View File
@@ -163,6 +163,7 @@ do_test exclusive2-1.10 {
do_test exclusive2-1.11 {
expr {[t1sig] eq $::sig}
} {0}
db2 close
#--------------------------------------------------------------------
# These tests - exclusive2-2.X - are similar to exclusive2-1.X,
@@ -252,7 +253,6 @@ do_test exclusive2-2.8 {
#
db close
db2 close
catch {close $::fd}
file delete -force test.db
file delete -force test.db-journal
@@ -262,47 +262,48 @@ do_test exclusive2-3.0 {
execsql {
BEGIN;
CREATE TABLE t1(a UNIQUE);
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
INSERT INTO t1 VALUES(randstr(200, 200));
COMMIT;
}
readPagerChangeCounter test.db
} {1}
do_test exclusive2-3.1 {
execsql {
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
}
readPagerChangeCounter test.db
} {2}
do_test exclusive2-3.2 {
execsql {
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
}
readPagerChangeCounter test.db
} {3}
do_test exclusive2-3.3 {
execsql {
PRAGMA locking_mode = exclusive;
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
}
readPagerChangeCounter test.db
} {4}
do_test exclusive2-3.4 {
breakpoint
execsql {
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
}
readPagerChangeCounter test.db
} {4}
do_test exclusive2-3.5 {
execsql {
PRAGMA locking_mode = normal;
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
}
readPagerChangeCounter test.db
} {4}
do_test exclusive2-3.6 {
execsql {
INSERT INTO t1 VALUES(randstr(10, 400));
INSERT INTO t1 VALUES(randstr(200, 200));
}
readPagerChangeCounter test.db
} {5}
+9 -3
View File
@@ -1414,9 +1414,15 @@ do_test fkey2-17.1.2 {
set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy]
sqlite3_step $STMT
} {SQLITE_CONSTRAINT}
do_test fkey2-17.1.3 {
sqlite3_step $STMT
} {SQLITE_CONSTRAINT}
ifcapable autoreset {
do_test fkey2-17.1.3 {
sqlite3_step $STMT
} {SQLITE_CONSTRAINT}
} else {
do_test fkey2-17.1.3 {
sqlite3_step $STMT
} {SQLITE_MISUSE}
}
do_test fkey2-17.1.4 {
sqlite3_finalize $STMT
} {SQLITE_CONSTRAINT}
+42
View File
@@ -337,6 +337,48 @@ do_execsql_test 7.4 {
FROM t10 WHERE t10 MATCH 'record'
} {blob 20 blob 20}
#-------------------------------------------------------------------------
# Test a special case - matchinfo('nxa') with many zero length documents.
# Special because "x" internally uses a statement used by both "n" and "a".
# This was causing a problem at one point in the obscure case where the
# total number of bytes of data stored in an fts3 table was greater than
# the number of rows. i.e. when the following query returns true:
#
# SELECT sum(length(content)) < count(*) FROM fts4table;
#
do_execsql_test 8.1 {
CREATE VIRTUAL TABLE t11 USING fts4;
INSERT INTO t11(t11) VALUES('nodesize=24');
INSERT INTO t11 VALUES('quitealongstringoftext');
INSERT INTO t11 VALUES('anotherquitealongstringoftext');
INSERT INTO t11 VALUES('athirdlongstringoftext');
INSERT INTO t11 VALUES('andonemoreforgoodluck');
}
do_test 8.2 {
for {set i 0} {$i < 200} {incr i} {
execsql { INSERT INTO t11 VALUES('') }
}
execsql { INSERT INTO t11(t11) VALUES('optimize') }
} {}
do_execsql_test 8.3 {
SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*'
} {{204 1 3 3 0} {204 1 3 3 0} {204 1 3 3 0}}
# Corruption related tests.
do_execsql_test 8.4.1.1 { UPDATE t11_stat SET value = X'0000'; }
do_catchsql_test 8.5.1.2 {
SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*'
} {1 {database disk image is malformed}}
do_execsql_test 8.4.2.1 { UPDATE t11_stat SET value = X'00'; }
do_catchsql_test 8.5.2.2 {
SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*'
} {1 {database disk image is malformed}}
do_execsql_test 8.4.3.1 { UPDATE t11_stat SET value = NULL; }
do_catchsql_test 8.5.3.2 {
SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*'
} {1 {database disk image is malformed}}
finish_test
+5 -6
View File
@@ -45,7 +45,7 @@ do_test jrnlmode3-1.2 {
ROLLBACK;
SELECT * FROM t1;
}
} {1 2}
} {1}
db close
file delete -force test.db test.db-journal
@@ -67,7 +67,7 @@ do_test jrnlmode3-2.2 {
ROLLBACK;
SELECT * FROM t1;
}
} {1 2}
} {1}
# Test cases to verify that we can move from any journal_mode
# to any other, as long as we are not in a transaction. Verify
@@ -112,15 +112,14 @@ foreach fromjmode $all_journal_modes {
db eval "PRAGMA journal_mode=$tojmode"
} $fromjmode
# Rollback the transaction. Verify that the rollback occurred
# if journal_mode!=OFF.
# Rollback the transaction.
#
do_test jrnlmode3-3.$cnt.4 {
db eval {
ROLLBACK;
SELECT * FROM t1;
}
} [expr {$fromjmode=="off"?$cnt:""}]
} {}
# Now change the journal mode again. This time the new mode
# should take.
@@ -143,7 +142,7 @@ foreach fromjmode $all_journal_modes {
db eval {
SELECT * FROM t1;
}
} [expr {$tojmode=="off"?"1":""}]
} {}
}
}
+22 -10
View File
@@ -46,36 +46,48 @@ do_test lookaside-1.1 {
do_test lookaside-1.2 {
sqlite3_db_config_lookaside db 1 18 18
} {0}
do_test lookaside-1.3 {
sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 0
do_test lookaside-1.3.1 {
sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 0
} {0 0 0}
do_test lookaside-1.3.2 {
sqlite3_db_status db DBSTATUS_LOOKASIDE_HIT 0
} {0 0 0}
do_test lookaside-1.3.3 {
sqlite3_db_status db DBSTATUS_LOOKASIDE_MISS_SIZE 0
} {0 0 0}
do_test lookaside-1.3.4 {
sqlite3_db_status db DBSTATUS_LOOKASIDE_MISS_FULL 0
} {0 0 0}
do_test lookaside-1.4 {
db eval {CREATE TABLE t1(w,x,y,z);}
foreach {x y z} [sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 0] break
expr {$x==0 && $y<$z && $z==18}
foreach {x y z} [sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 0] break
set p [lindex [sqlite3_db_status db DBSTATUS_LOOKASIDE_HIT 0] 2]
set q [lindex [sqlite3_db_status db DBSTATUS_LOOKASIDE_MISS_SIZE 0] 2]
set r [lindex [sqlite3_db_status db DBSTATUS_LOOKASIDE_MISS_FULL 0] 2]
expr {$x==0 && $y<$z && $z==18 && $p>0 && $q>0 && $r>0}
} {0}
do_test lookaside-1.5 {
foreach {x y z} [sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 1] break
foreach {x y z} [sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 1] break
expr {$x==0 && $y<$z && $z==18}
} {0}
do_test lookaside-1.6 {
foreach {x y z} [sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 0] break
foreach {x y z} [sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 0] break
expr {$x==0 && $y==$z && $y<18}
} {1}
do_test lookaside-1.7 {
db cache flush
foreach {x y z} [sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 0] break
foreach {x y z} [sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 0] break
expr {$x==0 && $y==0 && $z<18}
} {1}
do_test lookaside-1.8 {
db cache flush
foreach {x y z} [sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 1] break
foreach {x y z} [sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 1] break
expr {$x==0 && $y==0 && $z<18}
} {1}
do_test lookaside-1.9 {
db cache flush
sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 0
sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 0
} {0 0 0}
do_test lookaside-2.1 {
@@ -83,7 +95,7 @@ do_test lookaside-2.1 {
} {0}
do_test lookaside-2.2 {
db eval {CREATE TABLE t2(x);}
foreach {x y z} [sqlite3_db_status db SQLITE_DBSTATUS_LOOKASIDE_USED 0] break
foreach {x y z} [sqlite3_db_status db DBSTATUS_LOOKASIDE_USED 0] break
expr {$x==0 && $y<$z && $z>10 && $z<100}
} {1}
do_test lookaside-2.3 {
+13 -1
View File
@@ -106,6 +106,10 @@ set FAULTSIM(cantopen-persistent) [list \
#
# -test Script to execute after -body.
#
# -install Script to execute after faultsim -injectinstall
#
# -uninstall Script to execute after faultsim -uninjectinstall
#
proc do_faultsim_test {name args} {
global FAULTSIM
@@ -113,6 +117,8 @@ proc do_faultsim_test {name args} {
set DEFAULT(-prep) ""
set DEFAULT(-body) ""
set DEFAULT(-test) ""
set DEFAULT(-install) ""
set DEFAULT(-uninstall) ""
fix_testname name
@@ -129,7 +135,9 @@ proc do_faultsim_test {name args} {
set faultlist [concat $faultlist $flist]
}
set testspec [list -prep $O(-prep) -body $O(-body) -test $O(-test)]
set testspec [list -prep $O(-prep) -body $O(-body) \
-test $O(-test) -install $O(-install) -uninstall $O(-uninstall)
]
foreach f [lsort -unique $faultlist] {
eval do_one_faultsim_test "$name-$f" $FAULTSIM($f) $testspec
}
@@ -294,6 +302,8 @@ proc do_one_faultsim_test {testname args} {
set DEFAULT(-prep) ""
set DEFAULT(-body) ""
set DEFAULT(-test) ""
set DEFAULT(-install) ""
set DEFAULT(-uninstall) ""
array set O [array get DEFAULT]
array set O $args
@@ -307,6 +317,7 @@ proc do_one_faultsim_test {testname args} {
"
eval $O(-injectinstall)
eval $O(-install)
set stop 0
for {set iFail 1} {!$stop} {incr iFail} {
@@ -338,6 +349,7 @@ proc do_one_faultsim_test {testname args} {
if {$nfail==0} { set stop 1 }
}
eval $O(-uninstall)
eval $O(-injectuninstall)
}
+2 -1
View File
@@ -96,9 +96,10 @@ sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-2 {PRAGMA page_size=1024}
#show_memstats
set MEMORY_MANAGEMENT $sqlite_options(memorymanage)
do_test memsubsys1-2.3 {
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} [expr ($AUTOVACUUM+$TEMP_STORE>=2)*1024]
} [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024]
do_test memsubsys1-2.4 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 20
+11 -3
View File
@@ -101,8 +101,14 @@ ifcapable threadsafe&&shared_cache {
set enable_shared_cache [sqlite3_enable_shared_cache 1]
foreach {mode mutexes} {
singlethread {}
multithread {fast static_lru static_master static_mem static_open static_prng }
serialized {fast recursive static_lru static_master static_mem static_open static_prng}
multithread {
fast static_lru static_master static_mem static_open static_prng
static_pmem
}
serialized {
fast recursive static_lru static_master static_mem static_open
static_prng static_pmem
}
} {
do_test mutex1.2.$mode.1 {
@@ -120,7 +126,9 @@ ifcapable threadsafe&&shared_cache {
INSERT INTO abc VALUES(1, 2, 3);
}
} {}
ifcapable !memorymanage {
regsub { static_lru} $mutexes {} mutexes
}
do_test mutex1.2.$mode.3 {
mutex_counters counters
+2 -2
View File
@@ -1614,7 +1614,7 @@ do_catchsql_test pager1-14.1.2 {
} {0 {}}
do_execsql_test pager1-14.1.3 {
SELECT * FROM t1;
} {1 2 3 4}
} {1 2}
do_catchsql_test pager1-14.1.4 {
BEGIN;
INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
@@ -1623,7 +1623,7 @@ do_catchsql_test pager1-14.1.4 {
do_execsql_test pager1-14.1.5 {
COMMIT;
SELECT * FROM t1;
} {1 2 3 4 2 2 4 4}
} {1 2 2 2}
#-------------------------------------------------------------------------
# Test opening and closing the pager sub-system with different values
+1 -1
View File
@@ -133,7 +133,7 @@ do_test pager2-2.1 {
ROLLBACK;
SELECT * FROM t1;
}
} {off 1 2}
} {off}
do_test pager2-2.2 {
faultsim_delete_and_reopen
execsql {
+63
View File
@@ -0,0 +1,63 @@
# 2011 January 28
#
# 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
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
if {[permutation] == "inmemory_journal"} {
finish_test
return
}
# Create a database with page-size 2048 bytes that uses 2 pages. Populate
# it so that if the page-size is changed to 1024 bytes and the db vacuumed,
# the new db size is 3 pages.
#
do_test pagerfault3-pre1 {
execsql {
PRAGMA page_size = 2048;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(randomblob(1200));
PRAGMA page_count;
}
} {2}
do_test pagerfault3-pre2 {
faultsim_save_and_close
faultsim_restore_and_reopen
execsql {
PRAGMA page_size = 1024;
VACUUM;
PRAGMA page_count;
}
} {3}
# Now do the page-size change and VACUUM with IO error injection. When
# an IO error is injected into the final xSync() of the commit, the pager
# will have to extend the db file from 3072 to 4096 byts when rolling
# back the hot-journal file. This is a special case in pager_truncate().
#
do_faultsim_test pagerfault3-1 -faults ioerr-transient -prep {
faultsim_restore_and_reopen
} -body {
execsql {
PRAGMA page_size = 1024;
VACUUM;
}
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check
}
finish_test
+8
View File
@@ -21,6 +21,14 @@ source $testdir/tester.tcl
#
do_not_use_codec
# Only works with a mode-2 pcache where all pcaches share a single set
# of pages.
#
ifcapable {!memorymanage && threadsafe} {
finish_test
return
}
# The pcache module limits the number of pages available to purgeable
# caches to the sum of the 'cache_size' values for the set of open
# caches. This block of tests, pcache-1.*, test that the library behaves
+1 -1
View File
@@ -905,7 +905,7 @@ if {[wal_is_wal_mode]==0} {
ROLLBACK;
SELECT * FROM t1;
}
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
} {1 2 3 4 5 6 7 8 9 10 11 12}
}
db close
+53
View File
@@ -0,0 +1,53 @@
# 2011 January 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 implements regression tests for SQLite library.
#
# This file implements tests to verify that ticket [5d863f876e] has been
# fixed.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
do_multiclient_test tn {
do_test $tn.1 {
sql1 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
PRAGMA journal_mode = WAL;
VACUUM;
PRAGMA journal_mode = DELETE;
}
} {wal delete}
do_test $tn.2 {
sql2 { SELECT * FROM t1 }
} {1 2 3 4}
do_test $tn.3 {
sql1 {
INSERT INTO t1 VALUES(5, 6);
PRAGMA journal_mode = WAL;
VACUUM;
PRAGMA journal_mode = DELETE;
}
} {wal delete}
do_test $tn.2 {
sql2 { PRAGMA integrity_check }
} {ok}
}
finish_test
+152
View File
@@ -0,0 +1,152 @@
# 2011 Jan 21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the "sqlite3_trace()" API. Specifically,
# it tests the special handling of nested SQL statements (those executed
# by virtual table or user function callbacks). These statements are treated
# differently in two respects:
#
# 1. Each line of the statement is prefixed with "-- " to turn it into
# an SQL comment.
#
# 2. Parameter expansion is not performed.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !trace { finish_test ; return }
set ::testprefix trace2
proc sql {zSql} { db one $zSql }
proc trace {zSql} { lappend ::trace $zSql }
db func sql sql
db trace trace
proc do_trace_test {tn sql expected} {
# Test that the list of string passed to the trace callback when $sql
# is executed is equivalent to the list of strings in $expected.
#
set ::trace [list]
execsql $sql
uplevel do_test $tn [list {set ::trace}] [list [list {*}$expected]]
}
proc do_trace_select_test {tn sql expected} {
uplevel [list do_trace_test ${tn}.a $sql $expected]
# Now execute each SQL statement passed to the trace callback in the
# block above. Check that this causes the same set of strings to be
# passed to the trace callback again. i.e. that executing the output
# of the trace callback is equivalent to the SQL script in $sql.
#
set sqllist $::trace
set ::trace [list]
foreach item $sqllist { execsql $item }
uplevel do_test $tn.b [list {set ::trace}] [list $sqllist]
}
do_trace_select_test 1.1 {
SELECT 1, 2, 3;
} {
"SELECT 1, 2, 3;"
}
do_trace_select_test 1.2 {
SELECT sql('SELECT 1, 2, 3');
} {
"SELECT sql('SELECT 1, 2, 3');"
"-- SELECT 1, 2, 3"
}
do_trace_select_test 1.3 {
SELECT sql('SELECT 1,
2,
3'
);
} {
"SELECT sql('SELECT 1,
2,
3'
);"
"-- SELECT 1,
-- 2,
-- 3"
}
do_trace_select_test 1.4 {
SELECT sql('SELECT 1,
3'
);
} {
"SELECT sql('SELECT 1,
3'
);"
"-- SELECT 1,
--
--
-- 3"
}
do_trace_select_test 1.5 {
SELECT $var, sql('SELECT 1,
$var,
3'
);
} {
"SELECT NULL, sql('SELECT 1,
$var,
3'
);"
"-- SELECT 1,
-- $var,
-- 3"
}
ifcapable fts3 {
do_execsql_test 2.1 {
CREATE VIRTUAL TABLE x1 USING fts4;
INSERT INTO x1 VALUES('Cloudy, with a high near 16');
INSERT INTO x1 VALUES('Wind chill values as low as -13');
}
do_trace_test 2.2 {
INSERT INTO x1 VALUES('North northwest wind between 8 and 14 mph');
} {
"INSERT INTO x1 VALUES('North northwest wind between 8 and 14 mph');"
"-- INSERT INTO 'main'.'x1_content' VALUES(?,?)"
"-- REPLACE INTO 'main'.'x1_docsize' VALUES(?,?)"
"-- SELECT value FROM 'main'.'x1_stat' WHERE id=0"
"-- REPLACE INTO 'main'.'x1_stat' VALUES(0,?)"
"-- SELECT (SELECT max(idx) FROM 'main'.'x1_segdir' WHERE level = ?) + 1"
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
"-- INSERT INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
}
do_trace_test 2.3 {
INSERT INTO x1(x1) VALUES('optimize');
} {
"INSERT INTO x1(x1) VALUES('optimize');"
"-- SELECT count(*), max(level) FROM 'main'.'x1_segdir'"
"-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' ORDER BY level DESC, idx ASC"
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
"-- DELETE FROM 'main'.'x1_segdir'"
"-- INSERT INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
}
}
finish_test
+1 -1
View File
@@ -53,7 +53,7 @@ set in [open $TOP/manifest]
set zDate {}
while {![eof $in]} {
set line [gets $in]
if {[regexp {^D (2.*[0-9])} $line all date]} {
if {[regexp {^D (2[-0-9T:]+)} $line all date]} {
set zDate [string map {T { }} $date]
break
}
+1 -1
View File
@@ -200,7 +200,7 @@ do_test shell1-1.15.3 {
# -version show SQLite version
do_test shell1-1.16.1 {
catchcmd "-version test.db" ""
} {0 3.7.3}
} {0 3.7.5}
#----------------------------------------------------------------------------
# Test cases shell1-2.*: Basic "dot" command token parsing.
+175 -12
View File
@@ -57,8 +57,9 @@ static void out_of_memory(void){
*/
static unsigned char *getContent(int ofst, int nByte){
unsigned char *aData;
aData = malloc(nByte);
aData = malloc(nByte+32);
if( aData==0 ) out_of_memory();
memset(aData, 0, nByte+32);
lseek(db, ofst, SEEK_SET);
read(db, aData, nByte);
return aData;
@@ -181,56 +182,189 @@ static void print_db_header(void){
}
/*
** Create a description for a single cell.
** Describe cell content.
*/
static int describeCell(unsigned char cType, unsigned char *a, char **pzDesc){
static int describeContent(
unsigned char *a, /* Cell content */
int nLocal, /* Bytes in a[] */
char *zDesc /* Write description here */
){
int nDesc = 0;
int n, i, j;
i64 x, v;
const unsigned char *pData;
const unsigned char *pLimit;
char sep = ' ';
pLimit = &a[nLocal];
n = decodeVarint(a, &x);
pData = &a[x];
a += n;
i = x - n;
while( i>0 && pData<=pLimit ){
n = decodeVarint(a, &x);
a += n;
i -= n;
nLocal -= n;
zDesc[0] = sep;
sep = ',';
nDesc++;
zDesc++;
if( x==0 ){
sprintf(zDesc, "*"); /* NULL is a "*" */
}else if( x>=1 && x<=6 ){
v = (signed char)pData[0];
pData++;
switch( x ){
case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
case 4: v = (v<<8) + pData[0]; pData++;
case 3: v = (v<<8) + pData[0]; pData++;
case 2: v = (v<<8) + pData[0]; pData++;
}
sprintf(zDesc, "%lld", v);
}else if( x==7 ){
sprintf(zDesc, "real");
pData += 8;
}else if( x==8 ){
sprintf(zDesc, "0");
}else if( x==9 ){
sprintf(zDesc, "1");
}else if( x>=12 ){
int size = (x-12)/2;
if( (x&1)==0 ){
sprintf(zDesc, "blob(%d)", size);
}else{
sprintf(zDesc, "txt(%d)", size);
}
pData += size;
}
j = strlen(zDesc);
zDesc += j;
nDesc += j;
}
return nDesc;
}
/*
** Compute the local payload size given the total payload size and
** the page size.
*/
static int localPayload(i64 nPayload, char cType){
int maxLocal;
int minLocal;
int surplus;
int nLocal;
if( cType==13 ){
/* Table leaf */
maxLocal = pagesize-35;
minLocal = (pagesize-12)*32/255-23;
}else{
maxLocal = (pagesize-12)*64/255-23;
minLocal = (pagesize-12)*32/255-23;
}
if( nPayload>maxLocal ){
surplus = minLocal + (nPayload-minLocal)%(pagesize-4);
if( surplus<=maxLocal ){
nLocal = surplus;
}else{
nLocal = minLocal;
}
}else{
nLocal = nPayload;
}
return nLocal;
}
/*
** Create a description for a single cell.
**
** The return value is the local cell size.
*/
static int describeCell(
unsigned char cType, /* Page type */
unsigned char *a, /* Cell content */
int showCellContent, /* Show cell content if true */
char **pzDesc /* Store description here */
){
int i;
int nDesc = 0;
int n = 0;
int leftChild;
i64 nPayload;
i64 rowid;
static char zDesc[100];
int nLocal;
static char zDesc[1000];
i = 0;
if( cType<=5 ){
leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
a += 4;
n += 4;
sprintf(zDesc, "left-child: %d ", leftChild);
sprintf(zDesc, "lx: %d ", leftChild);
nDesc = strlen(zDesc);
}
if( cType!=5 ){
i = decodeVarint(a, &nPayload);
a += i;
n += i;
sprintf(&zDesc[nDesc], "sz: %lld ", nPayload);
sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
nDesc += strlen(&zDesc[nDesc]);
nLocal = localPayload(nPayload, cType);
}else{
nPayload = nLocal = 0;
}
if( cType==5 || cType==13 ){
i = decodeVarint(a, &rowid);
a += i;
n += i;
sprintf(&zDesc[nDesc], "rowid: %lld ", rowid);
sprintf(&zDesc[nDesc], "r: %lld ", rowid);
nDesc += strlen(&zDesc[nDesc]);
}
if( nLocal<nPayload ){
int ovfl;
unsigned char *b = &a[nLocal];
ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
nDesc += strlen(&zDesc[nDesc]);
n += 4;
}
if( showCellContent && cType!=5 ){
nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
}
*pzDesc = zDesc;
return n;
return nLocal+n;
}
/*
** Decode a btree page
*/
static void decode_btree_page(unsigned char *a, int pgno, int hdrSize){
static void decode_btree_page(
unsigned char *a, /* Page content */
int pgno, /* Page number */
int hdrSize, /* Size of the page header. 0 or 100 */
char *zArgs /* Flags to control formatting */
){
const char *zType = "unknown";
int nCell;
int i;
int i, j;
int iCellPtr;
int showCellContent = 0;
int showMap = 0;
char *zMap = 0;
switch( a[0] ){
case 2: zType = "index interior node"; break;
case 5: zType = "table interior node"; break;
case 10: zType = "index leaf"; break;
case 13: zType = "table leaf"; break;
}
while( zArgs[0] ){
switch( zArgs[0] ){
case 'c': showCellContent = 1; break;
case 'm': showMap = 1; break;
}
zArgs++;
}
printf("Decode of btree page %d:\n", pgno);
print_decode_line(a, 0, 1, zType);
print_decode_line(a, 1, 2, "Offset to first freeblock");
@@ -244,13 +378,40 @@ static void decode_btree_page(unsigned char *a, int pgno, int hdrSize){
}else{
iCellPtr = 8;
}
if( nCell>0 ){
printf(" key: lx=left-child n=payload-size r=rowid\n");
}
if( showMap ){
zMap = malloc(pagesize);
memset(zMap, '.', pagesize);
memset(zMap, '1', hdrSize);
memset(&zMap[hdrSize], 'H', iCellPtr);
memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
}
for(i=0; i<nCell; i++){
int cofst = iCellPtr + i*2;
char *zDesc;
int n;
cofst = a[cofst]*256 + a[cofst+1];
describeCell(a[0], &a[cofst-hdrSize], &zDesc);
n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
if( showMap ){
char zBuf[30];
memset(&zMap[cofst], '*', n);
zMap[cofst] = '[';
zMap[cofst+n-1] = ']';
sprintf(zBuf, "%d", i);
j = strlen(zBuf);
if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
}
printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
}
if( showMap ){
for(i=0; i<pagesize; i+=64){
printf(" %03x: %.64s\n", i, &zMap[i]);
}
free(zMap);
}
}
/*
@@ -300,6 +461,8 @@ static void usage(const char *argv0){
" NNN..MMM Show hex of pages NNN through MMM\n"
" NNN..end Show hex of pages NNN through end of file\n"
" NNNb Decode btree page NNN\n"
" NNNbc Decode btree page NNN and show content\n"
" NNNbm Decode btree page NNN and show a layout map\n"
" NNNt Decode freelist trunk page NNN\n"
" NNNtd Show leave freelist pages on the decode\n"
" NNNtr Recurisvely decode freelist starting at NNN\n"
@@ -361,7 +524,7 @@ int main(int argc, char **argv){
nByte = pagesize;
}
a = getContent(ofst, nByte);
decode_btree_page(a, iStart, hdrSize);
decode_btree_page(a, iStart, hdrSize, &zLeft[1]);
free(a);
continue;
}else if( zLeft && zLeft[0]=='t' ){