[libgda] Switched to SQlite 3.7.17 and SlqCipher 2.2.0



commit fd2e8b3f3b08bb71830810967babe063a4b1ca95
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sun Jun 30 15:38:59 2013 +0200

    Switched to SQlite 3.7.17 and SlqCipher 2.2.0

 libgda/sqlite/sqlite-src/PragmasPatch |    6 +-
 libgda/sqlite/sqlite-src/sqlite3.c    |11692 ++++--
 libgda/sqlite/sqlite-src/sqlite3.h    |  192 +-
 providers/sqlcipher/sqlcipher.patch   |65083 ++++++++++++++++++++++++++++++++-
 4 files changed, 71384 insertions(+), 5589 deletions(-)
---
diff --git a/libgda/sqlite/sqlite-src/PragmasPatch b/libgda/sqlite/sqlite-src/PragmasPatch
index b0b53da..a8f87f9 100644
--- a/libgda/sqlite/sqlite-src/PragmasPatch
+++ b/libgda/sqlite/sqlite-src/PragmasPatch
@@ -1,6 +1,6 @@
---- sqlite3.c.orig     2012-10-04 21:49:28.000000000 +0200
-+++ sqlite3.c  2012-12-22 18:10:51.472282229 +0100
-@@ -92000,6 +92000,60 @@
+--- sqlite3.c.orig     2013-05-20 12:56:34.000000000 +0200
++++ sqlite3.c  2013-06-30 15:08:52.994949387 +0200
+@@ -94348,6 +94348,60 @@
  
  #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
    /*
diff --git a/libgda/sqlite/sqlite-src/sqlite3.c b/libgda/sqlite/sqlite-src/sqlite3.c
index 712a8bc..3e7d7a5 100644
--- a/libgda/sqlite/sqlite-src/sqlite3.c
+++ b/libgda/sqlite/sqlite-src/sqlite3.c
@@ -1,6 +1,6 @@
 /******************************************************************************
 ** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.14.1.  By combining all the individual C code files into this 
+** version 3.7.17.  By combining all the individual C code files into this 
 ** single large file, the entire code can be compiled as a single translation
 ** unit.  This allows many compilers to do optimizations that would not be
 ** possible if the files were compiled separately.  Performance improvements
@@ -306,6 +306,10 @@
 # define _GNU_SOURCE
 #endif
 
+#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
+# define _BSD_SOURCE
+#endif
+
 /*
 ** Include standard header files as necessary
 */
@@ -358,11 +362,11 @@
 ** We support that for legacy.
 */
 #if !defined(SQLITE_THREADSAFE)
-#if defined(THREADSAFE)
-# define SQLITE_THREADSAFE THREADSAFE
-#else
-# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
-#endif
+# if defined(THREADSAFE)
+#   define SQLITE_THREADSAFE THREADSAFE
+# else
+#   define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
+# endif
 #endif
 
 /*
@@ -440,7 +444,8 @@
 **
 ** See also ticket #2741.
 */
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
+ && !defined(__APPLE__) && SQLITE_THREADSAFE
 #  define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */
 #endif
 
@@ -673,9 +678,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.14.1"
-#define SQLITE_VERSION_NUMBER 3007014
-#define SQLITE_SOURCE_ID      "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
+#define SQLITE_VERSION        "3.7.17"
+#define SQLITE_VERSION_NUMBER 3007017
+#define SQLITE_SOURCE_ID      "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -854,7 +859,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** [sqlite3_blob_close | close] all [BLOB handles], and 
 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
-** sqlite3_close() is called on a [database connection] that still has
+** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
 ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
@@ -991,6 +996,8 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_FORMAT      24   /* Auxiliary database format error */
 #define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
 #define SQLITE_NOTADB      26   /* File opened that is not a database file */
+#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
+#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
 #define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
 #define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
 /* end-of-error-codes */
@@ -1040,14 +1047,29 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
 #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
+#define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
 #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
 #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
+#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
+#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -1287,6 +1309,9 @@ struct sqlite3_io_methods {
   void (*xShmBarrier)(sqlite3_file*);
   int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
   /* Methods above are valid for version 2 */
+  int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
+  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
+  /* Methods above are valid for version 3 */
   /* Additional methods may be added in future releases */
 };
 
@@ -1421,6 +1446,38 @@ struct sqlite3_io_methods {
 ** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
 ** file control occurs at the beginning of pragma statement analysis and so
 ** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^The [SQLITE_FCNTL_BUSYHANDLER]
+** file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
+** to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses.  The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()].  The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
+** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
+** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
+** maximum number of bytes that will be used for memory-mapped I/O.
+** The argument is a pointer to a value of type sqlite3_int64 that
+** is an advisory maximum number of bytes in the file to memory map.  The
+** pointer is overwritten with the old value.  The limit is not changed if
+** the value originally pointed to is negative, and so the current limit 
+** can be queried by passing in a pointer to a negative number.  This
+** file-control is used internally to implement [PRAGMA mmap_size].
+**
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -1437,6 +1494,9 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_VFSNAME                12
 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
 #define SQLITE_FCNTL_PRAGMA                 14
+#define SQLITE_FCNTL_BUSYHANDLER            15
+#define SQLITE_FCNTL_TEMPFILENAME           16
+#define SQLITE_FCNTL_MMAP_SIZE              18
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -2103,7 +2163,9 @@ struct sqlite3_mem_methods {
 ** page cache implementation into that object.)^ </dd>
 **
 ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
-** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
+** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
+** global [error log].
+** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
 ** function with a call signature of void(*)(void*,int,const char*), 
 ** and a pointer to void. ^If the function pointer is not NULL, it is
 ** invoked by [sqlite3_log()] to process each logging event.  ^If the
@@ -2133,10 +2195,54 @@ struct sqlite3_mem_methods {
 ** disabled. The default value may be changed by compiling with the
 ** [SQLITE_USE_URI] symbol defined.
 **
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer.  The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled.  Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
 ** <dd> These options are obsolete and should not be used by new code.
 ** They are retained for backwards compatibility but are now no-ops.
+** </dd>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.  An example of using this
+** configuration option can be seen in the "test_sqllog.c" source file in
+** the canonical SQLite source tree.</dd>
+**
+** [[SQLITE_CONFIG_MMAP_SIZE]]
+** <dt>SQLITE_CONFIG_MMAP_SIZE
+** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
+** that are the default mmap size limit (the default setting for
+** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
+** The default setting can be overridden by each database connection using
+** either the [PRAGMA mmap_size] command, or by using the
+** [SQLITE_FCNTL_MMAP_SIZE] file control.  The maximum allowed mmap size
+** cannot be changed at run-time.  Nor may the maximum allowed mmap size
+** exceed the compile-time maximum mmap size set by the
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.  
+** If either argument to this option is negative, then that argument is
+** changed to its compile-time default.
 ** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -2158,6 +2264,9 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_URI          17  /* int */
 #define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
 #define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
+#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
+#define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -2991,6 +3100,9 @@ SQLITE_API int sqlite3_set_authorizer(
 ** as each triggered subprogram is entered.  The callbacks for triggers
 ** contain a UTF-8 SQL comment that identifies the trigger.)^
 **
+** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit
+** the length of [bound parameter] expansion in the output of sqlite3_trace().
+**
 ** ^The callback function registered by sqlite3_profile() is invoked
 ** as each SQL statement finishes.  ^The profile callback contains
 ** the original statement text and an estimate of wall-clock time
@@ -3166,7 +3278,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     an error)^. 
 **     ^If "ro" is specified, then the database is opened for read-only 
 **     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
-**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
+**     third argument to sqlite3_open_v2(). ^If the mode option is set to 
 **     "rw", then the database is opened for read-write (but not create) 
 **     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
 **     been set. ^Value "rwc" is equivalent to setting both 
@@ -3182,7 +3294,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
 **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
-**     a URI filename, its value overrides any behaviour requested by setting
+**     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
 ** </ul>
 **
@@ -3318,6 +3430,11 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
 ** However, the error string might be overwritten or deallocated by
 ** subsequent calls to other SQLite interface functions.)^
 **
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
 ** When the serialized [threading mode] is in use, it might be the
 ** case that a second error occurs on a separate thread in between
 ** the time of the first error and the call to these interfaces.
@@ -3336,6 +3453,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db);
 SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
 SQLITE_API const char *sqlite3_errmsg(sqlite3*);
 SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
 
 /*
 ** CAPI3REF: SQL Statement Object
@@ -3523,7 +3641,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** <li>
 ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
 ** always used to do, [sqlite3_step()] will automatically recompile the SQL
-** statement and try to run it again.
+** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY]
+** retries will occur before sqlite3_step() gives up and returns an error.
 ** </li>
 **
 ** <li>
@@ -3727,6 +3846,9 @@ typedef struct sqlite3_context sqlite3_context;
 ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
 **
 ** ^The third argument is the value to bind to the parameter.
+** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
+** is ignored and the end result is the same as sqlite3_bind_null().
 **
 ** ^(In those routines that have a fourth argument, its value is the
 ** number of bytes in the parameter.  To be clear: the value is the
@@ -4494,7 +4616,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
 SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+                      void*,sqlite3_int64);
 #endif
 
 /*
@@ -4574,14 +4697,17 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** In those cases, sqlite3_aggregate_context() might be called for the
 ** first time from within xFinal().)^
 **
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is
-** less than or equal to zero or if a memory allocate error occurs.
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
 **
 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
 ** determined by the N parameter on first successful call.  Changing the
 ** value of N in subsequent call to sqlite3_aggregate_context() within
 ** the same aggregate function instance will not resize the memory
-** allocation.)^
+** allocation.)^  Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
+** pointless memory allocations occur.
 **
 ** ^SQLite automatically frees the memory allocated by 
 ** sqlite3_aggregate_context() when the aggregate query concludes.
@@ -4679,7 +4805,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
 ** the content before returning.
 **
 ** The typedef is necessary to work around problems in certain
-** C++ compilers.  See ticket #2191.
+** C++ compilers.
 */
 typedef void (*sqlite3_destructor_type)(void*);
 #define SQLITE_STATIC      ((sqlite3_destructor_type)0)
@@ -5298,6 +5424,9 @@ SQLITE_API void *sqlite3_update_hook(
 ** future releases of SQLite.  Applications that care about shared
 ** cache setting should set it explicitly.
 **
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
 ** See Also:  [SQLite Shared-Cache Mode]
 */
 SQLITE_API int sqlite3_enable_shared_cache(int);
@@ -5475,11 +5604,20 @@ SQLITE_API int sqlite3_table_column_metadata(
 ** ^This interface loads an SQLite extension library from the named file.
 **
 ** ^The sqlite3_load_extension() interface attempts to load an
-** SQLite extension library contained in the file zFile.
+** [SQLite extension] library contained in the file zFile.  If
+** the file cannot be loaded directly, attempts are made to load
+** with various operating-system specific extensions added.
+** So for example, if "samplelib" cannot be loaded, then names like
+** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
+** be tried also.
 **
 ** ^The entry point is zProc.
-** ^zProc may be 0, in which case the name of the entry point
-** defaults to "sqlite3_extension_init".
+** ^(zProc may be 0, in which case SQLite will try to come up with an
+** entry point name on its own.  It first tries "sqlite3_extension_init".
+** If that does not work, it constructs a name "sqlite3_X_init" where the
+** X is consists of the lower-case equivalent of all ASCII alphabetic
+** characters in the filename from the last "/" to the first following
+** "." and omitting any initial "lib".)^
 ** ^The sqlite3_load_extension() interface returns
 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
 ** ^If an error occurs and pzErrMsg is not 0, then the
@@ -5505,11 +5643,11 @@ SQLITE_API int sqlite3_load_extension(
 ** CAPI3REF: Enable Or Disable Extension Loading
 **
 ** ^So as not to open security holes in older applications that are
-** unprepared to deal with extension loading, and as a means of disabling
-** extension loading while evaluating user-entered SQL, the following API
+** unprepared to deal with [extension loading], and as a means of disabling
+** [extension loading] while evaluating user-entered SQL, the following API
 ** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
 **
-** ^Extension loading is off by default. See ticket #1863.
+** ^Extension loading is off by default.
 ** ^Call the sqlite3_enable_load_extension() routine with onoff==1
 ** to turn extension loading on and call it with onoff==0 to turn
 ** it back off again.
@@ -5521,7 +5659,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
 **
 ** ^This interface causes the xEntryPoint() function to be invoked for
 ** each new [database connection] that is created.  The idea here is that
-** xEntryPoint() is the entry point for a statically linked SQLite extension
+** xEntryPoint() is the entry point for a statically linked [SQLite extension]
 ** that is to be automatically loaded into all new database connections.
 **
 ** ^(Even though the function prototype shows that xEntryPoint() takes
@@ -6872,7 +7010,7 @@ struct sqlite3_pcache_page {
 ** parameter to help it determined what action to take:
 **
 ** <table border=1 width=85% align=center>
-** <tr><th> createFlag <th> Behaviour when page is not already in cache
+** <tr><th> createFlag <th> Behavior when page is not already in cache
 ** <tr><td> 0 <td> Do not allocate a new page.  Return NULL.
 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
 **                 Otherwise return NULL.
@@ -7302,9 +7440,24 @@ SQLITE_API int sqlite3_stricmp(const char *, const char *);
 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
 
 /*
+** CAPI3REF: String Globbing
+*
+** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches
+** the glob pattern P, and it returns non-zero if string X does not match
+** the glob pattern P.  ^The definition of glob pattern matching used in
+** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
+** SQL dialect used by SQLite.  ^The sqlite3_strglob(P,X) function is case
+** sensitive.
+**
+** Note that this routine returns zero on a match and non-zero if the strings
+** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
+*/
+SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
+
+/*
 ** CAPI3REF: Error Logging Interface
 **
-** ^The [sqlite3_log()] interface writes a message into the error log
+** ^The [sqlite3_log()] interface writes a message into the [error log]
 ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
 ** ^If logging is enabled, the zFormat string and subsequent arguments are
 ** used with [sqlite3_snprintf()] to generate the final output string.
@@ -7677,7 +7830,7 @@ struct sqlite3_rtree_geometry {
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This is the header file for the generic hash-table implemenation
+** This is the header file for the generic hash-table implementation
 ** used in SQLite.
 */
 #ifndef _SQLITE_HASH_H_
@@ -7989,6 +8142,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
 */
 #ifndef SQLITE_TEMP_STORE
 # define SQLITE_TEMP_STORE 1
+# define SQLITE_TEMP_STORE_xc 1  /* Exclude from ctime.c */
 #endif
 
 /*
@@ -8136,6 +8290,49 @@ SQLITE_PRIVATE const int sqlite3one;
 # define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
 #endif
 
+/*
+** Disable MMAP on platforms where it is known to not work
+*/
+#if defined(__OpenBSD__) || defined(__QNXNTO__)
+# undef SQLITE_MAX_MMAP_SIZE
+# define SQLITE_MAX_MMAP_SIZE 0
+#endif
+
+/*
+** Default maximum size of memory used by memory-mapped I/O in the VFS
+*/
+#ifdef __APPLE__
+# include <TargetConditionals.h>
+# if TARGET_OS_IPHONE
+#   undef SQLITE_MAX_MMAP_SIZE
+#   define SQLITE_MAX_MMAP_SIZE 0
+# endif
+#endif
+#ifndef SQLITE_MAX_MMAP_SIZE
+# if defined(__linux__) \
+  || defined(_WIN32) \
+  || (defined(__APPLE__) && defined(__MACH__)) \
+  || defined(__sun)
+#   define SQLITE_MAX_MMAP_SIZE 0x7fff0000  /* 2147418112 */
+# else
+#   define SQLITE_MAX_MMAP_SIZE 0
+# endif
+# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
+#endif
+
+/*
+** The default MMAP_SIZE is zero on all platforms.  Or, even if a larger
+** default MMAP_SIZE is specified at compile-time, make sure that it does
+** not exceed the maximum mmap size.
+*/
+#ifndef SQLITE_DEFAULT_MMAP_SIZE
+# define SQLITE_DEFAULT_MMAP_SIZE 0
+# define SQLITE_DEFAULT_MMAP_SIZE_xc 1  /* Exclude from ctime.c */
+#endif
+#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
+# undef SQLITE_DEFAULT_MMAP_SIZE
+# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
+#endif
 
 /*
 ** An instance of the following structure is used to store the busy-handler
@@ -8178,6 +8375,11 @@ struct BusyHandler {
 #define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))
 
 /*
+** Determine if the argument is a power of two
+*/
+#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
+
+/*
 ** The following value as a destructor means to use sqlite3DbFree().
 ** The sqlite3DbFree() routine requires two parameters instead of the 
 ** one parameter that destructors normally want.  So we have to introduce 
@@ -8263,6 +8465,7 @@ typedef struct Parse Parse;
 typedef struct RowSet RowSet;
 typedef struct Savepoint Savepoint;
 typedef struct Select Select;
+typedef struct SelectDest SelectDest;
 typedef struct SrcList SrcList;
 typedef struct StrAccum StrAccum;
 typedef struct Table Table;
@@ -8351,6 +8554,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
 
 SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
 SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
 SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
 SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
 SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
@@ -8359,6 +8563,9 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
 SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
 SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
 SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
+#endif
 SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
 SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
@@ -8402,6 +8609,8 @@ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
 SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
+
 /*
 ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
 ** should be one of the following values. The integer values are assigned 
@@ -8422,6 +8631,7 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 #define BTREE_TEXT_ENCODING       5
 #define BTREE_USER_VERSION        6
 #define BTREE_INCR_VACUUM         7
+#define BTREE_APPLICATION_ID      8
 
 /*
 ** Values that may be OR'd together to form the second argument of an
@@ -8869,7 +9079,7 @@ typedef struct VdbeOpList VdbeOpList;
 #define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */
 #define OPFLG_INITIALIZER {\
 /*   0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
+/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
 /*  16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
 /*  24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
 /*  32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
@@ -8916,7 +9126,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
 SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
 SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
@@ -9047,6 +9257,12 @@ typedef struct PgHdr DbPage;
 #define PAGER_JOURNALMODE_WAL         5   /* Use write-ahead logging */
 
 /*
+** Flags that make up the mask passed to sqlite3PagerAcquire().
+*/
+#define PAGER_ACQUIRE_NOCONTENT     0x01  /* Do not load data from disk */
+#define PAGER_ACQUIRE_READONLY      0x02  /* Read-only page is acceptable */
+
+/*
 ** The remainder of this file contains the declarations of the functions
 ** that make up the Pager sub-system API. See source code comments for 
 ** a detailed description of each routine.
@@ -9070,6 +9286,7 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
 SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
 SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
 SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
+SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
 SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
 SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
 SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
@@ -9106,11 +9323,14 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
 SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
 SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
 
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
-SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE   int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
+SQLITE_PRIVATE   int sqlite3PagerWalSupported(Pager *pPager);
+SQLITE_PRIVATE   int sqlite3PagerWalCallback(Pager *pPager);
+SQLITE_PRIVATE   int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
+SQLITE_PRIVATE   int sqlite3PagerCloseWal(Pager *pPager);
+#endif
+
 #ifdef SQLITE_ENABLE_ZIPVFS
 SQLITE_PRIVATE   int sqlite3PagerWalFramesize(Pager *pPager);
 #endif
@@ -9128,6 +9348,7 @@ SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
 SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *);
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
 
 /* Functions used to truncate the database file. */
 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
@@ -9212,6 +9433,8 @@ struct PgHdr {
 #define PGHDR_REUSE_UNLIKELY    0x010  /* A hint that reuse is unlikely */
 #define PGHDR_DONT_WRITE        0x020  /* Do not write content to disk */
 
+#define PGHDR_MMAP              0x040  /* This is an mmap page object */
+
 /* Initialize and shutdown the page cache subsystem */
 SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
 SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
@@ -9423,14 +9646,6 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 # define SQLITE_OS_WINRT 0
 #endif
 
-/*
-** When compiled for WinCE or WinRT, there is no concept of the current
-** directory.
- */
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-# define SQLITE_CURDIR 1
-#endif
-
 /* If the SET_FULLSYNC macro is not defined above, then make it
 ** a no-op
 */
@@ -9583,6 +9798,8 @@ SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
 SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
 SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
 SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
+SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
+SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
 
 
 /* 
@@ -9822,9 +10039,11 @@ struct sqlite3 {
   int nDb;                      /* Number of backends currently in use */
   int flags;                    /* Miscellaneous flags. See below */
   i64 lastRowid;                /* ROWID of most recent insert (see above) */
+  i64 szMmap;                   /* Default mmap_size setting */
   unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
   int errCode;                  /* Most recent error code (SQLITE_*) */
   int errMask;                  /* & result codes with this before returning */
+  u16 dbOptFlags;               /* Flags to enable/disable optimizations */
   u8 autoCommit;                /* The auto-commit flag. */
   u8 temp_store;                /* 1: file 2: memory 0: default */
   u8 mallocFailed;              /* True if we have seen a malloc failure */
@@ -9929,48 +10148,60 @@ struct sqlite3 {
 /*
 ** Possible values for the sqlite3.flags.
 */
-#define SQLITE_VdbeTrace      0x00000100  /* True to trace VDBE execution */
-#define SQLITE_InternChanges  0x00000200  /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames   0x00000400  /* Show full column names on SELECT */
-#define SQLITE_ShortColNames  0x00000800  /* Show short columns names */
-#define SQLITE_CountRows      0x00001000  /* Count rows changed by INSERT, */
+#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
+#define SQLITE_InternChanges  0x00000002  /* Uncommitted Hash table changes */
+#define SQLITE_FullColNames   0x00000004  /* Show full column names on SELECT */
+#define SQLITE_ShortColNames  0x00000008  /* Show short columns names */
+#define SQLITE_CountRows      0x00000010  /* Count rows changed by INSERT, */
                                           /*   DELETE, or UPDATE and return */
                                           /*   the count using a callback. */
-#define SQLITE_NullCallback   0x00002000  /* Invoke the callback once if the */
+#define SQLITE_NullCallback   0x00000020  /* Invoke the callback once if the */
                                           /*   result set is empty */
-#define SQLITE_SqlTrace       0x00004000  /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing    0x00008000  /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema    0x00010000  /* OK to update SQLITE_MASTER */
-                         /*   0x00020000  Unused */
-#define SQLITE_IgnoreChecks   0x00040000  /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0080000  /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt  0x00100000  /* Create new databases in format 1 */
-#define SQLITE_FullFSync      0x00200000  /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync  0x00400000  /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode   0x00800000  /* Ignore schema errors */
-#define SQLITE_ReverseOrder   0x01000000  /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers    0x02000000  /* Enable recursive triggers */
-#define SQLITE_ForeignKeys    0x04000000  /* Enforce foreign key constraints  */
-#define SQLITE_AutoIndex      0x08000000  /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin  0x10000000  /* Preference to built-in funcs */
-#define SQLITE_LoadExtension  0x20000000  /* Enable load_extension */
-#define SQLITE_EnableTrigger  0x40000000  /* True to enable triggers */
-
-/*
-** Bits of the sqlite3.flags field that are used by the
-** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface.
-** These must be the low-order bits of the flags field.
-*/
-#define SQLITE_QueryFlattener 0x01        /* Disable query flattening */
-#define SQLITE_ColumnCache    0x02        /* Disable the column cache */
-#define SQLITE_IndexSort      0x04        /* Disable indexes for sorting */
-#define SQLITE_IndexSearch    0x08        /* Disable indexes for searching */
-#define SQLITE_IndexCover     0x10        /* Disable index covering table */
-#define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
-#define SQLITE_IdxRealAsInt   0x80        /* Store REAL as INT in indices */
-#define SQLITE_DistinctOpt    0x80        /* DISTINCT using indexes */
-#define SQLITE_OptMask        0xff        /* Mask of all disablable opts */
+#define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00000200  /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
+#define SQLITE_FullFSync      0x00002000  /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync  0x00004000  /* Use full fsync for checkpoint */
+#define SQLITE_RecoveryMode   0x00008000  /* Ignore schema errors */
+#define SQLITE_ReverseOrder   0x00010000  /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers    0x00020000  /* Enable recursive triggers */
+#define SQLITE_ForeignKeys    0x00040000  /* Enforce foreign key constraints  */
+#define SQLITE_AutoIndex      0x00080000  /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin  0x00100000  /* Preference to built-in funcs */
+#define SQLITE_LoadExtension  0x00200000  /* Enable load_extension */
+#define SQLITE_EnableTrigger  0x00400000  /* True to enable triggers */
+
+/*
+** Bits of the sqlite3.dbOptFlags field that are used by the
+** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
+** selectively disable various optimizations.
+*/
+#define SQLITE_QueryFlattener 0x0001   /* Query flattening */
+#define SQLITE_ColumnCache    0x0002   /* Column cache */
+#define SQLITE_GroupByOrder   0x0004   /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x0008   /* Constant factoring */
+#define SQLITE_IdxRealAsInt   0x0010   /* Store REAL as INT in indices */
+#define SQLITE_DistinctOpt    0x0020   /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan   0x0040   /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x0080   /* ORDER BY of joins via index */
+#define SQLITE_SubqCoroutine  0x0100   /* Evaluate subqueries as coroutines */
+#define SQLITE_Transitive     0x0200   /* Transitive constraints */
+#define SQLITE_AllOpts        0xffff   /* All optimizations */
+
+/*
+** Macros for testing whether or not optimizations are enabled or disabled.
+*/
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+#define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)
+#define OptimizationEnabled(db, mask)   (((db)->dbOptFlags&(mask))==0)
+#else
+#define OptimizationDisabled(db, mask)  0
+#define OptimizationEnabled(db, mask)   1
+#endif
 
 /*
 ** Possible values for the sqlite.magic field.
@@ -10121,32 +10352,22 @@ struct Column {
   char *zDflt;     /* Original text of the default value */
   char *zType;     /* Data type for this column */
   char *zColl;     /* Collating sequence.  If NULL, use the default */
-  u8 notNull;      /* True if there is a NOT NULL constraint */
-  u8 isPrimKey;    /* True if this column is part of the PRIMARY KEY */
+  u8 notNull;      /* An OE_ code for handling a NOT NULL constraint */
   char affinity;   /* One of the SQLITE_AFF_... values */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-  u8 isHidden;     /* True if this column is 'hidden' */
-#endif
+  u16 colFlags;    /* Boolean properties.  See COLFLAG_ defines below */
 };
 
+/* Allowed values for Column.colFlags:
+*/
+#define COLFLAG_PRIMKEY  0x0001    /* Column is part of the primary key */
+#define COLFLAG_HIDDEN   0x0002    /* A hidden column in a virtual table */
+
 /*
 ** A "Collating Sequence" is defined by an instance of the following
 ** structure. Conceptually, a collating sequence consists of a name and
 ** a comparison routine that defines the order of that sequence.
 **
-** There may two separate implementations of the collation function, one
-** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
-** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
-** native byte order. When a collation sequence is invoked, SQLite selects
-** the version that will require the least expensive encoding
-** translations, if any.
-**
-** The CollSeq.pUser member variable is an extra parameter that passed in
-** as the first argument to the UTF-8 comparison function, xCmp.
-** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
-** xCmp16.
-**
-** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
+** If CollSeq.xCmp is NULL, it means that the
 ** collating sequence is undefined.  Indices built on an undefined
 ** collating sequence may not be read or written.
 */
@@ -10284,28 +10505,28 @@ struct VTable {
 */
 struct Table {
   char *zName;         /* Name of the table or view */
-  int iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
-  int nCol;            /* Number of columns in this table */
   Column *aCol;        /* Information about each column */
   Index *pIndex;       /* List of SQL indexes on this table. */
-  int tnum;            /* Root BTree node for this table (see note above) */
-  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
   Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
-  u16 nRef;            /* Number of pointers to this Table */
-  u8 tabFlags;         /* Mask of TF_* values */
-  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
   FKey *pFKey;         /* Linked list of all foreign keys in this table */
   char *zColAff;       /* String defining the affinity of each column */
 #ifndef SQLITE_OMIT_CHECK
   ExprList *pCheck;    /* All CHECK constraints */
 #endif
+  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
+  int tnum;            /* Root BTree node for this table (see note above) */
+  i16 iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
+  i16 nCol;            /* Number of columns in this table */
+  u16 nRef;            /* Number of pointers to this Table */
+  u8 tabFlags;         /* Mask of TF_* values */
+  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
 #ifndef SQLITE_OMIT_ALTERTABLE
   int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
 #endif
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  VTable *pVTable;     /* List of VTable objects. */
   int nModuleArg;      /* Number of arguments to the module */
   char **azModuleArg;  /* Text of all module args. [0] is module name */
+  VTable *pVTable;     /* List of VTable objects. */
 #endif
   Trigger *pTrigger;   /* List of triggers stored in pSchema */
   Schema *pSchema;     /* Schema that contains this table */
@@ -10329,7 +10550,7 @@ struct Table {
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #  define IsVirtual(X)      (((X)->tabFlags & TF_Virtual)!=0)
-#  define IsHiddenColumn(X) ((X)->isHidden)
+#  define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
 #else
 #  define IsVirtual(X)      0
 #  define IsHiddenColumn(X) 0
@@ -10480,20 +10701,20 @@ struct UnpackedRecord {
 ** element.
 */
 struct Index {
-  char *zName;     /* Name of this index */
-  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
-  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
-  Table *pTable;   /* The SQL table being indexed */
-  char *zColAff;   /* String defining the affinity of each column */
-  Index *pNext;    /* The next index associated with the same table */
-  Schema *pSchema; /* Schema containing this index */
-  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
-  char **azColl;   /* Array of collation sequence names for index */
-  int nColumn;     /* Number of columns in the table used by this index */
-  int tnum;        /* Page containing root of this index in database file */
-  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
-  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
-  u8 bUnordered;   /* Use this index for == or IN queries only */
+  char *zName;             /* Name of this index */
+  int *aiColumn;           /* Which columns are used by this index.  1st is 0 */
+  tRowcnt *aiRowEst;       /* From ANALYZE: Est. rows selected by each column */
+  Table *pTable;           /* The SQL table being indexed */
+  char *zColAff;           /* String defining the affinity of each column */
+  Index *pNext;            /* The next index associated with the same table */
+  Schema *pSchema;         /* Schema containing this index */
+  u8 *aSortOrder;          /* for each column: True==DESC, False==ASC */
+  char **azColl;           /* Array of collation sequence names for index */
+  int tnum;                /* DB Page containing root of this index */
+  u16 nColumn;             /* Number of columns in table used by this index */
+  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
+  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
 #ifdef SQLITE_ENABLE_STAT3
   int nSample;             /* Number of elements in aSample[] */
   tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
@@ -10674,13 +10895,15 @@ struct Expr {
     ExprList *pList;     /* Function arguments or in "<expr> IN (<expr-list)" */
     Select *pSelect;     /* Used for sub-selects and "<expr> IN (<select>)" */
   } x;
-  CollSeq *pColl;        /* The collation type of the column or 0 */
 
   /* If the EP_Reduced flag is set in the Expr.flags mask, then no
   ** space is allocated for the fields below this point. An attempt to
   ** access them will result in a segfault or malfunction.
   *********************************************************************/
 
+#if SQLITE_MAX_EXPR_DEPTH>0
+  int nHeight;           /* Height of the tree headed by this node */
+#endif
   int iTable;            /* TK_COLUMN: cursor number of table holding column
                          ** TK_REGISTER: register number
                          ** TK_TRIGGER: 1 -> new, 0 -> old */
@@ -10694,9 +10917,6 @@ struct Expr {
                          ** TK_AGG_FUNCTION: nesting depth */
   AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
   Table *pTab;           /* Table for TK_COLUMN expressions. */
-#if SQLITE_MAX_EXPR_DEPTH>0
-  int nHeight;           /* Height of the tree headed by this node */
-#endif
 };
 
 /*
@@ -10710,7 +10930,7 @@ struct Expr {
 #define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
 #define EP_DblQuoted  0x0040  /* token.z was originally in "..." */
 #define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
-#define EP_ExpCollate 0x0100  /* Collating sequence specified explicitly */
+#define EP_Collate    0x0100  /* Tree contains a TK_COLLATE opeartor */
 #define EP_FixedDest  0x0200  /* Result needed in a specific register */
 #define EP_IntValue   0x0400  /* Integer value contained in u.iValue */
 #define EP_xIsSelect  0x0800  /* x.pSelect is valid (otherwise x.pList is) */
@@ -10768,18 +10988,27 @@ struct Expr {
 ** list of "ID = expr" items in an UPDATE.  A list of expressions can
 ** also be used as the argument to a function, in which case the a.zName
 ** field is not used.
+**
+** By default the Expr.zSpan field holds a human-readable description of
+** the expression that is used in the generation of error messages and
+** column labels.  In this case, Expr.zSpan is typically the text of a
+** column expression as it exists in a SELECT statement.  However, if
+** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
+** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
+** form is used for name resolution with nested FROM clauses.
 */
 struct ExprList {
   int nExpr;             /* Number of expressions on the list */
   int iECursor;          /* VDBE Cursor associated with this ExprList */
   struct ExprList_item { /* For each expression in the list */
-    Expr *pExpr;           /* The list of expressions */
-    char *zName;           /* Token associated with this expression */
-    char *zSpan;           /* Original text of the expression */
-    u8 sortOrder;          /* 1 for DESC or 0 for ASC */
-    u8 done;               /* A flag to indicate when processing is finished */
-    u16 iOrderByCol;       /* For ORDER BY, column number in result set */
-    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
+    Expr *pExpr;            /* The list of expressions */
+    char *zName;            /* Token associated with this expression */
+    char *zSpan;            /* Original text of the expression */
+    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
+    unsigned done :1;       /* A flag to indicate when processing is finished */
+    unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
+    u16 iOrderByCol;        /* For ORDER BY, column number in result set */
+    u16 iAlias;             /* Index into Parse.aAlias[] for zName */
   } *a;                  /* Alloc a power of two greater or equal to nExpr */
 };
 
@@ -10854,6 +11083,7 @@ struct SrcList {
   i16 nSrc;        /* Number of tables or subqueries in the FROM clause */
   i16 nAlloc;      /* Number of entries allocated in a[] below */
   struct SrcList_item {
+    Schema *pSchema;  /* Schema to which this item is fixed */
     char *zDatabase;  /* Name of database holding this table */
     char *zName;      /* Name of the table */
     char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
@@ -10862,8 +11092,9 @@ struct SrcList {
     int addrFillSub;  /* Address of subroutine to manifest a subquery */
     int regReturn;    /* Register holding return address of addrFillSub */
     u8 jointype;      /* Type of join between this able and the previous */
-    u8 notIndexed;    /* True if there is a NOT INDEXED clause */
-    u8 isCorrelated;  /* True if sub-query is correlated */
+    unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
+    unsigned isCorrelated :1;  /* True if sub-query is correlated */
+    unsigned viaCoroutine :1;  /* Implemented as a co-routine */
 #ifndef SQLITE_OMIT_EXPLAIN
     u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
 #endif
@@ -10904,7 +11135,8 @@ struct SrcList {
 */
 struct WherePlan {
   u32 wsFlags;                   /* WHERE_* flags that describe the strategy */
-  u32 nEq;                       /* Number of == constraints */
+  u16 nEq;                       /* Number of == constraints */
+  u16 nOBSat;                    /* Number of ORDER BY terms satisfied */
   double nRow;                   /* Estimated number of rows (for EQP) */
   union {
     Index *pIdx;                   /* Index when WHERE_INDEXED is true */
@@ -10944,10 +11176,12 @@ struct WhereLevel {
       struct InLoop {
         int iCur;              /* The VDBE cursor used by this IN operator */
         int addrInTop;         /* Top of the IN loop */
+        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
       } *aInLoop;           /* Information about each nested IN operator */
     } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
     Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
   } u;
+  double rOptCost;      /* "Optimal" cost for this level */
 
   /* The following field is really not part of the current level.  But
   ** we need a place to cache virtual table index information for each
@@ -10980,24 +11214,28 @@ struct WhereLevel {
 ** into the second half to give some continuity.
 */
 struct WhereInfo {
-  Parse *pParse;       /* Parsing and code generating context */
-  u16 wctrlFlags;      /* Flags originally passed to sqlite3WhereBegin() */
-  u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
-  u8 untestedTerms;    /* Not all WHERE terms resolved by outer loop */
-  u8 eDistinct;
-  SrcList *pTabList;             /* List of tables in the join */
-  int iTop;                      /* The very beginning of the WHERE loop */
-  int iContinue;                 /* Jump here to continue with next record */
-  int iBreak;                    /* Jump here to break out of the loop */
-  int nLevel;                    /* Number of nested loop */
-  struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
-  double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE loop */
-  double nRowOut;                /* Estimated number of output rows */
-  WhereLevel a[1];               /* Information about each nest loop in WHERE */
+  Parse *pParse;            /* Parsing and code generating context */
+  SrcList *pTabList;        /* List of tables in the join */
+  u16 nOBSat;               /* Number of ORDER BY terms satisfied by indices */
+  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
+  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
+  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
+  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
+  int iTop;                 /* The very beginning of the WHERE loop */
+  int iContinue;            /* Jump here to continue with next record */
+  int iBreak;               /* Jump here to break out of the loop */
+  int nLevel;               /* Number of nested loop */
+  struct WhereClause *pWC;  /* Decomposition of the WHERE clause */
+  double savedNQueryLoop;   /* pParse->nQueryLoop outside the WHERE loop */
+  double nRowOut;           /* Estimated number of output rows */
+  WhereLevel a[1];          /* Information about each nest loop in WHERE */
 };
 
-#define WHERE_DISTINCT_UNIQUE 1
-#define WHERE_DISTINCT_ORDERED 2
+/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
+#define WHERE_DISTINCT_NOOP      0  /* DISTINCT keyword not used */
+#define WHERE_DISTINCT_UNIQUE    1  /* No duplicates */
+#define WHERE_DISTINCT_ORDERED   2  /* All duplicates are adjacent */
+#define WHERE_DISTINCT_UNORDERED 3  /* Duplicates are scattered */
 
 /*
 ** A NameContext defines a context in which to resolve table and column
@@ -11038,6 +11276,8 @@ struct NameContext {
 #define NC_HasAgg    0x02    /* One or more aggregate functions seen */
 #define NC_IsCheck   0x04    /* True if resolving names in a CHECK constraint */
 #define NC_InAggFunc 0x08    /* True if analyzing arguments to an agg func */
+#define NC_AsMaybe   0x10    /* Resolve to AS terms of the result set only
+                             ** if no other resolution is available */
 
 /*
 ** An instance of the following structure contains all information
@@ -11056,13 +11296,12 @@ struct NameContext {
 ** as the OP_OpenEphm instruction is coded because not
 ** enough information about the compound query is known at that point.
 ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
-** for the result set.  The KeyInfo for addrOpenTran[2] contains collating
+** for the result set.  The KeyInfo for addrOpenEphm[2] contains collating
 ** sequences for the ORDER BY clause.
 */
 struct Select {
   ExprList *pEList;      /* The fields of the result */
   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
-  char affinity;         /* MakeRecord with this affinity for SRT_Set */
   u16 selFlags;          /* Various SF_* values */
   int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
   int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
@@ -11083,14 +11322,16 @@ struct Select {
 ** Allowed values for Select.selFlags.  The "SF" prefix stands for
 ** "Select Flag".
 */
-#define SF_Distinct        0x01  /* Output should be DISTINCT */
-#define SF_Resolved        0x02  /* Identifiers have been resolved */
-#define SF_Aggregate       0x04  /* Contains aggregate functions */
-#define SF_UsesEphemeral   0x08  /* Uses the OpenEphemeral opcode */
-#define SF_Expanded        0x10  /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo     0x20  /* FROM subqueries have Table metadata */
-#define SF_UseSorter       0x40  /* Sort using a sorter */
-#define SF_Values          0x80  /* Synthesized from VALUES clause */
+#define SF_Distinct        0x0001  /* Output should be DISTINCT */
+#define SF_Resolved        0x0002  /* Identifiers have been resolved */
+#define SF_Aggregate       0x0004  /* Contains aggregate functions */
+#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
+#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
+#define SF_UseSorter       0x0040  /* Sort using a sorter */
+#define SF_Values          0x0080  /* Synthesized from VALUES clause */
+#define SF_Materialize     0x0100  /* Force materialization of views */
+#define SF_NestedFrom      0x0200  /* Part of a parenthesized FROM clause */
 
 
 /*
@@ -11113,13 +11354,12 @@ struct Select {
 #define SRT_Coroutine   10  /* Generate a single row of result */
 
 /*
-** A structure used to customize the behavior of sqlite3Select(). See
-** comments above sqlite3Select() for details.
+** An instance of this object describes where to put of the results of
+** a SELECT statement.
 */
-typedef struct SelectDest SelectDest;
 struct SelectDest {
-  u8 eDest;         /* How to dispose of the results */
-  u8 affSdst;       /* Affinity used when eDest==SRT_Set */
+  u8 eDest;         /* How to dispose of the results.  On of SRT_* above. */
+  char affSdst;     /* Affinity used when eDest==SRT_Set */
   int iSDParm;      /* A parameter used by the eDest disposal method */
   int iSdst;        /* Base register where results are written */
   int nSdst;        /* Number of registers allocated */
@@ -11320,6 +11560,7 @@ struct AuthContext {
 #define OPFLAG_TYPEOFARG     0x80    /* OP_Column only used for typeof() */
 #define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
 #define OPFLAG_P2ISREG       0x02    /* P2 to OP_Open** is a register number */
+#define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
 
 /*
  * Each trigger present in the database schema is stored as an instance of
@@ -11419,6 +11660,7 @@ struct TriggerStep {
 typedef struct DbFixer DbFixer;
 struct DbFixer {
   Parse *pParse;      /* The parsing context.  Error messages written here */
+  Schema *pSchema;    /* Fix items to this schema */
   const char *zDb;    /* Make sure all objects are contained in this database */
   const char *zType;  /* Type of the container - used for error messages */
   const Token *pName; /* Name of the container - used for error messages */
@@ -11461,6 +11703,7 @@ struct Sqlite3Config {
   int bCoreMutex;                   /* True to enable core mutexing */
   int bFullMutex;                   /* True to enable full mutexing */
   int bOpenUri;                     /* True to interpret filenames as URIs */
+  int bUseCis;                      /* Use covering indices for full-scans */
   int mxStrlen;                     /* Maximum string length */
   int szLookaside;                  /* Default lookaside buffer size */
   int nLookaside;                   /* Default lookaside buffer count */
@@ -11470,6 +11713,8 @@ struct Sqlite3Config {
   void *pHeap;                      /* Heap storage space */
   int nHeap;                        /* Size of pHeap[] */
   int mnReq, mxReq;                 /* Min and max heap requests sizes */
+  sqlite3_int64 szMmap;             /* mmap() space per open file */
+  sqlite3_int64 mxMmap;             /* Maximum value for szMmap */
   void *pScratch;                   /* Scratch memory */
   int szScratch;                    /* Size of each scratch buffer */
   int nScratch;                     /* Number of scratch buffers */
@@ -11490,6 +11735,10 @@ struct Sqlite3Config {
   void (*xLog)(void*,int,const char*); /* Function for logging */
   void *pLogArg;                       /* First argument to xLog() */
   int bLocaltimeFault;              /* True to fail localtime() calls */
+#ifdef SQLITE_ENABLE_SQLLOG
+  void(*xSqllog)(void*,sqlite3*,const char*, int);
+  void *pSqllogArg;
+#endif
 };
 
 /*
@@ -11500,6 +11749,7 @@ struct Walker {
   int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
   Parse *pParse;                            /* Parser context.  */
   int walkerDepth;                          /* Number of subqueries */
+  u8 bSelectDepthFirst;                     /* Do subqueries first */
   union {                                   /* Extra data for callback */
     NameContext *pNC;                          /* Naming context */
     int i;                                     /* Integer value */
@@ -11777,6 +12027,7 @@ SQLITE_PRIVATE   void sqlite3AutoincrementEnd(Parse *pParse);
 # define sqlite3AutoincrementBegin(X)
 # define sqlite3AutoincrementEnd(X)
 #endif
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
 SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
 SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
 SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
@@ -11796,23 +12047,21 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*
 SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
 SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
 SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
-                         Expr*,ExprList*,int,Expr*,Expr*);
+                         Expr*,ExprList*,u16,Expr*,Expr*);
 SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
 SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
 SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
 SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
 #endif
 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
-    Parse*,SrcList*,Expr*,ExprList**,ExprList*,u16,int);
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
 SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
@@ -11829,6 +12078,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
 SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
 SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
 SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
 SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
 SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
 SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
@@ -11871,7 +12121,7 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
 SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
 SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
 SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, char*, int);
+SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
 SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
 SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
 SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
@@ -11952,7 +12202,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
 SQLITE_PRIVATE int sqlite3Atoi(const char*);
 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
-SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8*, const u8**);
+SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
 
 /*
 ** Routines to read and write variable-length integers.  These used to
@@ -11984,8 +12234,11 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
 **     x = putVarint32( A, B );
 **
 */
-#define getVarint32(A,B)  (u8)((*(A)<(u8)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
-#define putVarint32(A,B)  (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : 
sqlite3PutVarint32((A), (B)))
+#define getVarint32(A,B)  \
+  (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
+#define putVarint32(A,B)  \
+  (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
+  sqlite3PutVarint32((A),(B)))
 #define getVarint    sqlite3GetVarint
 #define putVarint    sqlite3PutVarint
 
@@ -12000,13 +12253,20 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
+    defined(SQLITE_DEBUG_OS_TRACE)
+SQLITE_PRIVATE const char *sqlite3ErrName(int);
+#endif
+
 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
@@ -12053,13 +12313,14 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
 SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
 SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
 SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
 SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
 SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(sqlite3*, u8, CollSeq *, const char*);
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
 SQLITE_PRIVATE char sqlite3AffinityType(const char*);
 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
@@ -12163,8 +12424,10 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
 SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
 SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
 SQLITE_PRIVATE const char *sqlite3JournalModename(int);
-SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
-SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE   int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
+SQLITE_PRIVATE   int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#endif
 
 /* Declarations for functions in fkey.c. All of these are replaced by
 ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
@@ -12189,8 +12452,10 @@ SQLITE_PRIVATE   FKey *sqlite3FkReferences(Table *);
 #endif
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 SQLITE_PRIVATE   void sqlite3FkDelete(sqlite3 *, Table*);
+SQLITE_PRIVATE   int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
 #else
   #define sqlite3FkDelete(a,b)
+  #define sqlite3FkLocateIndex(a,b,c,d,e)
 #endif
 
 
@@ -12215,15 +12480,18 @@ SQLITE_PRIVATE   void sqlite3EndBenignMalloc(void);
 
 #define IN_INDEX_ROWID           1
 #define IN_INDEX_EPH             2
-#define IN_INDEX_INDEX           3
+#define IN_INDEX_INDEX_ASC       3
+#define IN_INDEX_INDEX_DESC      4
 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
 
 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
 SQLITE_PRIVATE   int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
 SQLITE_PRIVATE   int sqlite3JournalSize(sqlite3_vfs *);
 SQLITE_PRIVATE   int sqlite3JournalCreate(sqlite3_file *);
+SQLITE_PRIVATE   int sqlite3JournalExists(sqlite3_file *p);
 #else
   #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
+  #define sqlite3JournalExists(p) 1
 #endif
 
 SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
@@ -12452,6 +12720,10 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
 # define  SQLITE_USE_URI 0
 #endif
 
+#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#endif
+
 /*
 ** The following singleton contains the global configuration for
 ** the SQLite library.
@@ -12461,6 +12733,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    1,                         /* bCoreMutex */
    SQLITE_THREADSAFE==1,      /* bFullMutex */
    SQLITE_USE_URI,            /* bOpenUri */
+   SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
    0x7ffffffe,                /* mxStrlen */
    128,                       /* szLookaside */
    500,                       /* nLookaside */
@@ -12470,6 +12743,8 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    (void*)0,                  /* pHeap */
    0,                         /* nHeap */
    0, 0,                      /* mnHeap, mxHeap */
+   SQLITE_DEFAULT_MMAP_SIZE,  /* szMmap */
+   SQLITE_MAX_MMAP_SIZE,      /* mxMmap */
    (void*)0,                  /* pScratch */
    0,                         /* szScratch */
    0,                         /* nScratch */
@@ -12489,6 +12764,10 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    0,                         /* xLog */
    0,                         /* pLogArg */
    0,                         /* bLocaltimeFault */
+#ifdef SQLITE_ENABLE_SQLLOG
+   0,                         /* xSqllog */
+   0                          /* pSqllogArg */
+#endif
 };
 
 
@@ -12589,15 +12868,15 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_COVERAGE_TEST
   "COVERAGE_TEST",
 #endif
-#ifdef SQLITE_CURDIR
-  "CURDIR",
-#endif
 #ifdef SQLITE_DEBUG
   "DEBUG",
 #endif
 #ifdef SQLITE_DEFAULT_LOCKING_MODE
   "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
 #endif
+#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
+  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
+#endif
 #ifdef SQLITE_DISABLE_DIRSYNC
   "DISABLE_DIRSYNC",
 #endif
@@ -12688,6 +12967,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_LOCK_TRACE
   "LOCK_TRACE",
 #endif
+#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
+  "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
+#endif
 #ifdef SQLITE_MAX_SCHEMA_RETRY
   "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
 #endif
@@ -12745,11 +13027,6 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_OMIT_CHECK
   "OMIT_CHECK",
 #endif
-/* // redundant
-** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
-**   "OMIT_COMPILEOPTION_DIAGS",
-** #endif
-*/
 #ifdef SQLITE_OMIT_COMPLETE
   "OMIT_COMPLETE",
 #endif
@@ -12804,9 +13081,6 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_OMIT_MEMORYDB
   "OMIT_MEMORYDB",
 #endif
-#ifdef SQLITE_OMIT_MERGE_SORT
-  "OMIT_MERGE_SORT",
-#endif
 #ifdef SQLITE_OMIT_OR_OPTIMIZATION
   "OMIT_OR_OPTIMIZATION",
 #endif
@@ -12879,6 +13153,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_PROXY_DEBUG
   "PROXY_DEBUG",
 #endif
+#ifdef SQLITE_RTREE_INT_ONLY
+  "RTREE_INT_ONLY",
+#endif
 #ifdef SQLITE_SECURE_DELETE
   "SECURE_DELETE",
 #endif
@@ -12891,13 +13168,13 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_TCL
   "TCL",
 #endif
-#ifdef SQLITE_TEMP_STORE
+#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
   "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
 #endif
 #ifdef SQLITE_TEST
   "TEST",
 #endif
-#ifdef SQLITE_THREADSAFE
+#if defined(SQLITE_THREADSAFE)
   "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
 #endif
 #ifdef SQLITE_USE_ALLOCA
@@ -12923,8 +13200,11 @@ SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
   /* Since ArraySize(azCompileOpt) is normally in single digits, a
   ** linear search is adequate.  No need for a binary search. */
   for(i=0; i<ArraySize(azCompileOpt); i++){
-    if(   (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
-       && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
+    if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
+     && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
+    ){
+      return 1;
+    }
   }
   return 0;
 }
@@ -12982,6 +13262,14 @@ SQLITE_API const char *sqlite3_compileoption_get(int N){
 #define _VDBEINT_H_
 
 /*
+** The maximum number of times that a statement will try to reparse
+** itself before giving up and returning SQLITE_SCHEMA.
+*/
+#ifndef SQLITE_MAX_SCHEMA_RETRY
+# define SQLITE_MAX_SCHEMA_RETRY 50
+#endif
+
+/*
 ** SQL is translated into a sequence of instructions to be
 ** executed by a virtual machine.  Each instruction is an instance
 ** of the following structure.
@@ -13026,6 +13314,7 @@ struct VdbeCursor {
   Bool isIndex;         /* True if an index containing keys only - no data */
   Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
   Bool isSorter;        /* True if a new-style sorter */
+  Bool multiPseudo;     /* Multi-register pseudo-cursor */
   sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
   const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
   i64 seqCount;         /* Sequence counter */
@@ -13085,7 +13374,7 @@ struct VdbeFrame {
   VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
   void *token;            /* Copy of SubProgram.token */
   i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
-  u16 nCursor;            /* Number of entries in apCsr */
+  int nCursor;            /* Number of entries in apCsr */
   int pc;                 /* Program Counter in parent (calling) frame */
   int nOp;                /* Size of aOp array */
   int nMem;               /* Number of entries in aMem */
@@ -13150,7 +13439,9 @@ struct Mem {
 #define MEM_RowSet    0x0020   /* Value is a RowSet object */
 #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
 #define MEM_Invalid   0x0080   /* Value is undefined */
-#define MEM_TypeMask  0x00ff   /* Mask of type bits */
+#define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
+#define MEM_TypeMask  0x01ff   /* Mask of type bits */
+
 
 /* Whenever Mem contains a valid string or blob representation, one of
 ** the following flags must be set to determine the memory management
@@ -13236,6 +13527,11 @@ struct Explain {
   char zBase[100];   /* Initial space */
 };
 
+/* A bitfield type for use inside of structures.  Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft;  /* Bit Field Type */
+
 /*
 ** An instance of the virtual machine.  This structure contains the complete
 ** state of the virtual machine.
@@ -13264,7 +13560,7 @@ struct Vdbe {
   int nLabel;             /* Number of labels used */
   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[] */
+  int 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 */
@@ -13277,15 +13573,16 @@ struct Vdbe {
   int pc;                 /* The program counter */
   int rc;                 /* Value to return */
   u8 errorAction;         /* Recovery action to do in case of an error */
-  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 */
-  u8 runOnlyOnce;         /* Automatically expire on reset */
   u8 minWriteFileFormat;  /* Minimum file format for writable database files */
-  u8 inVtabMethod;        /* See comments above */
-  u8 usesStmtJournal;     /* True if uses a statement journal */
-  u8 readOnly;            /* True for read-only statements */
-  u8 isPrepareV2;         /* True if prepared with prepare_v2() */
+  bft explain:2;          /* True if EXPLAIN present on SQL command */
+  bft inVtabMethod:2;     /* See comments above */
+  bft changeCntOn:1;      /* True to update the change-counter */
+  bft expired:1;          /* True if the VM needs to be recompiled */
+  bft runOnlyOnce:1;      /* Automatically expire on reset */
+  bft usesStmtJournal:1;  /* True if uses a statement journal */
+  bft readOnly:1;         /* True for read-only statements */
+  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
+  bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
   int nChange;            /* Number of db changes made since last reset */
   yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
   yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
@@ -13383,15 +13680,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
 SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
 SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
 
-#ifdef SQLITE_OMIT_MERGE_SORT
-# define sqlite3VdbeSorterInit(Y,Z)      SQLITE_OK
-# define sqlite3VdbeSorterWrite(X,Y,Z)   SQLITE_OK
-# define sqlite3VdbeSorterClose(Y,Z)
-# define sqlite3VdbeSorterRowkey(Y,Z)    SQLITE_OK
-# define sqlite3VdbeSorterRewind(X,Y,Z)  SQLITE_OK
-# define sqlite3VdbeSorterNext(X,Y,Z)    SQLITE_OK
-# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
-#else
 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
@@ -13399,7 +13687,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
-#endif
 
 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
 SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
@@ -13631,7 +13918,8 @@ SQLITE_API int sqlite3_db_status(
 
       db->pnBytesFreed = &nByte;
       for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
-        sqlite3VdbeDeleteObject(db, pVdbe);
+        sqlite3VdbeClearObject(db, pVdbe);
+        sqlite3DbFree(db, pVdbe);
       }
       db->pnBytesFreed = 0;
 
@@ -14947,6 +15235,26 @@ SQLITE_PRIVATE int sqlite3OsShmMap(
   return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
 }
 
+#if SQLITE_MAX_MMAP_SIZE>0
+/* The real implementation of xFetch and xUnfetch */
+SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
+  DO_OS_MALLOC_TEST(id);
+  return id->pMethods->xFetch(id, iOff, iAmt, pp);
+}
+SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
+  return id->pMethods->xUnfetch(id, iOff, p);
+}
+#else
+/* No-op stubs to use when memory-mapped I/O is disabled */
+SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
+  *pp = 0;
+  return SQLITE_OK;
+}
+SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
+  return SQLITE_OK;
+}
+#endif
+
 /*
 ** The next group of routines are convenience wrappers around the
 ** VFS methods.
@@ -20527,25 +20835,23 @@ static const unsigned char sqlite3Utf8Trans1[] = {
         || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
   }
 SQLITE_PRIVATE u32 sqlite3Utf8Read(
-  const unsigned char *zIn,       /* First byte of UTF-8 character */
-  const unsigned char **pzNext    /* Write first byte past UTF-8 char here */
+  const unsigned char **pz    /* Pointer to string from which to read char */
 ){
   unsigned int c;
 
   /* Same as READ_UTF8() above but without the zTerm parameter.
   ** For this routine, we assume the UTF8 string is always zero-terminated.
   */
-  c = *(zIn++);
+  c = *((*pz)++);
   if( c>=0xc0 ){
     c = sqlite3Utf8Trans1[c-0xc0];
-    while( (*zIn & 0xc0)==0x80 ){
-      c = (c<<6) + (0x3f & *(zIn++));
+    while( (*(*pz) & 0xc0)==0x80 ){
+      c = (c<<6) + (0x3f & *((*pz)++));
     }
     if( c<0x80
         || (c&0xFFFFF800)==0xD800
         || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
   }
-  *pzNext = zIn;
   return c;
 }
 
@@ -20646,7 +20952,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
     if( desiredEnc==SQLITE_UTF16LE ){
       /* UTF-8 -> UTF-16 Little-endian */
       while( zIn<zTerm ){
-        /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */
         READ_UTF8(zIn, zTerm, c);
         WRITE_UTF16LE(z, c);
       }
@@ -20654,7 +20959,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
       assert( desiredEnc==SQLITE_UTF16BE );
       /* UTF-8 -> UTF-16 Big-endian */
       while( zIn<zTerm ){
-        /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */
         READ_UTF8(zIn, zTerm, c);
         WRITE_UTF16BE(z, c);
       }
@@ -20782,7 +21086,7 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
   u32 c;
 
   while( zIn[0] && zOut<=zIn ){
-    c = sqlite3Utf8Read(zIn, (const u8**)&zIn);
+    c = sqlite3Utf8Read((const u8**)&zIn);
     if( c!=0xfffd ){
       WRITE_UTF8(zOut, c);
     }
@@ -20887,7 +21191,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
     assert( n>0 && n<=4 );
     z[0] = 0;
     z = zBuf;
-    c = sqlite3Utf8Read(z, (const u8**)&z);
+    c = sqlite3Utf8Read((const u8**)&z);
     t = i;
     if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
     if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
@@ -21186,7 +21490,7 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
 */
 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
 #ifndef SQLITE_OMIT_FLOATING_POINT
-  int incr = (enc==SQLITE_UTF8?1:2);
+  int incr;
   const char *zEnd = z + length;
   /* sign * significand * (10 ^ (esign * exponent)) */
   int sign = 1;    /* sign of significand */
@@ -21197,10 +21501,22 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
   int eValid = 1;  /* True exponent is either not used or is well-formed */
   double result;
   int nDigits = 0;
+  int nonNum = 0;
 
+  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
   *pResult = 0.0;   /* Default return value, in case of an error */
 
-  if( enc==SQLITE_UTF16BE ) z++;
+  if( enc==SQLITE_UTF8 ){
+    incr = 1;
+  }else{
+    int i;
+    incr = 2;
+    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+    for(i=3-enc; i<length && z[i]==0; i+=2){}
+    nonNum = i<length;
+    zEnd = z+i+enc-3;
+    z += (enc&1);
+  }
 
   /* skip leading spaces */
   while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
@@ -21333,7 +21649,7 @@ do_atof_calc:
   *pResult = result;
 
   /* return true if number and no extra non-whitespace chracters after */
-  return z>=zEnd && nDigits>0 && eValid;
+  return z>=zEnd && nDigits>0 && eValid && nonNum==0;
 #else
   return !sqlite3Atoi64(z, pResult, length, enc);
 #endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -21382,21 +21698,33 @@ static int compare2pow63(const char *zNum, int incr){
 ** signed 64-bit integer, its negative -9223372036854665808 can be.
 **
 ** If zNum is too big for a 64-bit integer and is not
-** 9223372036854665808 then return 1.
+** 9223372036854665808  or if zNum contains any non-numeric text,
+** then return 1.
 **
 ** length is the number of bytes in the string (bytes, not characters).
 ** The string is not necessarily zero-terminated.  The encoding is
 ** given by enc.
 */
 SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
-  int incr = (enc==SQLITE_UTF8?1:2);
+  int incr;
   u64 u = 0;
   int neg = 0; /* assume positive */
   int i;
   int c = 0;
+  int nonNum = 0;
   const char *zStart;
   const char *zEnd = zNum + length;
-  if( enc==SQLITE_UTF16BE ) zNum++;
+  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+  if( enc==SQLITE_UTF8 ){
+    incr = 1;
+  }else{
+    incr = 2;
+    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+    for(i=3-enc; i<length && zNum[i]==0; i+=2){}
+    nonNum = i<length;
+    zEnd = zNum+i+enc-3;
+    zNum += (enc&1);
+  }
   while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
   if( zNum<zEnd ){
     if( *zNum=='-' ){
@@ -21421,7 +21749,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
   testcase( i==18 );
   testcase( i==19 );
   testcase( i==20 );
-  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){
+  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
     /* zNum is empty or contains non-numeric text or is longer
     ** than 19 digits (thus guaranteeing that it is too large) */
     return 1;
@@ -22305,7 +22633,7 @@ static void removeElementGivenHash(
   }
   sqlite3_free( elem );
   pH->count--;
-  if( pH->count<=0 ){
+  if( pH->count==0 ){
     assert( pH->first==0 );
     assert( pH->count==0 );
     sqlite3HashClear(pH);
@@ -22603,6 +22931,13 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 */
 #if SQLITE_OS_UNIX              /* This file is used on unix only */
 
+/* Use posix_fallocate() if it is available
+*/
+#if !defined(HAVE_POSIX_FALLOCATE) \
+      && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+# define HAVE_POSIX_FALLOCATE 1
+#endif
+
 /*
 ** There are various methods for file locking used for concurrency
 ** control:
@@ -22676,7 +23011,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 /* #include <time.h> */
 #include <sys/time.h>
 #include <errno.h>
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
 #include <sys/mman.h>
 #endif
 
@@ -22775,6 +23110,15 @@ struct unixFile {
   const char *zPath;                  /* Name of the file */
   unixShm *pShm;                      /* Shared memory segment information */
   int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
+  int nFetchOut;                      /* Number of outstanding xFetch refs */
+  sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
+  sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
+  sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
+  void *pMapRegion;                   /* Memory mapped region */
+#ifdef __QNXNTO__
+  int sectorSize;                     /* Device sector size */
+  int deviceCharacteristics;          /* Precomputed device characteristics */
+#endif
 #if SQLITE_ENABLE_LOCKING_STYLE
   int openFlags;                      /* The flags specified at open() */
 #endif
@@ -22795,7 +23139,9 @@ struct unixFile {
   unsigned char transCntrChng;   /* True if the transaction counter changed */
   unsigned char dbUpdate;        /* True if any part of database file changed */
   unsigned char inNormalWrite;   /* True if in a normal write operation */
+
 #endif
+
 #ifdef SQLITE_TEST
   /* In test mode, increase the size of this structure a bit so that 
   ** it is larger than the struct CrashFile defined in test6.c.
@@ -22819,6 +23165,7 @@ struct unixFile {
 #define UNIXFILE_DELETE      0x20     /* Delete on close */
 #define UNIXFILE_URI         0x40     /* Filename might have query parameters */
 #define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
+#define UNIXFILE_WARNED    0x0100     /* verifyDbFile() warnings have been issued */
 
 /*
 ** Include code that is common to all os_*.c files
@@ -23061,6 +23408,17 @@ SQLITE_API int sqlite3_open_file_count = 0;
 #endif
 
 /*
+** HAVE_MREMAP defaults to true on Linux and false everywhere else.
+*/
+#if !defined(HAVE_MREMAP)
+# if defined(__linux__) && defined(_GNU_SOURCE)
+#  define HAVE_MREMAP 1
+# else
+#  define HAVE_MREMAP 0
+# endif
+#endif
+
+/*
 ** Different Unix systems declare open() in different ways.  Same use
 ** open(const char*,int,mode_t).  Others use open(const char*,int,...).
 ** The difference is important when using a pointer to the function.
@@ -23091,7 +23449,7 @@ static int openDirectory(const char*, int*);
 ** to all overrideable system calls.
 */
 static struct unix_syscall {
-  const char *zName;            /* Name of the sytem call */
+  const char *zName;            /* Name of the system call */
   sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   sqlite3_syscall_ptr pDefault; /* Default value */
 } aSyscall[] = {
@@ -23166,11 +23524,7 @@ static struct unix_syscall {
 #define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
                     aSyscall[13].pCurrent)
 
-#if SQLITE_ENABLE_LOCKING_STYLE
   { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },
-#else
-  { "fchmod",       (sqlite3_syscall_ptr)0,          0  },
-#endif
 #define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
 
 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
@@ -23195,8 +23549,18 @@ static struct unix_syscall {
   { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
 #define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
 
-  { "umask",        (sqlite3_syscall_ptr)umask,           0 },
-#define osUmask     ((mode_t(*)(mode_t))aSyscall[21].pCurrent)
+  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
+#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
+
+  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
+#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
+
+#if HAVE_MREMAP
+  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
+#else
+  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
+#endif
+#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
 
 }; /* End of the overrideable system calls */
 
@@ -23302,14 +23666,7 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
 */
 static int robust_open(const char *z, int f, mode_t m){
   int fd;
-  mode_t m2;
-  mode_t origM = 0;
-  if( m==0 ){
-    m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
-  }else{
-    m2 = m;
-    origM = osUmask(0);
-  }
+  mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
   do{
 #if defined(O_CLOEXEC)
     fd = osOpen(z,f|O_CLOEXEC,m2);
@@ -23317,12 +23674,20 @@ static int robust_open(const char *z, int f, mode_t m){
     fd = osOpen(z,f,m2);
 #endif
   }while( fd<0 && errno==EINTR );
-  if( m ){
-    osUmask(origM);
-  }
+  if( fd>=0 ){
+    if( m!=0 ){
+      struct stat statbuf;
+      if( osFstat(fd, &statbuf)==0 
+       && statbuf.st_size==0
+       && (statbuf.st_mode&0777)!=m 
+      ){
+        osFchmod(fd, m);
+      }
+    }
 #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
-  if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
 #endif
+  }
   return fd;
 }
 
@@ -23528,7 +23893,6 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
 }
 
 
-
 /******************************************************************************
 ****************** Begin Unique File ID Utility Used By VxWorks ***************
 **
@@ -23864,7 +24228,6 @@ static int unixLogErrorAtLine(
   zErr = strerror(iErrno);
 #endif
 
-  assert( errcode!=SQLITE_OK );
   if( zPath==0 ) zPath = "";
   sqlite3_log(errcode,
       "os_unix.c:%d: (%d) %s(%s) - %s",
@@ -24031,6 +24394,50 @@ static int findInodeInfo(
 
 
 /*
+** Check a unixFile that is a database.  Verify the following:
+**
+** (1) There is exactly one hard link on the file
+** (2) The file is not a symbolic link
+** (3) The file has not been renamed or unlinked
+**
+** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
+*/
+static void verifyDbFile(unixFile *pFile){
+  struct stat buf;
+  int rc;
+  if( pFile->ctrlFlags & UNIXFILE_WARNED ){
+    /* One or more of the following warnings have already been issued.  Do not
+    ** repeat them so as not to clutter the error log */
+    return;
+  }
+  rc = osFstat(pFile->h, &buf);
+  if( rc!=0 ){
+    sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
+    pFile->ctrlFlags |= UNIXFILE_WARNED;
+    return;
+  }
+  if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
+    sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
+    pFile->ctrlFlags |= UNIXFILE_WARNED;
+    return;
+  }
+  if( buf.st_nlink>1 ){
+    sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
+    pFile->ctrlFlags |= UNIXFILE_WARNED;
+    return;
+  }
+  if( pFile->pInode!=0
+   && ((rc = osStat(pFile->zPath, &buf))!=0
+       || buf.st_ino!=pFile->pInode->fileId.ino)
+  ){
+    sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
+    pFile->ctrlFlags |= UNIXFILE_WARNED;
+    return;
+  }
+}
+
+
+/*
 ** This routine checks if there is a RESERVED lock held on the specified
 ** file by this or any other process. If such a lock is held, set *pResOut
 ** to a non-zero value otherwise *pResOut is set to zero.  The return value
@@ -24560,9 +24967,13 @@ end_unlock:
 ** the requested locking level, this routine is a no-op.
 */
 static int unixUnlock(sqlite3_file *id, int eFileLock){
+  assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
   return posixUnlock(id, eFileLock, 0);
 }
 
+static int unixMapfile(unixFile *pFd, i64 nByte);
+static void unixUnmapfile(unixFile *pFd);
+
 /*
 ** This function performs the parts of the "close file" operation 
 ** common to all locking schemes. It closes the directory and file
@@ -24575,6 +24986,7 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){
 */
 static int closeUnixFile(sqlite3_file *id){
   unixFile *pFile = (unixFile*)id;
+  unixUnmapfile(pFile);
   if( pFile->h>=0 ){
     robust_close(pFile, pFile->h, __LINE__);
     pFile->h = -1;
@@ -24601,6 +25013,7 @@ static int closeUnixFile(sqlite3_file *id){
 static int unixClose(sqlite3_file *id){
   int rc = SQLITE_OK;
   unixFile *pFile = (unixFile *)id;
+  verifyDbFile(pFile);
   unixUnlock(id, NO_LOCK);
   unixEnterMutex();
 
@@ -24669,7 +25082,7 @@ static int nolockClose(sqlite3_file *id) {
 /******************************************************************************
 ************************* Begin dot-file Locking ******************************
 **
-** The dotfile locking implementation uses the existance of separate lock
+** The dotfile locking implementation uses the existence of separate lock
 ** files (really a directory) to control access to the database.  This works
 ** on just about every filesystem imaginable.  But there are serious downsides:
 **
@@ -24684,7 +25097,7 @@ static int nolockClose(sqlite3_file *id) {
 **
 ** Dotfile locking works by creating a subdirectory in the same directory as
 ** the database and with the same name but with a ".lock" extension added.
-** The existance of a lock directory implies an EXCLUSIVE lock.  All other
+** The existence of a lock directory implies an EXCLUSIVE lock.  All other
 ** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
 */
 
@@ -24851,13 +25264,13 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
 ** Close a file.  Make sure the lock has been released before closing.
 */
 static int dotlockClose(sqlite3_file *id) {
-  int rc;
+  int rc = SQLITE_OK;
   if( id ){
     unixFile *pFile = (unixFile*)id;
     dotlockUnlock(id, NO_LOCK);
     sqlite3_free(pFile->lockingContext);
+    rc = closeUnixFile(id);
   }
-  rc = closeUnixFile(id);
   return rc;
 }
 /****************** End of the dot-file lock implementation *******************
@@ -25061,10 +25474,12 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
 ** Close a file.
 */
 static int flockClose(sqlite3_file *id) {
+  int rc = SQLITE_OK;
   if( id ){
     flockUnlock(id, NO_LOCK);
+    rc = closeUnixFile(id);
   }
-  return closeUnixFile(id);
+  return rc;
 }
 
 #endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
@@ -25775,6 +26190,8 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
   i64 newOffset;
 #endif
   TIMER_START;
+  assert( cnt==(cnt&0x1ffff) );
+  cnt &= 0x1ffff;
   do{
 #if defined(USE_PREAD)
     got = osPread(id->h, pBuf, cnt, offset);
@@ -25828,6 +26245,8 @@ static int unixRead(
   unixFile *pFile = (unixFile *)id;
   int got;
   assert( id );
+  assert( offset>=0 );
+  assert( amt>0 );
 
   /* If this is a database file (not a journal, master-journal or temp
   ** file), the bytes in the locking range should never be read or written. */
@@ -25838,6 +26257,23 @@ static int unixRead(
   );
 #endif
 
+#if SQLITE_MAX_MMAP_SIZE>0
+  /* Deal with as much of this read request as possible by transfering
+  ** data from the memory mapping using memcpy().  */
+  if( offset<pFile->mmapSize ){
+    if( offset+amt <= pFile->mmapSize ){
+      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
+      return SQLITE_OK;
+    }else{
+      int nCopy = pFile->mmapSize - offset;
+      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
+      pBuf = &((u8 *)pBuf)[nCopy];
+      amt -= nCopy;
+      offset += nCopy;
+    }
+  }
+#endif
+
   got = seekAndRead(pFile, offset, pBuf, amt);
   if( got==amt ){
     return SQLITE_OK;
@@ -25853,44 +26289,59 @@ static int unixRead(
 }
 
 /*
-** Seek to the offset in id->offset then read cnt bytes into pBuf.
-** Return the number of bytes actually read.  Update the offset.
-**
-** To avoid stomping the errno value on a failed write the lastErrno value
-** is set before returning.
+** Attempt to seek the file-descriptor passed as the first argument to
+** absolute offset iOff, then attempt to write nBuf bytes of data from
+** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, 
+** return the actual number of bytes written (which may be less than
+** nBuf).
 */
-static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
-  int got;
-#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
-  i64 newOffset;
-#endif
+static int seekAndWriteFd(
+  int fd,                         /* File descriptor to write to */
+  i64 iOff,                       /* File offset to begin writing at */
+  const void *pBuf,               /* Copy data from this buffer to the file */
+  int nBuf,                       /* Size of buffer pBuf in bytes */
+  int *piErrno                    /* OUT: Error number if error occurs */
+){
+  int rc = 0;                     /* Value returned by system call */
+
+  assert( nBuf==(nBuf&0x1ffff) );
+  nBuf &= 0x1ffff;
   TIMER_START;
+
 #if defined(USE_PREAD)
-  do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
+  do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
 #elif defined(USE_PREAD64)
-  do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
+  do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
 #else
   do{
-    newOffset = lseek(id->h, offset, SEEK_SET);
-    SimulateIOError( newOffset-- );
-    if( newOffset!=offset ){
-      if( newOffset == -1 ){
-        ((unixFile*)id)->lastErrno = errno;
-      }else{
-        ((unixFile*)id)->lastErrno = 0;
-      }
+    i64 iSeek = lseek(fd, iOff, SEEK_SET);
+    SimulateIOError( iSeek-- );
+
+    if( iSeek!=iOff ){
+      if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
       return -1;
     }
-    got = osWrite(id->h, pBuf, cnt);
-  }while( got<0 && errno==EINTR );
+    rc = osWrite(fd, pBuf, nBuf);
+  }while( rc<0 && errno==EINTR );
 #endif
+
   TIMER_END;
-  if( got<0 ){
-    ((unixFile*)id)->lastErrno = errno;
-  }
+  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
 
-  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
-  return got;
+  if( rc<0 && piErrno ) *piErrno = errno;
+  return rc;
+}
+
+
+/*
+** Seek to the offset in id->offset then read cnt bytes into pBuf.
+** Return the number of bytes actually read.  Update the offset.
+**
+** To avoid stomping the errno value on a failed write the lastErrno value
+** is set before returning.
+*/
+static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
+  return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
 }
 
 
@@ -25940,6 +26391,23 @@ static int unixWrite(
   }
 #endif
 
+#if SQLITE_MAX_MMAP_SIZE>0
+  /* Deal with as much of this write request as possible by transfering
+  ** data from the memory mapping using memcpy().  */
+  if( offset<pFile->mmapSize ){
+    if( offset+amt <= pFile->mmapSize ){
+      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
+      return SQLITE_OK;
+    }else{
+      int nCopy = pFile->mmapSize - offset;
+      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
+      pBuf = &((u8 *)pBuf)[nCopy];
+      amt -= nCopy;
+      offset += nCopy;
+    }
+  }
+#endif
+
   while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
     amt -= wrote;
     offset += wrote;
@@ -26167,7 +26635,7 @@ static int unixSync(sqlite3_file *id, int flags){
   }
 
   /* Also fsync the directory containing the file if the DIRSYNC flag
-  ** is set.  This is a one-time occurrance.  Many systems (examples: AIX)
+  ** is set.  This is a one-time occurrence.  Many systems (examples: AIX)
   ** are unable to fsync a directory, so ignore errors on the fsync.
   */
   if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
@@ -26222,6 +26690,14 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
     }
 #endif
 
+    /* If the file was just truncated to a size smaller than the currently
+    ** mapped region, reduce the effective mapping size as well. SQLite will
+    ** use read() and write() to access data beyond this point from now on.  
+    */
+    if( nByte<pFile->mmapSize ){
+      pFile->mmapSize = nByte;
+    }
+
     return SQLITE_OK;
   }
 }
@@ -26310,6 +26786,19 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
     }
   }
 
+  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
+    int rc;
+    if( pFile->szChunk<=0 ){
+      if( robust_ftruncate(pFile->h, nByte) ){
+        pFile->lastErrno = errno;
+        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
+      }
+    }
+
+    rc = unixMapfile(pFile, nByte);
+    return rc;
+  }
+
   return SQLITE_OK;
 }
 
@@ -26329,6 +26818,9 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
   }
 }
 
+/* Forward declaration */
+static int unixGetTempname(int nBuf, char *zBuf);
+
 /*
 ** Information and control of an open file handle.
 */
@@ -26366,6 +26858,26 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
       return SQLITE_OK;
     }
+    case SQLITE_FCNTL_TEMPFILENAME: {
+      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+      if( zTFile ){
+        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
+        *(char**)pArg = zTFile;
+      }
+      return SQLITE_OK;
+    }
+    case SQLITE_FCNTL_MMAP_SIZE: {
+      i64 newLimit = *(i64*)pArg;
+      if( newLimit>sqlite3GlobalConfig.mxMmap ){
+        newLimit = sqlite3GlobalConfig.mxMmap;
+      }
+      *(i64*)pArg = pFile->mmapSizeMax;
+      if( newLimit>=0 ){
+        pFile->mmapSizeMax = newLimit;
+        if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
+      }
+      return SQLITE_OK;
+    }
 #ifdef SQLITE_DEBUG
     /* The pager calls this method to signal that it has done
     ** a rollback and that the database is therefore unchanged and
@@ -26397,10 +26909,92 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
 ** a database and its journal file) that the sector size will be the
 ** same for both.
 */
-static int unixSectorSize(sqlite3_file *pFile){
-  (void)pFile;
+#ifndef __QNXNTO__ 
+static int unixSectorSize(sqlite3_file *NotUsed){
+  UNUSED_PARAMETER(NotUsed);
   return SQLITE_DEFAULT_SECTOR_SIZE;
 }
+#endif
+
+/*
+** The following version of unixSectorSize() is optimized for QNX.
+*/
+#ifdef __QNXNTO__
+#include <sys/dcmd_blk.h>
+#include <sys/statvfs.h>
+static int unixSectorSize(sqlite3_file *id){
+  unixFile *pFile = (unixFile*)id;
+  if( pFile->sectorSize == 0 ){
+    struct statvfs fsInfo;
+       
+    /* Set defaults for non-supported filesystems */
+    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+    pFile->deviceCharacteristics = 0;
+    if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
+      return pFile->sectorSize;
+    }
+
+    if( !strcmp(fsInfo.f_basetype, "tmp") ) {
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        SQLITE_IOCAP_ATOMIC4K |       /* All ram filesystem writes are atomic */
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( strstr(fsInfo.f_basetype, "etfs") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        /* etfs cluster size writes are atomic */
+        (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        SQLITE_IOCAP_ATOMIC |         /* All filesystem writes are atomic */
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        /* full bitset of atomics from max sector size and smaller */
+        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( strstr(fsInfo.f_basetype, "dos") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        /* full bitset of atomics from max sector size and smaller */
+        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else{
+      pFile->deviceCharacteristics =
+        SQLITE_IOCAP_ATOMIC512 |      /* blocks are atomic */
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        0;
+    }
+  }
+  /* Last chance verification.  If the sector size isn't a multiple of 512
+  ** then it isn't valid.*/
+  if( pFile->sectorSize % 512 != 0 ){
+    pFile->deviceCharacteristics = 0;
+    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+  }
+  return pFile->sectorSize;
+}
+#endif /* __QNXNTO__ */
 
 /*
 ** Return the device characteristics for the file.
@@ -26417,11 +27011,15 @@ static int unixSectorSize(sqlite3_file *pFile){
 */
 static int unixDeviceCharacteristics(sqlite3_file *id){
   unixFile *p = (unixFile*)id;
+  int rc = 0;
+#ifdef __QNXNTO__
+  if( p->sectorSize==0 ) unixSectorSize(id);
+  rc = p->deviceCharacteristics;
+#endif
   if( p->ctrlFlags & UNIXFILE_PSOW ){
-    return SQLITE_IOCAP_POWERSAFE_OVERWRITE;
-  }else{
-    return 0;
+    rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
   }
+  return rc;
 }
 
 #ifndef SQLITE_OMIT_WAL
@@ -26592,7 +27190,7 @@ static void unixShmPurge(unixFile *pFd){
     sqlite3_mutex_free(p->mutex);
     for(i=0; i<p->nRegion; i++){
       if( p->h>=0 ){
-        munmap(p->apRegion[i], p->szRegion);
+        osMunmap(p->apRegion[i], p->szRegion);
       }else{
         sqlite3_free(p->apRegion[i]);
       }
@@ -26832,16 +27430,32 @@ static int unixShmMap(
       if( sStat.st_size<nByte ){
         /* The requested memory region does not exist. If bExtend is set to
         ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
-        **
-        ** Alternatively, if bExtend is true, use ftruncate() to allocate
-        ** the requested memory region.
         */
-        if( !bExtend ) goto shmpage_out;
-        if( robust_ftruncate(pShmNode->h, nByte) ){
-          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
-                            pShmNode->zFilename);
+        if( !bExtend ){
           goto shmpage_out;
         }
+
+        /* Alternatively, if bExtend is true, extend the file. Do this by
+        ** writing a single byte to the end of each (OS) page being
+        ** allocated or extended. Technically, we need only write to the
+        ** last page in order to extend the file. But writing to all new
+        ** pages forces the OS to allocate them immediately, which reduces
+        ** the chances of SIGBUS while accessing the mapped region later on.
+        */
+        else{
+          static const int pgsz = 4096;
+          int iPg;
+
+          /* Write to the last byte of each newly allocated or extended page */
+          assert( (nByte % pgsz)==0 );
+          for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
+            if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
+              const char *zFile = pShmNode->zFilename;
+              rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
+              goto shmpage_out;
+            }
+          }
+        }
       }
     }
 
@@ -26857,9 +27471,9 @@ static int unixShmMap(
     while(pShmNode->nRegion<=iRegion){
       void *pMem;
       if( pShmNode->h>=0 ){
-        pMem = mmap(0, szRegion,
+        pMem = osMmap(0, szRegion,
             pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
-            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
+            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
         );
         if( pMem==MAP_FAILED ){
           rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
@@ -27075,6 +27689,236 @@ static int unixShmUnmap(
 #endif /* #ifndef SQLITE_OMIT_WAL */
 
 /*
+** If it is currently memory mapped, unmap file pFd.
+*/
+static void unixUnmapfile(unixFile *pFd){
+  assert( pFd->nFetchOut==0 );
+#if SQLITE_MAX_MMAP_SIZE>0
+  if( pFd->pMapRegion ){
+    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
+    pFd->pMapRegion = 0;
+    pFd->mmapSize = 0;
+    pFd->mmapSizeActual = 0;
+  }
+#endif
+}
+
+#if SQLITE_MAX_MMAP_SIZE>0
+/*
+** Return the system page size.
+*/
+static int unixGetPagesize(void){
+#if HAVE_MREMAP
+  return 512;
+#elif defined(_BSD_SOURCE)
+  return getpagesize();
+#else
+  return (int)sysconf(_SC_PAGESIZE);
+#endif
+}
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+
+#if SQLITE_MAX_MMAP_SIZE>0
+/*
+** Attempt to set the size of the memory mapping maintained by file 
+** descriptor pFd to nNew bytes. Any existing mapping is discarded.
+**
+** If successful, this function sets the following variables:
+**
+**       unixFile.pMapRegion
+**       unixFile.mmapSize
+**       unixFile.mmapSizeActual
+**
+** If unsuccessful, an error message is logged via sqlite3_log() and
+** the three variables above are zeroed. In this case SQLite should
+** continue accessing the database using the xRead() and xWrite()
+** methods.
+*/
+static void unixRemapfile(
+  unixFile *pFd,                  /* File descriptor object */
+  i64 nNew                        /* Required mapping size */
+){
+  const char *zErr = "mmap";
+  int h = pFd->h;                      /* File descriptor open on db file */
+  u8 *pOrig = (u8 *)pFd->pMapRegion;   /* Pointer to current file mapping */
+  i64 nOrig = pFd->mmapSizeActual;     /* Size of pOrig region in bytes */
+  u8 *pNew = 0;                        /* Location of new mapping */
+  int flags = PROT_READ;               /* Flags to pass to mmap() */
+
+  assert( pFd->nFetchOut==0 );
+  assert( nNew>pFd->mmapSize );
+  assert( nNew<=pFd->mmapSizeMax );
+  assert( nNew>0 );
+  assert( pFd->mmapSizeActual>=pFd->mmapSize );
+  assert( MAP_FAILED!=0 );
+
+  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
+
+  if( pOrig ){
+    const int szSyspage = unixGetPagesize();
+    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
+    u8 *pReq = &pOrig[nReuse];
+
+    /* Unmap any pages of the existing mapping that cannot be reused. */
+    if( nReuse!=nOrig ){
+      osMunmap(pReq, nOrig-nReuse);
+    }
+
+#if HAVE_MREMAP
+    pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
+    zErr = "mremap";
+#else
+    pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
+    if( pNew!=MAP_FAILED ){
+      if( pNew!=pReq ){
+        osMunmap(pNew, nNew - nReuse);
+        pNew = 0;
+      }else{
+        pNew = pOrig;
+      }
+    }
+#endif
+
+    /* The attempt to extend the existing mapping failed. Free it. */
+    if( pNew==MAP_FAILED || pNew==0 ){
+      osMunmap(pOrig, nReuse);
+    }
+  }
+
+  /* If pNew is still NULL, try to create an entirely new mapping. */
+  if( pNew==0 ){
+    pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
+  }
+
+  if( pNew==MAP_FAILED ){
+    pNew = 0;
+    nNew = 0;
+    unixLogError(SQLITE_OK, zErr, pFd->zPath);
+
+    /* If the mmap() above failed, assume that all subsequent mmap() calls
+    ** will probably fail too. Fall back to using xRead/xWrite exclusively
+    ** in this case.  */
+    pFd->mmapSizeMax = 0;
+  }
+  pFd->pMapRegion = (void *)pNew;
+  pFd->mmapSize = pFd->mmapSizeActual = nNew;
+}
+#endif
+
+/*
+** Memory map or remap the file opened by file-descriptor pFd (if the file
+** is already mapped, the existing mapping is replaced by the new). Or, if 
+** there already exists a mapping for this file, and there are still 
+** outstanding xFetch() references to it, this function is a no-op.
+**
+** If parameter nByte is non-negative, then it is the requested size of 
+** the mapping to create. Otherwise, if nByte is less than zero, then the 
+** requested size is the size of the file on disk. The actual size of the
+** created mapping is either the requested size or the value configured 
+** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
+**
+** SQLITE_OK is returned if no error occurs (even if the mapping is not
+** recreated as a result of outstanding references) or an SQLite error
+** code otherwise.
+*/
+static int unixMapfile(unixFile *pFd, i64 nByte){
+#if SQLITE_MAX_MMAP_SIZE>0
+  i64 nMap = nByte;
+  int rc;
+
+  assert( nMap>=0 || pFd->nFetchOut==0 );
+  if( pFd->nFetchOut>0 ) return SQLITE_OK;
+
+  if( nMap<0 ){
+    struct stat statbuf;          /* Low-level file information */
+    rc = osFstat(pFd->h, &statbuf);
+    if( rc!=SQLITE_OK ){
+      return SQLITE_IOERR_FSTAT;
+    }
+    nMap = statbuf.st_size;
+  }
+  if( nMap>pFd->mmapSizeMax ){
+    nMap = pFd->mmapSizeMax;
+  }
+
+  if( nMap!=pFd->mmapSize ){
+    if( nMap>0 ){
+      unixRemapfile(pFd, nMap);
+    }else{
+      unixUnmapfile(pFd);
+    }
+  }
+#endif
+
+  return SQLITE_OK;
+}
+
+/*
+** If possible, return a pointer to a mapping of file fd starting at offset
+** iOff. The mapping must be valid for at least nAmt bytes.
+**
+** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
+** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
+** Finally, if an error does occur, return an SQLite error code. The final
+** value of *pp is undefined in this case.
+**
+** If this function does return a pointer, the caller must eventually 
+** release the reference by calling unixUnfetch().
+*/
+static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
+#if SQLITE_MAX_MMAP_SIZE>0
+  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
+#endif
+  *pp = 0;
+
+#if SQLITE_MAX_MMAP_SIZE>0
+  if( pFd->mmapSizeMax>0 ){
+    if( pFd->pMapRegion==0 ){
+      int rc = unixMapfile(pFd, -1);
+      if( rc!=SQLITE_OK ) return rc;
+    }
+    if( pFd->mmapSize >= iOff+nAmt ){
+      *pp = &((u8 *)pFd->pMapRegion)[iOff];
+      pFd->nFetchOut++;
+    }
+  }
+#endif
+  return SQLITE_OK;
+}
+
+/*
+** If the third argument is non-NULL, then this function releases a 
+** reference obtained by an earlier call to unixFetch(). The second
+** argument passed to this function must be the same as the corresponding
+** argument that was passed to the unixFetch() invocation. 
+**
+** Or, if the third argument is NULL, then this function is being called 
+** to inform the VFS layer that, according to POSIX, any existing mapping 
+** may now be invalid and should be unmapped.
+*/
+static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
+  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
+  UNUSED_PARAMETER(iOff);
+
+  /* If p==0 (unmap the entire file) then there must be no outstanding 
+  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
+  ** then there must be at least one outstanding.  */
+  assert( (p==0)==(pFd->nFetchOut==0) );
+
+  /* If p!=0, it must match the iOff value. */
+  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
+
+  if( p ){
+    pFd->nFetchOut--;
+  }else{
+    unixUnmapfile(pFd);
+  }
+
+  assert( pFd->nFetchOut>=0 );
+  return SQLITE_OK;
+}
+
+/*
 ** Here ends the implementation of all sqlite3_file methods.
 **
 ********************** End sqlite3_file Methods *******************************
@@ -27132,7 +27976,9 @@ static const sqlite3_io_methods METHOD = {                                   \
    unixShmMap,                 /* xShmMap */                                 \
    unixShmLock,                /* xShmLock */                                \
    unixShmBarrier,             /* xShmBarrier */                             \
-   unixShmUnmap                /* xShmUnmap */                               \
+   unixShmUnmap,               /* xShmUnmap */                               \
+   unixFetch,                  /* xFetch */                                  \
+   unixUnfetch,                /* xUnfetch */                                \
 };                                                                           \
 static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
   UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
@@ -27149,7 +27995,7 @@ static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
 IOMETHODS(
   posixIoFinder,            /* Finder function name */
   posixIoMethods,           /* sqlite3_io_methods object name */
-  2,                        /* shared memory is enabled */
+  3,                        /* shared memory and mmap are enabled */
   unixClose,                /* xClose method */
   unixLock,                 /* xLock method */
   unixUnlock,               /* xUnlock method */
@@ -27400,11 +28246,12 @@ static int fillInUnixFile(
   pNew->pVfs = pVfs;
   pNew->zPath = zFilename;
   pNew->ctrlFlags = (u8)ctrlFlags;
+  pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
   if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                            "psow", SQLITE_POWERSAFE_OVERWRITE) ){
     pNew->ctrlFlags |= UNIXFILE_PSOW;
   }
-  if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
+  if( strcmp(pVfs->zName,"unix-excl")==0 ){
     pNew->ctrlFlags |= UNIXFILE_EXCL;
   }
 
@@ -27436,7 +28283,7 @@ static int fillInUnixFile(
     unixEnterMutex();
     rc = findInodeInfo(pNew, &pNew->pInode);
     if( rc!=SQLITE_OK ){
-      /* If an error occured in findInodeInfo(), close the file descriptor
+      /* If an error occurred in findInodeInfo(), close the file descriptor
       ** immediately, before releasing the mutex. findInodeInfo() may fail
       ** in two scenarios:
       **
@@ -27535,15 +28382,15 @@ static int fillInUnixFile(
     if( h>=0 ) robust_close(pNew, h, __LINE__);
     h = -1;
     osUnlink(zFilename);
-    isDelete = 0;
+    pNew->ctrlFlags |= UNIXFILE_DELETE;
   }
-  if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
 #endif
   if( rc!=SQLITE_OK ){
     if( h>=0 ) robust_close(pNew, h, __LINE__);
   }else{
     pNew->pMethod = pLockingStyle;
     OpenCounter(+1);
+    verifyDbFile(pNew);
   }
   return rc;
 }
@@ -28043,8 +28890,13 @@ static int unixDelete(
   int rc = SQLITE_OK;
   UNUSED_PARAMETER(NotUsed);
   SimulateIOError(return SQLITE_IOERR_DELETE);
-  if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
-    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+  if( osUnlink(zPath)==(-1) ){
+    if( errno==ENOENT ){
+      rc = SQLITE_IOERR_DELETE_NOENT;
+    }else{
+      rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+    }
+    return rc;
   }
 #ifndef SQLITE_DISABLE_DIRSYNC
   if( (dirSync & 1)!=0 ){
@@ -28069,7 +28921,7 @@ static int unixDelete(
 }
 
 /*
-** Test the existance of or access permissions of file zPath. The
+** Test the existence of or access permissions of file zPath. The
 ** test performed depends on the value of flags:
 **
 **     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
@@ -29632,7 +30484,7 @@ SQLITE_API int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==22 );
+  assert( ArraySize(aSyscall)==24 );
 
   /* Register all VFSes defined in the aVfs[] array */
   for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
@@ -29890,6 +30742,66 @@ SQLITE_API int sqlite3_open_file_count = 0;
 /************** Continuing where we left off in os_win.c *********************/
 
 /*
+** Compiling and using WAL mode requires several APIs that are only
+** available in Windows platforms based on the NT kernel.
+*/
+#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
+# error "WAL mode requires support from the Windows NT kernel, compile\
+ with SQLITE_OMIT_WAL."
+#endif
+
+/*
+** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#  define SQLITE_WIN32_HAS_ANSI
+#endif
+
+/*
+** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+#  define SQLITE_WIN32_HAS_WIDE
+#endif
+
+/*
+** Do we need to manually define the Win32 file mapping APIs for use with WAL
+** mode (e.g. these APIs are available in the Windows CE SDK; however, they
+** are not present in the header file)?
+*/
+#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
+/*
+** Two of the file mapping APIs are different under WinRT.  Figure out which
+** set we need.
+*/
+#if SQLITE_OS_WINRT
+WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
+        LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
+
+WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
+#else
+#if defined(SQLITE_WIN32_HAS_ANSI)
+WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
+        DWORD, DWORD, DWORD, LPCSTR);
+#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
+        DWORD, DWORD, DWORD, LPCWSTR);
+#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
+
+WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
+#endif /* SQLITE_OS_WINRT */
+
+/*
+** This file mapping API is common to both Win32 and WinRT.
+*/
+WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
+#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
+
+/*
 ** Macro to find the minimum of two numeric values.
 */
 #ifndef MIN
@@ -29955,11 +30867,20 @@ struct winFile {
   winceLock local;        /* Locks obtained by this instance of winFile */
   winceLock *shared;      /* Global shared lock memory for the file  */
 #endif
+#if SQLITE_MAX_MMAP_SIZE>0
+  int nFetchOut;                /* Number of outstanding xFetch references */
+  HANDLE hMap;                  /* Handle for accessing memory mapping */
+  void *pMapRegion;             /* Area memory mapped */
+  sqlite3_int64 mmapSize;       /* Usable size of mapped region */
+  sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
+  sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
+#endif
 };
 
 /*
 ** Allowed values for winFile.ctrlFlags
 */
+#define WINFILE_RDONLY          0x02   /* Connection is read only */
 #define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
 #define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
 
@@ -30094,14 +31015,6 @@ SQLITE_API int sqlite3_os_type = 0;
 static int sqlite3_os_type = 0;
 #endif
 
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-#  define SQLITE_WIN32_HAS_ANSI
-#endif
-
-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
-#  define SQLITE_WIN32_HAS_WIDE
-#endif
-
 #ifndef SYSCALL
 #  define SYSCALL sqlite3_syscall_ptr
 #endif
@@ -30121,7 +31034,7 @@ static int sqlite3_os_type = 0;
 ** to all overrideable system calls.
 */
 static struct win_syscall {
-  const char *zName;            /* Name of the sytem call */
+  const char *zName;            /* Name of the system call */
   sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   sqlite3_syscall_ptr pDefault; /* Default value */
 } aSyscall[] = {
@@ -30173,6 +31086,16 @@ static struct win_syscall {
 #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
         LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
 
+#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
+        !defined(SQLITE_OMIT_WAL))
+  { "CreateFileMappingA",      (SYSCALL)CreateFileMappingA,      0 },
+#else
+  { "CreateFileMappingA",      (SYSCALL)0,                       0 },
+#endif
+
+#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+        DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
+
 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
         !defined(SQLITE_OMIT_WAL))
   { "CreateFileMappingW",      (SYSCALL)CreateFileMappingW,      0 },
@@ -30181,7 +31104,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[6].pCurrent)
+        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "CreateMutexW",            (SYSCALL)CreateMutexW,            0 },
@@ -30190,7 +31113,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
-        LPCWSTR))aSyscall[7].pCurrent)
+        LPCWSTR))aSyscall[8].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "DeleteFileA",             (SYSCALL)DeleteFileA,             0 },
@@ -30198,7 +31121,7 @@ static struct win_syscall {
   { "DeleteFileA",             (SYSCALL)0,                       0 },
 #endif
 
-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[8].pCurrent)
+#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "DeleteFileW",             (SYSCALL)DeleteFileW,             0 },
@@ -30206,7 +31129,7 @@ static struct win_syscall {
   { "DeleteFileW",             (SYSCALL)0,                       0 },
 #endif
 
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[9].pCurrent)
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
 
 #if SQLITE_OS_WINCE
   { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
@@ -30215,7 +31138,7 @@ static struct win_syscall {
 #endif
 
 #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-        LPFILETIME))aSyscall[10].pCurrent)
+        LPFILETIME))aSyscall[11].pCurrent)
 
 #if SQLITE_OS_WINCE
   { "FileTimeToSystemTime",    (SYSCALL)FileTimeToSystemTime,    0 },
@@ -30224,11 +31147,11 @@ static struct win_syscall {
 #endif
 
 #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-        LPSYSTEMTIME))aSyscall[11].pCurrent)
+        LPSYSTEMTIME))aSyscall[12].pCurrent)
 
   { "FlushFileBuffers",        (SYSCALL)FlushFileBuffers,        0 },
 
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[12].pCurrent)
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "FormatMessageA",          (SYSCALL)FormatMessageA,          0 },
@@ -30237,7 +31160,7 @@ static struct win_syscall {
 #endif
 
 #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
-        DWORD,va_list*))aSyscall[13].pCurrent)
+        DWORD,va_list*))aSyscall[14].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "FormatMessageW",          (SYSCALL)FormatMessageW,          0 },
@@ -30246,15 +31169,19 @@ static struct win_syscall {
 #endif
 
 #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
-        DWORD,va_list*))aSyscall[14].pCurrent)
+        DWORD,va_list*))aSyscall[15].pCurrent)
 
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "FreeLibrary",             (SYSCALL)FreeLibrary,             0 },
+#else
+  { "FreeLibrary",             (SYSCALL)0,                       0 },
+#endif
 
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[15].pCurrent)
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
 
   { "GetCurrentProcessId",     (SYSCALL)GetCurrentProcessId,     0 },
 
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[16].pCurrent)
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
 
 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
   { "GetDiskFreeSpaceA",       (SYSCALL)GetDiskFreeSpaceA,       0 },
@@ -30263,7 +31190,7 @@ static struct win_syscall {
 #endif
 
 #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
-        LPDWORD))aSyscall[17].pCurrent)
+        LPDWORD))aSyscall[18].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetDiskFreeSpaceW",       (SYSCALL)GetDiskFreeSpaceW,       0 },
@@ -30272,7 +31199,7 @@ static struct win_syscall {
 #endif
 
 #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
-        LPDWORD))aSyscall[18].pCurrent)
+        LPDWORD))aSyscall[19].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetFileAttributesA",      (SYSCALL)GetFileAttributesA,      0 },
@@ -30280,7 +31207,7 @@ static struct win_syscall {
   { "GetFileAttributesA",      (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[19].pCurrent)
+#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFileAttributesW",      (SYSCALL)GetFileAttributesW,      0 },
@@ -30288,7 +31215,7 @@ static struct win_syscall {
   { "GetFileAttributesW",      (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[20].pCurrent)
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFileAttributesExW",    (SYSCALL)GetFileAttributesExW,    0 },
@@ -30297,7 +31224,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
-        LPVOID))aSyscall[21].pCurrent)
+        LPVOID))aSyscall[22].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "GetFileSize",             (SYSCALL)GetFileSize,             0 },
@@ -30305,7 +31232,7 @@ static struct win_syscall {
   { "GetFileSize",             (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[22].pCurrent)
+#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
 
 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
   { "GetFullPathNameA",        (SYSCALL)GetFullPathNameA,        0 },
@@ -30314,7 +31241,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
-        LPSTR*))aSyscall[23].pCurrent)
+        LPSTR*))aSyscall[24].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFullPathNameW",        (SYSCALL)GetFullPathNameW,        0 },
@@ -30323,12 +31250,13 @@ static struct win_syscall {
 #endif
 
 #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
-        LPWSTR*))aSyscall[24].pCurrent)
+        LPWSTR*))aSyscall[25].pCurrent)
 
   { "GetLastError",            (SYSCALL)GetLastError,            0 },
 
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[25].pCurrent)
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
 
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
 #if SQLITE_OS_WINCE
   /* The GetProcAddressA() routine is only available on Windows CE. */
   { "GetProcAddressA",         (SYSCALL)GetProcAddressA,         0 },
@@ -30337,9 +31265,12 @@ static struct win_syscall {
   ** an ANSI string regardless of the _UNICODE setting */
   { "GetProcAddressA",         (SYSCALL)GetProcAddress,          0 },
 #endif
+#else
+  { "GetProcAddressA",         (SYSCALL)0,                       0 },
+#endif
 
 #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
-        LPCSTR))aSyscall[26].pCurrent)
+        LPCSTR))aSyscall[27].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "GetSystemInfo",           (SYSCALL)GetSystemInfo,           0 },
@@ -30347,11 +31278,11 @@ static struct win_syscall {
   { "GetSystemInfo",           (SYSCALL)0,                       0 },
 #endif
 
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[27].pCurrent)
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
 
   { "GetSystemTime",           (SYSCALL)GetSystemTime,           0 },
 
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[28].pCurrent)
+#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
 
 #if !SQLITE_OS_WINCE
   { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
@@ -30360,7 +31291,7 @@ static struct win_syscall {
 #endif
 
 #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
-        LPFILETIME))aSyscall[29].pCurrent)
+        LPFILETIME))aSyscall[30].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetTempPathA",            (SYSCALL)GetTempPathA,            0 },
@@ -30368,7 +31299,7 @@ static struct win_syscall {
   { "GetTempPathA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[30].pCurrent)
+#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetTempPathW",            (SYSCALL)GetTempPathW,            0 },
@@ -30376,7 +31307,7 @@ static struct win_syscall {
   { "GetTempPathW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[31].pCurrent)
+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "GetTickCount",            (SYSCALL)GetTickCount,            0 },
@@ -30384,7 +31315,7 @@ static struct win_syscall {
   { "GetTickCount",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[32].pCurrent)
+#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
@@ -30393,12 +31324,12 @@ static struct win_syscall {
 #endif
 
 #define osGetVersionExA ((BOOL(WINAPI*)( \
-        LPOSVERSIONINFOA))aSyscall[33].pCurrent)
+        LPOSVERSIONINFOA))aSyscall[34].pCurrent)
 
   { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },
 
 #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
-        SIZE_T))aSyscall[34].pCurrent)
+        SIZE_T))aSyscall[35].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapCreate",              (SYSCALL)HeapCreate,              0 },
@@ -30407,7 +31338,7 @@ static struct win_syscall {
 #endif
 
 #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
-        SIZE_T))aSyscall[35].pCurrent)
+        SIZE_T))aSyscall[36].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },
@@ -30415,21 +31346,21 @@ static struct win_syscall {
   { "HeapDestroy",             (SYSCALL)0,                       0 },
 #endif
 
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent)
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
 
   { "HeapFree",                (SYSCALL)HeapFree,                0 },
 
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[37].pCurrent)
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
 
   { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },
 
 #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
-        SIZE_T))aSyscall[38].pCurrent)
+        SIZE_T))aSyscall[39].pCurrent)
 
   { "HeapSize",                (SYSCALL)HeapSize,                0 },
 
 #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[39].pCurrent)
+        LPCVOID))aSyscall[40].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapValidate",            (SYSCALL)HeapValidate,            0 },
@@ -30438,23 +31369,24 @@ static struct win_syscall {
 #endif
 
 #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[40].pCurrent)
+        LPCVOID))aSyscall[41].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_ANSI)
+#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
 #else
   { "LoadLibraryA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[41].pCurrent)
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
 
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+        !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadLibraryW",            (SYSCALL)LoadLibraryW,            0 },
 #else
   { "LoadLibraryW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[42].pCurrent)
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "LocalFree",               (SYSCALL)LocalFree,               0 },
@@ -30462,7 +31394,7 @@ static struct win_syscall {
   { "LocalFree",               (SYSCALL)0,                       0 },
 #endif
 
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[43].pCurrent)
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "LockFile",                (SYSCALL)LockFile,                0 },
@@ -30472,7 +31404,7 @@ static struct win_syscall {
 
 #ifndef osLockFile
 #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[44].pCurrent)
+        DWORD))aSyscall[45].pCurrent)
 #endif
 
 #if !SQLITE_OS_WINCE
@@ -30483,7 +31415,7 @@ static struct win_syscall {
 
 #ifndef osLockFileEx
 #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[45].pCurrent)
+        LPOVERLAPPED))aSyscall[46].pCurrent)
 #endif
 
 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
@@ -30493,26 +31425,26 @@ static struct win_syscall {
 #endif
 
 #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        SIZE_T))aSyscall[46].pCurrent)
+        SIZE_T))aSyscall[47].pCurrent)
 
   { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },
 
 #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
-        int))aSyscall[47].pCurrent)
+        int))aSyscall[48].pCurrent)
 
   { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
 
 #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
-        LARGE_INTEGER*))aSyscall[48].pCurrent)
+        LARGE_INTEGER*))aSyscall[49].pCurrent)
 
   { "ReadFile",                (SYSCALL)ReadFile,                0 },
 
 #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[49].pCurrent)
+        LPOVERLAPPED))aSyscall[50].pCurrent)
 
   { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },
 
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[50].pCurrent)
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },
@@ -30521,7 +31453,7 @@ static struct win_syscall {
 #endif
 
 #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
-        DWORD))aSyscall[51].pCurrent)
+        DWORD))aSyscall[52].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "Sleep",                   (SYSCALL)Sleep,                   0 },
@@ -30529,12 +31461,12 @@ static struct win_syscall {
   { "Sleep",                   (SYSCALL)0,                       0 },
 #endif
 
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[52].pCurrent)
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
 
   { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },
 
 #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
-        LPFILETIME))aSyscall[53].pCurrent)
+        LPFILETIME))aSyscall[54].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "UnlockFile",              (SYSCALL)UnlockFile,              0 },
@@ -30544,7 +31476,7 @@ static struct win_syscall {
 
 #ifndef osUnlockFile
 #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[54].pCurrent)
+        DWORD))aSyscall[55].pCurrent)
 #endif
 
 #if !SQLITE_OS_WINCE
@@ -30554,7 +31486,7 @@ static struct win_syscall {
 #endif
 
 #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[55].pCurrent)
+        LPOVERLAPPED))aSyscall[56].pCurrent)
 
 #if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
   { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },
@@ -30562,17 +31494,17 @@ static struct win_syscall {
   { "UnmapViewOfFile",         (SYSCALL)0,                       0 },
 #endif
 
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
 
   { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },
 
 #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
-        LPCSTR,LPBOOL))aSyscall[57].pCurrent)
+        LPCSTR,LPBOOL))aSyscall[58].pCurrent)
 
   { "WriteFile",               (SYSCALL)WriteFile,               0 },
 
 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[58].pCurrent)
+        LPOVERLAPPED))aSyscall[59].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "CreateEventExW",          (SYSCALL)CreateEventExW,          0 },
@@ -30581,7 +31513,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
-        DWORD,DWORD))aSyscall[59].pCurrent)
+        DWORD,DWORD))aSyscall[60].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "WaitForSingleObject",     (SYSCALL)WaitForSingleObject,     0 },
@@ -30590,7 +31522,7 @@ static struct win_syscall {
 #endif
 
 #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
-        DWORD))aSyscall[60].pCurrent)
+        DWORD))aSyscall[61].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "WaitForSingleObjectEx",   (SYSCALL)WaitForSingleObjectEx,   0 },
@@ -30599,7 +31531,7 @@ static struct win_syscall {
 #endif
 
 #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
-        BOOL))aSyscall[61].pCurrent)
+        BOOL))aSyscall[62].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "SetFilePointerEx",        (SYSCALL)SetFilePointerEx,        0 },
@@ -30608,7 +31540,7 @@ static struct win_syscall {
 #endif
 
 #define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
-        PLARGE_INTEGER,DWORD))aSyscall[62].pCurrent)
+        PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
@@ -30617,7 +31549,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
-        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[63].pCurrent)
+        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
   { "MapViewOfFileFromApp",    (SYSCALL)MapViewOfFileFromApp,    0 },
@@ -30626,7 +31558,7 @@ static struct win_syscall {
 #endif
 
 #define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
-        SIZE_T))aSyscall[64].pCurrent)
+        SIZE_T))aSyscall[65].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "CreateFile2",             (SYSCALL)CreateFile2,             0 },
@@ -30635,16 +31567,16 @@ static struct win_syscall {
 #endif
 
 #define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
-        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[65].pCurrent)
+        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
 
-#if SQLITE_OS_WINRT
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadPackagedLibrary",     (SYSCALL)LoadPackagedLibrary,     0 },
 #else
   { "LoadPackagedLibrary",     (SYSCALL)0,                       0 },
 #endif
 
 #define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
-        DWORD))aSyscall[66].pCurrent)
+        DWORD))aSyscall[67].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetTickCount64",          (SYSCALL)GetTickCount64,          0 },
@@ -30652,7 +31584,7 @@ static struct win_syscall {
   { "GetTickCount64",          (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[67].pCurrent)
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetNativeSystemInfo",     (SYSCALL)GetNativeSystemInfo,     0 },
@@ -30661,7 +31593,7 @@ static struct win_syscall {
 #endif
 
 #define osGetNativeSystemInfo ((VOID(WINAPI*)( \
-        LPSYSTEM_INFO))aSyscall[68].pCurrent)
+        LPSYSTEM_INFO))aSyscall[69].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "OutputDebugStringA",      (SYSCALL)OutputDebugStringA,      0 },
@@ -30669,7 +31601,7 @@ static struct win_syscall {
   { "OutputDebugStringA",      (SYSCALL)0,                       0 },
 #endif
 
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[69].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "OutputDebugStringW",      (SYSCALL)OutputDebugStringW,      0 },
@@ -30677,11 +31609,11 @@ static struct win_syscall {
   { "OutputDebugStringW",      (SYSCALL)0,                       0 },
 #endif
 
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent)
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
 
   { "GetProcessHeap",          (SYSCALL)GetProcessHeap,          0 },
 
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent)
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
   { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
@@ -30690,7 +31622,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
-        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[72].pCurrent)
+        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
 
 }; /* End of the overrideable system calls */
 
@@ -30782,7 +31714,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
 ** (if available).
 */
 
-SQLITE_API void sqlite3_win32_write_debug(char *zBuf, int nBuf){
+SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
   char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
   int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
   if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
@@ -30848,6 +31780,8 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
 */
 #if SQLITE_OS_WINCE || SQLITE_OS_WINRT
 # define isNT()  (1)
+#elif !defined(SQLITE_WIN32_HAS_WIDE)
+# define isNT()  (0)
 #else
   static int isNT(void){
     if( sqlite3_os_type==0 ){
@@ -30858,7 +31792,7 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
     }
     return sqlite3_os_type==2;
   }
-#endif /* SQLITE_OS_WINCE */
+#endif
 
 #ifdef SQLITE_WIN32_MALLOC
 /*
@@ -31068,7 +32002,7 @@ static LPWSTR utf8ToUnicode(const char *zFilename){
   if( nChar==0 ){
     return 0;
   }
-  zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
+  zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
   if( zWideFilename==0 ){
     return 0;
   }
@@ -31093,7 +32027,7 @@ static char *unicodeToUtf8(LPCWSTR zWideFilename){
   if( nByte == 0 ){
     return 0;
   }
-  zFilename = sqlite3_malloc( nByte );
+  zFilename = sqlite3MallocZero( nByte );
   if( zFilename==0 ){
     return 0;
   }
@@ -31123,7 +32057,7 @@ static LPWSTR mbcsToUnicode(const char *zFilename){
   if( nByte==0 ){
     return 0;
   }
-  zMbcsFilename = sqlite3_malloc( nByte*sizeof(zMbcsFilename[0]) );
+  zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
   if( zMbcsFilename==0 ){
     return 0;
   }
@@ -31152,7 +32086,7 @@ static char *unicodeToMbcs(LPCWSTR zWideFilename){
   if( nByte == 0 ){
     return 0;
   }
-  zFilename = sqlite3_malloc( nByte );
+  zFilename = sqlite3MallocZero( nByte );
   if( zFilename==0 ){
     return 0;
   }
@@ -31306,7 +32240,7 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
   }
 #endif
   if( 0 == dwLen ){
-    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno);
+    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
   }else{
     /* copy a maximum of nBuf chars to output buffer */
     sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
@@ -31349,7 +32283,7 @@ static int winLogErrorAtLine(
   for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
   zMsg[i] = 0;
   sqlite3_log(errcode,
-      "os_win.c:%d: (%d) %s(%s) - %s",
+      "os_win.c:%d: (%lu) %s(%s) - %s",
       iLine, lastErrno, zFunc, zPath, zMsg
   );
 
@@ -31413,9 +32347,10 @@ static void logIoerr(int nRetry){
 /*************************************************************************
 ** This section contains code for WinCE only.
 */
+#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
 /*
-** Windows CE does not have a localtime() function.  So create a
-** substitute.
+** The MSVC CRT on Windows CE may not have a localtime() function.  So
+** create a substitute.
 */
 /* #include <time.h> */
 struct tm *__cdecl localtime(const time_t *t)
@@ -31439,6 +32374,7 @@ struct tm *__cdecl localtime(const time_t *t)
   y.tm_sec = pTm.wSecond;
   return &y;
 }
+#endif
 
 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
 
@@ -31460,15 +32396,17 @@ static void winceMutexAcquire(HANDLE h){
 ** Create the mutex and shared memory used for locking in the file
 ** descriptor pFile
 */
-static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
+static int winceCreateLock(const char *zFilename, winFile *pFile){
   LPWSTR zTok;
   LPWSTR zName;
+  DWORD lastErrno;
+  BOOL bLogged = FALSE;
   BOOL bInit = TRUE;
 
   zName = utf8ToUnicode(zFilename);
   if( zName==0 ){
     /* out of memory */
-    return FALSE;
+    return SQLITE_IOERR_NOMEM;
   }
 
   /* Initialize the local lockdata */
@@ -31485,9 +32423,10 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
   pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
   if (!pFile->hMutex){
     pFile->lastErrno = osGetLastError();
-    winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock1", zFilename);
+    winLogError(SQLITE_IOERR, pFile->lastErrno,
+                "winceCreateLock1", zFilename);
     sqlite3_free(zName);
-    return FALSE;
+    return SQLITE_IOERR;
   }
 
   /* Acquire the mutex before continuing */
@@ -31504,41 +32443,49 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
 
   /* Set a flag that indicates we're the first to create the memory so it 
   ** must be zero-initialized */
-  if (osGetLastError() == ERROR_ALREADY_EXISTS){
+  lastErrno = osGetLastError();
+  if (lastErrno == ERROR_ALREADY_EXISTS){
     bInit = FALSE;
   }
 
   sqlite3_free(zName);
 
   /* If we succeeded in making the shared memory handle, map it. */
-  if (pFile->hShared){
+  if( pFile->hShared ){
     pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
              FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
     /* If mapping failed, close the shared memory handle and erase it */
-    if (!pFile->shared){
+    if( !pFile->shared ){
       pFile->lastErrno = osGetLastError();
-      winLogError(SQLITE_ERROR, pFile->lastErrno,
-               "winceCreateLock2", zFilename);
+      winLogError(SQLITE_IOERR, pFile->lastErrno,
+                  "winceCreateLock2", zFilename);
+      bLogged = TRUE;
       osCloseHandle(pFile->hShared);
       pFile->hShared = NULL;
     }
   }
 
   /* If shared memory could not be created, then close the mutex and fail */
-  if (pFile->hShared == NULL){
+  if( pFile->hShared==NULL ){
+    if( !bLogged ){
+      pFile->lastErrno = lastErrno;
+      winLogError(SQLITE_IOERR, pFile->lastErrno,
+                  "winceCreateLock3", zFilename);
+      bLogged = TRUE;
+    }
     winceMutexRelease(pFile->hMutex);
     osCloseHandle(pFile->hMutex);
     pFile->hMutex = NULL;
-    return FALSE;
+    return SQLITE_IOERR;
   }
   
   /* Initialize the shared memory if we're supposed to */
-  if (bInit) {
+  if( bInit ){
     memset(pFile->shared, 0, sizeof(winceLock));
   }
 
   winceMutexRelease(pFile->hMutex);
-  return TRUE;
+  return SQLITE_OK;
 }
 
 /*
@@ -31617,7 +32564,8 @@ static BOOL winceLockFile(
   }
 
   /* Want a pending lock? */
-  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+           && nNumberOfBytesToLockLow == 1){
     /* If no pending lock has been acquired, then acquire it */
     if (pFile->shared->bPending == 0) {
       pFile->shared->bPending = TRUE;
@@ -31627,7 +32575,8 @@ static BOOL winceLockFile(
   }
 
   /* Want a reserved lock? */
-  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+           && nNumberOfBytesToLockLow == 1){
     if (pFile->shared->bReserved == 0) {
       pFile->shared->bReserved = TRUE;
       pFile->local.bReserved = TRUE;
@@ -31670,7 +32619,8 @@ static BOOL winceUnlockFile(
 
     /* Did we just have a reader lock? */
     else if (pFile->local.nReaders){
-      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
+      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
+             || nNumberOfBytesToUnlockLow == 1);
       pFile->local.nReaders --;
       if (pFile->local.nReaders == 0)
       {
@@ -31681,7 +32631,8 @@ static BOOL winceUnlockFile(
   }
 
   /* Releasing a pending lock */
-  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+           && nNumberOfBytesToUnlockLow == 1){
     if (pFile->local.bPending){
       pFile->local.bPending = FALSE;
       pFile->shared->bPending = FALSE;
@@ -31689,7 +32640,8 @@ static BOOL winceUnlockFile(
     }
   }
   /* Releasing a reserved lock */
-  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+           && nNumberOfBytesToUnlockLow == 1){
     if (pFile->local.bReserved) {
       pFile->local.bReserved = FALSE;
       pFile->shared->bReserved = FALSE;
@@ -31792,6 +32744,8 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
   DWORD dwRet;                    /* Value returned by SetFilePointer() */
   DWORD lastErrno;                /* Value returned by GetLastError() */
 
+  OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
+
   upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
   lowerBits = (LONG)(iOffset & 0xffffffff);
 
@@ -31799,7 +32753,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
   ** containing the lower 32-bits of the new file-offset. Or, if it fails,
   ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
   ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
-  ** whether an error has actually occured, it is also necessary to call 
+  ** whether an error has actually occurred, it is also necessary to call 
   ** GetLastError().
   */
   dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -31809,9 +32763,11 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
     pFile->lastErrno = lastErrno;
     winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
              "seekWinFile", pFile->zPath);
+    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
     return 1;
   }
 
+  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
   return 0;
 #else
   /*
@@ -31828,13 +32784,20 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
     pFile->lastErrno = osGetLastError();
     winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
              "seekWinFile", pFile->zPath);
+    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
     return 1;
   }
 
+  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
   return 0;
 #endif
 }
 
+#if SQLITE_MAX_MMAP_SIZE>0
+/* Forward references to VFS methods */
+static int winUnmapfile(winFile*);
+#endif
+
 /*
 ** Close a file.
 **
@@ -31854,7 +32817,14 @@ static int winClose(sqlite3_file *id){
 #ifndef SQLITE_OMIT_WAL
   assert( pFile->pShm==0 );
 #endif
-  OSTRACE(("CLOSE %d\n", pFile->h));
+  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
+  OSTRACE(("CLOSE file=%p\n", pFile->h));
+
+#if SQLITE_MAX_MMAP_SIZE>0
+  rc = winUnmapfile(pFile);
+  if( rc!=SQLITE_OK ) return rc;
+#endif
+
   do{
     rc = osCloseHandle(pFile->h);
     /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -31874,11 +32844,11 @@ static int winClose(sqlite3_file *id){
     sqlite3_free(pFile->zDeleteOnClose);
   }
 #endif
-  OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
   if( rc ){
     pFile->h = NULL;
   }
   OpenCounter(-1);
+  OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
   return rc ? SQLITE_OK
             : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
                           "winClose", pFile->zPath);
@@ -31903,11 +32873,33 @@ static int winRead(
   int nRetry = 0;                 /* Number of retrys */
 
   assert( id!=0 );
+  assert( amt>0 );
+  assert( offset>=0 );
   SimulateIOError(return SQLITE_IOERR_READ);
-  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
+  OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
+           pFile->h, pBuf, amt, offset, pFile->locktype));
+
+#if SQLITE_MAX_MMAP_SIZE>0
+  /* Deal with as much of this read request as possible by transfering
+  ** data from the memory mapping using memcpy().  */
+  if( offset<pFile->mmapSize ){
+    if( offset+amt <= pFile->mmapSize ){
+      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
+      OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
+      return SQLITE_OK;
+    }else{
+      int nCopy = (int)(pFile->mmapSize - offset);
+      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
+      pBuf = &((u8 *)pBuf)[nCopy];
+      amt -= nCopy;
+      offset += nCopy;
+    }
+  }
+#endif
 
 #if SQLITE_OS_WINCE
   if( seekWinFile(pFile, offset) ){
+    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
     return SQLITE_FULL;
   }
   while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
@@ -31921,6 +32913,7 @@ static int winRead(
     DWORD lastErrno;
     if( retryIoerr(&nRetry, &lastErrno) ) continue;
     pFile->lastErrno = lastErrno;
+    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
     return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
              "winRead", pFile->zPath);
   }
@@ -31928,9 +32921,11 @@ static int winRead(
   if( nRead<(DWORD)amt ){
     /* Unread parts of the buffer must be zero-filled */
     memset(&((char*)pBuf)[nRead], 0, amt-nRead);
+    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
     return SQLITE_IOERR_SHORT_READ;
   }
 
+  OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
   return SQLITE_OK;
 }
 
@@ -31944,7 +32939,7 @@ static int winWrite(
   int amt,                        /* Number of bytes to write */
   sqlite3_int64 offset            /* Offset into the file to begin writing at */
 ){
-  int rc = 0;                     /* True if error has occured, else false */
+  int rc = 0;                     /* True if error has occurred, else false */
   winFile *pFile = (winFile*)id;  /* File handle */
   int nRetry = 0;                 /* Number of retries */
 
@@ -31953,7 +32948,26 @@ static int winWrite(
   SimulateIOError(return SQLITE_IOERR_WRITE);
   SimulateDiskfullError(return SQLITE_FULL);
 
-  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
+  OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
+           pFile->h, pBuf, amt, offset, pFile->locktype));
+
+#if SQLITE_MAX_MMAP_SIZE>0
+  /* Deal with as much of this write request as possible by transfering
+  ** data from the memory mapping using memcpy().  */
+  if( offset<pFile->mmapSize ){
+    if( offset+amt <= pFile->mmapSize ){
+      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
+      OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
+      return SQLITE_OK;
+    }else{
+      int nCopy = (int)(pFile->mmapSize - offset);
+      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
+      pBuf = &((u8 *)pBuf)[nCopy];
+      amt -= nCopy;
+      offset += nCopy;
+    }
+  }
+#endif
 
 #if SQLITE_OS_WINCE
   rc = seekWinFile(pFile, offset);
@@ -31984,7 +32998,8 @@ static int winWrite(
         if( retryIoerr(&nRetry, &lastErrno) ) continue;
         break;
       }
-      if( nWrite<=0 ){
+      assert( nWrite==0 || nWrite<=(DWORD)nRem );
+      if( nWrite==0 || nWrite>(DWORD)nRem ){
         lastErrno = osGetLastError();
         break;
       }
@@ -32005,13 +33020,16 @@ static int winWrite(
   if( rc ){
     if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
        || ( pFile->lastErrno==ERROR_DISK_FULL )){
+      OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
       return SQLITE_FULL;
     }
+    OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
     return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
              "winWrite", pFile->zPath);
   }else{
     logIoerr(nRetry);
   }
+  OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
   return SQLITE_OK;
 }
 
@@ -32021,11 +33039,12 @@ static int winWrite(
 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
   winFile *pFile = (winFile*)id;  /* File handle object */
   int rc = SQLITE_OK;             /* Return code for this function */
+  DWORD lastErrno;
 
   assert( pFile );
-
-  OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
   SimulateIOError(return SQLITE_IOERR_TRUNCATE);
+  OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
+           pFile->h, nByte, pFile->locktype));
 
   /* If the user has configured a chunk-size for this file, truncate the
   ** file so that it consists of an integer number of chunks (i.e. the
@@ -32039,14 +33058,25 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
   /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
   if( seekWinFile(pFile, nByte) ){
     rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-             "winTruncate1", pFile->zPath);
-  }else if( 0==osSetEndOfFile(pFile->h) ){
-    pFile->lastErrno = osGetLastError();
+                     "winTruncate1", pFile->zPath);
+  }else if( 0==osSetEndOfFile(pFile->h) &&
+            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
+    pFile->lastErrno = lastErrno;
     rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-             "winTruncate2", pFile->zPath);
+                     "winTruncate2", pFile->zPath);
+  }
+
+#if SQLITE_MAX_MMAP_SIZE>0
+  /* If the file was truncated to a size smaller than the currently
+  ** mapped region, reduce the effective mapping size as well. SQLite will
+  ** use read() and write() to access data beyond this point from now on.
+  */
+  if( pFile->pMapRegion && nByte<pFile->mmapSize ){
+    pFile->mmapSize = nByte;
   }
+#endif
 
-  OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
+  OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
   return rc;
 }
 
@@ -32086,13 +33116,14 @@ static int winSync(sqlite3_file *id, int flags){
       || (flags&0x0F)==SQLITE_SYNC_FULL
   );
 
-  OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
-
   /* Unix cannot, but some systems may return SQLITE_FULL from here. This
   ** line is to test that doing so does not cause any problems.
   */
   SimulateDiskfullError( return SQLITE_FULL );
 
+  OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
+           pFile->h, flags, pFile->locktype));
+
 #ifndef SQLITE_TEST
   UNUSED_PARAMETER(flags);
 #else
@@ -32111,9 +33142,11 @@ static int winSync(sqlite3_file *id, int flags){
   rc = osFlushFileBuffers(pFile->h);
   SimulateIOError( rc=FALSE );
   if( rc ){
+    OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
     return SQLITE_OK;
   }else{
     pFile->lastErrno = osGetLastError();
+    OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
     return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
              "winSync", pFile->zPath);
   }
@@ -32128,7 +33161,10 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
   int rc = SQLITE_OK;
 
   assert( id!=0 );
+  assert( pSize!=0 );
   SimulateIOError(return SQLITE_IOERR_FSTAT);
+  OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
+
 #if SQLITE_OS_WINRT
   {
     FILE_STANDARD_INFO info;
@@ -32157,6 +33193,8 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
     }
   }
 #endif
+  OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
+           pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
   return rc;
 }
 
@@ -32198,6 +33236,7 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
 */
 static int getReadLock(winFile *pFile){
   int res;
+  OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
   if( isNT() ){
 #if SQLITE_OS_WINCE
     /*
@@ -32223,6 +33262,7 @@ static int getReadLock(winFile *pFile){
     pFile->lastErrno = osGetLastError();
     /* No need to log a failure to lock */
   }
+  OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
   return res;
 }
 
@@ -32232,6 +33272,7 @@ static int getReadLock(winFile *pFile){
 static int unlockReadLock(winFile *pFile){
   int res;
   DWORD lastErrno;
+  OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
   if( isNT() ){
     res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
   }
@@ -32245,6 +33286,7 @@ static int unlockReadLock(winFile *pFile){
     winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
              "unlockReadLock", pFile->zPath);
   }
+  OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
   return res;
 }
 
@@ -32283,14 +33325,15 @@ static int winLock(sqlite3_file *id, int locktype){
   DWORD lastErrno = NO_ERROR;
 
   assert( id!=0 );
-  OSTRACE(("LOCK %d %d was %d(%d)\n",
-           pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));
+  OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
+           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
 
   /* If there is already a lock of this type or more restrictive on the
   ** OsFile, do nothing. Don't use the end_lock: exit path, as
   ** sqlite3OsEnterMutex() hasn't been called yet.
   */
   if( pFile->locktype>=locktype ){
+    OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
     return SQLITE_OK;
   }
 
@@ -32318,7 +33361,8 @@ static int winLock(sqlite3_file *id, int locktype){
       ** If you are using this code as a model for alternative VFSes, do not
       ** copy this retry logic.  It is a hack intended for Windows only.
       */
-      OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
+      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
+               pFile->h, cnt, sqlite3ErrName(res)));
       if( cnt ) sqlite3_win32_sleep(1);
     }
     gotPendingLock = res;
@@ -32363,14 +33407,12 @@ static int winLock(sqlite3_file *id, int locktype){
   if( locktype==EXCLUSIVE_LOCK && res ){
     assert( pFile->locktype>=SHARED_LOCK );
     res = unlockReadLock(pFile);
-    OSTRACE(("unreadlock = %d\n", res));
     res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
                       SHARED_SIZE, 0);
     if( res ){
       newLocktype = EXCLUSIVE_LOCK;
     }else{
       lastErrno = osGetLastError();
-      OSTRACE(("error-code = %d\n", lastErrno));
       getReadLock(pFile);
     }
   }
@@ -32388,12 +33430,14 @@ static int winLock(sqlite3_file *id, int locktype){
   if( res ){
     rc = SQLITE_OK;
   }else{
-    OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
-           locktype, newLocktype));
+    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
+             pFile->h, locktype, newLocktype));
     pFile->lastErrno = lastErrno;
     rc = SQLITE_BUSY;
   }
   pFile->locktype = (u8)newLocktype;
+  OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
+           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
   return rc;
 }
 
@@ -32407,20 +33451,23 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
   winFile *pFile = (winFile*)id;
 
   SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+  OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
 
   assert( id!=0 );
   if( pFile->locktype>=RESERVED_LOCK ){
     rc = 1;
-    OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
+    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
   }else{
-    rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
+    rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
     if( rc ){
       winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
     }
     rc = !rc;
-    OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
+    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
   }
   *pResOut = rc;
+  OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
+           pFile->h, pResOut, *pResOut));
   return SQLITE_OK;
 }
 
@@ -32441,8 +33488,8 @@ static int winUnlock(sqlite3_file *id, int locktype){
   int rc = SQLITE_OK;
   assert( pFile!=0 );
   assert( locktype<=SHARED_LOCK );
-  OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
-          pFile->locktype, pFile->sharedLockByte));
+  OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
+           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
   type = pFile->locktype;
   if( type>=EXCLUSIVE_LOCK ){
     winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
@@ -32463,6 +33510,8 @@ static int winUnlock(sqlite3_file *id, int locktype){
     winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
   }
   pFile->locktype = (u8)locktype;
+  OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
+           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
   return rc;
 }
 
@@ -32482,22 +33531,29 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
   }
 }
 
+/* Forward declaration */
+static int getTempname(int nBuf, char *zBuf);
+
 /*
 ** Control and query of the open file handle.
 */
 static int winFileControl(sqlite3_file *id, int op, void *pArg){
   winFile *pFile = (winFile*)id;
+  OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
   switch( op ){
     case SQLITE_FCNTL_LOCKSTATE: {
       *(int*)pArg = pFile->locktype;
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_LAST_ERRNO: {
       *(int*)pArg = (int)pFile->lastErrno;
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_CHUNK_SIZE: {
       pFile->szChunk = *(int *)pArg;
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_SIZE_HINT: {
@@ -32512,20 +33568,25 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
             SimulateIOErrorBenign(0);
           }
         }
+        OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
         return rc;
       }
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_PERSIST_WAL: {
       winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
       winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_VFSNAME: {
       *(char**)pArg = sqlite3_mprintf("win32");
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_WIN32_AV_RETRY: {
@@ -32540,9 +33601,32 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
       }else{
         a[1] = win32IoerrRetryDelay;
       }
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+      return SQLITE_OK;
+    }
+    case SQLITE_FCNTL_TEMPFILENAME: {
+      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
+      if( zTFile ){
+        getTempname(pFile->pVfs->mxPathname, zTFile);
+        *(char**)pArg = zTFile;
+      }
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
+#if SQLITE_MAX_MMAP_SIZE>0
+    case SQLITE_FCNTL_MMAP_SIZE: {
+      i64 newLimit = *(i64*)pArg;
+      if( newLimit>sqlite3GlobalConfig.mxMmap ){
+        newLimit = sqlite3GlobalConfig.mxMmap;
+      }
+      *(i64*)pArg = pFile->mmapSizeMax;
+      if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
+      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+      return SQLITE_OK;
+    }
+#endif
   }
+  OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
   return SQLITE_NOTFOUND;
 }
 
@@ -32570,8 +33654,6 @@ static int winDeviceCharacteristics(sqlite3_file *id){
          ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
 }
 
-#ifndef SQLITE_OMIT_WAL
-
 /* 
 ** Windows will only let you create file view mappings
 ** on allocation size granularity boundaries.
@@ -32580,6 +33662,8 @@ static int winDeviceCharacteristics(sqlite3_file *id){
 */
 SYSTEM_INFO winSysInfo;
 
+#ifndef SQLITE_OMIT_WAL
+
 /*
 ** Helper functions to obtain and relinquish the global mutex. The
 ** global mutex is used to protect the winLockInfo objects used by 
@@ -32703,6 +33787,9 @@ static int winShmSystemLock(
   /* Access to the winShmNode object is serialized by the caller */
   assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
 
+  OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
+           pFile->hFile.h, lockType, ofst, nByte));
+
   /* Release/Acquire the system-level lock */
   if( lockType==_SHM_UNLCK ){
     rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
@@ -32720,11 +33807,9 @@ static int winShmSystemLock(
     rc = SQLITE_BUSY;
   }
 
-  OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n", 
-           pFile->hFile.h,
-           rc==SQLITE_OK ? "ok" : "failed",
-           lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
-           pFile->lastErrno));
+  OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
+           pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" :
+           "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
 
   return rc;
 }
@@ -32744,6 +33829,8 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
   winShmNode *p;
   BOOL bRc;
   assert( winShmMutexHeld() );
+  OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
+           osGetCurrentProcessId(), deleteFlag));
   pp = &winShmNodeList;
   while( (p = *pp)!=0 ){
     if( p->nRef==0 ){
@@ -32751,15 +33838,13 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
       if( p->mutex ) sqlite3_mutex_free(p->mutex);
       for(i=0; i<p->nRegion; i++){
         bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
-        OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
-                 (int)osGetCurrentProcessId(), i,
-                 bRc ? "ok" : "failed"));
+        OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
+                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
         bRc = osCloseHandle(p->aRegion[i].hMap);
-        OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n",
-                 (int)osGetCurrentProcessId(), i,
-                 bRc ? "ok" : "failed"));
+        OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
+                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
       }
-      if( p->hFile.h != INVALID_HANDLE_VALUE ){
+      if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
         SimulateIOErrorBenign(1);
         winClose((sqlite3_file *)&p->hFile);
         SimulateIOErrorBenign(0);
@@ -32799,16 +33884,14 @@ static int winOpenSharedMemory(winFile *pDbFd){
   /* Allocate space for the new sqlite3_shm object.  Also speculatively
   ** allocate space for a new winShmNode and filename.
   */
-  p = sqlite3_malloc( sizeof(*p) );
+  p = sqlite3MallocZero( sizeof(*p) );
   if( p==0 ) return SQLITE_IOERR_NOMEM;
-  memset(p, 0, sizeof(*p));
   nName = sqlite3Strlen30(pDbFd->zPath);
-  pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 17 );
+  pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
   if( pNew==0 ){
     sqlite3_free(p);
     return SQLITE_IOERR_NOMEM;
   }
-  memset(pNew, 0, sizeof(*pNew) + nName + 17);
   pNew->zFilename = (char*)&pNew[1];
   sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
   sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); 
@@ -32841,7 +33924,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
     rc = winOpen(pDbFd->pVfs,
                  pShmNode->zFilename,             /* Name of the file (UTF-8) */
                  (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
-                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
+                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                  0);
     if( SQLITE_OK!=rc ){
       goto shm_open_err;
@@ -33038,9 +34121,9 @@ static int winShmLock(
     }
   }
   sqlite3_mutex_leave(pShmNode->mutex);
-  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
-           p->id, (int)osGetCurrentProcessId(), p->sharedMask, p->exclMask,
-           rc ? "failed" : "ok"));
+  OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
+           osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
+           sqlite3ErrName(rc)));
   return rc;
 }
 
@@ -33145,20 +34228,24 @@ static int winShmMap(
     pShmNode->aRegion = apNew;
 
     while( pShmNode->nRegion<=iRegion ){
-      HANDLE hMap;                /* file-mapping handle */
+      HANDLE hMap = NULL;         /* file-mapping handle */
       void *pMap = 0;             /* Mapped memory region */
      
 #if SQLITE_OS_WINRT
       hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
           NULL, PAGE_READWRITE, nByte, NULL
       );
-#else
+#elif defined(SQLITE_WIN32_HAS_WIDE)
       hMap = osCreateFileMappingW(pShmNode->hFile.h, 
           NULL, PAGE_READWRITE, 0, nByte, NULL
       );
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+      hMap = osCreateFileMappingA(pShmNode->hFile.h, 
+          NULL, PAGE_READWRITE, 0, nByte, NULL
+      );
 #endif
-      OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
-               (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte,
+      OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
+               osGetCurrentProcessId(), pShmNode->nRegion, nByte,
                hMap ? "ok" : "failed"));
       if( hMap ){
         int iOffset = pShmNode->nRegion*szRegion;
@@ -33172,8 +34259,8 @@ static int winShmMap(
             0, iOffset - iOffsetShift, szRegion + iOffsetShift
         );
 #endif
-        OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n",
-                 (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
+        OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
+                 osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
                  szRegion, pMap ? "ok" : "failed"));
       }
       if( !pMap ){
@@ -33211,6 +34298,230 @@ shmpage_out:
 #endif /* #ifndef SQLITE_OMIT_WAL */
 
 /*
+** Cleans up the mapped region of the specified file, if any.
+*/
+#if SQLITE_MAX_MMAP_SIZE>0
+static int winUnmapfile(winFile *pFile){
+  assert( pFile!=0 );
+  OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
+           "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
+           osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
+           pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
+  if( pFile->pMapRegion ){
+    if( !osUnmapViewOfFile(pFile->pMapRegion) ){
+      pFile->lastErrno = osGetLastError();
+      OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
+               "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
+               pFile->pMapRegion));
+      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
+                         "winUnmap1", pFile->zPath);
+    }
+    pFile->pMapRegion = 0;
+    pFile->mmapSize = 0;
+    pFile->mmapSizeActual = 0;
+  }
+  if( pFile->hMap!=NULL ){
+    if( !osCloseHandle(pFile->hMap) ){
+      pFile->lastErrno = osGetLastError();
+      OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
+               osGetCurrentProcessId(), pFile, pFile->hMap));
+      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
+                         "winUnmap2", pFile->zPath);
+    }
+    pFile->hMap = NULL;
+  }
+  OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
+           osGetCurrentProcessId(), pFile));
+  return SQLITE_OK;
+}
+
+/*
+** Memory map or remap the file opened by file-descriptor pFd (if the file
+** is already mapped, the existing mapping is replaced by the new). Or, if 
+** there already exists a mapping for this file, and there are still 
+** outstanding xFetch() references to it, this function is a no-op.
+**
+** If parameter nByte is non-negative, then it is the requested size of 
+** the mapping to create. Otherwise, if nByte is less than zero, then the 
+** requested size is the size of the file on disk. The actual size of the
+** created mapping is either the requested size or the value configured 
+** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
+**
+** SQLITE_OK is returned if no error occurs (even if the mapping is not
+** recreated as a result of outstanding references) or an SQLite error
+** code otherwise.
+*/
+static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
+  sqlite3_int64 nMap = nByte;
+  int rc;
+
+  assert( nMap>=0 || pFd->nFetchOut==0 );
+  OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
+           osGetCurrentProcessId(), pFd, nByte));
+
+  if( pFd->nFetchOut>0 ) return SQLITE_OK;
+
+  if( nMap<0 ){
+    rc = winFileSize((sqlite3_file*)pFd, &nMap);
+    if( rc ){
+      OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
+               osGetCurrentProcessId(), pFd));
+      return SQLITE_IOERR_FSTAT;
+    }
+  }
+  if( nMap>pFd->mmapSizeMax ){
+    nMap = pFd->mmapSizeMax;
+  }
+  nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
+ 
+  if( nMap==0 && pFd->mmapSize>0 ){
+    winUnmapfile(pFd);
+  }
+  if( nMap!=pFd->mmapSize ){
+    void *pNew = 0;
+    DWORD protect = PAGE_READONLY;
+    DWORD flags = FILE_MAP_READ;
+
+    winUnmapfile(pFd);
+    if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
+      protect = PAGE_READWRITE;
+      flags |= FILE_MAP_WRITE;
+    }
+#if SQLITE_OS_WINRT
+    pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
+#elif defined(SQLITE_WIN32_HAS_WIDE)
+    pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
+                                (DWORD)((nMap>>32) & 0xffffffff),
+                                (DWORD)(nMap & 0xffffffff), NULL);
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+    pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
+                                (DWORD)((nMap>>32) & 0xffffffff),
+                                (DWORD)(nMap & 0xffffffff), NULL);
+#endif
+    if( pFd->hMap==NULL ){
+      pFd->lastErrno = osGetLastError();
+      rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
+                       "winMapfile", pFd->zPath);
+      /* Log the error, but continue normal operation using xRead/xWrite */
+      OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
+               osGetCurrentProcessId(), pFd));
+      return SQLITE_OK;
+    }
+    assert( (nMap % winSysInfo.dwPageSize)==0 );
+#if SQLITE_OS_WINRT
+    pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
+#else
+    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
+    pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
+#endif
+    if( pNew==NULL ){
+      osCloseHandle(pFd->hMap);
+      pFd->hMap = NULL;
+      pFd->lastErrno = osGetLastError();
+      winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
+                  "winMapfile", pFd->zPath);
+      OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
+               osGetCurrentProcessId(), pFd));
+      return SQLITE_OK;
+    }
+    pFd->pMapRegion = pNew;
+    pFd->mmapSize = nMap;
+    pFd->mmapSizeActual = nMap;
+  }
+
+  OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
+           osGetCurrentProcessId(), pFd));
+  return SQLITE_OK;
+}
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+
+/*
+** If possible, return a pointer to a mapping of file fd starting at offset
+** iOff. The mapping must be valid for at least nAmt bytes.
+**
+** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
+** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
+** Finally, if an error does occur, return an SQLite error code. The final
+** value of *pp is undefined in this case.
+**
+** If this function does return a pointer, the caller must eventually 
+** release the reference by calling winUnfetch().
+*/
+static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
+#if SQLITE_MAX_MMAP_SIZE>0
+  winFile *pFd = (winFile*)fd;   /* The underlying database file */
+#endif
+  *pp = 0;
+
+  OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
+           osGetCurrentProcessId(), fd, iOff, nAmt, pp));
+
+#if SQLITE_MAX_MMAP_SIZE>0
+  if( pFd->mmapSizeMax>0 ){
+    if( pFd->pMapRegion==0 ){
+      int rc = winMapfile(pFd, -1);
+      if( rc!=SQLITE_OK ){
+        OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
+                 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
+        return rc;
+      }
+    }
+    if( pFd->mmapSize >= iOff+nAmt ){
+      *pp = &((u8 *)pFd->pMapRegion)[iOff];
+      pFd->nFetchOut++;
+    }
+  }
+#endif
+
+  OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
+           osGetCurrentProcessId(), fd, pp, *pp));
+  return SQLITE_OK;
+}
+
+/*
+** If the third argument is non-NULL, then this function releases a 
+** reference obtained by an earlier call to winFetch(). The second
+** argument passed to this function must be the same as the corresponding
+** argument that was passed to the winFetch() invocation. 
+**
+** Or, if the third argument is NULL, then this function is being called 
+** to inform the VFS layer that, according to POSIX, any existing mapping 
+** may now be invalid and should be unmapped.
+*/
+static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
+#if SQLITE_MAX_MMAP_SIZE>0
+  winFile *pFd = (winFile*)fd;   /* The underlying database file */
+
+  /* If p==0 (unmap the entire file) then there must be no outstanding 
+  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
+  ** then there must be at least one outstanding.  */
+  assert( (p==0)==(pFd->nFetchOut==0) );
+
+  /* If p!=0, it must match the iOff value. */
+  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
+
+  OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
+           osGetCurrentProcessId(), pFd, iOff, p));
+
+  if( p ){
+    pFd->nFetchOut--;
+  }else{
+    /* FIXME:  If Windows truly always prevents truncating or deleting a
+    ** file while a mapping is held, then the following winUnmapfile() call
+    ** is unnecessary can can be omitted - potentially improving
+    ** performance.  */
+    winUnmapfile(pFd);
+  }
+
+  assert( pFd->nFetchOut>=0 );
+#endif
+
+  OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
+           osGetCurrentProcessId(), fd));
+  return SQLITE_OK;
+}
+
+/*
 ** Here ends the implementation of all sqlite3_file methods.
 **
 ********************** End sqlite3_file Methods *******************************
@@ -33221,7 +34532,7 @@ shmpage_out:
 ** sqlite3_file for win32.
 */
 static const sqlite3_io_methods winIoMethod = {
-  2,                              /* iVersion */
+  3,                              /* iVersion */
   winClose,                       /* xClose */
   winRead,                        /* xRead */
   winWrite,                       /* xWrite */
@@ -33237,7 +34548,9 @@ static const sqlite3_io_methods winIoMethod = {
   winShmMap,                      /* xShmMap */
   winShmLock,                     /* xShmLock */
   winShmBarrier,                  /* xShmBarrier */
-  winShmUnmap                     /* xShmUnmap */
+  winShmUnmap,                    /* xShmUnmap */
+  winFetch,                       /* xFetch */
+  winUnfetch                      /* xUnfetch */
 };
 
 /****************************************************************************
@@ -33301,6 +34614,7 @@ static int getTempname(int nBuf, char *zBuf){
       sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
       sqlite3_free(zMulti);
     }else{
+      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
       return SQLITE_IOERR_NOMEM;
     }
   }
@@ -33314,6 +34628,7 @@ static int getTempname(int nBuf, char *zBuf){
       sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
       sqlite3_free(zUtf8);
     }else{
+      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
       return SQLITE_IOERR_NOMEM;
     }
   }
@@ -33326,6 +34641,7 @@ static int getTempname(int nBuf, char *zBuf){
   nTempPath = sqlite3Strlen30(zTempPath);
 
   if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
+    OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
     return SQLITE_ERROR;
   }
 
@@ -33343,8 +34659,8 @@ static int getTempname(int nBuf, char *zBuf){
   zBuf[j] = 0;
   zBuf[j+1] = 0;
 
-  OSTRACE(("TEMP FILENAME: %s\n", zBuf));
-  return SQLITE_OK; 
+  OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
+  return SQLITE_OK;
 }
 
 /*
@@ -33413,9 +34729,7 @@ static int winOpen(
   int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
   int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
   int isCreate     = (flags & SQLITE_OPEN_CREATE);
-#ifndef NDEBUG
   int isReadonly   = (flags & SQLITE_OPEN_READONLY);
-#endif
   int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
 
 #ifndef NDEBUG
@@ -33426,6 +34740,9 @@ static int winOpen(
   ));
 #endif
 
+  OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
+           zUtf8Name, id, flags, pOutFlags));
+
   /* Check the following statements are true: 
   **
   **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
@@ -33452,8 +34769,9 @@ static int winOpen(
        || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
   );
 
-  assert( id!=0 );
-  UNUSED_PARAMETER(pVfs);
+  assert( pFile!=0 );
+  memset(pFile, 0, sizeof(winFile));
+  pFile->h = INVALID_HANDLE_VALUE;
 
 #if SQLITE_OS_WINRT
   if( !sqlite3_temp_directory ){
@@ -33462,15 +34780,15 @@ static int winOpen(
   }
 #endif
 
-  pFile->h = INVALID_HANDLE_VALUE;
-
   /* If the second argument to this function is NULL, generate a 
   ** temporary file name to use 
   */
   if( !zUtf8Name ){
     assert(isDelete && !isOpenJournal);
+    memset(zTmpname, 0, MAX_PATH+2);
     rc = getTempname(MAX_PATH+2, zTmpname);
     if( rc!=SQLITE_OK ){
+      OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
       return rc;
     }
     zUtf8Name = zTmpname;
@@ -33486,11 +34804,13 @@ static int winOpen(
   /* Convert the filename to the system encoding. */
   zConverted = convertUtf8Filename(zUtf8Name);
   if( zConverted==0 ){
+    OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
     return SQLITE_IOERR_NOMEM;
   }
 
   if( winIsDir(zConverted) ){
     sqlite3_free(zConverted);
+    OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
     return SQLITE_CANTOPEN_ISDIR;
   }
 
@@ -33581,9 +34901,8 @@ static int winOpen(
 #endif
   logIoerr(cnt);
 
-  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
-           h, zName, dwDesiredAccess, 
-           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
+  OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
+           dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
 
   if( h==INVALID_HANDLE_VALUE ){
     pFile->lastErrno = lastErrno;
@@ -33591,7 +34910,9 @@ static int winOpen(
     sqlite3_free(zConverted);
     if( isReadWrite && !isExclusive ){
       return winOpen(pVfs, zName, id, 
-             ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
+         ((flags|SQLITE_OPEN_READONLY) &
+                     ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
+         pOutFlags);
     }else{
       return SQLITE_CANTOPEN_BKPT;
     }
@@ -33605,26 +34926,18 @@ static int winOpen(
     }
   }
 
-  memset(pFile, 0, sizeof(*pFile));
-  pFile->pMethod = &winIoMethod;
-  pFile->h = h;
-  pFile->lastErrno = NO_ERROR;
-  pFile->pVfs = pVfs;
-#ifndef SQLITE_OMIT_WAL
-  pFile->pShm = 0;
-#endif
-  pFile->zPath = zName;
-  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
-    pFile->ctrlFlags |= WINFILE_PSOW;
-  }
+  OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
+           "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
+           *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
 
 #if SQLITE_OS_WINCE
   if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
-       && !winceCreateLock(zName, pFile)
+       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
   ){
     osCloseHandle(h);
     sqlite3_free(zConverted);
-    return SQLITE_CANTOPEN_BKPT;
+    OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
+    return rc;
   }
   if( isTemp ){
     pFile->zDeleteOnClose = zConverted;
@@ -33634,6 +34947,25 @@ static int winOpen(
     sqlite3_free(zConverted);
   }
 
+  pFile->pMethod = &winIoMethod;
+  pFile->pVfs = pVfs;
+  pFile->h = h;
+  if( isReadonly ){
+    pFile->ctrlFlags |= WINFILE_RDONLY;
+  }
+  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+    pFile->ctrlFlags |= WINFILE_PSOW;
+  }
+  pFile->lastErrno = NO_ERROR;
+  pFile->zPath = zName;
+#if SQLITE_MAX_MMAP_SIZE>0
+  pFile->hMap = NULL;
+  pFile->pMapRegion = 0;
+  pFile->mmapSize = 0;
+  pFile->mmapSizeActual = 0;
+  pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
+#endif
+
   OpenCounter(+1);
   return rc;
 }
@@ -33664,6 +34996,8 @@ static int winDelete(
   UNUSED_PARAMETER(syncDir);
 
   SimulateIOError(return SQLITE_IOERR_DELETE);
+  OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
+
   zConverted = convertUtf8Filename(zFilename);
   if( zConverted==0 ){
     return SQLITE_IOERR_NOMEM;
@@ -33677,14 +35011,26 @@ static int winDelete(
                                   &sAttrData) ){
         attr = sAttrData.dwFileAttributes;
       }else{
-        rc = SQLITE_OK; /* Already gone? */
+        lastErrno = osGetLastError();
+        if( lastErrno==ERROR_FILE_NOT_FOUND
+         || lastErrno==ERROR_PATH_NOT_FOUND ){
+          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+        }else{
+          rc = SQLITE_ERROR;
+        }
         break;
       }
 #else
       attr = osGetFileAttributesW(zConverted);
 #endif
       if ( attr==INVALID_FILE_ATTRIBUTES ){
-        rc = SQLITE_OK; /* Already gone? */
+        lastErrno = osGetLastError();
+        if( lastErrno==ERROR_FILE_NOT_FOUND
+         || lastErrno==ERROR_PATH_NOT_FOUND ){
+          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+        }else{
+          rc = SQLITE_ERROR;
+        }
         break;
       }
       if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
@@ -33706,7 +35052,13 @@ static int winDelete(
     do {
       attr = osGetFileAttributesA(zConverted);
       if ( attr==INVALID_FILE_ATTRIBUTES ){
-        rc = SQLITE_OK; /* Already gone? */
+        lastErrno = osGetLastError();
+        if( lastErrno==ERROR_FILE_NOT_FOUND
+         || lastErrno==ERROR_PATH_NOT_FOUND ){
+          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+        }else{
+          rc = SQLITE_ERROR;
+        }
         break;
       }
       if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
@@ -33724,19 +35076,19 @@ static int winDelete(
     } while(1);
   }
 #endif
-  if( rc ){
+  if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
     rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
              "winDelete", zFilename);
   }else{
     logIoerr(cnt);
   }
   sqlite3_free(zConverted);
-  OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
+  OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
   return rc;
 }
 
 /*
-** Check the existance and status of a file.
+** Check the existence and status of a file.
 */
 static int winAccess(
   sqlite3_vfs *pVfs,         /* Not used on win32 */
@@ -33751,8 +35103,12 @@ static int winAccess(
   UNUSED_PARAMETER(pVfs);
 
   SimulateIOError( return SQLITE_IOERR_ACCESS; );
+  OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
+           zFilename, flags, pResOut));
+
   zConverted = convertUtf8Filename(zFilename);
   if( zConverted==0 ){
+    OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
     return SQLITE_IOERR_NOMEM;
   }
   if( isNT() ){
@@ -33803,6 +35159,8 @@ static int winAccess(
       assert(!"Invalid flags argument");
   }
   *pResOut = rc;
+  OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
+           zFilename, pResOut, *pResOut));
   return SQLITE_OK;
 }
 
@@ -33870,16 +35228,12 @@ static int winFullPathname(
     */
     char zOut[MAX_PATH+1];
     memset(zOut, 0, MAX_PATH+1);
-    cygwin_conv_to_win32_path(zRelative, zOut); /* POSIX to Win32 */
+    cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
+                     MAX_PATH+1);
     sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
                      sqlite3_data_directory, zOut);
   }else{
-    /*
-    ** NOTE: The Cygwin docs state that the maximum length needed
-    **       for the buffer passed to cygwin_conv_to_full_win32_path
-    **       is MAX_PATH.
-    */
-    cygwin_conv_to_full_win32_path(zRelative, zFull);
+    cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
   }
   return SQLITE_OK;
 #endif
@@ -33904,7 +35258,7 @@ static int winFullPathname(
 #endif
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
-  int nByte;
+  DWORD nByte;
   void *zConverted;
   char *zOut;
 
@@ -33938,13 +35292,27 @@ static int winFullPathname(
   }
   if( isNT() ){
     LPWSTR zTemp;
-    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0) + 3;
-    zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
+    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameW1", zConverted);
+      sqlite3_free(zConverted);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
+    nByte += 3;
+    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
     if( zTemp==0 ){
       sqlite3_free(zConverted);
       return SQLITE_IOERR_NOMEM;
     }
-    osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+    nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameW2", zConverted);
+      sqlite3_free(zConverted);
+      sqlite3_free(zTemp);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
     sqlite3_free(zConverted);
     zOut = unicodeToUtf8(zTemp);
     sqlite3_free(zTemp);
@@ -33952,13 +35320,27 @@ static int winFullPathname(
 #ifdef SQLITE_WIN32_HAS_ANSI
   else{
     char *zTemp;
-    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
-    zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
+    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameA1", zConverted);
+      sqlite3_free(zConverted);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
+    nByte += 3;
+    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
     if( zTemp==0 ){
       sqlite3_free(zConverted);
       return SQLITE_IOERR_NOMEM;
     }
-    osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+    nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameA2", zConverted);
+      sqlite3_free(zConverted);
+      sqlite3_free(zTemp);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
     sqlite3_free(zConverted);
     zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
     sqlite3_free(zTemp);
@@ -34009,9 +35391,9 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
   UNUSED_PARAMETER(pVfs);
   getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
 }
-static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
+static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
   UNUSED_PARAMETER(pVfs);
-  return (void(*)(void))osGetProcAddressA((HANDLE)pHandle, zSymbol);
+  return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
 }
 static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
   UNUSED_PARAMETER(pVfs);
@@ -34109,7 +35491,8 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
 #endif
   /* 2^32 - to avoid use of LL and warnings in gcc */
   static const sqlite3_int64 max32BitValue = 
-      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
+      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
+      (sqlite3_int64)294967296;
 
 #if SQLITE_OS_WINCE
   SYSTEMTIME time;
@@ -34216,9 +35599,8 @@ SQLITE_API int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==73 );
+  assert( ArraySize(aSyscall)==74 );
 
-#ifndef SQLITE_OMIT_WAL
   /* get memory map allocation granularity */
   memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
 #if SQLITE_OS_WINRT
@@ -34226,8 +35608,8 @@ SQLITE_API int sqlite3_os_init(void){
 #else
   osGetSystemInfo(&winSysInfo);
 #endif
-  assert(winSysInfo.dwAllocationGranularity > 0);
-#endif
+  assert( winSysInfo.dwAllocationGranularity>0 );
+  assert( winSysInfo.dwPageSize>0 );
 
   sqlite3_vfs_register(&winVfs, 1);
   return SQLITE_OK; 
@@ -34235,7 +35617,7 @@ SQLITE_API int sqlite3_os_init(void){
 
 SQLITE_API int sqlite3_os_end(void){ 
 #if SQLITE_OS_WINRT
-  if( sleepObj != NULL ){
+  if( sleepObj!=NULL ){
     osCloseHandle(sleepObj);
     sleepObj = NULL;
   }
@@ -34320,7 +35702,7 @@ SQLITE_API int sqlite3_os_end(void){
 /*
 ** A bitmap is an instance of the following structure.
 **
-** This bitmap records the existance of zero or more bits
+** This bitmap records the existence of zero or more bits
 ** with values between 1 and iSize, inclusive.
 **
 ** There are three possible representations of the bitmap.
@@ -36864,7 +38246,6 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
 # define sqlite3WalClose(w,x,y,z)                0
 # define sqlite3WalBeginReadTransaction(y,z)     0
 # define sqlite3WalEndReadTransaction(z)
-# define sqlite3WalRead(v,w,x,y,z)               0
 # define sqlite3WalDbsize(y)                     0
 # define sqlite3WalBeginWriteTransaction(y)      0
 # define sqlite3WalEndWriteTransaction(x)        0
@@ -36877,6 +38258,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
 # define sqlite3WalExclusiveMode(y,z)            0
 # define sqlite3WalHeapMemory(z)                 0
 # define sqlite3WalFramesize(z)                  0
+# define sqlite3WalFindFrame(x,y,z)              0
 #else
 
 #define WAL_SAVEPOINT_NDATA 4
@@ -36904,7 +38286,8 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
 SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
 
 /* Read a page from the write-ahead log, if it is present. */
-SQLITE_PRIVATE int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
+SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
+SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
 
 /* If the WAL is not empty, return the size of the database. */
 SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
@@ -37222,7 +38605,7 @@ int sqlite3PagerTrace=1;  /* True to enable tracing */
 **    * A write transaction is active.
 **    * An EXCLUSIVE or greater lock is held on the database file.
 **    * All writing and syncing of journal and database data has finished.
-**      If no error occured, all that remains is to finalize the journal to
+**      If no error occurred, all that remains is to finalize the journal to
 **      commit the transaction. If an error did occur, the caller will need
 **      to rollback the transaction. 
 **
@@ -37470,7 +38853,7 @@ struct PagerSavepoint {
 **
 ** doNotSpill, doNotSyncSpill
 **
-**   These two boolean variables control the behaviour of cache-spills
+**   These two boolean variables control the behavior of cache-spills
 **   (calls made by the pcache module to the pagerStress() routine to
 **   write cached data to the file-system in order to free up memory).
 **
@@ -37604,6 +38987,11 @@ struct Pager {
   PagerSavepoint *aSavepoint; /* Array of active savepoints */
   int nSavepoint;             /* Number of elements in aSavepoint[] */
   char dbFileVers[16];        /* Changes whenever database file changes */
+
+  u8 bUseFetch;               /* True to use xFetch() */
+  int nMmapOut;               /* Number of mmap pages currently outstanding */
+  sqlite3_int64 szMmap;       /* Desired maximum mmap size */
+  PgHdr *pMmapFreelist;       /* List of free mmap page headers (pDirty) */
   /*
   ** End of the routinely-changing class members
   ***************************************************************************/
@@ -37715,6 +39103,16 @@ static const unsigned char aJournalMagic[] = {
 #endif
 
 /*
+** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
+** interfaces to access the database using memory-mapped I/O.
+*/
+#if SQLITE_MAX_MMAP_SIZE>0
+# define USEFETCH(x) ((x)->bUseFetch)
+#else
+# define USEFETCH(x) 0
+#endif
+
+/*
 ** The maximum legal page number is (2^31 - 1).
 */
 #define PAGER_MAX_PGNO 2147483647
@@ -38348,7 +39746,7 @@ static int writeJournalHdr(Pager *pPager){
     memset(zHeader, 0, sizeof(aJournalMagic)+4);
   }
 
-  /* The random check-hash initialiser */ 
+  /* The random check-hash initializer */ 
   sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
   put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
   /* The initial database size */
@@ -38787,6 +40185,8 @@ static int pager_error(Pager *pPager, int rc){
   return rc;
 }
 
+static int pager_truncate(Pager *pPager, Pgno nPage);
+
 /*
 ** This routine ends a transaction. A transaction is usually ended by 
 ** either a COMMIT or a ROLLBACK operation. This routine may be called 
@@ -38840,7 +40240,7 @@ static int pager_error(Pager *pPager, int rc){
 ** to the first error encountered (the journal finalization one) is
 ** returned.
 */
-static int pager_end_transaction(Pager *pPager, int hasMaster){
+static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
   int rc = SQLITE_OK;      /* Error code from journal finalization operation */
   int rc2 = SQLITE_OK;     /* Error code from db file unlock operation */
 
@@ -38890,12 +40290,13 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
       ** file should be closed and deleted. If this connection writes to
       ** the database file, it will do so using an in-memory journal. 
       */
+      int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
       assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
            || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
            || pPager->journalMode==PAGER_JOURNALMODE_WAL 
       );
       sqlite3OsClose(pPager->jfd);
-      if( !pPager->tempFile ){
+      if( bDelete ){
         rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
       }
     }
@@ -38925,7 +40326,17 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
     */
     rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
     assert( rc2==SQLITE_OK );
+  }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
+    /* This branch is taken when committing a transaction in rollback-journal
+    ** mode if the database file on disk is larger than the database image.
+    ** At this point the journal has been finalized and the transaction 
+    ** successfully committed, but the EXCLUSIVE lock is still held on the
+    ** file. So it is safe to truncate the database file to its minimum
+    ** required size.  */
+    assert( pPager->eLock==EXCLUSIVE_LOCK );
+    rc = pager_truncate(pPager, pPager->dbSize);
   }
+
   if( !pPager->exclusiveMode 
    && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
   ){
@@ -38964,7 +40375,7 @@ static void pagerUnlockAndRollback(Pager *pPager){
       sqlite3EndBenignMalloc();
     }else if( !pPager->exclusiveMode ){
       assert( pPager->eState==PAGER_READER );
-      pager_end_transaction(pPager, 0);
+      pager_end_transaction(pPager, 0, 0);
     }
   }
   pager_unlock(pPager);
@@ -39188,7 +40599,7 @@ static int pager_playback_one_page(
     i64 ofst = (pgno-1)*(i64)pPager->pageSize;
     testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
     assert( !pagerUseWal(pPager) );
-    rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst);
+    rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
     if( pgno>pPager->dbFileSize ){
       pPager->dbFileSize = pgno;
     }
@@ -39459,6 +40870,21 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
 }
 
 /*
+** Return a sanitized version of the sector-size of OS file pFile. The
+** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
+*/
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
+  int iRet = sqlite3OsSectorSize(pFile);
+  if( iRet<32 ){
+    iRet = 512;
+  }else if( iRet>MAX_SECTOR_SIZE ){
+    assert( MAX_SECTOR_SIZE>=512 );
+    iRet = MAX_SECTOR_SIZE;
+  }
+  return iRet;
+}
+
+/*
 ** Set the value of the Pager.sectorSize variable for the given
 ** pager based on the value returned by the xSectorSize method
 ** of the open database file. The sector size will be used used 
@@ -39493,14 +40919,7 @@ static void setSectorSize(Pager *pPager){
     ** call will segfault. */
     pPager->sectorSize = 512;
   }else{
-    pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
-    if( pPager->sectorSize<32 ){
-      pPager->sectorSize = 512;
-    }
-    if( pPager->sectorSize>MAX_SECTOR_SIZE ){
-      assert( MAX_SECTOR_SIZE>=512 );
-      pPager->sectorSize = MAX_SECTOR_SIZE;
-    }
+    pPager->sectorSize = sqlite3SectorSize(pPager->fd);
   }
 }
 
@@ -39571,6 +40990,7 @@ static int pager_playback(Pager *pPager, int isHot){
   int res = 1;             /* Value returned by sqlite3OsAccess() */
   char *zMaster = 0;       /* Name of master journal file if any */
   int needPagerReset;      /* True to reset page prior to first page rollback */
+  int nPlayback = 0;       /* Total number of pages restored from journal */
 
   /* Figure out how many records are in the journal.  Abort early if
   ** the journal is empty.
@@ -39671,7 +41091,9 @@ static int pager_playback(Pager *pPager, int isHot){
         needPagerReset = 0;
       }
       rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
-      if( rc!=SQLITE_OK ){
+      if( rc==SQLITE_OK ){
+        nPlayback++;
+      }else{
         if( rc==SQLITE_DONE ){
           pPager->journalOff = szJ;
           break;
@@ -39731,7 +41153,7 @@ end_playback:
     rc = sqlite3PagerSync(pPager);
   }
   if( rc==SQLITE_OK ){
-    rc = pager_end_transaction(pPager, zMaster[0]!='\0');
+    rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
     testcase( rc!=SQLITE_OK );
   }
   if( rc==SQLITE_OK && zMaster[0] && res ){
@@ -39741,6 +41163,10 @@ end_playback:
     rc = pager_delmaster(pPager, zMaster);
     testcase( rc!=SQLITE_OK );
   }
+  if( isHot && nPlayback ){
+    sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
+                nPlayback, pPager->zJournal);
+  }
 
   /* The Pager.sectorSize variable may have been updated while rolling
   ** back a journal created by a process with a different sector size
@@ -39762,11 +41188,10 @@ end_playback:
 ** If an IO error occurs, then the IO error is returned to the caller.
 ** Otherwise, SQLITE_OK is returned.
 */
-static int readDbPage(PgHdr *pPg){
+static int readDbPage(PgHdr *pPg, u32 iFrame){
   Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
   Pgno pgno = pPg->pgno;       /* Page number to read */
   int rc = SQLITE_OK;          /* Return code */
-  int isInWal = 0;             /* True if page is in log file */
   int pgsz = pPager->pageSize; /* Number of bytes to read */
 
   assert( pPager->eState>=PAGER_READER && !MEMDB );
@@ -39778,11 +41203,13 @@ static int readDbPage(PgHdr *pPg){
     return SQLITE_OK;
   }
 
-  if( pagerUseWal(pPager) ){
+#ifndef SQLITE_OMIT_WAL
+  if( iFrame ){
     /* Try to pull the page from the write-ahead log. */
-    rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData);
-  }
-  if( rc==SQLITE_OK && !isInWal ){
+    rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
+  }else
+#endif
+  {
     i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
     rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
     if( rc==SQLITE_IOERR_SHORT_READ ){
@@ -39861,12 +41288,17 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
   Pager *pPager = (Pager *)pCtx;
   PgHdr *pPg;
 
+  assert( pagerUseWal(pPager) );
   pPg = sqlite3PagerLookup(pPager, iPg);
   if( pPg ){
     if( sqlite3PcachePageRefcount(pPg)==1 ){
       sqlite3PcacheDrop(pPg);
     }else{
-      rc = readDbPage(pPg);
+      u32 iFrame = 0;
+      rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
+      if( rc==SQLITE_OK ){
+        rc = readDbPage(pPg, iFrame);
+      }
       if( rc==SQLITE_OK ){
         pPager->xReiniter(pPg);
       }
@@ -40010,6 +41442,7 @@ static int pagerBeginReadTransaction(Pager *pPager){
   rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
   if( rc!=SQLITE_OK || changed ){
     pager_reset(pPager);
+    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
   }
 
   return rc;
@@ -40100,6 +41533,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
     if( rc ) return rc;
     if( nPage==0 ){
       rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+      if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
       isWal = 0;
     }else{
       rc = sqlite3OsAccess(
@@ -40271,6 +41705,29 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
 }
 
 /*
+** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
+*/
+static void pagerFixMaplimit(Pager *pPager){
+#if SQLITE_MAX_MMAP_SIZE>0
+  sqlite3_file *fd = pPager->fd;
+  if( isOpen(fd) ){
+    sqlite3_int64 sz;
+    pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
+    sz = pPager->szMmap;
+    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
+  }
+#endif
+}
+
+/*
+** Change the maximum size of any memory mapping made of the database file.
+*/
+SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
+  pPager->szMmap = szMmap;
+  pagerFixMaplimit(pPager);
+}
+
+/*
 ** Free as much memory as possible from the pager.
 */
 SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
@@ -40417,9 +41874,16 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
   Pager *pPager,                       /* Pager object */
   int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
   void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
-){  
+){
   pPager->xBusyHandler = xBusyHandler;
   pPager->pBusyHandlerArg = pBusyHandlerArg;
+
+  if( isOpen(pPager->fd) ){
+    void **ap = (void **)&pPager->xBusyHandler;
+    assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+    assert( ap[1]==pBusyHandlerArg );
+    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
+  }
 }
 
 /*
@@ -40498,6 +41962,7 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR
     assert( nReserve>=0 && nReserve<1000 );
     pPager->nReserve = (i16)nReserve;
     pagerReportSize(pPager);
+    pagerFixMaplimit(pPager);
   }
   return rc;
 }
@@ -40651,7 +42116,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
 ** dirty page were to be discarded from the cache via the pagerStress()
 ** routine, pagerStress() would not write the current page content to
 ** the database file. If a savepoint transaction were rolled back after
-** this happened, the correct behaviour would be to restore the current
+** this happened, the correct behavior would be to restore the current
 ** content of the page. However, since this content is not present in either
 ** the database file or the portion of the rollback journal and 
 ** sub-journal rolled back the content could not be restored and the
@@ -40675,12 +42140,26 @@ static void assertTruncateConstraint(Pager *pPager){
 ** function does not actually modify the database file on disk. It 
 ** just sets the internal state of the pager object so that the 
 ** truncation will be done when the current transaction is committed.
+**
+** This function is only called right before committing a transaction.
+** Once this function has been called, the transaction must either be
+** rolled back or committed. It is not safe to call this function and
+** then continue writing to the database.
 */
 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
   assert( pPager->dbSize>=nPage );
   assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
   pPager->dbSize = nPage;
-  assertTruncateConstraint(pPager);
+
+  /* At one point the code here called assertTruncateConstraint() to
+  ** ensure that all pages being truncated away by this operation are,
+  ** if one or more savepoints are open, present in the savepoint 
+  ** journal so that they can be restored if the savepoint is rolled
+  ** back. This is no longer necessary as this function is now only
+  ** called right before committing a transaction. So although the 
+  ** Pager object may still have open savepoints (Pager.nSavepoint!=0), 
+  ** they cannot be rolled back. So the assertTruncateConstraint() call
+  ** is no longer correct. */
 }
 
 
@@ -40710,6 +42189,81 @@ static int pagerSyncHotJournal(Pager *pPager){
 }
 
 /*
+** Obtain a reference to a memory mapped page object for page number pgno. 
+** The new object will use the pointer pData, obtained from xFetch().
+** If successful, set *ppPage to point to the new page reference
+** and return SQLITE_OK. Otherwise, return an SQLite error code and set
+** *ppPage to zero.
+**
+** Page references obtained by calling this function should be released
+** by calling pagerReleaseMapPage().
+*/
+static int pagerAcquireMapPage(
+  Pager *pPager,                  /* Pager object */
+  Pgno pgno,                      /* Page number */
+  void *pData,                    /* xFetch()'d data for this page */
+  PgHdr **ppPage                  /* OUT: Acquired page object */
+){
+  PgHdr *p;                       /* Memory mapped page to return */
+
+  if( pPager->pMmapFreelist ){
+    *ppPage = p = pPager->pMmapFreelist;
+    pPager->pMmapFreelist = p->pDirty;
+    p->pDirty = 0;
+    memset(p->pExtra, 0, pPager->nExtra);
+  }else{
+    *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
+    if( p==0 ){
+      sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
+      return SQLITE_NOMEM;
+    }
+    p->pExtra = (void *)&p[1];
+    p->flags = PGHDR_MMAP;
+    p->nRef = 1;
+    p->pPager = pPager;
+  }
+
+  assert( p->pExtra==(void *)&p[1] );
+  assert( p->pPage==0 );
+  assert( p->flags==PGHDR_MMAP );
+  assert( p->pPager==pPager );
+  assert( p->nRef==1 );
+
+  p->pgno = pgno;
+  p->pData = pData;
+  pPager->nMmapOut++;
+
+  return SQLITE_OK;
+}
+
+/*
+** Release a reference to page pPg. pPg must have been returned by an 
+** earlier call to pagerAcquireMapPage().
+*/
+static void pagerReleaseMapPage(PgHdr *pPg){
+  Pager *pPager = pPg->pPager;
+  pPager->nMmapOut--;
+  pPg->pDirty = pPager->pMmapFreelist;
+  pPager->pMmapFreelist = pPg;
+
+  assert( pPager->fd->pMethods->iVersion>=3 );
+  sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
+}
+
+/*
+** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
+*/
+static void pagerFreeMapHdrs(Pager *pPager){
+  PgHdr *p;
+  PgHdr *pNext;
+  for(p=pPager->pMmapFreelist; p; p=pNext){
+    pNext = p->pDirty;
+    sqlite3_free(p);
+  }
+}
+
+
+/*
 ** Shutdown the page cache.  Free all memory and close all files.
 **
 ** If a transaction was in progress when this routine is called, that
@@ -40729,6 +42283,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
   assert( assert_pager_state(pPager) );
   disable_simulated_io_errors();
   sqlite3BeginBenignMalloc();
+  pagerFreeMapHdrs(pPager);
   /* pPager->errCode = 0; */
   pPager->exclusiveMode = 0;
 #ifndef SQLITE_OMIT_WAL
@@ -40990,7 +42545,9 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
   ** file size will be.
   */
   assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
-  if( rc==SQLITE_OK && pPager->dbSize>pPager->dbHintSize ){
+  if( rc==SQLITE_OK 
+   && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize 
+  ){
     sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
     sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
     pPager->dbHintSize = pPager->dbSize;
@@ -41397,7 +42954,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
     memcpy(pPager->zFilename, zPathname, nPathname);
     if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
     memcpy(pPager->zJournal, zPathname, nPathname);
-    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1);
+    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
     sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
 #ifndef SQLITE_OMIT_WAL
     pPager->zWal = &pPager->zJournal[nPathname+8+1];
@@ -41544,6 +43101,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
   /* pPager->pBusyHandlerArg = 0; */
   pPager->xReiniter = xReinit;
   /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
+  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
 
   *ppPager = pPager;
   return SQLITE_OK;
@@ -41733,6 +43291,11 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
       goto failed;
     }
     if( bHotJournal ){
+      if( pPager->readOnly ){
+        rc = SQLITE_READONLY_ROLLBACK;
+        goto failed;
+      }
+
       /* Get an EXCLUSIVE lock on the database file. At this point it is
       ** important that a RESERVED lock is not obtained on the way to the
       ** EXCLUSIVE lock. If it were, another process might open the
@@ -41830,9 +43393,11 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
       );
     }
 
-    if( !pPager->tempFile 
-     && (pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0) 
-    ){
+    if( !pPager->tempFile && (
+        pPager->pBackup 
+     || sqlite3PcachePagecount(pPager->pPCache)>0 
+     || USEFETCH(pPager)
+    )){
       /* The shared-lock has just been acquired on the database file
       ** and there are already pages in the cache (from a previous
       ** read or write transaction).  Check to see if the database
@@ -41858,7 +43423,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
       if( nPage>0 ){
         IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
         rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
-        if( rc!=SQLITE_OK ){
+        if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
           goto failed;
         }
       }else{
@@ -41867,6 +43432,16 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
 
       if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
         pager_reset(pPager);
+
+        /* Unmap the database file. It is possible that external processes
+        ** may have truncated the database file and then extended it back
+        ** to its original size while this process was not holding a lock.
+        ** In this case there may exist a Pager.pMap mapping that appears
+        ** to be the right size but is not actually valid. Avoid this
+        ** possibility by unmapping the db here. */
+        if( USEFETCH(pPager) ){
+          sqlite3OsUnfetch(pPager->fd, 0, 0);
+        }
       }
     }
 
@@ -41908,7 +43483,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
 ** nothing to rollback, so this routine is a no-op.
 */ 
 static void pagerUnlockIfUnused(Pager *pPager){
-  if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
+  if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
     pagerUnlockAndRollback(pPager);
   }
 }
@@ -41967,13 +43542,27 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
   Pager *pPager,      /* The pager open on the database file */
   Pgno pgno,          /* Page number to fetch */
   DbPage **ppPage,    /* Write a pointer to the page here */
-  int noContent       /* Do not bother reading content from disk if true */
+  int flags           /* PAGER_ACQUIRE_XXX flags */
 ){
-  int rc;
-  PgHdr *pPg;
+  int rc = SQLITE_OK;
+  PgHdr *pPg = 0;
+  u32 iFrame = 0;                 /* Frame to read from WAL file */
+  const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
+
+  /* It is acceptable to use a read-only (mmap) page for any page except
+  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
+  ** flag was specified by the caller. And so long as the db is not a 
+  ** temporary or in-memory database.  */
+  const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
+   && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
+#ifdef SQLITE_HAS_CODEC
+   && pPager->xCodec==0
+#endif
+  );
 
   assert( pPager->eState>=PAGER_READER );
   assert( assert_pager_state(pPager) );
+  assert( noContent==0 || bMmapOk==0 );
 
   if( pgno==0 ){
     return SQLITE_CORRUPT_BKPT;
@@ -41984,6 +43573,39 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
   if( pPager->errCode!=SQLITE_OK ){
     rc = pPager->errCode;
   }else{
+
+    if( bMmapOk && pagerUseWal(pPager) ){
+      rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
+      if( rc!=SQLITE_OK ) goto pager_acquire_err;
+    }
+
+    if( iFrame==0 && bMmapOk ){
+      void *pData = 0;
+
+      rc = sqlite3OsFetch(pPager->fd, 
+          (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
+      );
+
+      if( rc==SQLITE_OK && pData ){
+        if( pPager->eState>PAGER_READER ){
+          (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
+        }
+        if( pPg==0 ){
+          rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
+        }else{
+          sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
+        }
+        if( pPg ){
+          assert( rc==SQLITE_OK );
+          *ppPage = pPg;
+          return SQLITE_OK;
+        }
+      }
+      if( rc!=SQLITE_OK ){
+        goto pager_acquire_err;
+      }
+    }
+
     rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
   }
 
@@ -42042,9 +43664,13 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
       memset(pPg->pData, 0, pPager->pageSize);
       IOTRACE(("ZERO %p %d\n", pPager, pgno));
     }else{
+      if( pagerUseWal(pPager) && bMmapOk==0 ){
+        rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
+        if( rc!=SQLITE_OK ) goto pager_acquire_err;
+      }
       assert( pPg->pPager==pPager );
       pPager->aStat[PAGER_STAT_MISS]++;
-      rc = readDbPage(pPg);
+      rc = readDbPage(pPg, iFrame);
       if( rc!=SQLITE_OK ){
         goto pager_acquire_err;
       }
@@ -42097,7 +43723,11 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
 SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
   if( pPg ){
     Pager *pPager = pPg->pPager;
-    sqlite3PcacheRelease(pPg);
+    if( pPg->flags & PGHDR_MMAP ){
+      pagerReleaseMapPage(pPg);
+    }else{
+      sqlite3PcacheRelease(pPg);
+    }
     pagerUnlockIfUnused(pPager);
   }
 }
@@ -42432,6 +44062,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
   Pager *pPager = pPg->pPager;
   Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
 
+  assert( (pPg->flags & PGHDR_MMAP)==0 );
   assert( pPager->eState>=PAGER_WRITER_LOCKED );
   assert( pPager->eState!=PAGER_ERROR );
   assert( assert_pager_state(pPager) );
@@ -42599,7 +44230,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
 # define DIRECT_MODE isDirectMode
 #endif
 
-  if( !pPager->changeCountDone && pPager->dbSize>0 ){
+  if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
     PgHdr *pPgHdr;                /* Reference to page 1 */
 
     assert( !pPager->tempFile && isOpen(pPager->fd) );
@@ -42631,6 +44262,11 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
           pPager->aStat[PAGER_STAT_WRITE]++;
         }
         if( rc==SQLITE_OK ){
+          /* Update the pager's copy of the change-counter. Otherwise, the
+          ** next time a read transaction is opened the cache will be
+          ** flushed (as the change-counter values will not match).  */
+          const void *pCopy = (const void *)&((const char *)zBuf)[24];
+          memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
           pPager->changeCountDone = 1;
         }
       }else{
@@ -42817,38 +44453,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
   #endif
       if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
   
-      /* If this transaction has made the database smaller, then all pages
-      ** being discarded by the truncation must be written to the journal
-      ** file. This can only happen in auto-vacuum mode.
-      **
-      ** Before reading the pages with page numbers larger than the 
-      ** current value of Pager.dbSize, set dbSize back to the value
-      ** that it took at the start of the transaction. Otherwise, the
-      ** calls to sqlite3PagerGet() return zeroed pages instead of 
-      ** reading data from the database file.
-      */
-  #ifndef SQLITE_OMIT_AUTOVACUUM
-      if( pPager->dbSize<pPager->dbOrigSize 
-       && pPager->journalMode!=PAGER_JOURNALMODE_OFF
-      ){
-        Pgno i;                                   /* Iterator variable */
-        const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
-        const Pgno dbSize = pPager->dbSize;       /* Database image size */ 
-        pPager->dbSize = pPager->dbOrigSize;
-        for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
-          if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
-            PgHdr *pPage;             /* Page to journal */
-            rc = sqlite3PagerGet(pPager, i, &pPage);
-            if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-            rc = sqlite3PagerWrite(pPage);
-            sqlite3PagerUnref(pPage);
-            if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-          }
-        }
-        pPager->dbSize = dbSize;
-      } 
-  #endif
-  
       /* Write the master journal name into the journal file. If a master 
       ** journal file name has already been written to the journal file, 
       ** or if zMaster is NULL (no master journal), then this call is a no-op.
@@ -42876,11 +44480,14 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
         goto commit_phase_one_exit;
       }
       sqlite3PcacheCleanAll(pPager->pPCache);
-  
-      /* If the file on disk is not the same size as the database image,
-      ** then use pager_truncate to grow or shrink the file here.
-      */
-      if( pPager->dbSize!=pPager->dbFileSize ){
+
+      /* If the file on disk is smaller than the database image, use 
+      ** pager_truncate to grow the file here. This can happen if the database
+      ** image was extended as part of the current transaction and then the
+      ** last page in the db image moved to the free-list. In this case the
+      ** last page is never written out to disk, leaving the database file
+      ** undersized. Fix this now if it is the case.  */
+      if( pPager->dbSize>pPager->dbFileSize ){
         Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
         assert( pPager->eState==PAGER_WRITER_DBMOD );
         rc = pager_truncate(pPager, nNew);
@@ -42953,7 +44560,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
   }
 
   PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
-  rc = pager_end_transaction(pPager, pPager->setMaster);
+  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
   return pager_error(pPager, rc);
 }
 
@@ -42998,11 +44605,11 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
   if( pagerUseWal(pPager) ){
     int rc2;
     rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
-    rc2 = pager_end_transaction(pPager, pPager->setMaster);
+    rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
     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);
+    rc = pager_end_transaction(pPager, 0, 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.
@@ -43017,7 +44624,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
   }
 
   assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
-  assert( rc==SQLITE_OK || rc==SQLITE_FULL
+  assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
           || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
 
   /* If an error occurs during a ROLLBACK, we can no longer trust the pager
@@ -43400,7 +45007,8 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
   */
   if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
     needSyncPgno = pPg->pgno;
-    assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+    assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
+            pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
     assert( pPg->flags&PGHDR_DIRTY );
   }
 
@@ -43750,11 +45358,12 @@ static int pagerOpenWal(Pager *pPager){
   ** (e.g. due to malloc() failure), return an error code.
   */
   if( rc==SQLITE_OK ){
-    rc = sqlite3WalOpen(pPager->pVfs, 
+    rc = sqlite3WalOpen(pPager->pVfs,
         pPager->fd, pPager->zWal, pPager->exclusiveMode,
         pPager->journalSizeLimit, &pPager->pWal
     );
   }
+  pagerFixMaplimit(pPager);
 
   return rc;
 }
@@ -43845,11 +45454,14 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
       rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
                            pPager->pageSize, (u8*)pPager->pTmpSpace);
       pPager->pWal = 0;
+      pagerFixMaplimit(pPager);
     }
   }
   return rc;
 }
 
+#endif /* !SQLITE_OMIT_WAL */
+
 #ifdef SQLITE_ENABLE_ZIPVFS
 /*
 ** A read-lock must be held on the pager when this function is called. If
@@ -43879,8 +45491,6 @@ SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
 }
 #endif /* SQLITE_HAS_CODEC */
 
-#endif /* !SQLITE_OMIT_WAL */
-
 #endif /* SQLITE_OMIT_DISKIO */
 
 /************** End of pager.c ***********************************************/
@@ -45093,8 +46703,9 @@ finished:
     ** checkpointing the log file.
     */
     if( pWal->hdr.nPage ){
-      sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
-          pWal->hdr.nPage, pWal->zWalName
+      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
+          "recovered %d frames from WAL file %s",
+          pWal->hdr.mxFrame, pWal->zWalName
       );
     }
   }
@@ -45608,8 +47219,8 @@ static int walCheckpoint(
       rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
     }
 
-    /* If the database file may grow as a result of this checkpoint, hint
-    ** about the eventual size of the db file to the VFS layer. 
+    /* If the database may grow as a result of this checkpoint, hint
+    ** about the eventual size of the db file to the VFS layer.
     */
     if( rc==SQLITE_OK ){
       i64 nReq = ((i64)mxPage * szPage);
@@ -45619,6 +47230,7 @@ static int walCheckpoint(
       }
     }
 
+
     /* Iterate through the contents of the WAL, copying data to the db file. */
     while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
       i64 iOffset;
@@ -46173,19 +47785,17 @@ SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){
 }
 
 /*
-** Read a page from the WAL, if it is present in the WAL and if the 
-** current read transaction is configured to use the WAL.  
+** Search the wal file for page pgno. If found, set *piRead to the frame that
+** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
+** to zero.
 **
-** The *pInWal is set to 1 if the requested page is in the WAL and
-** has been loaded.  Or *pInWal is set to 0 if the page was not in 
-** the WAL and needs to be read out of the database.
+** Return SQLITE_OK if successful, or an error code if an error occurs. If an
+** error does occur, the final value of *piRead is undefined.
 */
-SQLITE_PRIVATE int sqlite3WalRead(
+SQLITE_PRIVATE int sqlite3WalFindFrame(
   Wal *pWal,                      /* WAL handle */
   Pgno pgno,                      /* Database page number to read data for */
-  int *pInWal,                    /* OUT: True if data is read from WAL */
-  int nOut,                       /* Size of buffer pOut in bytes */
-  u8 *pOut                        /* Buffer to write page data to */
+  u32 *piRead                     /* OUT: Frame number (or zero) */
 ){
   u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
   u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
@@ -46201,7 +47811,7 @@ SQLITE_PRIVATE int sqlite3WalRead(
   ** WAL were empty.
   */
   if( iLast==0 || pWal->readLock==0 ){
-    *pInWal = 0;
+    *piRead = 0;
     return SQLITE_OK;
   }
 
@@ -46272,26 +47882,31 @@ SQLITE_PRIVATE int sqlite3WalRead(
   }
 #endif
 
-  /* If iRead is non-zero, then it is the log frame number that contains the
-  ** required page. Read and return data from the log file.
-  */
-  if( iRead ){
-    int sz;
-    i64 iOffset;
-    sz = pWal->hdr.szPage;
-    sz = (sz&0xfe00) + ((sz&0x0001)<<16);
-    testcase( sz<=32768 );
-    testcase( sz>=65536 );
-    iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
-    *pInWal = 1;
-    /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
-    return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
-  }
-
-  *pInWal = 0;
+  *piRead = iRead;
   return SQLITE_OK;
 }
 
+/*
+** Read the contents of frame iRead from the wal file into buffer pOut
+** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
+** error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3WalReadFrame(
+  Wal *pWal,                      /* WAL handle */
+  u32 iRead,                      /* Frame to read */
+  int nOut,                       /* Size of buffer pOut in bytes */
+  u8 *pOut                        /* Buffer to write page data to */
+){
+  int sz;
+  i64 iOffset;
+  sz = pWal->hdr.szPage;
+  sz = (sz&0xfe00) + ((sz&0x0001)<<16);
+  testcase( sz<=32768 );
+  testcase( sz>=65536 );
+  iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
+  /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
+  return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
+}
 
 /* 
 ** Return the size of the database in pages (or zero, if unknown).
@@ -46404,7 +48019,7 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
       assert( walFramePgno(pWal, iFrame)!=1 );
       rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
     }
-    walCleanupHash(pWal);
+    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
   }
   assert( rc==SQLITE_OK );
   return rc;
@@ -46714,7 +48329,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
   */
   if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
     if( pWal->padToSectorBoundary ){
-      int sectorSize = sqlite3OsSectorSize(pWal->pWalFd);
+      int sectorSize = sqlite3SectorSize(pWal->pWalFd);
       w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
       while( iOffset<w.iSyncPoint ){
         rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
@@ -46838,6 +48453,9 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
   /* Read the wal-index header. */
   if( rc==SQLITE_OK ){
     rc = walIndexReadHdr(pWal, &isChanged);
+    if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
+      sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
+    }
   }
 
   /* Copy data from the log to the database file. */
@@ -47404,6 +49022,7 @@ struct BtShared {
 #ifndef SQLITE_OMIT_AUTOVACUUM
   u8 autoVacuum;        /* True if auto-vacuum is enabled */
   u8 incrVacuum;        /* True if incr-vacuum is enabled */
+  u8 bDoTruncate;       /* True to truncate db on commit */
 #endif
   u8 inTransaction;     /* Transaction state */
   u8 max1bytePayload;   /* Maximum first byte of cell for a 1-byte payload */
@@ -47970,6 +49589,25 @@ int sqlite3BtreeTrace=1;  /* True to enable tracing */
 */
 #define get2byteNotZero(X)  (((((int)get2byte(X))-1)&0xffff)+1)
 
+/*
+** Values passed as the 5th argument to allocateBtreePage()
+*/
+#define BTALLOC_ANY   0           /* Allocate any page */
+#define BTALLOC_EXACT 1           /* Allocate exact page if possible */
+#define BTALLOC_LE    2           /* Allocate any page <= the parameter */
+
+/*
+** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not 
+** defined, or 0 if it is. For example:
+**
+**   bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define IfNotOmitAV(expr) (expr)
+#else
+#define IfNotOmitAV(expr) 0
+#endif
+
 #ifndef SQLITE_OMIT_SHARED_CACHE
 /*
 ** A list of BtShared objects that are eligible for participation
@@ -48484,6 +50122,19 @@ static void btreeClearHasContent(BtShared *pBt){
 }
 
 /*
+** Release all of the apPage[] pages for a cursor.
+*/
+static void btreeReleaseAllCursorPages(BtCursor *pCur){
+  int i;
+  for(i=0; i<=pCur->iPage; i++){
+    releasePage(pCur->apPage[i]);
+    pCur->apPage[i] = 0;
+  }
+  pCur->iPage = -1;
+}
+
+
+/*
 ** Save the current cursor position in the variables BtCursor.nKey 
 ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
 **
@@ -48522,12 +50173,7 @@ static int saveCursorPosition(BtCursor *pCur){
   assert( !pCur->apPage[0]->intKey || !pCur->pKey );
 
   if( rc==SQLITE_OK ){
-    int i;
-    for(i=0; i<=pCur->iPage; i++){
-      releasePage(pCur->apPage[i]);
-      pCur->apPage[i] = 0;
-    }
-    pCur->iPage = -1;
+    btreeReleaseAllCursorPages(pCur);
     pCur->eState = CURSOR_REQUIRESEEK;
   }
 
@@ -48545,11 +50191,15 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
   assert( sqlite3_mutex_held(pBt->mutex) );
   assert( pExcept==0 || pExcept->pBt==pBt );
   for(p=pBt->pCursor; p; p=p->pNext){
-    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && 
-        p->eState==CURSOR_VALID ){
-      int rc = saveCursorPosition(p);
-      if( SQLITE_OK!=rc ){
-        return rc;
+    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
+      if( p->eState==CURSOR_VALID ){
+        int rc = saveCursorPosition(p);
+        if( SQLITE_OK!=rc ){
+          return rc;
+        }
+      }else{
+        testcase( p->iPage>0 );
+        btreeReleaseAllCursorPages(p);
       }
     }
   }
@@ -49477,13 +51127,17 @@ static int btreeGetPage(
   BtShared *pBt,       /* The btree */
   Pgno pgno,           /* Number of the page to fetch */
   MemPage **ppPage,    /* Return the page in this parameter */
-  int noContent        /* Do not load page content if true */
+  int noContent,       /* Do not load page content if true */
+  int bReadonly        /* True if a read-only (mmap) page is ok */
 ){
   int rc;
   DbPage *pDbPage;
+  int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0) 
+            | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);
 
+  assert( noContent==0 || bReadonly==0 );
   assert( sqlite3_mutex_held(pBt->mutex) );
-  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
+  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
   if( rc ) return rc;
   *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
   return SQLITE_OK;
@@ -49526,9 +51180,10 @@ SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
 ** may remain unchanged, or it may be set to an invalid value.
 */
 static int getAndInitPage(
-  BtShared *pBt,          /* The database file */
-  Pgno pgno,           /* Number of the page to get */
-  MemPage **ppPage     /* Write the page pointer here */
+  BtShared *pBt,                  /* The database file */
+  Pgno pgno,                      /* Number of the page to get */
+  MemPage **ppPage,               /* Write the page pointer here */
+  int bReadonly                   /* True if a read-only (mmap) page is ok */
 ){
   int rc;
   assert( sqlite3_mutex_held(pBt->mutex) );
@@ -49536,7 +51191,7 @@ static int getAndInitPage(
   if( pgno>btreePagecount(pBt) ){
     rc = SQLITE_CORRUPT_BKPT;
   }else{
-    rc = btreeGetPage(pBt, pgno, ppPage, 0);
+    rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
     if( rc==SQLITE_OK ){
       rc = btreeInitPage(*ppPage);
       if( rc!=SQLITE_OK ){
@@ -49767,6 +51422,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
     rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
                           EXTRA_SIZE, flags, vfsFlags, pageReinit);
     if( rc==SQLITE_OK ){
+      sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
       rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
     }
     if( rc!=SQLITE_OK ){
@@ -50034,6 +51690,19 @@ SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
 }
 
 /*
+** Change the limit on the amount of the database file that may be
+** memory mapped.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
+  BtShared *pBt = p->pBt;
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
+  sqlite3BtreeLeave(p);
+  return SQLITE_OK;
+}
+
+/*
 ** Change the way data is synced to disk in order to increase or decrease
 ** how well the database resists damage due to OS crashes and power
 ** failures.  Level 1 is the same as asynchronous (no syncs() occur and
@@ -50127,6 +51796,24 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
   return p->pBt->pageSize;
 }
 
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+/*
+** This function is similar to sqlite3BtreeGetReserve(), except that it
+** may only be called if it is guaranteed that the b-tree mutex is already
+** held.
+**
+** This is useful in one special case in the backup API code where it is
+** known that the shared b-tree mutex is held, but the mutex on the 
+** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
+** were to be called, it might collide with some other operation on the
+** database handle that owns *p, causing undefined behavior.
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
+  assert( sqlite3_mutex_held(p->pBt->mutex) );
+  return p->pBt->pageSize - p->pBt->usableSize;
+}
+#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */
+
 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
 /*
 ** Return the number of bytes of space at the end of every page that
@@ -50240,7 +51927,7 @@ static int lockBtree(BtShared *pBt){
   assert( pBt->pPage1==0 );
   rc = sqlite3PagerSharedLock(pBt->pPager);
   if( rc!=SQLITE_OK ) return rc;
-  rc = btreeGetPage(pBt, 1, &pPage1, 0);
+  rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
   if( rc!=SQLITE_OK ) return rc;
 
   /* Do some checking to help insure the file we opened really is
@@ -50376,6 +52063,29 @@ page1_init_failed:
   return rc;
 }
 
+#ifndef NDEBUG
+/*
+** Return the number of cursors open on pBt. This is for use
+** in assert() expressions, so it is only compiled if NDEBUG is not
+** defined.
+**
+** Only write cursors are counted if wrOnly is true.  If wrOnly is
+** false then all cursors are counted.
+**
+** For the purposes of this routine, a cursor is any cursor that
+** is capable of reading or writing to the databse.  Cursors that
+** have been tripped into the CURSOR_FAULT state are not counted.
+*/
+static int countValidCursors(BtShared *pBt, int wrOnly){
+  BtCursor *pCur;
+  int r = 0;
+  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
+    if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; 
+  }
+  return r;
+}
+#endif
+
 /*
 ** If there are no outstanding cursors and we are not in the middle
 ** of a transaction but there is a read lock on the database, then
@@ -50386,7 +52096,7 @@ page1_init_failed:
 */
 static void unlockBtreeIfUnused(BtShared *pBt){
   assert( sqlite3_mutex_held(pBt->mutex) );
-  assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE );
+  assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
   if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
     assert( pBt->pPage1->aData );
     assert( sqlite3PagerRefcount(pBt->pPager)==1 );
@@ -50441,6 +52151,20 @@ static int newDatabase(BtShared *pBt){
 }
 
 /*
+** Initialize the first page of the database file (creating a database
+** consisting of a single page and no schema objects). Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
+  int rc;
+  sqlite3BtreeEnter(p);
+  p->pBt->nPage = 0;
+  rc = newDatabase(p->pBt);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+
+/*
 ** Attempt to start a new transaction. A write-transaction
 ** is started if the second argument is nonzero, otherwise a read-
 ** transaction.  If the second argument is 2 or more and exclusive
@@ -50490,6 +52214,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
   if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
     goto trans_begun;
   }
+  assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
 
   /* Write transactions are not possible on a read-only database */
   if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
@@ -50784,7 +52509,7 @@ static int relocatePage(
   ** iPtrPage.
   */
   if( eType!=PTRMAP_ROOTPAGE ){
-    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
+    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
     if( rc!=SQLITE_OK ){
       return rc;
     }
@@ -50806,24 +52531,23 @@ static int relocatePage(
 static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
 
 /*
-** Perform a single step of an incremental-vacuum. If successful,
-** return SQLITE_OK. If there is no work to do (and therefore no
-** point in calling this function again), return SQLITE_DONE.
+** Perform a single step of an incremental-vacuum. If successful, return
+** SQLITE_OK. If there is no work to do (and therefore no point in 
+** calling this function again), return SQLITE_DONE. Or, if an error 
+** occurs, return some other error code.
+**
+** More specificly, this function attempts to re-organize the database so 
+** that the last page of the file currently in use is no longer in use.
 **
-** More specificly, this function attempts to re-organize the 
-** database so that the last page of the file currently in use
-** is no longer in use.
+** Parameter nFin is the number of pages that this database would contain
+** were this function called until it returns SQLITE_DONE.
 **
-** If the nFin parameter is non-zero, this function assumes
-** that the caller will keep calling incrVacuumStep() until
-** it returns SQLITE_DONE or an error, and that nFin is the
-** number of pages the database file will contain after this 
-** process is complete.  If nFin is zero, it is assumed that
-** incrVacuumStep() will be called a finite amount of times
-** which may or may not empty the freelist.  A full autovacuum
-** has nFin>0.  A "PRAGMA incremental_vacuum" has nFin==0.
+** If the bCommit parameter is non-zero, this function assumes that the 
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE 
+** or an error. bCommit is passed true for an auto-vacuum-on-commmit 
+** operation, or false for an incremental vacuum.
 */
-static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
+static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
   Pgno nFreeList;           /* Number of pages still on the free-list */
   int rc;
 
@@ -50848,15 +52572,15 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
     }
 
     if( eType==PTRMAP_FREEPAGE ){
-      if( nFin==0 ){
+      if( bCommit==0 ){
         /* Remove the page from the files free-list. This is not required
-        ** if nFin is non-zero. In that case, the free-list will be
+        ** if bCommit is non-zero. In that case, the free-list will be
         ** truncated to zero after this function returns, so it doesn't 
         ** matter if it still contains some garbage entries.
         */
         Pgno iFreePg;
         MemPage *pFreePg;
-        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);
+        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT);
         if( rc!=SQLITE_OK ){
           return rc;
         }
@@ -50866,34 +52590,37 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
     } else {
       Pgno iFreePg;             /* Index of free page to move pLastPg to */
       MemPage *pLastPg;
+      u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
+      Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */
 
-      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
+      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
 
-      /* If nFin is zero, this loop runs exactly once and page pLastPg
+      /* If bCommit is zero, this loop runs exactly once and page pLastPg
       ** is swapped with the first free page pulled off the free list.
       **
-      ** On the other hand, if nFin is greater than zero, then keep
+      ** On the other hand, if bCommit is greater than zero, then keep
       ** looping until a free-page located within the first nFin pages
       ** of the file is found.
       */
+      if( bCommit==0 ){
+        eMode = BTALLOC_LE;
+        iNear = nFin;
+      }
       do {
         MemPage *pFreePg;
-        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0);
+        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
         if( rc!=SQLITE_OK ){
           releasePage(pLastPg);
           return rc;
         }
         releasePage(pFreePg);
-      }while( nFin!=0 && iFreePg>nFin );
+      }while( bCommit && iFreePg>nFin );
       assert( iFreePg<iLastPg );
       
-      rc = sqlite3PagerWrite(pLastPg->pDbPage);
-      if( rc==SQLITE_OK ){
-        rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
-      }
+      rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
       releasePage(pLastPg);
       if( rc!=SQLITE_OK ){
         return rc;
@@ -50901,30 +52628,40 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
     }
   }
 
-  if( nFin==0 ){
-    iLastPg--;
-    while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
-      if( PTRMAP_ISPAGE(pBt, iLastPg) ){
-        MemPage *pPg;
-        rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-        rc = sqlite3PagerWrite(pPg->pDbPage);
-        releasePage(pPg);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-      }
+  if( bCommit==0 ){
+    do {
       iLastPg--;
-    }
-    sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
+    }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) );
+    pBt->bDoTruncate = 1;
     pBt->nPage = iLastPg;
   }
   return SQLITE_OK;
 }
 
 /*
+** The database opened by the first argument is an auto-vacuum database
+** nOrig pages in size containing nFree free pages. Return the expected 
+** size of the database in pages following an auto-vacuum operation.
+*/
+static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
+  int nEntry;                     /* Number of entries on one ptrmap page */
+  Pgno nPtrmap;                   /* Number of PtrMap pages to be freed */
+  Pgno nFin;                      /* Return value */
+
+  nEntry = pBt->usableSize/5;
+  nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
+  nFin = nOrig - nFree - nPtrmap;
+  if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
+    nFin--;
+  }
+  while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
+    nFin--;
+  }
+
+  return nFin;
+}
+
+/*
 ** A write-transaction must be opened before calling this function.
 ** It performs a single unit of work towards an incremental vacuum.
 **
@@ -50941,11 +52678,24 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
   if( !pBt->autoVacuum ){
     rc = SQLITE_DONE;
   }else{
-    invalidateAllOverflowCache(pBt);
-    rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
-    if( rc==SQLITE_OK ){
-      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
-      put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+    Pgno nOrig = btreePagecount(pBt);
+    Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
+    Pgno nFin = finalDbSize(pBt, nOrig, nFree);
+
+    if( nOrig<nFin ){
+      rc = SQLITE_CORRUPT_BKPT;
+    }else if( nFree>0 ){
+      rc = saveAllCursors(pBt, 0, 0);
+      if( rc==SQLITE_OK ){
+        invalidateAllOverflowCache(pBt);
+        rc = incrVacuumStep(pBt, nFin, nOrig, 0);
+      }
+      if( rc==SQLITE_OK ){
+        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+        put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+      }
+    }else{
+      rc = SQLITE_DONE;
     }
   }
   sqlite3BtreeLeave(p);
@@ -50972,9 +52722,7 @@ static int autoVacuumCommit(BtShared *pBt){
   if( !pBt->incrVacuum ){
     Pgno nFin;         /* Number of pages in database after autovacuuming */
     Pgno nFree;        /* Number of pages on the freelist initially */
-    Pgno nPtrmap;      /* Number of PtrMap pages to be freed */
     Pgno iFree;        /* The next page to be freed */
-    int nEntry;        /* Number of entries on one ptrmap page */
     Pgno nOrig;        /* Database size before freeing */
 
     nOrig = btreePagecount(pBt);
@@ -50987,26 +52735,20 @@ static int autoVacuumCommit(BtShared *pBt){
     }
 
     nFree = get4byte(&pBt->pPage1->aData[36]);
-    nEntry = pBt->usableSize/5;
-    nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
-    nFin = nOrig - nFree - nPtrmap;
-    if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
-      nFin--;
-    }
-    while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
-      nFin--;
-    }
+    nFin = finalDbSize(pBt, nOrig, nFree);
     if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
-
+    if( nFin<nOrig ){
+      rc = saveAllCursors(pBt, 0, 0);
+    }
     for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
-      rc = incrVacuumStep(pBt, nFin, iFree);
+      rc = incrVacuumStep(pBt, nFin, iFree, 1);
     }
     if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
       rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
       put4byte(&pBt->pPage1->aData[32], 0);
       put4byte(&pBt->pPage1->aData[36], 0);
       put4byte(&pBt->pPage1->aData[28], nFin);
-      sqlite3PagerTruncateImage(pBt->pPager, nFin);
+      pBt->bDoTruncate = 1;
       pBt->nPage = nFin;
     }
     if( rc!=SQLITE_OK ){
@@ -51014,7 +52756,7 @@ static int autoVacuumCommit(BtShared *pBt){
     }
   }
 
-  assert( nRef==sqlite3PagerRefcount(pPager) );
+  assert( nRef>=sqlite3PagerRefcount(pPager) );
   return rc;
 }
 
@@ -51061,6 +52803,9 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
         return rc;
       }
     }
+    if( pBt->bDoTruncate ){
+      sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
+    }
 #endif
     rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
     sqlite3BtreeLeave(p);
@@ -51076,7 +52821,9 @@ static void btreeEndTransaction(Btree *p){
   BtShared *pBt = p->pBt;
   assert( sqlite3BtreeHoldsMutex(p) );
 
-  btreeClearHasContent(pBt);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  pBt->bDoTruncate = 0;
+#endif
   if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
     /* If there are other active statements that belong to this database
     ** handle, downgrade to a read-only transaction. The other statements
@@ -51151,6 +52898,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
       return rc;
     }
     pBt->inTransaction = TRANS_READ;
+    btreeClearHasContent(pBt);
   }
 
   btreeEndTransaction(p);
@@ -51172,27 +52920,6 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){
   return rc;
 }
 
-#ifndef NDEBUG
-/*
-** Return the number of write-cursors open on this handle. This is for use
-** in assert() expressions, so it is only compiled if NDEBUG is not
-** defined.
-**
-** For the purposes of this routine, a write-cursor is any cursor that
-** is capable of writing to the databse.  That means the cursor was
-** originally opened for writing and the cursor has not be disabled
-** by having its state changed to CURSOR_FAULT.
-*/
-static int countWriteCursors(BtShared *pBt){
-  BtCursor *pCur;
-  int r = 0;
-  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; 
-  }
-  return r;
-}
-#endif
-
 /*
 ** This routine sets the state to CURSOR_FAULT and the error
 ** code to errCode for every cursor on BtShared that pBtree
@@ -51264,7 +52991,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
     /* The rollback may have destroyed the pPage1->aData value.  So
     ** call btreeGetPage() on page 1 again to make
     ** sure pPage1->aData is set correctly. */
-    if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
+    if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
       int nPage = get4byte(28+(u8*)pPage1->aData);
       testcase( nPage==0 );
       if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
@@ -51272,8 +52999,9 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
       pBt->nPage = nPage;
       releasePage(pPage1);
     }
-    assert( countWriteCursors(pBt)==0 );
+    assert( countValidCursors(pBt, 1)==0 );
     pBt->inTransaction = TRANS_READ;
+    btreeClearHasContent(pBt);
   }
 
   btreeEndTransaction(p);
@@ -51698,7 +53426,7 @@ static int getOverflowPage(
 
   assert( next==0 || rc==SQLITE_DONE );
   if( rc==SQLITE_OK ){
-    rc = btreeGetPage(pBt, ovfl, &pPage, 0);
+    rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
     assert( rc==SQLITE_OK || pPage==0 );
     if( rc==SQLITE_OK ){
       next = get4byte(pPage->aData);
@@ -51919,7 +53647,9 @@ static int accessPayload(
 
         {
           DbPage *pDbPage;
-          rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
+          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
+              (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
+          );
           if( rc==SQLITE_OK ){
             aPayload = sqlite3PagerGetData(pDbPage);
             nextPage = get4byte(aPayload);
@@ -52098,10 +53828,11 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
   assert( cursorHoldsMutex(pCur) );
   assert( pCur->eState==CURSOR_VALID );
   assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
+  assert( pCur->iPage>=0 );
   if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
     return SQLITE_CORRUPT_BKPT;
   }
-  rc = getAndInitPage(pBt, newPgno, &pNewPage);
+  rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
   if( rc ) return rc;
   pCur->apPage[i+1] = pNewPage;
   pCur->aiIdx[i+1] = 0;
@@ -52218,7 +53949,7 @@ static int moveToRoot(BtCursor *pCur){
     pCur->eState = CURSOR_INVALID;
     return SQLITE_OK;
   }else{
-    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
+    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
     if( rc!=SQLITE_OK ){
       pCur->eState = CURSOR_INVALID;
       return rc;
@@ -52748,21 +54479,23 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
 ** an error.  *ppPage and *pPgno are undefined in the event of an error.
 ** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
 **
-** If the "nearby" parameter is not 0, then a (feeble) effort is made to 
+** If the "nearby" parameter is not 0, then an effort is made to 
 ** locate a page close to the page number "nearby".  This can be used in an
 ** attempt to keep related pages close to each other in the database file,
 ** which in turn can make database access faster.
 **
-** If the "exact" parameter is not 0, and the page-number nearby exists 
-** anywhere on the free-list, then it is guarenteed to be returned. This
-** is only used by auto-vacuum databases when allocating a new table.
+** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
+** anywhere on the free-list, then it is guaranteed to be returned.  If
+** eMode is BTALLOC_LT then the page returned will be less than or equal
+** to nearby if any such page exists.  If eMode is BTALLOC_ANY then there
+** are no restrictions on which page is returned.
 */
 static int allocateBtreePage(
-  BtShared *pBt, 
-  MemPage **ppPage, 
-  Pgno *pPgno, 
-  Pgno nearby,
-  u8 exact
+  BtShared *pBt,         /* The btree */
+  MemPage **ppPage,      /* Store pointer to the allocated page here */
+  Pgno *pPgno,           /* Store the page number here */
+  Pgno nearby,           /* Search for a page near this one */
+  u8 eMode               /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
 ){
   MemPage *pPage1;
   int rc;
@@ -52773,6 +54506,7 @@ static int allocateBtreePage(
   Pgno mxPage;     /* Total size of the database file */
 
   assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
   pPage1 = pBt->pPage1;
   mxPage = btreePagecount(pBt);
   n = get4byte(&pPage1->aData[36]);
@@ -52785,21 +54519,24 @@ static int allocateBtreePage(
     Pgno iTrunk;
     u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
     
-    /* If the 'exact' parameter was true and a query of the pointer-map
+    /* If eMode==BTALLOC_EXACT and a query of the pointer-map
     ** shows that the page 'nearby' is somewhere on the free-list, then
     ** the entire-list will be searched for that page.
     */
 #ifndef SQLITE_OMIT_AUTOVACUUM
-    if( exact && nearby<=mxPage ){
-      u8 eType;
-      assert( nearby>0 );
-      assert( pBt->autoVacuum );
-      rc = ptrmapGet(pBt, nearby, &eType, 0);
-      if( rc ) return rc;
-      if( eType==PTRMAP_FREEPAGE ){
-        searchList = 1;
+    if( eMode==BTALLOC_EXACT ){
+      if( nearby<=mxPage ){
+        u8 eType;
+        assert( nearby>0 );
+        assert( pBt->autoVacuum );
+        rc = ptrmapGet(pBt, nearby, &eType, 0);
+        if( rc ) return rc;
+        if( eType==PTRMAP_FREEPAGE ){
+          searchList = 1;
+        }
       }
-      *pPgno = nearby;
+    }else if( eMode==BTALLOC_LE ){
+      searchList = 1;
     }
 #endif
 
@@ -52812,7 +54549,8 @@ static int allocateBtreePage(
 
     /* The code within this loop is run only once if the 'searchList' variable
     ** is not true. Otherwise, it runs once for each trunk-page on the
-    ** free-list until the page 'nearby' is located.
+    ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT)
+    ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT)
     */
     do {
       pPrevTrunk = pTrunk;
@@ -52825,7 +54563,7 @@ static int allocateBtreePage(
       if( iTrunk>mxPage ){
         rc = SQLITE_CORRUPT_BKPT;
       }else{
-        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
+        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
       }
       if( rc ){
         pTrunk = 0;
@@ -52854,11 +54592,13 @@ static int allocateBtreePage(
         rc = SQLITE_CORRUPT_BKPT;
         goto end_allocate_page;
 #ifndef SQLITE_OMIT_AUTOVACUUM
-      }else if( searchList && nearby==iTrunk ){
+      }else if( searchList 
+            && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE)) 
+      ){
         /* The list is being searched and this trunk page is the page
         ** to allocate, regardless of whether it has leaves.
         */
-        assert( *pPgno==iTrunk );
+        *pPgno = iTrunk;
         *ppPage = pTrunk;
         searchList = 0;
         rc = sqlite3PagerWrite(pTrunk->pDbPage);
@@ -52887,7 +54627,7 @@ static int allocateBtreePage(
             goto end_allocate_page;
           }
           testcase( iNewTrunk==mxPage );
-          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
+          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
           if( rc!=SQLITE_OK ){
             goto end_allocate_page;
           }
@@ -52921,14 +54661,24 @@ static int allocateBtreePage(
         unsigned char *aData = pTrunk->aData;
         if( nearby>0 ){
           u32 i;
-          int dist;
           closest = 0;
-          dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
-          for(i=1; i<k; i++){
-            int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
-            if( d2<dist ){
-              closest = i;
-              dist = d2;
+          if( eMode==BTALLOC_LE ){
+            for(i=0; i<k; i++){
+              iPage = get4byte(&aData[8+i*4]);
+              if( iPage<=nearby ){
+                closest = i;
+                break;
+              }
+            }
+          }else{
+            int dist;
+            dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
+            for(i=1; i<k; i++){
+              int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
+              if( d2<dist ){
+                closest = i;
+                dist = d2;
+              }
             }
           }
         }else{
@@ -52942,7 +54692,9 @@ static int allocateBtreePage(
           goto end_allocate_page;
         }
         testcase( iPage==mxPage );
-        if( !searchList || iPage==nearby ){
+        if( !searchList 
+         || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) 
+        ){
           int noContent;
           *pPgno = iPage;
           TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
@@ -52955,7 +54707,7 @@ static int allocateBtreePage(
           }
           put4byte(&aData[4], k-1);
           noContent = !btreeGetHasContent(pBt, *pPgno);
-          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
+          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
           if( rc==SQLITE_OK ){
             rc = sqlite3PagerWrite((*ppPage)->pDbPage);
             if( rc!=SQLITE_OK ){
@@ -52969,8 +54721,26 @@ static int allocateBtreePage(
       pPrevTrunk = 0;
     }while( searchList );
   }else{
-    /* There are no pages on the freelist, so create a new page at the
-    ** end of the file */
+    /* There are no pages on the freelist, so append a new page to the
+    ** database image.
+    **
+    ** Normally, new pages allocated by this block can be requested from the
+    ** pager layer with the 'no-content' flag set. This prevents the pager
+    ** from trying to read the pages content from disk. However, if the
+    ** current transaction has already run one or more incremental-vacuum
+    ** steps, then the page we are about to allocate may contain content
+    ** that is required in the event of a rollback. In this case, do
+    ** not set the no-content flag. This causes the pager to load and journal
+    ** the current page content before overwriting it.
+    **
+    ** Note that the pager will not actually attempt to load or journal 
+    ** content for any page that really does lie past the end of the database
+    ** file on disk. So the effects of disabling the no-content optimization
+    ** here are confined to those pages that lie between the end of the
+    ** database image and the end of the database file.
+    */
+    int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
+
     rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
     if( rc ) return rc;
     pBt->nPage++;
@@ -52985,7 +54755,7 @@ static int allocateBtreePage(
       MemPage *pPg = 0;
       TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
       assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
-      rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
+      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
       if( rc==SQLITE_OK ){
         rc = sqlite3PagerWrite(pPg->pDbPage);
         releasePage(pPg);
@@ -52999,7 +54769,7 @@ static int allocateBtreePage(
     *pPgno = pBt->nPage;
 
     assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
-    rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
+    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
     if( rc ) return rc;
     rc = sqlite3PagerWrite((*ppPage)->pDbPage);
     if( rc!=SQLITE_OK ){
@@ -53067,7 +54837,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
     /* If the secure_delete option is enabled, then
     ** always fully overwrite deleted information with zeros.
     */
-    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
+    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
      ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
     ){
       goto freepage_out;
@@ -53094,7 +54864,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
     u32 nLeaf;                /* Initial number of leaf cells on trunk page */
 
     iTrunk = get4byte(&pPage1->aData[32]);
-    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
+    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
     if( rc!=SQLITE_OK ){
       goto freepage_out;
     }
@@ -53140,7 +54910,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
   ** first trunk in the free-list is full. Either way, the page being freed
   ** will become the new first trunk page in the free-list.
   */
-  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
+  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
     goto freepage_out;
   }
   rc = sqlite3PagerWrite(pPage->pDbPage);
@@ -53183,7 +54953,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
     return SQLITE_OK;  /* No overflow pages. Return without doing anything */
   }
   if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
-    return SQLITE_CORRUPT;  /* Cell extends past end of page */
+    return SQLITE_CORRUPT_BKPT;  /* Cell extends past end of page */
   }
   ovflPgno = get4byte(&pCell[info.iOverflow]);
   assert( pBt->usableSize > 4 );
@@ -53327,7 +55097,7 @@ static int fillInCell(
       ** If this is the first overflow page, then write a partial entry 
       ** to the pointer-map. If we write nothing to this pointer-map slot,
       ** then the optimistic overflow chain processing in clearCell()
-      ** may misinterpret the uninitialised values and delete the
+      ** may misinterpret the uninitialized values and delete the
       ** wrong pages from the database.
       */
       if( pBt->autoVacuum && rc==SQLITE_OK ){
@@ -53639,7 +55409,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
   assert( pPage->nOverflow==1 );
 
   /* This error condition is now caught prior to reaching this function */
-  if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
+  if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;
 
   /* Allocate a new page. This page will become the right-sibling of 
   ** pPage. Make the parent page writable, so that the new divider cell
@@ -53941,7 +55711,7 @@ static int balance_nonroot(
   }
   pgno = get4byte(pRight);
   while( 1 ){
-    rc = getAndInitPage(pBt, pgno, &apOld[i]);
+    rc = getAndInitPage(pBt, pgno, &apOld[i], 0);
     if( rc ){
       memset(apOld, 0, (i+1)*sizeof(MemPage*));
       goto balance_cleanup;
@@ -54800,7 +56570,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
   insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
   assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
 
-  /* If no error has occured and pPage has an overflow cell, call balance() 
+  /* If no error has occurred and pPage has an overflow cell, call balance() 
   ** to redistribute the cells within the tree. Since balance() may move
   ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
   ** variables.
@@ -55014,7 +56784,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
     ** be moved to the allocated page (unless the allocated page happens
     ** to reside at pgnoRoot).
     */
-    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
+    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
     if( rc!=SQLITE_OK ){
       return rc;
     }
@@ -55029,10 +56799,17 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
       u8 eType = 0;
       Pgno iPtrPage = 0;
 
+      /* Save the positions of any open cursors. This is required in
+      ** case they are holding a reference to an xFetch reference
+      ** corresponding to page pgnoRoot.  */
+      rc = saveAllCursors(pBt, 0, 0);
       releasePage(pPageMove);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
 
       /* Move the page currently at pgnoRoot to pgnoMove. */
-      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
+      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
@@ -55053,7 +56830,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
       if( rc!=SQLITE_OK ){
         return rc;
       }
-      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
+      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
@@ -55129,7 +56906,7 @@ static int clearDatabasePage(
     return SQLITE_CORRUPT_BKPT;
   }
 
-  rc = getAndInitPage(pBt, pgno, &pPage);
+  rc = getAndInitPage(pBt, pgno, &pPage, 0);
   if( rc ) return rc;
   for(i=0; i<pPage->nCell; i++){
     pCell = findCell(pPage, i);
@@ -55231,7 +57008,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
     return SQLITE_LOCKED_SHAREDCACHE;
   }
 
-  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
+  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
   if( rc ) return rc;
   rc = sqlite3BtreeClearTable(p, iTable, 0);
   if( rc ){
@@ -55266,7 +57043,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
         */
         MemPage *pMove;
         releasePage(pPage);
-        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
         if( rc!=SQLITE_OK ){
           return rc;
         }
@@ -55276,7 +57053,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
           return rc;
         }
         pMove = 0;
-        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
         freePage(pMove, &rc);
         releasePage(pMove);
         if( rc!=SQLITE_OK ){
@@ -55688,7 +57465,7 @@ static int checkTreePage(
   usableSize = pBt->usableSize;
   if( iPage==0 ) return 0;
   if( checkRef(pCheck, iPage, zParentContext) ) return 0;
-  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
+  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
     checkAppendMsg(pCheck, zContext,
        "unable to get the page. error code=%d", rc);
     return 0;
@@ -55921,7 +57698,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
   }
   i = PENDING_BYTE_PAGE(pBt);
   if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
-  sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
+  sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
   sCheck.errMsg.useMalloc = 2;
 
   /* Check the integrity of the freelist
@@ -56160,6 +57937,17 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
     return SQLITE_ABORT;
   }
 
+  /* Save the positions of all other cursors open on this table. This is
+  ** required in case any of them are holding references to an xFetch
+  ** version of the b-tree page modified by the accessPayload call below.
+  **
+  ** Note that pCsr must be open on a BTREE_INTKEY table and saveCursorPosition()
+  ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence
+  ** saveAllCursors can only return SQLITE_OK.
+  */
+  VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
+  assert( rc==SQLITE_OK );
+
   /* Check some assumptions: 
   **   (a) the cursor is open for writing,
   **   (b) there is a read/write transaction open,
@@ -56456,20 +58244,28 @@ static int isFatalError(int rc){
 ** page iSrcPg from the source database. Copy this data into the 
 ** destination database.
 */
-static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
+static int backupOnePage(
+  sqlite3_backup *p,              /* Backup handle */
+  Pgno iSrcPg,                    /* Source database page to backup */
+  const u8 *zSrcData,             /* Source database page data */
+  int bUpdate                     /* True for an update, false otherwise */
+){
   Pager * const pDestPager = sqlite3BtreePager(p->pDest);
   const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
   int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
   const int nCopy = MIN(nSrcPgsz, nDestPgsz);
   const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
 #ifdef SQLITE_HAS_CODEC
-  int nSrcReserve = sqlite3BtreeGetReserve(p->pSrc);
+  /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
+  ** guaranteed that the shared-mutex is held by this thread, handle
+  ** p->pSrc may not actually be the owner.  */
+  int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
   int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
 #endif
-
   int rc = SQLITE_OK;
   i64 iOff;
 
+  assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
   assert( p->bDestLocked );
   assert( !isFatalError(p->rc) );
   assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
@@ -56526,6 +58322,9 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
       */
       memcpy(zOut, zIn, nCopy);
       ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
+      if( iOff==0 && bUpdate==0 ){
+        sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
+      }
     }
     sqlite3PagerUnref(pDestPg);
   }
@@ -56630,9 +58429,10 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
       const Pgno iSrcPg = p->iNext;                 /* Source page number */
       if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
         DbPage *pSrcPg;                             /* Source page object */
-        rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
+        rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
+                                 PAGER_ACQUIRE_READONLY);
         if( rc==SQLITE_OK ){
-          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
+          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
           sqlite3PagerUnref(pSrcPg);
         }
       }
@@ -56654,7 +58454,13 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
     ** same schema version.
     */
     if( rc==SQLITE_DONE ){
-      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+      if( nSrcPage==0 ){
+        rc = sqlite3BtreeNewDb(p->pDest);
+        nSrcPage = 1;
+      }
+      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+        rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+      }
       if( rc==SQLITE_OK ){
         if( p->pDestDb ){
           sqlite3ResetAllSchemasOfConnection(p->pDestDb);
@@ -56688,7 +58494,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
         }else{
           nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
         }
-        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
+        assert( nDestTruncate>0 );
 
         if( pgszSrc<pgszDest ){
           /* If the source page-size is smaller than the destination page-size,
@@ -56702,22 +58508,38 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
           */
           const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
           sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
+          Pgno iPg;
+          int nDstPage;
           i64 iOff;
           i64 iEnd;
 
           assert( pFile );
-          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
+          assert( nDestTruncate==0 
+              || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
                 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
              && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
           ));
 
-          /* This call ensures that all data required to recreate the original
+          /* This block 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);
+          sqlite3PagerPagecount(pDestPager, &nDstPage);
+          for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
+            if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
+              DbPage *pPg;
+              rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
+              if( rc==SQLITE_OK ){
+                rc = sqlite3PagerWrite(pPg);
+                sqlite3PagerUnref(pPg);
+              }
+            }
+          }
+          if( rc==SQLITE_OK ){
+            rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+          }
 
           /* Write the extra pages and truncate the database file as required */
           iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
@@ -56744,6 +58566,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
             rc = sqlite3PagerSync(pDestPager);
           }
         }else{
+          sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
           rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
         }
     
@@ -56872,7 +58695,7 @@ SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, con
       int rc;
       assert( p->pDestDb );
       sqlite3_mutex_enter(p->pDestDb->mutex);
-      rc = backupOnePage(p, iPage, aData);
+      rc = backupOnePage(p, iPage, aData, 1);
       sqlite3_mutex_leave(p->pDestDb->mutex);
       assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
       if( rc!=SQLITE_OK ){
@@ -56995,7 +58818,9 @@ copy_finished:
 ** between formats.
 */
 SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
+#ifndef SQLITE_OMIT_UTF16
   int rc;
+#endif
   assert( (pMem->flags&MEM_RowSet)==0 );
   assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
            || desiredEnc==SQLITE_UTF16BE );
@@ -58140,18 +59965,6 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
 ** But that file was getting too big so this subroutines were split out.
 */
 
-
-
-/*
-** When debugging the code generator in a symbolic debugger, one can
-** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed
-** as they are added to the instruction stream.
-*/
-#ifdef SQLITE_DEBUG
-SQLITE_PRIVATE int sqlite3VdbeAddopTrace = 0;
-#endif
-
-
 /*
 ** Create a new virtual database engine.
 */
@@ -58176,7 +59989,7 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
 SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
   assert( isPrepareV2==1 || isPrepareV2==0 );
   if( p==0 ) return;
-#ifdef SQLITE_OMIT_TRACE
+#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
   if( !isPrepareV2 ) return;
 #endif
   assert( p->zSql==0 );
@@ -58281,7 +60094,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
   pOp->p4type = P4_NOTUSED;
 #ifdef SQLITE_DEBUG
   pOp->zComment = 0;
-  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+  if( p->db->flags & SQLITE_VdbeAddopTrace ){
+    sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+  }
 #endif
 #ifdef VDBE_PROFILE
   pOp->cycles = 0;
@@ -58500,7 +60315,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
      || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
 #endif
      || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
-      && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
     ){
       hasAbort = 1;
       break;
@@ -58508,7 +60323,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
   }
   sqlite3DbFree(v->db, sIter.apSub);
 
-  /* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
+  /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
   ** If malloc failed, then the while() loop above may not have iterated
   ** through all opcodes and hasAbort may be set incorrectly. Return
   ** true for this case to prevent the assert() in the callers frame
@@ -58635,7 +60450,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
       pOut->p5 = 0;
 #ifdef SQLITE_DEBUG
       pOut->zComment = 0;
-      if( sqlite3VdbeAddopTrace ){
+      if( p->db->flags & SQLITE_VdbeAddopTrace ){
         sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
       }
 #endif
@@ -58846,6 +60661,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
     addr = p->nOp - 1;
   }
   pOp = &p->aOp[addr];
+  assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
   freeP4(db, pOp->p4type, pOp->p4.p);
   pOp->p4.p = 0;
   if( n==P4_INT32 ){
@@ -58868,10 +60684,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
       u8 *aSortOrder;
       memcpy((char*)pKeyInfo, zP4, nByte - nField);
       aSortOrder = pKeyInfo->aSortOrder;
-      if( aSortOrder ){
-        pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
-        memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
-      }
+      assert( aSortOrder!=0 );
+      pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
+      memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
       pOp->p4type = P4_KEYINFO;
     }else{
       p->db->mallocFailed = 1;
@@ -58984,26 +60799,23 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
     case P4_KEYINFO: {
       int i, j;
       KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
+      assert( pKeyInfo->aSortOrder!=0 );
       sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
       i = sqlite3Strlen30(zTemp);
       for(j=0; j<pKeyInfo->nField; j++){
         CollSeq *pColl = pKeyInfo->aColl[j];
-        if( pColl ){
-          int n = sqlite3Strlen30(pColl->zName);
-          if( i+n>nTemp-6 ){
-            memcpy(&zTemp[i],",...",4);
-            break;
-          }
-          zTemp[i++] = ',';
-          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){
-            zTemp[i++] = '-';
-          }
-          memcpy(&zTemp[i], pColl->zName,n+1);
-          i += n;
-        }else if( i+4<nTemp-6 ){
-          memcpy(&zTemp[i],",nil",4);
-          i += 4;
+        const char *zColl = pColl ? pColl->zName : "nil";
+        int n = sqlite3Strlen30(zColl);
+        if( i+n>nTemp-6 ){
+          memcpy(&zTemp[i],",...",4);
+          break;
         }
+        zTemp[i++] = ',';
+        if( pKeyInfo->aSortOrder[j] ){
+          zTemp[i++] = '-';
+        }
+        memcpy(&zTemp[i], zColl, n+1);
+        i += n;
       }
       zTemp[i++] = ')';
       zTemp[i] = 0;
@@ -59664,7 +61476,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
     zEnd = &zCsr[nByte];
   }while( nByte && !db->mallocFailed );
 
-  p->nCursor = (u16)nCursor;
+  p->nCursor = nCursor;
   p->nOnceFlag = nOnce;
   if( p->aVar ){
     p->nVar = (ynVar)nVar;
@@ -59893,7 +61705,9 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
     if( sqlite3BtreeIsInTrans(pBt) ){
       needXcommit = 1;
       if( i!=1 ) nTrans++;
+      sqlite3BtreeEnter(pBt);
       rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
+      sqlite3BtreeLeave(pBt);
     }
   }
   if( rc!=SQLITE_OK ){
@@ -59904,7 +61718,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
   if( needXcommit && db->xCommitCallback ){
     rc = db->xCommitCallback(db->pCommitArg);
     if( rc ){
-      return SQLITE_CONSTRAINT;
+      return SQLITE_CONSTRAINT_COMMITHOOK;
     }
   }
 
@@ -60141,7 +61955,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
 
   /* If p->iStatement is greater than zero, then this Vdbe opened a 
   ** statement transaction that should be closed here. The only exception
-  ** is that an IO error may have occured, causing an emergency rollback.
+  ** is that an IO error may have occurred, causing an emergency rollback.
   ** In this case (db->nStatement==0), and there is nothing to do.
   */
   if( db->nStatement && p->iStatement ){
@@ -60196,14 +62010,14 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
 ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
 **
 ** If there are outstanding FK violations and this function returns 
-** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
-** an error message to it. Then return SQLITE_ERROR.
+** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
+** and write an error message to it. Then return SQLITE_ERROR.
 */
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
   sqlite3 *db = p->db;
   if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
-    p->rc = SQLITE_CONSTRAINT;
+    p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
     p->errorAction = OE_Abort;
     sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
     return SQLITE_ERROR;
@@ -60277,7 +62091,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
       **
       ** Even if the statement is read-only, it is important to perform
       ** a statement or transaction rollback operation. If the error 
-      ** occured while writing to the journal, sub-journal or database
+      ** occurred while writing to the journal, sub-journal or database
       ** file as part of an effort to free up cache space (see function
       ** pagerStress() in pager.c), the rollback is required to restore 
       ** the pager to a consistent state.
@@ -60318,7 +62132,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
             sqlite3VdbeLeave(p);
             return SQLITE_ERROR;
           }
-          rc = SQLITE_CONSTRAINT;
+          rc = SQLITE_CONSTRAINT_FOREIGNKEY;
         }else{ 
           /* The auto-commit flag is true, the vdbe program was successful 
           ** or hit an 'OR FAIL' constraint and there are no deferred foreign
@@ -60361,7 +62175,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
     if( eStatementOp ){
       rc = sqlite3VdbeCloseStatement(p, eStatementOp);
       if( rc ){
-        if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
+        if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
           p->rc = rc;
           sqlite3DbFree(db, p->zErrMsg);
           p->zErrMsg = 0;
@@ -60447,6 +62261,27 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
   return rc;
 }
 
+#ifdef SQLITE_ENABLE_SQLLOG
+/*
+** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, 
+** invoke it.
+*/
+static void vdbeInvokeSqllog(Vdbe *v){
+  if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
+    char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
+    assert( v->db->init.busy==0 );
+    if( zExpanded ){
+      sqlite3GlobalConfig.xSqllog(
+          sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
+      );
+      sqlite3DbFree(v->db, zExpanded);
+    }
+  }
+}
+#else
+# define vdbeInvokeSqllog(x)
+#endif
+
 /*
 ** Clean up a VDBE after execution but do not delete the VDBE just yet.
 ** Write any error messages into *pzErrMsg.  Return the result code.
@@ -60474,6 +62309,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
   ** instructions yet, leave the main database error information unchanged.
   */
   if( p->pc>=0 ){
+    vdbeInvokeSqllog(p);
     sqlite3VdbeTransferError(p);
     sqlite3DbFree(db, p->zErrMsg);
     p->zErrMsg = 0;
@@ -60555,12 +62391,14 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
 }
 
 /*
-** Free all memory associated with the Vdbe passed as the second argument.
+** Free all memory associated with the Vdbe passed as the second argument,
+** except for object itself, which is preserved.
+**
 ** The difference between this function and sqlite3VdbeDelete() is that
 ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
-** the database connection.
+** the database connection and frees the object itself.
 */
-SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
   SubProgram *pSub, *pNext;
   int i;
   assert( p->db==0 || p->db==db );
@@ -60581,7 +62419,6 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
   sqlite3DbFree(db, p->zExplain);
   sqlite3DbFree(db, p->pExplain);
 #endif
-  sqlite3DbFree(db, p);
 }
 
 /*
@@ -60593,6 +62430,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
   if( NEVER(p==0) ) return;
   db = p->db;
   assert( sqlite3_mutex_held(db->mutex) );
+  sqlite3VdbeClearObject(db, p);
   if( p->pPrev ){
     p->pPrev->pNext = p->pNext;
   }else{
@@ -60604,7 +62442,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
   }
   p->magic = VDBE_MAGIC_DEAD;
   p->db = 0;
-  sqlite3VdbeDeleteObject(db, p);
+  sqlite3DbFree(db, p);
 }
 
 /*
@@ -60667,7 +62505,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
 ** the blob of data that it corresponds to. In a table record, all serial
 ** types are stored at the start of the record, and the blobs of data at
 ** the end. Hence these functions allow the caller to handle the
-** serial-type and data blob seperately.
+** serial-type and data blob separately.
 **
 ** The following table describes the various storage classes for data:
 **
@@ -60706,9 +62544,6 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
 #   define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
     i64 i = pMem->u.i;
     u64 u;
-    if( file_format>=4 && (i&1)==i ){
-      return 8+(u32)i;
-    }
     if( i<0 ){
       if( i<(-MAX_6BYTE) ) return 6;
       /* Previous test prevents:  u = -(-9223372036854775808) */
@@ -60716,7 +62551,9 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
     }else{
       u = i;
     }
-    if( u<=127 ) return 1;
+    if( u<=127 ){
+      return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1;
+    }
     if( u<=32767 ) return 2;
     if( u<=8388607 ) return 3;
     if( u<=2147483647 ) return 4;
@@ -61001,6 +62838,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
   }
 
   p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+  assert( pKeyInfo->aSortOrder!=0 );
   p->pKeyInfo = pKeyInfo;
   p->nField = pKeyInfo->nField + 1;
   return p;
@@ -61094,6 +62932,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
   idx1 = getVarint32(aKey1, szHdr1);
   d1 = szHdr1;
   nField = pKeyInfo->nField;
+  assert( pKeyInfo->aSortOrder!=0 );
   while( idx1<szHdr1 && i<pPKey2->nField ){
     u32 serial_type1;
 
@@ -61113,7 +62952,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
       assert( mem1.zMalloc==0 );  /* See comment below */
 
       /* Invert the result if we are using DESC sort order. */
-      if( pKeyInfo->aSortOrder && i<nField && pKeyInfo->aSortOrder[i] ){
+      if( i<nField && pKeyInfo->aSortOrder[i] ){
         rc = -rc;
       }
     
@@ -61806,7 +63645,7 @@ end_of_step:
   assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
   if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
     /* If this statement was prepared using sqlite3_prepare_v2(), and an
-    ** error has occured, then return the error code in p->rc to the
+    ** error has occurred, then return the error code in p->rc to the
     ** caller. Set the error code in the database handle to the same value.
     */ 
     rc = sqlite3VdbeTransferError(p);
@@ -61815,14 +63654,6 @@ end_of_step:
 }
 
 /*
-** The maximum number of times that a statement will try to reparse
-** itself before giving up and returning SQLITE_SCHEMA.
-*/
-#ifndef SQLITE_MAX_SCHEMA_RETRY
-# define SQLITE_MAX_SCHEMA_RETRY 5
-#endif
-
-/*
 ** This is the top-level implementation of sqlite3_step().  Call
 ** sqlite3Step() to do most of the work.  If a schema error occurs,
 ** call sqlite3Reprepare() and try again.
@@ -61839,10 +63670,12 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
   }
   db = v->db;
   sqlite3_mutex_enter(db->mutex);
+  v->doingRerun = 0;
   while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
          && cnt++ < SQLITE_MAX_SCHEMA_RETRY
          && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
     sqlite3_reset(pStmt);
+    v->doingRerun = 1;
     assert( v->expired==0 );
   }
   if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
@@ -62557,7 +64390,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa
   if( zName ){
     for(i=0; i<p->nzVar; i++){
       const char *z = p->azVar[i];
-      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
+      if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
         return i+1;
       }
     }
@@ -62723,6 +64556,11 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
 ** then the returned string holds a copy of zRawSql with "-- " prepended
 ** to each line of text.
 **
+** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then
+** then long strings and blobs are truncated to that many bytes.  This
+** can be used to prevent unreasonably large trace strings when dealing
+** with large (multi-megabyte) strings and blobs.
+**
 ** The calling function is responsible for making sure the memory returned
 ** is eventually freed.
 **
@@ -62793,30 +64631,49 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
       }else if( pVar->flags & MEM_Real ){
         sqlite3XPrintf(&out, "%!.15g", pVar->r);
       }else if( pVar->flags & MEM_Str ){
+        int nOut;  /* Number of bytes of the string text to include in output */
 #ifndef SQLITE_OMIT_UTF16
         u8 enc = ENC(db);
+        Mem utf8;
         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
+          pVar = &utf8;
+        }
 #endif
-        {
-          sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
+        nOut = pVar->n;
+#ifdef SQLITE_TRACE_SIZE_LIMIT
+        if( nOut>SQLITE_TRACE_SIZE_LIMIT ){
+          nOut = SQLITE_TRACE_SIZE_LIMIT;
+          while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
         }
+#endif    
+        sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
+#ifdef SQLITE_TRACE_SIZE_LIMIT
+        if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
+#endif
+#ifndef SQLITE_OMIT_UTF16
+        if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
+#endif
       }else if( pVar->flags & MEM_Zero ){
         sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
       }else{
+        int nOut;  /* Number of bytes of the blob to include in output */
         assert( pVar->flags & MEM_Blob );
         sqlite3StrAccumAppend(&out, "x'", 2);
-        for(i=0; i<pVar->n; i++){
+        nOut = pVar->n;
+#ifdef SQLITE_TRACE_SIZE_LIMIT
+        if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
+#endif
+        for(i=0; i<nOut; i++){
           sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
         }
         sqlite3StrAccumAppend(&out, "'", 1);
+#ifdef SQLITE_TRACE_SIZE_LIMIT
+        if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
+#endif
       }
     }
   }
@@ -63094,11 +64951,7 @@ SQLITE_API int sqlite3_found_count = 0;
        && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
 
 /* Return true if the cursor was opened using the OP_OpenSorter opcode. */
-#ifdef SQLITE_OMIT_MERGE_SORT
-# define isSorter(x) 0
-#else
 # define isSorter(x) ((x)->pSorter!=0)
-#endif
 
 /*
 ** Argument pMem points at a register that will be passed to a
@@ -63364,7 +65217,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
 ** Print the value of a register for tracing purposes:
 */
 static void memTracePrint(FILE *out, Mem *p){
-  if( p->flags & MEM_Null ){
+  if( p->flags & MEM_Invalid ){
+    fprintf(out, " undefined");
+  }else if( p->flags & MEM_Null ){
     fprintf(out, " NULL");
   }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
     fprintf(out, " si:%lld", p->u.i);
@@ -63615,6 +65470,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     } aa;
     struct OP_Null_stack_vars {
       int cnt;
+      u16 nullFlag;
     } ab;
     struct OP_Variable_stack_vars {
       Mem *pVar;       /* Value being transferred */
@@ -63625,39 +65481,43 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int p1;          /* Register to copy from */
       int p2;          /* Register to copy to */
     } ad;
+    struct OP_Copy_stack_vars {
+      int n;
+    } ae;
     struct OP_ResultRow_stack_vars {
       Mem *pMem;
       int i;
-    } ae;
+    } af;
     struct OP_Concat_stack_vars {
       i64 nByte;
-    } af;
+    } ag;
     struct OP_Remainder_stack_vars {
+      char bIntint;   /* Started out as two integer operands */
       int flags;      /* Combined MEM_* flags from both inputs */
       i64 iA;         /* Integer value of left operand */
       i64 iB;         /* Integer value of right operand */
       double rA;      /* Real value of left operand */
       double rB;      /* Real value of right operand */
-    } ag;
+    } ah;
     struct OP_Function_stack_vars {
       int i;
       Mem *pArg;
       sqlite3_context ctx;
       sqlite3_value **apVal;
       int n;
-    } ah;
+    } ai;
     struct OP_ShiftRight_stack_vars {
       i64 iA;
       u64 uA;
       i64 iB;
       u8 op;
-    } ai;
+    } aj;
     struct OP_Ge_stack_vars {
       int res;            /* Result of the comparison of pIn1 against pIn3 */
       char affinity;      /* Affinity to use for comparison */
       u16 flags1;         /* Copy of initial value of pIn1->flags */
       u16 flags3;         /* Copy of initial value of pIn3->flags */
-    } aj;
+    } ak;
     struct OP_Compare_stack_vars {
       int n;
       int i;
@@ -63667,14 +65527,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int idx;
       CollSeq *pColl;    /* Collating sequence to use on this term */
       int bRev;          /* True for DESCENDING sort order */
-    } ak;
+    } al;
     struct OP_Or_stack_vars {
       int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
       int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-    } al;
+    } am;
     struct OP_IfNot_stack_vars {
       int c;
-    } am;
+    } an;
     struct OP_Column_stack_vars {
       u32 payloadSize;   /* Number of bytes in the record */
       i64 payloadSize64; /* Number of bytes in the record */
@@ -63699,11 +65559,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int avail;         /* Number of bytes of available data */
       u32 t;             /* A type code from the record header */
       Mem *pReg;         /* PseudoTable input register */
-    } an;
+    } ao;
     struct OP_Affinity_stack_vars {
       const char *zAffinity;   /* The affinity to be applied */
       char cAff;               /* A single character of affinity */
-    } ao;
+    } ap;
     struct OP_MakeRecord_stack_vars {
       u8 *zNewRecord;        /* A buffer to hold the data for the new record */
       Mem *pRec;             /* The new record */
@@ -63720,11 +65580,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int file_format;       /* File format to use for encoding */
       int i;                 /* Space used in zNewRecord[] */
       int len;               /* Length of a field */
-    } ap;
+    } aq;
     struct OP_Count_stack_vars {
       i64 nEntry;
       BtCursor *pCrsr;
-    } aq;
+    } ar;
     struct OP_Savepoint_stack_vars {
       int p1;                         /* Value of P1 operand */
       char *zName;                    /* Name of savepoint */
@@ -63734,28 +65594,28 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Savepoint *pTmp;
       int iSavepoint;
       int ii;
-    } ar;
+    } as;
     struct OP_AutoCommit_stack_vars {
       int desiredAutoCommit;
       int iRollback;
       int turnOnAC;
-    } as;
+    } at;
     struct OP_Transaction_stack_vars {
       Btree *pBt;
-    } at;
+    } au;
     struct OP_ReadCookie_stack_vars {
       int iMeta;
       int iDb;
       int iCookie;
-    } au;
+    } av;
     struct OP_SetCookie_stack_vars {
       Db *pDb;
-    } av;
+    } aw;
     struct OP_VerifyCookie_stack_vars {
       int iMeta;
       int iGen;
       Btree *pBt;
-    } aw;
+    } ax;
     struct OP_OpenWrite_stack_vars {
       int nField;
       KeyInfo *pKeyInfo;
@@ -63765,16 +65625,16 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Btree *pX;
       VdbeCursor *pCur;
       Db *pDb;
-    } ax;
+    } ay;
     struct OP_OpenEphemeral_stack_vars {
       VdbeCursor *pCx;
-    } ay;
+    } az;
     struct OP_SorterOpen_stack_vars {
       VdbeCursor *pCx;
-    } az;
+    } ba;
     struct OP_OpenPseudo_stack_vars {
       VdbeCursor *pCx;
-    } ba;
+    } bb;
     struct OP_SeekGt_stack_vars {
       int res;
       int oc;
@@ -63782,10 +65642,10 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       UnpackedRecord r;
       int nField;
       i64 iKey;      /* The rowid we are to seek to */
-    } bb;
+    } bc;
     struct OP_Seek_stack_vars {
       VdbeCursor *pC;
-    } bc;
+    } bd;
     struct OP_Found_stack_vars {
       int alreadyExists;
       VdbeCursor *pC;
@@ -63794,7 +65654,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       UnpackedRecord *pIdxKey;
       UnpackedRecord r;
       char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-    } bd;
+    } be;
     struct OP_IsUnique_stack_vars {
       u16 ii;
       VdbeCursor *pCx;
@@ -63803,13 +65663,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Mem *aMx;
       UnpackedRecord r;                  /* B-Tree index search key */
       i64 R;                             /* Rowid stored in register P3 */
-    } be;
+    } bf;
     struct OP_NotExists_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
       u64 iKey;
-    } bf;
+    } bg;
     struct OP_NewRowid_stack_vars {
       i64 v;                 /* The new rowid */
       VdbeCursor *pC;        /* Cursor of table to get the new rowid */
@@ -63817,7 +65677,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int cnt;               /* Counter to limit the number of searches */
       Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
       VdbeFrame *pFrame;     /* Root frame of VDBE */
-    } bg;
+    } bh;
     struct OP_InsertInt_stack_vars {
       Mem *pData;       /* MEM cell holding data for the record to be inserted */
       Mem *pKey;        /* MEM cell holding key  for the record */
@@ -63828,89 +65688,89 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       const char *zDb;  /* database name - used by the update hook */
       const char *zTbl; /* Table name - used by the opdate hook */
       int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-    } bh;
+    } bi;
     struct OP_Delete_stack_vars {
       i64 iKey;
       VdbeCursor *pC;
-    } bi;
+    } bj;
     struct OP_SorterCompare_stack_vars {
       VdbeCursor *pC;
       int res;
-    } bj;
+    } bk;
     struct OP_SorterData_stack_vars {
       VdbeCursor *pC;
-    } bk;
+    } bl;
     struct OP_RowData_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       u32 n;
       i64 n64;
-    } bl;
+    } bm;
     struct OP_Rowid_stack_vars {
       VdbeCursor *pC;
       i64 v;
       sqlite3_vtab *pVtab;
       const sqlite3_module *pModule;
-    } bm;
+    } bn;
     struct OP_NullRow_stack_vars {
       VdbeCursor *pC;
-    } bn;
+    } bo;
     struct OP_Last_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
-    } bo;
+    } bp;
     struct OP_Rewind_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
-    } bp;
+    } bq;
     struct OP_Next_stack_vars {
       VdbeCursor *pC;
       int res;
-    } bq;
+    } br;
     struct OP_IdxInsert_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int nKey;
       const char *zKey;
-    } br;
+    } bs;
     struct OP_IdxDelete_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
       UnpackedRecord r;
-    } bs;
+    } bt;
     struct OP_IdxRowid_stack_vars {
       BtCursor *pCrsr;
       VdbeCursor *pC;
       i64 rowid;
-    } bt;
+    } bu;
     struct OP_IdxGE_stack_vars {
       VdbeCursor *pC;
       int res;
       UnpackedRecord r;
-    } bu;
+    } bv;
     struct OP_Destroy_stack_vars {
       int iMoved;
       int iCnt;
       Vdbe *pVdbe;
       int iDb;
-    } bv;
+    } bw;
     struct OP_Clear_stack_vars {
       int nChange;
-    } bw;
+    } bx;
     struct OP_CreateTable_stack_vars {
       int pgno;
       int flags;
       Db *pDb;
-    } bx;
+    } by;
     struct OP_ParseSchema_stack_vars {
       int iDb;
       const char *zMaster;
       char *zSql;
       InitData initData;
-    } by;
+    } bz;
     struct OP_IntegrityCk_stack_vars {
       int nRoot;      /* Number of tables to check.  (Number of root pages.) */
       int *aRoot;     /* Array of rootpage numbers for tables to be checked */
@@ -63918,14 +65778,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int nErr;       /* Number of errors reported */
       char *z;        /* Text of the error report */
       Mem *pnErr;     /* Register keeping track of errors remaining */
-    } bz;
+    } ca;
     struct OP_RowSetRead_stack_vars {
       i64 val;
-    } ca;
+    } cb;
     struct OP_RowSetTest_stack_vars {
       int iSet;
       int exists;
-    } cb;
+    } cc;
     struct OP_Program_stack_vars {
       int nMem;               /* Number of memory registers for sub-program */
       int nByte;              /* Bytes of runtime space required for sub-program */
@@ -63935,15 +65795,15 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       VdbeFrame *pFrame;      /* New vdbe frame to execute in */
       SubProgram *pProgram;   /* Sub-program to execute */
       void *t;                /* Token identifying trigger */
-    } cc;
+    } cd;
     struct OP_Param_stack_vars {
       VdbeFrame *pFrame;
       Mem *pIn;
-    } cd;
+    } ce;
     struct OP_MemMax_stack_vars {
       Mem *pIn1;
       VdbeFrame *pFrame;
-    } ce;
+    } cf;
     struct OP_AggStep_stack_vars {
       int n;
       int i;
@@ -63951,34 +65811,36 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Mem *pRec;
       sqlite3_context ctx;
       sqlite3_value **apVal;
-    } cf;
+    } cg;
     struct OP_AggFinal_stack_vars {
       Mem *pMem;
-    } cg;
+    } ch;
     struct OP_Checkpoint_stack_vars {
       int i;                          /* Loop counter */
       int aRes[3];                    /* Results */
       Mem *pMem;                      /* Write results here */
-    } ch;
+    } ci;
     struct OP_JournalMode_stack_vars {
       Btree *pBt;                     /* Btree to change journal mode of */
       Pager *pPager;                  /* Pager associated with pBt */
       int eNew;                       /* New journal mode */
       int eOld;                       /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
       const char *zFilename;          /* Name of database file for pPager */
-    } ci;
+#endif
+    } cj;
     struct OP_IncrVacuum_stack_vars {
       Btree *pBt;
-    } cj;
+    } ck;
     struct OP_VBegin_stack_vars {
       VTable *pVTab;
-    } ck;
+    } cl;
     struct OP_VOpen_stack_vars {
       VdbeCursor *pCur;
       sqlite3_vtab_cursor *pVtabCursor;
       sqlite3_vtab *pVtab;
       sqlite3_module *pModule;
-    } cl;
+    } cm;
     struct OP_VFilter_stack_vars {
       int nArg;
       int iQuery;
@@ -63991,23 +65853,23 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int res;
       int i;
       Mem **apArg;
-    } cm;
+    } cn;
     struct OP_VColumn_stack_vars {
       sqlite3_vtab *pVtab;
       const sqlite3_module *pModule;
       Mem *pDest;
       sqlite3_context sContext;
-    } cn;
+    } co;
     struct OP_VNext_stack_vars {
       sqlite3_vtab *pVtab;
       const sqlite3_module *pModule;
       int res;
       VdbeCursor *pCur;
-    } co;
+    } cp;
     struct OP_VRename_stack_vars {
       sqlite3_vtab *pVtab;
       Mem *pName;
-    } cp;
+    } cq;
     struct OP_VUpdate_stack_vars {
       sqlite3_vtab *pVtab;
       sqlite3_module *pModule;
@@ -64016,11 +65878,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       sqlite_int64 rowid;
       Mem **apArg;
       Mem *pX;
-    } cq;
+    } cr;
     struct OP_Trace_stack_vars {
       char *zTrace;
       char *z;
-    } cr;
+    } cs;
   } u;
   /* End automatically generated code
   ********************************************************************/
@@ -64322,7 +66184,7 @@ case OP_Halt: {
   if( rc==SQLITE_BUSY ){
     p->rc = rc = SQLITE_BUSY;
   }else{
-    assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
+    assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
     assert( rc==SQLITE_OK || db->nDeferredCons>0 );
     rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
   }
@@ -64411,25 +66273,30 @@ case OP_String: {          /* out2-prerelease */
   break;
 }
 
-/* Opcode: Null * P2 P3 * *
+/* Opcode: Null P1 P2 P3 * *
 **
 ** Write a NULL into registers P2.  If P3 greater than P2, then also write
-** NULL into register P3 and ever register in between P2 and P3.  If P3
+** NULL into register P3 and every register in between P2 and P3.  If P3
 ** is less than P2 (typically P3 is zero) then only register P2 is
-** set to NULL
+** set to NULL.
+**
+** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
+** NULL values will not compare equal even if SQLITE_NULLEQ is set on
+** OP_Ne or OP_Eq.
 */
 case OP_Null: {           /* out2-prerelease */
 #if 0  /* local variables moved into u.ab */
   int cnt;
+  u16 nullFlag;
 #endif /* local variables moved into u.ab */
   u.ab.cnt = pOp->p3-pOp->p2;
   assert( pOp->p3<=p->nMem );
-  pOut->flags = MEM_Null;
+  pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
   while( u.ab.cnt>0 ){
     pOut++;
     memAboutToChange(p, pOut);
     VdbeMemRelease(pOut);
-    pOut->flags = MEM_Null;
+    pOut->flags = u.ab.nullFlag;
     u.ab.cnt--;
   }
   break;
@@ -64474,10 +66341,10 @@ case OP_Variable: {            /* out2-prerelease */
 
 /* Opcode: Move P1 P2 P3 * *
 **
-** Move the values in register P1..P1+P3-1 over into
-** registers P2..P2+P3-1.  Registers P1..P1+P1-1 are
+** Move the values in register P1..P1+P3 over into
+** registers P2..P2+P3.  Registers P1..P1+P3 are
 ** left holding a NULL.  It is an error for register ranges
-** P1..P1+P3-1 and P2..P2+P3-1 to overlap.
+** P1..P1+P3 and P2..P2+P3 to overlap.
 */
 case OP_Move: {
 #if 0  /* local variables moved into u.ad */
@@ -64487,7 +66354,7 @@ case OP_Move: {
   int p2;          /* Register to copy to */
 #endif /* local variables moved into u.ad */
 
-  u.ad.n = pOp->p3;
+  u.ad.n = pOp->p3 + 1;
   u.ad.p1 = pOp->p1;
   u.ad.p2 = pOp->p2;
   assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
@@ -64516,20 +66383,33 @@ case OP_Move: {
   break;
 }
 
-/* Opcode: Copy P1 P2 * * *
+/* Opcode: Copy P1 P2 P3 * *
 **
-** Make a copy of register P1 into register P2.
+** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
 **
 ** This instruction makes a deep copy of the value.  A duplicate
 ** is made of any string or blob constant.  See also OP_SCopy.
 */
-case OP_Copy: {             /* in1, out2 */
+case OP_Copy: {
+#if 0  /* local variables moved into u.ae */
+  int n;
+#endif /* local variables moved into u.ae */
+
+  u.ae.n = pOp->p3;
   pIn1 = &aMem[pOp->p1];
   pOut = &aMem[pOp->p2];
   assert( pOut!=pIn1 );
-  sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
-  Deephemeralize(pOut);
-  REGISTER_TRACE(pOp->p2, pOut);
+  while( 1 ){
+    sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+    Deephemeralize(pOut);
+#ifdef SQLITE_DEBUG
+    pOut->pScopyFrom = 0;
+#endif
+    REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
+    if( (u.ae.n--)==0 ) break;
+    pOut++;
+    pIn1++;
+  }
   break;
 }
 
@@ -64566,10 +66446,10 @@ case OP_SCopy: {            /* in1, out2 */
 ** row.
 */
 case OP_ResultRow: {
-#if 0  /* local variables moved into u.ae */
+#if 0  /* local variables moved into u.af */
   Mem *pMem;
   int i;
-#endif /* local variables moved into u.ae */
+#endif /* local variables moved into u.af */
   assert( p->nResColumn==pOp->p2 );
   assert( pOp->p1>0 );
   assert( pOp->p1+pOp->p2<=p->nMem+1 );
@@ -64611,15 +66491,15 @@ case OP_ResultRow: {
   ** and have an assigned type.  The results are de-ephemeralized as
   ** a side effect.
   */
-  u.ae.pMem = p->pResultSet = &aMem[pOp->p1];
-  for(u.ae.i=0; u.ae.i<pOp->p2; u.ae.i++){
-    assert( memIsValid(&u.ae.pMem[u.ae.i]) );
-    Deephemeralize(&u.ae.pMem[u.ae.i]);
-    assert( (u.ae.pMem[u.ae.i].flags & MEM_Ephem)==0
-            || (u.ae.pMem[u.ae.i].flags & (MEM_Str|MEM_Blob))==0 );
-    sqlite3VdbeMemNulTerminate(&u.ae.pMem[u.ae.i]);
-    sqlite3VdbeMemStoreType(&u.ae.pMem[u.ae.i]);
-    REGISTER_TRACE(pOp->p1+u.ae.i, &u.ae.pMem[u.ae.i]);
+  u.af.pMem = p->pResultSet = &aMem[pOp->p1];
+  for(u.af.i=0; u.af.i<pOp->p2; u.af.i++){
+    assert( memIsValid(&u.af.pMem[u.af.i]) );
+    Deephemeralize(&u.af.pMem[u.af.i]);
+    assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0
+            || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 );
+    sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]);
+    sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]);
+    REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]);
   }
   if( db->mallocFailed ) goto no_mem;
 
@@ -64643,9 +66523,9 @@ case OP_ResultRow: {
 ** to avoid a memcpy().
 */
 case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
-#if 0  /* local variables moved into u.af */
+#if 0  /* local variables moved into u.ag */
   i64 nByte;
-#endif /* local variables moved into u.af */
+#endif /* local variables moved into u.ag */
 
   pIn1 = &aMem[pOp->p1];
   pIn2 = &aMem[pOp->p2];
@@ -64658,22 +66538,22 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
   if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
   Stringify(pIn1, encoding);
   Stringify(pIn2, encoding);
-  u.af.nByte = pIn1->n + pIn2->n;
-  if( u.af.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  u.ag.nByte = pIn1->n + pIn2->n;
+  if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
   MemSetTypeFlag(pOut, MEM_Str);
-  if( sqlite3VdbeMemGrow(pOut, (int)u.af.nByte+2, pOut==pIn2) ){
+  if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){
     goto no_mem;
   }
   if( pOut!=pIn2 ){
     memcpy(pOut->z, pIn2->z, pIn2->n);
   }
   memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
-  pOut->z[u.af.nByte] = 0;
-  pOut->z[u.af.nByte+1] = 0;
+  pOut->z[u.ag.nByte] = 0;
+  pOut->z[u.ag.nByte+1] = 0;
   pOut->flags |= MEM_Term;
-  pOut->n = (int)u.af.nByte;
+  pOut->n = (int)u.ag.nByte;
   pOut->enc = encoding;
   UPDATE_MAX_BLOBSIZE(pOut);
   break;
@@ -64717,76 +66597,79 @@ case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
 case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
 case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
 case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
-#if 0  /* local variables moved into u.ag */
+#if 0  /* local variables moved into u.ah */
+  char bIntint;   /* Started out as two integer operands */
   int flags;      /* Combined MEM_* flags from both inputs */
   i64 iA;         /* Integer value of left operand */
   i64 iB;         /* Integer value of right operand */
   double rA;      /* Real value of left operand */
   double rB;      /* Real value of right operand */
-#endif /* local variables moved into u.ag */
+#endif /* local variables moved into u.ah */
 
   pIn1 = &aMem[pOp->p1];
   applyNumericAffinity(pIn1);
   pIn2 = &aMem[pOp->p2];
   applyNumericAffinity(pIn2);
   pOut = &aMem[pOp->p3];
-  u.ag.flags = pIn1->flags | pIn2->flags;
-  if( (u.ag.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+  u.ah.flags = pIn1->flags | pIn2->flags;
+  if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
   if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
-    u.ag.iA = pIn1->u.i;
-    u.ag.iB = pIn2->u.i;
+    u.ah.iA = pIn1->u.i;
+    u.ah.iB = pIn2->u.i;
+    u.ah.bIntint = 1;
     switch( pOp->opcode ){
-      case OP_Add:       if( sqlite3AddInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
-      case OP_Subtract:  if( sqlite3SubInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
-      case OP_Multiply:  if( sqlite3MulInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
+      case OP_Add:       if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
+      case OP_Subtract:  if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
+      case OP_Multiply:  if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
       case OP_Divide: {
-        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ag.iA==-1 && u.ag.iB==SMALLEST_INT64 ) goto fp_math;
-        u.ag.iB /= u.ag.iA;
+        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+        if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
+        u.ah.iB /= u.ah.iA;
         break;
       }
       default: {
-        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ag.iA==-1 ) u.ag.iA = 1;
-        u.ag.iB %= u.ag.iA;
+        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+        if( u.ah.iA==-1 ) u.ah.iA = 1;
+        u.ah.iB %= u.ah.iA;
         break;
       }
     }
-    pOut->u.i = u.ag.iB;
+    pOut->u.i = u.ah.iB;
     MemSetTypeFlag(pOut, MEM_Int);
   }else{
+    u.ah.bIntint = 0;
 fp_math:
-    u.ag.rA = sqlite3VdbeRealValue(pIn1);
-    u.ag.rB = sqlite3VdbeRealValue(pIn2);
+    u.ah.rA = sqlite3VdbeRealValue(pIn1);
+    u.ah.rB = sqlite3VdbeRealValue(pIn2);
     switch( pOp->opcode ){
-      case OP_Add:         u.ag.rB += u.ag.rA;       break;
-      case OP_Subtract:    u.ag.rB -= u.ag.rA;       break;
-      case OP_Multiply:    u.ag.rB *= u.ag.rA;       break;
+      case OP_Add:         u.ah.rB += u.ah.rA;       break;
+      case OP_Subtract:    u.ah.rB -= u.ah.rA;       break;
+      case OP_Multiply:    u.ah.rB *= u.ah.rA;       break;
       case OP_Divide: {
         /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-        if( u.ag.rA==(double)0 ) goto arithmetic_result_is_null;
-        u.ag.rB /= u.ag.rA;
+        if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null;
+        u.ah.rB /= u.ah.rA;
         break;
       }
       default: {
-        u.ag.iA = (i64)u.ag.rA;
-        u.ag.iB = (i64)u.ag.rB;
-        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ag.iA==-1 ) u.ag.iA = 1;
-        u.ag.rB = (double)(u.ag.iB % u.ag.iA);
+        u.ah.iA = (i64)u.ah.rA;
+        u.ah.iB = (i64)u.ah.rB;
+        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+        if( u.ah.iA==-1 ) u.ah.iA = 1;
+        u.ah.rB = (double)(u.ah.iB % u.ah.iA);
         break;
       }
     }
 #ifdef SQLITE_OMIT_FLOATING_POINT
-    pOut->u.i = u.ag.rB;
+    pOut->u.i = u.ah.rB;
     MemSetTypeFlag(pOut, MEM_Int);
 #else
-    if( sqlite3IsNaN(u.ag.rB) ){
+    if( sqlite3IsNaN(u.ah.rB) ){
       goto arithmetic_result_is_null;
     }
-    pOut->r = u.ag.rB;
+    pOut->r = u.ah.rB;
     MemSetTypeFlag(pOut, MEM_Real);
-    if( (u.ag.flags & MEM_Real)==0 ){
+    if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
       sqlite3VdbeIntegerAffinity(pOut);
     }
 #endif
@@ -64838,70 +66721,70 @@ case OP_CollSeq: {
 ** See also: AggStep and AggFinal
 */
 case OP_Function: {
-#if 0  /* local variables moved into u.ah */
+#if 0  /* local variables moved into u.ai */
   int i;
   Mem *pArg;
   sqlite3_context ctx;
   sqlite3_value **apVal;
   int n;
-#endif /* local variables moved into u.ah */
+#endif /* local variables moved into u.ai */
 
-  u.ah.n = pOp->p5;
-  u.ah.apVal = p->apArg;
-  assert( u.ah.apVal || u.ah.n==0 );
+  u.ai.n = pOp->p5;
+  u.ai.apVal = p->apArg;
+  assert( u.ai.apVal || u.ai.n==0 );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
   pOut = &aMem[pOp->p3];
   memAboutToChange(p, pOut);
 
-  assert( u.ah.n==0 || (pOp->p2>0 && pOp->p2+u.ah.n<=p->nMem+1) );
-  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ah.n );
-  u.ah.pArg = &aMem[pOp->p2];
-  for(u.ah.i=0; u.ah.i<u.ah.n; u.ah.i++, u.ah.pArg++){
-    assert( memIsValid(u.ah.pArg) );
-    u.ah.apVal[u.ah.i] = u.ah.pArg;
-    Deephemeralize(u.ah.pArg);
-    sqlite3VdbeMemStoreType(u.ah.pArg);
-    REGISTER_TRACE(pOp->p2+u.ah.i, u.ah.pArg);
+  assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
+  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ai.n );
+  u.ai.pArg = &aMem[pOp->p2];
+  for(u.ai.i=0; u.ai.i<u.ai.n; u.ai.i++, u.ai.pArg++){
+    assert( memIsValid(u.ai.pArg) );
+    u.ai.apVal[u.ai.i] = u.ai.pArg;
+    Deephemeralize(u.ai.pArg);
+    sqlite3VdbeMemStoreType(u.ai.pArg);
+    REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
   }
 
   assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
   if( pOp->p4type==P4_FUNCDEF ){
-    u.ah.ctx.pFunc = pOp->p4.pFunc;
-    u.ah.ctx.pVdbeFunc = 0;
+    u.ai.ctx.pFunc = pOp->p4.pFunc;
+    u.ai.ctx.pVdbeFunc = 0;
   }else{
-    u.ah.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
-    u.ah.ctx.pFunc = u.ah.ctx.pVdbeFunc->pFunc;
+    u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
+    u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
   }
 
-  u.ah.ctx.s.flags = MEM_Null;
-  u.ah.ctx.s.db = db;
-  u.ah.ctx.s.xDel = 0;
-  u.ah.ctx.s.zMalloc = 0;
+  u.ai.ctx.s.flags = MEM_Null;
+  u.ai.ctx.s.db = db;
+  u.ai.ctx.s.xDel = 0;
+  u.ai.ctx.s.zMalloc = 0;
 
   /* The output cell may already have a buffer allocated. Move
-  ** the pointer to u.ah.ctx.s so in case the user-function can use
+  ** the pointer to u.ai.ctx.s so in case the user-function can use
   ** the already allocated buffer instead of allocating a new one.
   */
-  sqlite3VdbeMemMove(&u.ah.ctx.s, pOut);
-  MemSetTypeFlag(&u.ah.ctx.s, MEM_Null);
+  sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
+  MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
 
-  u.ah.ctx.isError = 0;
-  if( u.ah.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+  u.ai.ctx.isError = 0;
+  if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
     assert( pOp>aOp );
     assert( pOp[-1].p4type==P4_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.ah.ctx.pColl = pOp[-1].p4.pColl;
+    u.ai.ctx.pColl = pOp[-1].p4.pColl;
   }
   db->lastRowid = lastRowid;
-  (*u.ah.ctx.pFunc->xFunc)(&u.ah.ctx, u.ah.n, u.ah.apVal); /* IMP: R-24505-23230 */
+  (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
   lastRowid = db->lastRowid;
 
   /* If any auxiliary data functions have been called by this user function,
   ** immediately call the destructor for any non-static values.
   */
-  if( u.ah.ctx.pVdbeFunc ){
-    sqlite3VdbeDeleteAuxData(u.ah.ctx.pVdbeFunc, pOp->p1);
-    pOp->p4.pVdbeFunc = u.ah.ctx.pVdbeFunc;
+  if( u.ai.ctx.pVdbeFunc ){
+    sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
+    pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
     pOp->p4type = P4_VDBEFUNC;
   }
 
@@ -64911,19 +66794,19 @@ case OP_Function: {
     ** to return a value. The following call releases any resources
     ** associated with such a value.
     */
-    sqlite3VdbeMemRelease(&u.ah.ctx.s);
+    sqlite3VdbeMemRelease(&u.ai.ctx.s);
     goto no_mem;
   }
 
   /* If the function returned an error, throw an exception */
-  if( u.ah.ctx.isError ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ah.ctx.s));
-    rc = u.ah.ctx.isError;
+  if( u.ai.ctx.isError ){
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
+    rc = u.ai.ctx.isError;
   }
 
   /* Copy the result of the function into register P3 */
-  sqlite3VdbeChangeEncoding(&u.ah.ctx.s, encoding);
-  sqlite3VdbeMemMove(pOut, &u.ah.ctx.s);
+  sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
+  sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
   if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
   }
@@ -64971,12 +66854,12 @@ case OP_BitAnd:                 /* same as TK_BITAND, in1, in2, out3 */
 case OP_BitOr:                  /* same as TK_BITOR, in1, in2, out3 */
 case OP_ShiftLeft:              /* same as TK_LSHIFT, in1, in2, out3 */
 case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
-#if 0  /* local variables moved into u.ai */
+#if 0  /* local variables moved into u.aj */
   i64 iA;
   u64 uA;
   i64 iB;
   u8 op;
-#endif /* local variables moved into u.ai */
+#endif /* local variables moved into u.aj */
 
   pIn1 = &aMem[pOp->p1];
   pIn2 = &aMem[pOp->p2];
@@ -64985,38 +66868,38 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
     sqlite3VdbeMemSetNull(pOut);
     break;
   }
-  u.ai.iA = sqlite3VdbeIntValue(pIn2);
-  u.ai.iB = sqlite3VdbeIntValue(pIn1);
-  u.ai.op = pOp->opcode;
-  if( u.ai.op==OP_BitAnd ){
-    u.ai.iA &= u.ai.iB;
-  }else if( u.ai.op==OP_BitOr ){
-    u.ai.iA |= u.ai.iB;
-  }else if( u.ai.iB!=0 ){
-    assert( u.ai.op==OP_ShiftRight || u.ai.op==OP_ShiftLeft );
+  u.aj.iA = sqlite3VdbeIntValue(pIn2);
+  u.aj.iB = sqlite3VdbeIntValue(pIn1);
+  u.aj.op = pOp->opcode;
+  if( u.aj.op==OP_BitAnd ){
+    u.aj.iA &= u.aj.iB;
+  }else if( u.aj.op==OP_BitOr ){
+    u.aj.iA |= u.aj.iB;
+  }else if( u.aj.iB!=0 ){
+    assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft );
 
     /* If shifting by a negative amount, shift in the other direction */
-    if( u.ai.iB<0 ){
+    if( u.aj.iB<0 ){
       assert( OP_ShiftRight==OP_ShiftLeft+1 );
-      u.ai.op = 2*OP_ShiftLeft + 1 - u.ai.op;
-      u.ai.iB = u.ai.iB>(-64) ? -u.ai.iB : 64;
+      u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op;
+      u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64;
     }
 
-    if( u.ai.iB>=64 ){
-      u.ai.iA = (u.ai.iA>=0 || u.ai.op==OP_ShiftLeft) ? 0 : -1;
+    if( u.aj.iB>=64 ){
+      u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1;
     }else{
-      memcpy(&u.ai.uA, &u.ai.iA, sizeof(u.ai.uA));
-      if( u.ai.op==OP_ShiftLeft ){
-        u.ai.uA <<= u.ai.iB;
+      memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA));
+      if( u.aj.op==OP_ShiftLeft ){
+        u.aj.uA <<= u.aj.iB;
       }else{
-        u.ai.uA >>= u.ai.iB;
+        u.aj.uA >>= u.aj.iB;
         /* Sign-extend on a right shift of a negative number */
-        if( u.ai.iA<0 ) u.ai.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ai.iB);
+        if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB);
       }
-      memcpy(&u.ai.iA, &u.ai.uA, sizeof(u.ai.iA));
+      memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA));
     }
   }
-  pOut->u.i = u.ai.iA;
+  pOut->u.i = u.aj.iA;
   MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
@@ -65208,6 +67091,10 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
 **
 ** If the SQLITE_STOREP2 bit of P5 is set, then do not jump.  Instead,
 ** store a boolean result (either 0, or 1, or NULL) in register P2.
+**
+** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered
+** equal to one another, provided that they do not have their MEM_Cleared
+** bit set.
 */
 /* Opcode: Ne P1 P2 P3 P4 P5
 **
@@ -65257,18 +67144,18 @@ case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
 case OP_Le:               /* same as TK_LE, jump, in1, in3 */
 case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
 case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
-#if 0  /* local variables moved into u.aj */
+#if 0  /* local variables moved into u.ak */
   int res;            /* Result of the comparison of pIn1 against pIn3 */
   char affinity;      /* Affinity to use for comparison */
   u16 flags1;         /* Copy of initial value of pIn1->flags */
   u16 flags3;         /* Copy of initial value of pIn3->flags */
-#endif /* local variables moved into u.aj */
+#endif /* local variables moved into u.ak */
 
   pIn1 = &aMem[pOp->p1];
   pIn3 = &aMem[pOp->p3];
-  u.aj.flags1 = pIn1->flags;
-  u.aj.flags3 = pIn3->flags;
-  if( (u.aj.flags1 | u.aj.flags3)&MEM_Null ){
+  u.ak.flags1 = pIn1->flags;
+  u.ak.flags3 = pIn3->flags;
+  if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){
     /* One or both operands are NULL */
     if( pOp->p5 & SQLITE_NULLEQ ){
       /* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -65276,7 +67163,15 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
       ** or not both operands are null.
       */
       assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
-      u.aj.res = (u.aj.flags1 & u.aj.flags3 & MEM_Null)==0;
+      assert( (u.ak.flags1 & MEM_Cleared)==0 );
+      if( (u.ak.flags1&MEM_Null)!=0
+       && (u.ak.flags3&MEM_Null)!=0
+       && (u.ak.flags3&MEM_Cleared)==0
+      ){
+        u.ak.res = 0;  /* Results are equal */
+      }else{
+        u.ak.res = 1;  /* Results are not equal */
+      }
     }else{
       /* SQLITE_NULLEQ is clear and at least one operand is NULL,
       ** then the result is always NULL.
@@ -65293,40 +67188,40 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
     }
   }else{
     /* Neither operand is NULL.  Do a comparison. */
-    u.aj.affinity = pOp->p5 & SQLITE_AFF_MASK;
-    if( u.aj.affinity ){
-      applyAffinity(pIn1, u.aj.affinity, encoding);
-      applyAffinity(pIn3, u.aj.affinity, encoding);
+    u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
+    if( u.ak.affinity ){
+      applyAffinity(pIn1, u.ak.affinity, encoding);
+      applyAffinity(pIn3, u.ak.affinity, encoding);
       if( db->mallocFailed ) goto no_mem;
     }
 
     assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
     ExpandBlob(pIn1);
     ExpandBlob(pIn3);
-    u.aj.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+    u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
   }
   switch( pOp->opcode ){
-    case OP_Eq:    u.aj.res = u.aj.res==0;     break;
-    case OP_Ne:    u.aj.res = u.aj.res!=0;     break;
-    case OP_Lt:    u.aj.res = u.aj.res<0;      break;
-    case OP_Le:    u.aj.res = u.aj.res<=0;     break;
-    case OP_Gt:    u.aj.res = u.aj.res>0;      break;
-    default:       u.aj.res = u.aj.res>=0;     break;
+    case OP_Eq:    u.ak.res = u.ak.res==0;     break;
+    case OP_Ne:    u.ak.res = u.ak.res!=0;     break;
+    case OP_Lt:    u.ak.res = u.ak.res<0;      break;
+    case OP_Le:    u.ak.res = u.ak.res<=0;     break;
+    case OP_Gt:    u.ak.res = u.ak.res>0;      break;
+    default:       u.ak.res = u.ak.res>=0;     break;
   }
 
   if( pOp->p5 & SQLITE_STOREP2 ){
     pOut = &aMem[pOp->p2];
     memAboutToChange(p, pOut);
     MemSetTypeFlag(pOut, MEM_Int);
-    pOut->u.i = u.aj.res;
+    pOut->u.i = u.ak.res;
     REGISTER_TRACE(pOp->p2, pOut);
-  }else if( u.aj.res ){
+  }else if( u.ak.res ){
     pc = pOp->p2-1;
   }
 
   /* Undo any changes made by applyAffinity() to the input registers. */
-  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.aj.flags1&MEM_TypeMask);
-  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.aj.flags3&MEM_TypeMask);
+  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask);
+  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask);
   break;
 }
 
@@ -65335,9 +67230,9 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 ** Set the permutation used by the OP_Compare operator to be the array
 ** of integers in P4.
 **
-** The permutation is only valid until the next OP_Permutation, OP_Compare,
-** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
-** immediately prior to the OP_Compare.
+** The permutation is only valid until the next OP_Compare that has
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should 
+** occur immediately prior to the OP_Compare.
 */
 case OP_Permutation: {
   assert( pOp->p4type==P4_INTARRAY );
@@ -65346,12 +67241,17 @@ case OP_Permutation: {
   break;
 }
 
-/* Opcode: Compare P1 P2 P3 P4 *
+/* Opcode: Compare P1 P2 P3 P4 P5
 **
 ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
 ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
 ** the comparison for use by the next OP_Jump instruct.
 **
+** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
+** determined by the most recent OP_Permutation operator.  If the
+** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
+** order.
+**
 ** P4 is a KeyInfo structure that defines collating sequences and sort
 ** orders for the comparison.  The permutation applies to registers
 ** only.  The KeyInfo elements are used sequentially.
@@ -65361,7 +67261,7 @@ case OP_Permutation: {
 ** and strings are less than blobs.
 */
 case OP_Compare: {
-#if 0  /* local variables moved into u.ak */
+#if 0  /* local variables moved into u.al */
   int n;
   int i;
   int p1;
@@ -65370,37 +67270,38 @@ case OP_Compare: {
   int idx;
   CollSeq *pColl;    /* Collating sequence to use on this term */
   int bRev;          /* True for DESCENDING sort order */
-#endif /* local variables moved into u.ak */
+#endif /* local variables moved into u.al */
 
-  u.ak.n = pOp->p3;
-  u.ak.pKeyInfo = pOp->p4.pKeyInfo;
-  assert( u.ak.n>0 );
-  assert( u.ak.pKeyInfo!=0 );
-  u.ak.p1 = pOp->p1;
-  u.ak.p2 = pOp->p2;
+  if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
+  u.al.n = pOp->p3;
+  u.al.pKeyInfo = pOp->p4.pKeyInfo;
+  assert( u.al.n>0 );
+  assert( u.al.pKeyInfo!=0 );
+  u.al.p1 = pOp->p1;
+  u.al.p2 = pOp->p2;
 #if SQLITE_DEBUG
   if( aPermute ){
     int k, mx = 0;
-    for(k=0; k<u.ak.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
-    assert( u.ak.p1>0 && u.ak.p1+mx<=p->nMem+1 );
-    assert( u.ak.p2>0 && u.ak.p2+mx<=p->nMem+1 );
+    for(k=0; k<u.al.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+    assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
+    assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
   }else{
-    assert( u.ak.p1>0 && u.ak.p1+u.ak.n<=p->nMem+1 );
-    assert( u.ak.p2>0 && u.ak.p2+u.ak.n<=p->nMem+1 );
+    assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
+    assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
   }
 #endif /* SQLITE_DEBUG */
-  for(u.ak.i=0; u.ak.i<u.ak.n; u.ak.i++){
-    u.ak.idx = aPermute ? aPermute[u.ak.i] : u.ak.i;
-    assert( memIsValid(&aMem[u.ak.p1+u.ak.idx]) );
-    assert( memIsValid(&aMem[u.ak.p2+u.ak.idx]) );
-    REGISTER_TRACE(u.ak.p1+u.ak.idx, &aMem[u.ak.p1+u.ak.idx]);
-    REGISTER_TRACE(u.ak.p2+u.ak.idx, &aMem[u.ak.p2+u.ak.idx]);
-    assert( u.ak.i<u.ak.pKeyInfo->nField );
-    u.ak.pColl = u.ak.pKeyInfo->aColl[u.ak.i];
-    u.ak.bRev = u.ak.pKeyInfo->aSortOrder[u.ak.i];
-    iCompare = sqlite3MemCompare(&aMem[u.ak.p1+u.ak.idx], &aMem[u.ak.p2+u.ak.idx], u.ak.pColl);
+  for(u.al.i=0; u.al.i<u.al.n; u.al.i++){
+    u.al.idx = aPermute ? aPermute[u.al.i] : u.al.i;
+    assert( memIsValid(&aMem[u.al.p1+u.al.idx]) );
+    assert( memIsValid(&aMem[u.al.p2+u.al.idx]) );
+    REGISTER_TRACE(u.al.p1+u.al.idx, &aMem[u.al.p1+u.al.idx]);
+    REGISTER_TRACE(u.al.p2+u.al.idx, &aMem[u.al.p2+u.al.idx]);
+    assert( u.al.i<u.al.pKeyInfo->nField );
+    u.al.pColl = u.al.pKeyInfo->aColl[u.al.i];
+    u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i];
+    iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl);
     if( iCompare ){
-      if( u.ak.bRev ) iCompare = -iCompare;
+      if( u.al.bRev ) iCompare = -iCompare;
       break;
     }
   }
@@ -65445,35 +67346,35 @@ case OP_Jump: {             /* jump */
 */
 case OP_And:              /* same as TK_AND, in1, in2, out3 */
 case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
-#if 0  /* local variables moved into u.al */
+#if 0  /* local variables moved into u.am */
   int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
   int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-#endif /* local variables moved into u.al */
+#endif /* local variables moved into u.am */
 
   pIn1 = &aMem[pOp->p1];
   if( pIn1->flags & MEM_Null ){
-    u.al.v1 = 2;
+    u.am.v1 = 2;
   }else{
-    u.al.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+    u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0;
   }
   pIn2 = &aMem[pOp->p2];
   if( pIn2->flags & MEM_Null ){
-    u.al.v2 = 2;
+    u.am.v2 = 2;
   }else{
-    u.al.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+    u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0;
   }
   if( pOp->opcode==OP_And ){
     static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
-    u.al.v1 = and_logic[u.al.v1*3+u.al.v2];
+    u.am.v1 = and_logic[u.am.v1*3+u.am.v2];
   }else{
     static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
-    u.al.v1 = or_logic[u.al.v1*3+u.al.v2];
+    u.am.v1 = or_logic[u.am.v1*3+u.am.v2];
   }
   pOut = &aMem[pOp->p3];
-  if( u.al.v1==2 ){
+  if( u.am.v1==2 ){
     MemSetTypeFlag(pOut, MEM_Null);
   }else{
-    pOut->u.i = u.al.v1;
+    pOut->u.i = u.am.v1;
     MemSetTypeFlag(pOut, MEM_Int);
   }
   break;
@@ -65517,8 +67418,6 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 **
 ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
 ** set the flag and fall through to the next instruction.
-**
-** See also: JumpOnce
 */
 case OP_Once: {             /* jump */
   assert( pOp->p1<p->nOnceFlag );
@@ -65544,21 +67443,21 @@ case OP_Once: {             /* jump */
 */
 case OP_If:                 /* jump, in1 */
 case OP_IfNot: {            /* jump, in1 */
-#if 0  /* local variables moved into u.am */
+#if 0  /* local variables moved into u.an */
   int c;
-#endif /* local variables moved into u.am */
+#endif /* local variables moved into u.an */
   pIn1 = &aMem[pOp->p1];
   if( pIn1->flags & MEM_Null ){
-    u.am.c = pOp->p3;
+    u.an.c = pOp->p3;
   }else{
 #ifdef SQLITE_OMIT_FLOATING_POINT
-    u.am.c = sqlite3VdbeIntValue(pIn1)!=0;
+    u.an.c = sqlite3VdbeIntValue(pIn1)!=0;
 #else
-    u.am.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+    u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0;
 #endif
-    if( pOp->opcode==OP_IfNot ) u.am.c = !u.am.c;
+    if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c;
   }
-  if( u.am.c ){
+  if( u.an.c ){
     pc = pOp->p2-1;
   }
   break;
@@ -65613,7 +67512,7 @@ case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
 ** skipped for length() and all content loading can be skipped for typeof().
 */
 case OP_Column: {
-#if 0  /* local variables moved into u.an */
+#if 0  /* local variables moved into u.ao */
   u32 payloadSize;   /* Number of bytes in the record */
   i64 payloadSize64; /* Number of bytes in the record */
   int p1;            /* P1 value of the opcode */
@@ -65637,126 +67536,131 @@ case OP_Column: {
   int avail;         /* Number of bytes of available data */
   u32 t;             /* A type code from the record header */
   Mem *pReg;         /* PseudoTable input register */
-#endif /* local variables moved into u.an */
+#endif /* local variables moved into u.ao */
 
 
-  u.an.p1 = pOp->p1;
-  u.an.p2 = pOp->p2;
-  u.an.pC = 0;
-  memset(&u.an.sMem, 0, sizeof(u.an.sMem));
-  assert( u.an.p1<p->nCursor );
+  u.ao.p1 = pOp->p1;
+  u.ao.p2 = pOp->p2;
+  u.ao.pC = 0;
+  memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
+  assert( u.ao.p1<p->nCursor );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.an.pDest = &aMem[pOp->p3];
-  memAboutToChange(p, u.an.pDest);
-  u.an.zRec = 0;
+  u.ao.pDest = &aMem[pOp->p3];
+  memAboutToChange(p, u.ao.pDest);
+  u.ao.zRec = 0;
 
-  /* This block sets the variable u.an.payloadSize to be the total number of
+  /* This block sets the variable u.ao.payloadSize to be the total number of
   ** bytes in the record.
   **
-  ** u.an.zRec is set to be the complete text of the record if it is available.
+  ** u.ao.zRec is set to be the complete text of the record if it is available.
   ** The complete record text is always available for pseudo-tables
   ** If the record is stored in a cursor, the complete record text
-  ** might be available in the  u.an.pC->aRow cache.  Or it might not be.
-  ** If the data is unavailable,  u.an.zRec is set to NULL.
+  ** might be available in the  u.ao.pC->aRow cache.  Or it might not be.
+  ** If the data is unavailable,  u.ao.zRec is set to NULL.
   **
   ** We also compute the number of columns in the record.  For cursors,
   ** the number of columns is stored in the VdbeCursor.nField element.
   */
-  u.an.pC = p->apCsr[u.an.p1];
-  assert( u.an.pC!=0 );
+  u.ao.pC = p->apCsr[u.ao.p1];
+  assert( u.ao.pC!=0 );
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  assert( u.an.pC->pVtabCursor==0 );
+  assert( u.ao.pC->pVtabCursor==0 );
 #endif
-  u.an.pCrsr = u.an.pC->pCursor;
-  if( u.an.pCrsr!=0 ){
+  u.ao.pCrsr = u.ao.pC->pCursor;
+  if( u.ao.pCrsr!=0 ){
     /* The record is stored in a B-Tree */
-    rc = sqlite3VdbeCursorMoveto(u.an.pC);
+    rc = sqlite3VdbeCursorMoveto(u.ao.pC);
     if( rc ) goto abort_due_to_error;
-    if( u.an.pC->nullRow ){
-      u.an.payloadSize = 0;
-    }else if( u.an.pC->cacheStatus==p->cacheCtr ){
-      u.an.payloadSize = u.an.pC->payloadSize;
-      u.an.zRec = (char*)u.an.pC->aRow;
-    }else if( u.an.pC->isIndex ){
-      assert( sqlite3BtreeCursorIsValid(u.an.pCrsr) );
-      VVA_ONLY(rc =) sqlite3BtreeKeySize(u.an.pCrsr, &u.an.payloadSize64);
+    if( u.ao.pC->nullRow ){
+      u.ao.payloadSize = 0;
+    }else if( u.ao.pC->cacheStatus==p->cacheCtr ){
+      u.ao.payloadSize = u.ao.pC->payloadSize;
+      u.ao.zRec = (char*)u.ao.pC->aRow;
+    }else if( u.ao.pC->isIndex ){
+      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+      VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64);
       assert( rc==SQLITE_OK );   /* True because of CursorMoveto() call above */
       /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
-      ** payload size, so it is impossible for u.an.payloadSize64 to be
+      ** payload size, so it is impossible for u.ao.payloadSize64 to be
       ** larger than 32 bits. */
-      assert( (u.an.payloadSize64 & SQLITE_MAX_U32)==(u64)u.an.payloadSize64 );
-      u.an.payloadSize = (u32)u.an.payloadSize64;
+      assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 );
+      u.ao.payloadSize = (u32)u.ao.payloadSize64;
     }else{
-      assert( sqlite3BtreeCursorIsValid(u.an.pCrsr) );
-      VVA_ONLY(rc =) sqlite3BtreeDataSize(u.an.pCrsr, &u.an.payloadSize);
+      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+      VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
       assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
     }
-  }else if( ALWAYS(u.an.pC->pseudoTableReg>0) ){
-    u.an.pReg = &aMem[u.an.pC->pseudoTableReg];
-    assert( u.an.pReg->flags & MEM_Blob );
-    assert( memIsValid(u.an.pReg) );
-    u.an.payloadSize = u.an.pReg->n;
-    u.an.zRec = u.an.pReg->z;
-    u.an.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
-    assert( u.an.payloadSize==0 || u.an.zRec!=0 );
+  }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
+    u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
+    if( u.ao.pC->multiPseudo ){
+      sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
+      Deephemeralize(u.ao.pDest);
+      goto op_column_out;
+    }
+    assert( u.ao.pReg->flags & MEM_Blob );
+    assert( memIsValid(u.ao.pReg) );
+    u.ao.payloadSize = u.ao.pReg->n;
+    u.ao.zRec = u.ao.pReg->z;
+    u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
+    assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
   }else{
     /* Consider the row to be NULL */
-    u.an.payloadSize = 0;
+    u.ao.payloadSize = 0;
   }
 
-  /* If u.an.payloadSize is 0, then just store a NULL.  This can happen because of
+  /* If u.ao.payloadSize is 0, then just store a NULL.  This can happen because of
   ** nullRow or because of a corrupt database. */
-  if( u.an.payloadSize==0 ){
-    MemSetTypeFlag(u.an.pDest, MEM_Null);
+  if( u.ao.payloadSize==0 ){
+    MemSetTypeFlag(u.ao.pDest, MEM_Null);
     goto op_column_out;
   }
   assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
-  if( u.an.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  if( u.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
 
-  u.an.nField = u.an.pC->nField;
-  assert( u.an.p2<u.an.nField );
+  u.ao.nField = u.ao.pC->nField;
+  assert( u.ao.p2<u.ao.nField );
 
   /* Read and parse the table header.  Store the results of the parse
   ** into the record header cache fields of the cursor.
   */
-  u.an.aType = u.an.pC->aType;
-  if( u.an.pC->cacheStatus==p->cacheCtr ){
-    u.an.aOffset = u.an.pC->aOffset;
+  u.ao.aType = u.ao.pC->aType;
+  if( u.ao.pC->cacheStatus==p->cacheCtr ){
+    u.ao.aOffset = u.ao.pC->aOffset;
   }else{
-    assert(u.an.aType);
-    u.an.avail = 0;
-    u.an.pC->aOffset = u.an.aOffset = &u.an.aType[u.an.nField];
-    u.an.pC->payloadSize = u.an.payloadSize;
-    u.an.pC->cacheStatus = p->cacheCtr;
+    assert(u.ao.aType);
+    u.ao.avail = 0;
+    u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField];
+    u.ao.pC->payloadSize = u.ao.payloadSize;
+    u.ao.pC->cacheStatus = p->cacheCtr;
 
     /* Figure out how many bytes are in the header */
-    if( u.an.zRec ){
-      u.an.zData = u.an.zRec;
+    if( u.ao.zRec ){
+      u.ao.zData = u.ao.zRec;
     }else{
-      if( u.an.pC->isIndex ){
-        u.an.zData = (char*)sqlite3BtreeKeyFetch(u.an.pCrsr, &u.an.avail);
+      if( u.ao.pC->isIndex ){
+        u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail);
       }else{
-        u.an.zData = (char*)sqlite3BtreeDataFetch(u.an.pCrsr, &u.an.avail);
+        u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.avail);
       }
       /* If KeyFetch()/DataFetch() managed to get the entire payload,
-      ** save the payload in the u.an.pC->aRow cache.  That will save us from
+      ** save the payload in the u.ao.pC->aRow cache.  That will save us from
       ** having to make additional calls to fetch the content portion of
       ** the record.
       */
-      assert( u.an.avail>=0 );
-      if( u.an.payloadSize <= (u32)u.an.avail ){
-        u.an.zRec = u.an.zData;
-        u.an.pC->aRow = (u8*)u.an.zData;
+      assert( u.ao.avail>=0 );
+      if( u.ao.payloadSize <= (u32)u.ao.avail ){
+        u.ao.zRec = u.ao.zData;
+        u.ao.pC->aRow = (u8*)u.ao.zData;
       }else{
-        u.an.pC->aRow = 0;
+        u.ao.pC->aRow = 0;
       }
     }
     /* The following assert is true in all cases except when
     ** the database file has been corrupted externally.
-    **    assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */
-    u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset);
+    **    assert( u.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */
+    u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset);
 
     /* Make sure a corrupt database has not given us an oversize header.
     ** Do this now to avoid an oversize memory allocation.
@@ -65767,26 +67671,26 @@ case OP_Column: {
     ** 3-byte type for each of the maximum of 32768 columns plus three
     ** extra bytes for the header length itself.  32768*3 + 3 = 98307.
     */
-    if( u.an.offset > 98307 ){
+    if( u.ao.offset > 98307 ){
       rc = SQLITE_CORRUPT_BKPT;
       goto op_column_out;
     }
 
-    /* Compute in u.an.len the number of bytes of data we need to read in order
-    ** to get u.an.nField type values.  u.an.offset is an upper bound on this.  But
-    ** u.an.nField might be significantly less than the true number of columns
-    ** in the table, and in that case, 5*u.an.nField+3 might be smaller than u.an.offset.
-    ** We want to minimize u.an.len in order to limit the size of the memory
-    ** allocation, especially if a corrupt database file has caused u.an.offset
+    /* Compute in u.ao.len the number of bytes of data we need to read in order
+    ** to get u.ao.nField type values.  u.ao.offset is an upper bound on this.  But
+    ** u.ao.nField might be significantly less than the true number of columns
+    ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset.
+    ** We want to minimize u.ao.len in order to limit the size of the memory
+    ** allocation, especially if a corrupt database file has caused u.ao.offset
     ** to be oversized. Offset is limited to 98307 above.  But 98307 might
     ** still exceed Robson memory allocation limits on some configurations.
-    ** On systems that cannot tolerate large memory allocations, u.an.nField*5+3
-    ** will likely be much smaller since u.an.nField will likely be less than
+    ** On systems that cannot tolerate large memory allocations, u.ao.nField*5+3
+    ** will likely be much smaller since u.ao.nField will likely be less than
     ** 20 or so.  This insures that Robson memory allocation limits are
     ** not exceeded even for corrupt database files.
     */
-    u.an.len = u.an.nField*5 + 3;
-    if( u.an.len > (int)u.an.offset ) u.an.len = (int)u.an.offset;
+    u.ao.len = u.ao.nField*5 + 3;
+    if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.offset;
 
     /* The KeyFetch() or DataFetch() above are fast and will get the entire
     ** record header in most cases.  But they will fail to get the complete
@@ -65794,51 +67698,51 @@ case OP_Column: {
     ** in the B-Tree.  When that happens, use sqlite3VdbeMemFromBtree() to
     ** acquire the complete header text.
     */
-    if( !u.an.zRec && u.an.avail<u.an.len ){
-      u.an.sMem.flags = 0;
-      u.an.sMem.db = 0;
-      rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, 0, u.an.len, u.an.pC->isIndex, &u.an.sMem);
+    if( !u.ao.zRec && u.ao.avail<u.ao.len ){
+      u.ao.sMem.flags = 0;
+      u.ao.sMem.db = 0;
+      rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, 0, u.ao.len, u.ao.pC->isIndex, &u.ao.sMem);
       if( rc!=SQLITE_OK ){
         goto op_column_out;
       }
-      u.an.zData = u.an.sMem.z;
+      u.ao.zData = u.ao.sMem.z;
     }
-    u.an.zEndHdr = (u8 *)&u.an.zData[u.an.len];
-    u.an.zIdx = (u8 *)&u.an.zData[u.an.szHdr];
+    u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len];
+    u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.szHdr];
 
-    /* Scan the header and use it to fill in the u.an.aType[] and u.an.aOffset[]
-    ** arrays.  u.an.aType[u.an.i] will contain the type integer for the u.an.i-th
-    ** column and u.an.aOffset[u.an.i] will contain the u.an.offset from the beginning
-    ** of the record to the start of the data for the u.an.i-th column
+    /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[]
+    ** arrays.  u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th
+    ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning
+    ** of the record to the start of the data for the u.ao.i-th column
     */
-    for(u.an.i=0; u.an.i<u.an.nField; u.an.i++){
-      if( u.an.zIdx<u.an.zEndHdr ){
-        u.an.aOffset[u.an.i] = u.an.offset;
-        if( u.an.zIdx[0]<0x80 ){
-          u.an.t = u.an.zIdx[0];
-          u.an.zIdx++;
+    for(u.ao.i=0; u.ao.i<u.ao.nField; u.ao.i++){
+      if( u.ao.zIdx<u.ao.zEndHdr ){
+        u.ao.aOffset[u.ao.i] = u.ao.offset;
+        if( u.ao.zIdx[0]<0x80 ){
+          u.ao.t = u.ao.zIdx[0];
+          u.ao.zIdx++;
         }else{
-          u.an.zIdx += sqlite3GetVarint32(u.an.zIdx, &u.an.t);
+          u.ao.zIdx += sqlite3GetVarint32(u.ao.zIdx, &u.ao.t);
         }
-        u.an.aType[u.an.i] = u.an.t;
-        u.an.szField = sqlite3VdbeSerialTypeLen(u.an.t);
-        u.an.offset += u.an.szField;
-        if( u.an.offset<u.an.szField ){  /* True if u.an.offset overflows */
-          u.an.zIdx = &u.an.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
+        u.ao.aType[u.ao.i] = u.ao.t;
+        u.ao.szField = sqlite3VdbeSerialTypeLen(u.ao.t);
+        u.ao.offset += u.ao.szField;
+        if( u.ao.offset<u.ao.szField ){  /* True if u.ao.offset overflows */
+          u.ao.zIdx = &u.ao.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
           break;
         }
       }else{
-        /* If u.an.i is less that u.an.nField, then there are fewer fields in this
+        /* If u.ao.i is less that u.ao.nField, then there are fewer fields in this
         ** record than SetNumColumns indicated there are columns in the
-        ** table. Set the u.an.offset for any extra columns not present in
+        ** table. Set the u.ao.offset for any extra columns not present in
         ** the record to 0. This tells code below to store the default value
         ** for the column instead of deserializing a value from the record.
         */
-        u.an.aOffset[u.an.i] = 0;
+        u.ao.aOffset[u.ao.i] = 0;
       }
     }
-    sqlite3VdbeMemRelease(&u.an.sMem);
-    u.an.sMem.flags = MEM_Null;
+    sqlite3VdbeMemRelease(&u.ao.sMem);
+    u.ao.sMem.flags = MEM_Null;
 
     /* If we have read more header data than was contained in the header,
     ** or if the end of the last field appears to be past the end of the
@@ -65846,78 +67750,78 @@ case OP_Column: {
     ** of the record (when all fields present), then we must be dealing
     ** with a corrupt database.
     */
-    if( (u.an.zIdx > u.an.zEndHdr) || (u.an.offset > u.an.payloadSize)
-         || (u.an.zIdx==u.an.zEndHdr && u.an.offset!=u.an.payloadSize) ){
+    if( (u.ao.zIdx > u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize)
+         || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.payloadSize) ){
       rc = SQLITE_CORRUPT_BKPT;
       goto op_column_out;
     }
   }
 
-  /* Get the column information. If u.an.aOffset[u.an.p2] is non-zero, then
-  ** deserialize the value from the record. If u.an.aOffset[u.an.p2] is zero,
+  /* Get the column information. If u.ao.aOffset[u.ao.p2] is non-zero, then
+  ** deserialize the value from the record. If u.ao.aOffset[u.ao.p2] is zero,
   ** then there are not enough fields in the record to satisfy the
   ** request.  In this case, set the value NULL or to P4 if P4 is
   ** a pointer to a Mem object.
   */
-  if( u.an.aOffset[u.an.p2] ){
+  if( u.ao.aOffset[u.ao.p2] ){
     assert( rc==SQLITE_OK );
-    if( u.an.zRec ){
+    if( u.ao.zRec ){
       /* This is the common case where the whole row fits on a single page */
-      VdbeMemRelease(u.an.pDest);
-      sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
+      VdbeMemRelease(u.ao.pDest);
+      sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest);
     }else{
       /* This branch happens only when the row overflows onto multiple pages */
-      u.an.t = u.an.aType[u.an.p2];
+      u.ao.t = u.ao.aType[u.ao.p2];
       if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
-       && ((u.an.t>=12 && (u.an.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
+       && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
       ){
         /* Content is irrelevant for the typeof() function and for
         ** the length(X) function if X is a blob.  So we might as well use
         ** bogus content rather than reading content from disk.  NULL works
-        ** for text and blob and whatever is in the u.an.payloadSize64 variable
+        ** for text and blob and whatever is in the u.ao.payloadSize64 variable
         ** will work for everything else. */
-        u.an.zData = u.an.t<12 ? (char*)&u.an.payloadSize64 : 0;
+        u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0;
       }else{
-        u.an.len = sqlite3VdbeSerialTypeLen(u.an.t);
-        sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
-        rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len,  u.an.pC->isIndex,
-                                     &u.an.sMem);
+        u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t);
+        sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest);
+        rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len,  u.ao.pC->isIndex,
+                                     &u.ao.sMem);
         if( rc!=SQLITE_OK ){
           goto op_column_out;
         }
-        u.an.zData = u.an.sMem.z;
+        u.ao.zData = u.ao.sMem.z;
       }
-      sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.t, u.an.pDest);
+      sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest);
     }
-    u.an.pDest->enc = encoding;
+    u.ao.pDest->enc = encoding;
   }else{
     if( pOp->p4type==P4_MEM ){
-      sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
+      sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static);
     }else{
-      MemSetTypeFlag(u.an.pDest, MEM_Null);
+      MemSetTypeFlag(u.ao.pDest, MEM_Null);
     }
   }
 
   /* If we dynamically allocated space to hold the data (in the
   ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
-  ** dynamically allocated space over to the u.an.pDest structure.
+  ** dynamically allocated space over to the u.ao.pDest structure.
   ** This prevents a memory copy.
   */
-  if( u.an.sMem.zMalloc ){
-    assert( u.an.sMem.z==u.an.sMem.zMalloc );
-    assert( !(u.an.pDest->flags & MEM_Dyn) );
-    assert( !(u.an.pDest->flags & (MEM_Blob|MEM_Str)) || u.an.pDest->z==u.an.sMem.z );
-    u.an.pDest->flags &= ~(MEM_Ephem|MEM_Static);
-    u.an.pDest->flags |= MEM_Term;
-    u.an.pDest->z = u.an.sMem.z;
-    u.an.pDest->zMalloc = u.an.sMem.zMalloc;
+  if( u.ao.sMem.zMalloc ){
+    assert( u.ao.sMem.z==u.ao.sMem.zMalloc );
+    assert( !(u.ao.pDest->flags & MEM_Dyn) );
+    assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z );
+    u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static);
+    u.ao.pDest->flags |= MEM_Term;
+    u.ao.pDest->z = u.ao.sMem.z;
+    u.ao.pDest->zMalloc = u.ao.sMem.zMalloc;
   }
 
-  rc = sqlite3VdbeMemMakeWriteable(u.an.pDest);
+  rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest);
 
 op_column_out:
-  UPDATE_MAX_BLOBSIZE(u.an.pDest);
-  REGISTER_TRACE(pOp->p3, u.an.pDest);
+  UPDATE_MAX_BLOBSIZE(u.ao.pDest);
+  REGISTER_TRACE(pOp->p3, u.ao.pDest);
   break;
 }
 
@@ -65930,20 +67834,20 @@ op_column_out:
 ** memory cell in the range.
 */
 case OP_Affinity: {
-#if 0  /* local variables moved into u.ao */
+#if 0  /* local variables moved into u.ap */
   const char *zAffinity;   /* The affinity to be applied */
   char cAff;               /* A single character of affinity */
-#endif /* local variables moved into u.ao */
+#endif /* local variables moved into u.ap */
 
-  u.ao.zAffinity = pOp->p4.z;
-  assert( u.ao.zAffinity!=0 );
-  assert( u.ao.zAffinity[pOp->p2]==0 );
+  u.ap.zAffinity = pOp->p4.z;
+  assert( u.ap.zAffinity!=0 );
+  assert( u.ap.zAffinity[pOp->p2]==0 );
   pIn1 = &aMem[pOp->p1];
-  while( (u.ao.cAff = *(u.ao.zAffinity++))!=0 ){
+  while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
     assert( pIn1 <= &p->aMem[p->nMem] );
     assert( memIsValid(pIn1) );
     ExpandBlob(pIn1);
-    applyAffinity(pIn1, u.ao.cAff, encoding);
+    applyAffinity(pIn1, u.ap.cAff, encoding);
     pIn1++;
   }
   break;
@@ -65965,7 +67869,7 @@ case OP_Affinity: {
 ** If P4 is NULL then all index fields have the affinity NONE.
 */
 case OP_MakeRecord: {
-#if 0  /* local variables moved into u.ap */
+#if 0  /* local variables moved into u.aq */
   u8 *zNewRecord;        /* A buffer to hold the data for the new record */
   Mem *pRec;             /* The new record */
   u64 nData;             /* Number of bytes of data space */
@@ -65981,7 +67885,7 @@ case OP_MakeRecord: {
   int file_format;       /* File format to use for encoding */
   int i;                 /* Space used in zNewRecord[] */
   int len;               /* Length of a field */
-#endif /* local variables moved into u.ap */
+#endif /* local variables moved into u.aq */
 
   /* Assuming the record contains N fields, the record format looks
   ** like this:
@@ -65998,16 +67902,16 @@ case OP_MakeRecord: {
   ** hdr-size field is also a varint which is the offset from the beginning
   ** of the record to data0.
   */
-  u.ap.nData = 0;         /* Number of bytes of data space */
-  u.ap.nHdr = 0;          /* Number of bytes of header space */
-  u.ap.nZero = 0;         /* Number of zero bytes at the end of the record */
-  u.ap.nField = pOp->p1;
-  u.ap.zAffinity = pOp->p4.z;
-  assert( u.ap.nField>0 && pOp->p2>0 && pOp->p2+u.ap.nField<=p->nMem+1 );
-  u.ap.pData0 = &aMem[u.ap.nField];
-  u.ap.nField = pOp->p2;
-  u.ap.pLast = &u.ap.pData0[u.ap.nField-1];
-  u.ap.file_format = p->minWriteFileFormat;
+  u.aq.nData = 0;         /* Number of bytes of data space */
+  u.aq.nHdr = 0;          /* Number of bytes of header space */
+  u.aq.nZero = 0;         /* Number of zero bytes at the end of the record */
+  u.aq.nField = pOp->p1;
+  u.aq.zAffinity = pOp->p4.z;
+  assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
+  u.aq.pData0 = &aMem[u.aq.nField];
+  u.aq.nField = pOp->p2;
+  u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
+  u.aq.file_format = p->minWriteFileFormat;
 
   /* Identify the output register */
   assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
@@ -66017,34 +67921,34 @@ case OP_MakeRecord: {
   /* Loop through the elements that will make up the record to figure
   ** out how much space is required for the new record.
   */
-  for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){
-    assert( memIsValid(u.ap.pRec) );
-    if( u.ap.zAffinity ){
-      applyAffinity(u.ap.pRec, u.ap.zAffinity[u.ap.pRec-u.ap.pData0], encoding);
+  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+    assert( memIsValid(u.aq.pRec) );
+    if( u.aq.zAffinity ){
+      applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding);
     }
-    if( u.ap.pRec->flags&MEM_Zero && u.ap.pRec->n>0 ){
-      sqlite3VdbeMemExpandBlob(u.ap.pRec);
+    if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){
+      sqlite3VdbeMemExpandBlob(u.aq.pRec);
     }
-    u.ap.serial_type = sqlite3VdbeSerialType(u.ap.pRec, u.ap.file_format);
-    u.ap.len = sqlite3VdbeSerialTypeLen(u.ap.serial_type);
-    u.ap.nData += u.ap.len;
-    u.ap.nHdr += sqlite3VarintLen(u.ap.serial_type);
-    if( u.ap.pRec->flags & MEM_Zero ){
+    u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+    u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type);
+    u.aq.nData += u.aq.len;
+    u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type);
+    if( u.aq.pRec->flags & MEM_Zero ){
       /* Only pure zero-filled BLOBs can be input to this Opcode.
       ** We do not allow blobs with a prefix and a zero-filled tail. */
-      u.ap.nZero += u.ap.pRec->u.nZero;
-    }else if( u.ap.len ){
-      u.ap.nZero = 0;
+      u.aq.nZero += u.aq.pRec->u.nZero;
+    }else if( u.aq.len ){
+      u.aq.nZero = 0;
     }
   }
 
   /* Add the initial header varint and total the size */
-  u.ap.nHdr += u.ap.nVarint = sqlite3VarintLen(u.ap.nHdr);
-  if( u.ap.nVarint<sqlite3VarintLen(u.ap.nHdr) ){
-    u.ap.nHdr++;
+  u.aq.nHdr += u.aq.nVarint = sqlite3VarintLen(u.aq.nHdr);
+  if( u.aq.nVarint<sqlite3VarintLen(u.aq.nHdr) ){
+    u.aq.nHdr++;
   }
-  u.ap.nByte = u.ap.nHdr+u.ap.nData-u.ap.nZero;
-  if( u.ap.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  u.aq.nByte = u.aq.nHdr+u.aq.nData-u.aq.nZero;
+  if( u.aq.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
 
@@ -66053,28 +67957,28 @@ case OP_MakeRecord: {
   ** be one of the input registers (because the following call to
   ** sqlite3VdbeMemGrow() could clobber the value before it is used).
   */
-  if( sqlite3VdbeMemGrow(pOut, (int)u.ap.nByte, 0) ){
+  if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){
     goto no_mem;
   }
-  u.ap.zNewRecord = (u8 *)pOut->z;
+  u.aq.zNewRecord = (u8 *)pOut->z;
 
   /* Write the record */
-  u.ap.i = putVarint32(u.ap.zNewRecord, u.ap.nHdr);
-  for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){
-    u.ap.serial_type = sqlite3VdbeSerialType(u.ap.pRec, u.ap.file_format);
-    u.ap.i += putVarint32(&u.ap.zNewRecord[u.ap.i], u.ap.serial_type);      /* serial type */
+  u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr);
+  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+    u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+    u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type);      /* serial type */
   }
-  for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){  /* serial data */
-    u.ap.i += sqlite3VdbeSerialPut(&u.ap.zNewRecord[u.ap.i], (int)(u.ap.nByte-u.ap.i), 
u.ap.pRec,u.ap.file_format);
+  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){  /* serial data */
+    u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), 
u.aq.pRec,u.aq.file_format);
   }
-  assert( u.ap.i==u.ap.nByte );
+  assert( u.aq.i==u.aq.nByte );
 
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  pOut->n = (int)u.ap.nByte;
+  pOut->n = (int)u.aq.nByte;
   pOut->flags = MEM_Blob | MEM_Dyn;
   pOut->xDel = 0;
-  if( u.ap.nZero ){
-    pOut->u.nZero = u.ap.nZero;
+  if( u.aq.nZero ){
+    pOut->u.nZero = u.aq.nZero;
     pOut->flags |= MEM_Zero;
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
@@ -66090,18 +67994,18 @@ case OP_MakeRecord: {
 */
 #ifndef SQLITE_OMIT_BTREECOUNT
 case OP_Count: {         /* out2-prerelease */
-#if 0  /* local variables moved into u.aq */
+#if 0  /* local variables moved into u.ar */
   i64 nEntry;
   BtCursor *pCrsr;
-#endif /* local variables moved into u.aq */
+#endif /* local variables moved into u.ar */
 
-  u.aq.pCrsr = p->apCsr[pOp->p1]->pCursor;
-  if( ALWAYS(u.aq.pCrsr) ){
-    rc = sqlite3BtreeCount(u.aq.pCrsr, &u.aq.nEntry);
+  u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor;
+  if( ALWAYS(u.ar.pCrsr) ){
+    rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry);
   }else{
-    u.aq.nEntry = 0;
+    u.ar.nEntry = 0;
   }
-  pOut->u.i = u.aq.nEntry;
+  pOut->u.i = u.ar.nEntry;
   break;
 }
 #endif
@@ -66113,7 +68017,7 @@ case OP_Count: {         /* out2-prerelease */
 ** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
 */
 case OP_Savepoint: {
-#if 0  /* local variables moved into u.ar */
+#if 0  /* local variables moved into u.as */
   int p1;                         /* Value of P1 operand */
   char *zName;                    /* Name of savepoint */
   int nName;
@@ -66122,20 +68026,20 @@ case OP_Savepoint: {
   Savepoint *pTmp;
   int iSavepoint;
   int ii;
-#endif /* local variables moved into u.ar */
+#endif /* local variables moved into u.as */
 
-  u.ar.p1 = pOp->p1;
-  u.ar.zName = pOp->p4.z;
+  u.as.p1 = pOp->p1;
+  u.as.zName = pOp->p4.z;
 
-  /* Assert that the u.ar.p1 parameter is valid. Also that if there is no open
+  /* Assert that the u.as.p1 parameter is valid. Also that if there is no open
   ** transaction, then there cannot be any savepoints.
   */
   assert( db->pSavepoint==0 || db->autoCommit==0 );
-  assert( u.ar.p1==SAVEPOINT_BEGIN||u.ar.p1==SAVEPOINT_RELEASE||u.ar.p1==SAVEPOINT_ROLLBACK );
+  assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
   assert( db->pSavepoint || db->isTransactionSavepoint==0 );
   assert( checkSavepointCount(db) );
 
-  if( u.ar.p1==SAVEPOINT_BEGIN ){
+  if( u.as.p1==SAVEPOINT_BEGIN ){
     if( db->writeVdbeCnt>0 ){
       /* A new savepoint cannot be created if there are active write
       ** statements (i.e. open read/write incremental blob handles).
@@ -66144,7 +68048,7 @@ case OP_Savepoint: {
         "SQL statements in progress");
       rc = SQLITE_BUSY;
     }else{
-      u.ar.nName = sqlite3Strlen30(u.ar.zName);
+      u.as.nName = sqlite3Strlen30(u.as.zName);
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       /* This call is Ok even if this savepoint is actually a transaction
@@ -66158,10 +68062,10 @@ case OP_Savepoint: {
 #endif
 
       /* Create a new savepoint structure. */
-      u.ar.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.ar.nName+1);
-      if( u.ar.pNew ){
-        u.ar.pNew->zName = (char *)&u.ar.pNew[1];
-        memcpy(u.ar.pNew->zName, u.ar.zName, u.ar.nName+1);
+      u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1);
+      if( u.as.pNew ){
+        u.as.pNew->zName = (char *)&u.as.pNew[1];
+        memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1);
 
         /* If there is no open transaction, then mark this as a special
         ** "transaction savepoint". */
@@ -66173,27 +68077,27 @@ case OP_Savepoint: {
         }
 
         /* Link the new savepoint into the database handle's list. */
-        u.ar.pNew->pNext = db->pSavepoint;
-        db->pSavepoint = u.ar.pNew;
-        u.ar.pNew->nDeferredCons = db->nDeferredCons;
+        u.as.pNew->pNext = db->pSavepoint;
+        db->pSavepoint = u.as.pNew;
+        u.as.pNew->nDeferredCons = db->nDeferredCons;
       }
     }
   }else{
-    u.ar.iSavepoint = 0;
+    u.as.iSavepoint = 0;
 
     /* Find the named savepoint. If there is no such savepoint, then an
     ** an error is returned to the user.  */
     for(
-      u.ar.pSavepoint = db->pSavepoint;
-      u.ar.pSavepoint && sqlite3StrICmp(u.ar.pSavepoint->zName, u.ar.zName);
-      u.ar.pSavepoint = u.ar.pSavepoint->pNext
+      u.as.pSavepoint = db->pSavepoint;
+      u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
+      u.as.pSavepoint = u.as.pSavepoint->pNext
     ){
-      u.ar.iSavepoint++;
+      u.as.iSavepoint++;
     }
-    if( !u.ar.pSavepoint ){
-      sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
+    if( !u.as.pSavepoint ){
+      sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
       rc = SQLITE_ERROR;
-    }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){
+    }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
       /* It is not possible to release (commit) a savepoint if there are
       ** active write statements.
       */
@@ -66207,8 +68111,8 @@ case OP_Savepoint: {
       ** and this is a RELEASE command, then the current transaction
       ** is committed.
       */
-      int isTransaction = u.ar.pSavepoint->pNext==0 && db->isTransactionSavepoint;
-      if( isTransaction && u.ar.p1==SAVEPOINT_RELEASE ){
+      int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
+      if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
         if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
           goto vdbe_return;
         }
@@ -66222,19 +68126,19 @@ case OP_Savepoint: {
         db->isTransactionSavepoint = 0;
         rc = p->rc;
       }else{
-        u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
-        if( u.ar.p1==SAVEPOINT_ROLLBACK ){
-          for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
-            sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT);
+        u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
+        if( u.as.p1==SAVEPOINT_ROLLBACK ){
+          for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
+            sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT);
           }
         }
-        for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
-          rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
+        for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
+          rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
           if( rc!=SQLITE_OK ){
             goto abort_due_to_error;
           }
         }
-        if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+        if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
           sqlite3ExpirePreparedStatements(db);
           sqlite3ResetAllSchemasOfConnection(db);
           db->flags = (db->flags | SQLITE_InternChanges);
@@ -66243,10 +68147,10 @@ case OP_Savepoint: {
 
       /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
       ** savepoints nested inside of the savepoint being operated on. */
-      while( db->pSavepoint!=u.ar.pSavepoint ){
-        u.ar.pTmp = db->pSavepoint;
-        db->pSavepoint = u.ar.pTmp->pNext;
-        sqlite3DbFree(db, u.ar.pTmp);
+      while( db->pSavepoint!=u.as.pSavepoint ){
+        u.as.pTmp = db->pSavepoint;
+        db->pSavepoint = u.as.pTmp->pNext;
+        sqlite3DbFree(db, u.as.pTmp);
         db->nSavepoint--;
       }
 
@@ -66254,19 +68158,19 @@ case OP_Savepoint: {
       ** too. If it is a ROLLBACK TO, then set the number of deferred
       ** constraint violations present in the database to the value stored
       ** when the savepoint was created.  */
-      if( u.ar.p1==SAVEPOINT_RELEASE ){
-        assert( u.ar.pSavepoint==db->pSavepoint );
-        db->pSavepoint = u.ar.pSavepoint->pNext;
-        sqlite3DbFree(db, u.ar.pSavepoint);
+      if( u.as.p1==SAVEPOINT_RELEASE ){
+        assert( u.as.pSavepoint==db->pSavepoint );
+        db->pSavepoint = u.as.pSavepoint->pNext;
+        sqlite3DbFree(db, u.as.pSavepoint);
         if( !isTransaction ){
           db->nSavepoint--;
         }
       }else{
-        db->nDeferredCons = u.ar.pSavepoint->nDeferredCons;
+        db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
       }
 
       if( !isTransaction ){
-        rc = sqlite3VtabSavepoint(db, u.ar.p1, u.ar.iSavepoint);
+        rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
       }
     }
@@ -66285,21 +68189,21 @@ case OP_Savepoint: {
 ** This instruction causes the VM to halt.
 */
 case OP_AutoCommit: {
-#if 0  /* local variables moved into u.as */
+#if 0  /* local variables moved into u.at */
   int desiredAutoCommit;
   int iRollback;
   int turnOnAC;
-#endif /* local variables moved into u.as */
+#endif /* local variables moved into u.at */
 
-  u.as.desiredAutoCommit = pOp->p1;
-  u.as.iRollback = pOp->p2;
-  u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit;
-  assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 );
-  assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 );
+  u.at.desiredAutoCommit = pOp->p1;
+  u.at.iRollback = pOp->p2;
+  u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
+  assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
+  assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 );
   assert( db->activeVdbeCnt>0 );  /* At least this one VM is active */
 
 #if 0
-  if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
+  if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){
     /* If this instruction implements a ROLLBACK and other VMs are
     ** still running, and a transaction is active, return an error indicating
     ** that the other VMs must complete first.
@@ -66309,25 +68213,25 @@ case OP_AutoCommit: {
     rc = SQLITE_BUSY;
   }else
 #endif
-  if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
+  if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){
     /* If this instruction implements a COMMIT and other VMs are writing
     ** return an error indicating that the other VMs must complete first.
     */
     sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
         "SQL statements in progress");
     rc = SQLITE_BUSY;
-  }else if( u.as.desiredAutoCommit!=db->autoCommit ){
-    if( u.as.iRollback ){
-      assert( u.as.desiredAutoCommit==1 );
+  }else if( u.at.desiredAutoCommit!=db->autoCommit ){
+    if( u.at.iRollback ){
+      assert( u.at.desiredAutoCommit==1 );
       sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
       db->autoCommit = 1;
     }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
       goto vdbe_return;
     }else{
-      db->autoCommit = (u8)u.as.desiredAutoCommit;
+      db->autoCommit = (u8)u.at.desiredAutoCommit;
       if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
         p->pc = pc;
-        db->autoCommit = (u8)(1-u.as.desiredAutoCommit);
+        db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
         p->rc = rc = SQLITE_BUSY;
         goto vdbe_return;
       }
@@ -66342,8 +68246,8 @@ case OP_AutoCommit: {
     goto vdbe_return;
   }else{
     sqlite3SetString(&p->zErrMsg, db,
-        (!u.as.desiredAutoCommit)?"cannot start a transaction within a transaction":(
-        (u.as.iRollback)?"cannot rollback - no transaction is active":
+        (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
+        (u.at.iRollback)?"cannot rollback - no transaction is active":
                    "cannot commit - no transaction is active"));
 
     rc = SQLITE_ERROR;
@@ -66383,16 +68287,16 @@ case OP_AutoCommit: {
 ** If P2 is zero, then a read-lock is obtained on the database file.
 */
 case OP_Transaction: {
-#if 0  /* local variables moved into u.at */
+#if 0  /* local variables moved into u.au */
   Btree *pBt;
-#endif /* local variables moved into u.at */
+#endif /* local variables moved into u.au */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.at.pBt = db->aDb[pOp->p1].pBt;
+  u.au.pBt = db->aDb[pOp->p1].pBt;
 
-  if( u.at.pBt ){
-    rc = sqlite3BtreeBeginTrans(u.at.pBt, pOp->p2);
+  if( u.au.pBt ){
+    rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
     if( rc==SQLITE_BUSY ){
       p->pc = pc;
       p->rc = rc = SQLITE_BUSY;
@@ -66405,7 +68309,7 @@ case OP_Transaction: {
     if( pOp->p2 && p->usesStmtJournal
      && (db->autoCommit==0 || db->activeVdbeCnt>1)
     ){
-      assert( sqlite3BtreeIsInTrans(u.at.pBt) );
+      assert( sqlite3BtreeIsInTrans(u.au.pBt) );
       if( p->iStatement==0 ){
         assert( db->nStatement>=0 && db->nSavepoint>=0 );
         db->nStatement++;
@@ -66414,7 +68318,7 @@ case OP_Transaction: {
 
       rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
       if( rc==SQLITE_OK ){
-        rc = sqlite3BtreeBeginStmt(u.at.pBt, p->iStatement);
+        rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
       }
 
       /* Store the current value of the database handles deferred constraint
@@ -66439,21 +68343,21 @@ case OP_Transaction: {
 ** executing this instruction.
 */
 case OP_ReadCookie: {               /* out2-prerelease */
-#if 0  /* local variables moved into u.au */
+#if 0  /* local variables moved into u.av */
   int iMeta;
   int iDb;
   int iCookie;
-#endif /* local variables moved into u.au */
+#endif /* local variables moved into u.av */
 
-  u.au.iDb = pOp->p1;
-  u.au.iCookie = pOp->p3;
+  u.av.iDb = pOp->p1;
+  u.av.iCookie = pOp->p3;
   assert( pOp->p3<SQLITE_N_BTREE_META );
-  assert( u.au.iDb>=0 && u.au.iDb<db->nDb );
-  assert( db->aDb[u.au.iDb].pBt!=0 );
-  assert( (p->btreeMask & (((yDbMask)1)<<u.au.iDb))!=0 );
+  assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
+  assert( db->aDb[u.av.iDb].pBt!=0 );
+  assert( (p->btreeMask & (((yDbMask)1)<<u.av.iDb))!=0 );
 
-  sqlite3BtreeGetMeta(db->aDb[u.au.iDb].pBt, u.au.iCookie, (u32 *)&u.au.iMeta);
-  pOut->u.i = u.au.iMeta;
+  sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
+  pOut->u.i = u.av.iMeta;
   break;
 }
 
@@ -66468,26 +68372,26 @@ case OP_ReadCookie: {               /* out2-prerelease */
 ** A transaction must be started before executing this opcode.
 */
 case OP_SetCookie: {       /* in3 */
-#if 0  /* local variables moved into u.av */
+#if 0  /* local variables moved into u.aw */
   Db *pDb;
-#endif /* local variables moved into u.av */
+#endif /* local variables moved into u.aw */
   assert( pOp->p2<SQLITE_N_BTREE_META );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.av.pDb = &db->aDb[pOp->p1];
-  assert( u.av.pDb->pBt!=0 );
+  u.aw.pDb = &db->aDb[pOp->p1];
+  assert( u.aw.pDb->pBt!=0 );
   assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
   pIn3 = &aMem[pOp->p3];
   sqlite3VdbeMemIntegerify(pIn3);
   /* See note about index shifting on OP_ReadCookie */
-  rc = sqlite3BtreeUpdateMeta(u.av.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+  rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i);
   if( pOp->p2==BTREE_SCHEMA_VERSION ){
     /* When the schema cookie changes, record the new cookie internally */
-    u.av.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+    u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
     db->flags |= SQLITE_InternChanges;
   }else if( pOp->p2==BTREE_FILE_FORMAT ){
     /* Record changes in the file format */
-    u.av.pDb->pSchema->file_format = (u8)pIn3->u.i;
+    u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
   }
   if( pOp->p1==1 ){
     /* Invalidate all prepared statements whenever the TEMP database
@@ -66517,23 +68421,23 @@ case OP_SetCookie: {       /* in3 */
 ** invoked.
 */
 case OP_VerifyCookie: {
-#if 0  /* local variables moved into u.aw */
+#if 0  /* local variables moved into u.ax */
   int iMeta;
   int iGen;
   Btree *pBt;
-#endif /* local variables moved into u.aw */
+#endif /* local variables moved into u.ax */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
   assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
-  u.aw.pBt = db->aDb[pOp->p1].pBt;
-  if( u.aw.pBt ){
-    sqlite3BtreeGetMeta(u.aw.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.aw.iMeta);
-    u.aw.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+  u.ax.pBt = db->aDb[pOp->p1].pBt;
+  if( u.ax.pBt ){
+    sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
+    u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
   }else{
-    u.aw.iGen = u.aw.iMeta = 0;
+    u.ax.iGen = u.ax.iMeta = 0;
   }
-  if( u.aw.iMeta!=pOp->p2 || u.aw.iGen!=pOp->p3 ){
+  if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){
     sqlite3DbFree(db, p->zErrMsg);
     p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
     /* If the schema-cookie from the database file matches the cookie
@@ -66549,7 +68453,7 @@ case OP_VerifyCookie: {
     ** to be invalidated whenever sqlite3_step() is called from within
     ** a v-table method.
     */
-    if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){
+    if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
       sqlite3ResetOneSchema(db, pOp->p1);
     }
 
@@ -66610,7 +68514,7 @@ case OP_VerifyCookie: {
 */
 case OP_OpenRead:
 case OP_OpenWrite: {
-#if 0  /* local variables moved into u.ax */
+#if 0  /* local variables moved into u.ay */
   int nField;
   KeyInfo *pKeyInfo;
   int p2;
@@ -66619,7 +68523,7 @@ case OP_OpenWrite: {
   Btree *pX;
   VdbeCursor *pCur;
   Db *pDb;
-#endif /* local variables moved into u.ax */
+#endif /* local variables moved into u.ay */
 
   assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
   assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
@@ -66629,57 +68533,57 @@ case OP_OpenWrite: {
     break;
   }
 
-  u.ax.nField = 0;
-  u.ax.pKeyInfo = 0;
-  u.ax.p2 = pOp->p2;
-  u.ax.iDb = pOp->p3;
-  assert( u.ax.iDb>=0 && u.ax.iDb<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<u.ax.iDb))!=0 );
-  u.ax.pDb = &db->aDb[u.ax.iDb];
-  u.ax.pX = u.ax.pDb->pBt;
-  assert( u.ax.pX!=0 );
+  u.ay.nField = 0;
+  u.ay.pKeyInfo = 0;
+  u.ay.p2 = pOp->p2;
+  u.ay.iDb = pOp->p3;
+  assert( u.ay.iDb>=0 && u.ay.iDb<db->nDb );
+  assert( (p->btreeMask & (((yDbMask)1)<<u.ay.iDb))!=0 );
+  u.ay.pDb = &db->aDb[u.ay.iDb];
+  u.ay.pX = u.ay.pDb->pBt;
+  assert( u.ay.pX!=0 );
   if( pOp->opcode==OP_OpenWrite ){
-    u.ax.wrFlag = 1;
-    assert( sqlite3SchemaMutexHeld(db, u.ax.iDb, 0) );
-    if( u.ax.pDb->pSchema->file_format < p->minWriteFileFormat ){
-      p->minWriteFileFormat = u.ax.pDb->pSchema->file_format;
+    u.ay.wrFlag = 1;
+    assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) );
+    if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
+      p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
     }
   }else{
-    u.ax.wrFlag = 0;
+    u.ay.wrFlag = 0;
   }
   if( pOp->p5 & OPFLAG_P2ISREG ){
-    assert( u.ax.p2>0 );
-    assert( u.ax.p2<=p->nMem );
-    pIn2 = &aMem[u.ax.p2];
+    assert( u.ay.p2>0 );
+    assert( u.ay.p2<=p->nMem );
+    pIn2 = &aMem[u.ay.p2];
     assert( memIsValid(pIn2) );
     assert( (pIn2->flags & MEM_Int)!=0 );
     sqlite3VdbeMemIntegerify(pIn2);
-    u.ax.p2 = (int)pIn2->u.i;
-    /* The u.ax.p2 value always comes from a prior OP_CreateTable opcode and
-    ** that opcode will always set the u.ax.p2 value to 2 or more or else fail.
+    u.ay.p2 = (int)pIn2->u.i;
+    /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
+    ** that opcode will always set the u.ay.p2 value to 2 or more or else fail.
     ** If there were a failure, the prepared statement would have halted
     ** before reaching this instruction. */
-    if( NEVER(u.ax.p2<2) ) {
+    if( NEVER(u.ay.p2<2) ) {
       rc = SQLITE_CORRUPT_BKPT;
       goto abort_due_to_error;
     }
   }
   if( pOp->p4type==P4_KEYINFO ){
-    u.ax.pKeyInfo = pOp->p4.pKeyInfo;
-    u.ax.pKeyInfo->enc = ENC(p->db);
-    u.ax.nField = u.ax.pKeyInfo->nField+1;
+    u.ay.pKeyInfo = pOp->p4.pKeyInfo;
+    u.ay.pKeyInfo->enc = ENC(p->db);
+    u.ay.nField = u.ay.pKeyInfo->nField+1;
   }else if( pOp->p4type==P4_INT32 ){
-    u.ax.nField = pOp->p4.i;
+    u.ay.nField = pOp->p4.i;
   }
   assert( pOp->p1>=0 );
-  u.ax.pCur = allocateCursor(p, pOp->p1, u.ax.nField, u.ax.iDb, 1);
-  if( u.ax.pCur==0 ) goto no_mem;
-  u.ax.pCur->nullRow = 1;
-  u.ax.pCur->isOrdered = 1;
-  rc = sqlite3BtreeCursor(u.ax.pX, u.ax.p2, u.ax.wrFlag, u.ax.pKeyInfo, u.ax.pCur->pCursor);
-  u.ax.pCur->pKeyInfo = u.ax.pKeyInfo;
+  u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1);
+  if( u.ay.pCur==0 ) goto no_mem;
+  u.ay.pCur->nullRow = 1;
+  u.ay.pCur->isOrdered = 1;
+  rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor);
+  u.ay.pCur->pKeyInfo = u.ay.pKeyInfo;
   assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
-  sqlite3BtreeCursorHints(u.ax.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+  sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
 
   /* Since it performs no memory allocation or IO, the only value that
   ** sqlite3BtreeCursor() may return is SQLITE_OK. */
@@ -66689,8 +68593,8 @@ case OP_OpenWrite: {
   ** SQLite used to check if the root-page flags were sane at this point
   ** and report database corruption if they were not, but this check has
   ** since moved into the btree layer.  */
-  u.ax.pCur->isTable = pOp->p4type!=P4_KEYINFO;
-  u.ax.pCur->isIndex = !u.ax.pCur->isTable;
+  u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
+  u.ay.pCur->isIndex = !u.ay.pCur->isTable;
   break;
 }
 
@@ -66726,9 +68630,9 @@ case OP_OpenWrite: {
 */
 case OP_OpenAutoindex: 
 case OP_OpenEphemeral: {
-#if 0  /* local variables moved into u.ay */
+#if 0  /* local variables moved into u.az */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.ay */
+#endif /* local variables moved into u.az */
   static const int vfsFlags =
       SQLITE_OPEN_READWRITE |
       SQLITE_OPEN_CREATE |
@@ -66737,13 +68641,13 @@ case OP_OpenEphemeral: {
       SQLITE_OPEN_TRANSIENT_DB;
 
   assert( pOp->p1>=0 );
-  u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
-  if( u.ay.pCx==0 ) goto no_mem;
-  u.ay.pCx->nullRow = 1;
-  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ay.pCx->pBt,
+  u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+  if( u.az.pCx==0 ) goto no_mem;
+  u.az.pCx->nullRow = 1;
+  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt,
                         BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
   if( rc==SQLITE_OK ){
-    rc = sqlite3BtreeBeginTrans(u.ay.pCx->pBt, 1);
+    rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
   }
   if( rc==SQLITE_OK ){
     /* If a transient index is required, create it by calling
@@ -66754,55 +68658,52 @@ case OP_OpenEphemeral: {
     if( pOp->p4.pKeyInfo ){
       int pgno;
       assert( pOp->p4type==P4_KEYINFO );
-      rc = sqlite3BtreeCreateTable(u.ay.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+      rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
       if( rc==SQLITE_OK ){
         assert( pgno==MASTER_ROOT+1 );
-        rc = sqlite3BtreeCursor(u.ay.pCx->pBt, pgno, 1,
-                                (KeyInfo*)pOp->p4.z, u.ay.pCx->pCursor);
-        u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
-        u.ay.pCx->pKeyInfo->enc = ENC(p->db);
+        rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1,
+                                (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor);
+        u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+        u.az.pCx->pKeyInfo->enc = ENC(p->db);
       }
-      u.ay.pCx->isTable = 0;
+      u.az.pCx->isTable = 0;
     }else{
-      rc = sqlite3BtreeCursor(u.ay.pCx->pBt, MASTER_ROOT, 1, 0, u.ay.pCx->pCursor);
-      u.ay.pCx->isTable = 1;
+      rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
+      u.az.pCx->isTable = 1;
     }
   }
-  u.ay.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
-  u.ay.pCx->isIndex = !u.ay.pCx->isTable;
+  u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+  u.az.pCx->isIndex = !u.az.pCx->isTable;
   break;
 }
 
-/* Opcode: OpenSorter P1 P2 * P4 *
+/* Opcode: SorterOpen P1 P2 * P4 *
 **
 ** This opcode works like OP_OpenEphemeral except that it opens
 ** a transient index that is specifically designed to sort large
 ** tables using an external merge-sort algorithm.
 */
 case OP_SorterOpen: {
-#if 0  /* local variables moved into u.az */
+#if 0  /* local variables moved into u.ba */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.az */
-#ifndef SQLITE_OMIT_MERGE_SORT
-  u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
-  if( u.az.pCx==0 ) goto no_mem;
-  u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
-  u.az.pCx->pKeyInfo->enc = ENC(p->db);
-  u.az.pCx->isSorter = 1;
-  rc = sqlite3VdbeSorterInit(db, u.az.pCx);
-#else
-  pOp->opcode = OP_OpenEphemeral;
-  pc--;
-#endif
+#endif /* local variables moved into u.ba */
+
+  u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+  if( u.ba.pCx==0 ) goto no_mem;
+  u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+  u.ba.pCx->pKeyInfo->enc = ENC(p->db);
+  u.ba.pCx->isSorter = 1;
+  rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
   break;
 }
 
-/* Opcode: OpenPseudo P1 P2 P3 * *
+/* Opcode: OpenPseudo P1 P2 P3 * P5
 **
 ** Open a new cursor that points to a fake table that contains a single
 ** row of data.  The content of that one row in the content of memory
-** register P2.  In other words, cursor P1 becomes an alias for the 
-** MEM_Blob content contained in register P2.
+** register P2 when P5==0.  In other words, cursor P1 becomes an alias for the 
+** MEM_Blob content contained in register P2.  When P5==1, then the
+** row is represented by P3 consecutive registers beginning with P2.
 **
 ** A pseudo-table created by this opcode is used to hold a single
 ** row output from the sorter so that the row can be decomposed into
@@ -66813,17 +68714,18 @@ case OP_SorterOpen: {
 ** the pseudo-table.
 */
 case OP_OpenPseudo: {
-#if 0  /* local variables moved into u.ba */
+#if 0  /* local variables moved into u.bb */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.ba */
+#endif /* local variables moved into u.bb */
 
   assert( pOp->p1>=0 );
-  u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
-  if( u.ba.pCx==0 ) goto no_mem;
-  u.ba.pCx->nullRow = 1;
-  u.ba.pCx->pseudoTableReg = pOp->p2;
-  u.ba.pCx->isTable = 1;
-  u.ba.pCx->isIndex = 0;
+  u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+  if( u.bb.pCx==0 ) goto no_mem;
+  u.bb.pCx->nullRow = 1;
+  u.bb.pCx->pseudoTableReg = pOp->p2;
+  u.bb.pCx->isTable = 1;
+  u.bb.pCx->isIndex = 0;
+  u.bb.pCx->multiPseudo = pOp->p5;
   break;
 }
 
@@ -66895,35 +68797,35 @@ case OP_SeekLt:         /* jump, in3 */
 case OP_SeekLe:         /* jump, in3 */
 case OP_SeekGe:         /* jump, in3 */
 case OP_SeekGt: {       /* jump, in3 */
-#if 0  /* local variables moved into u.bb */
+#if 0  /* local variables moved into u.bc */
   int res;
   int oc;
   VdbeCursor *pC;
   UnpackedRecord r;
   int nField;
   i64 iKey;      /* The rowid we are to seek to */
-#endif /* local variables moved into u.bb */
+#endif /* local variables moved into u.bc */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p2!=0 );
-  u.bb.pC = p->apCsr[pOp->p1];
-  assert( u.bb.pC!=0 );
-  assert( u.bb.pC->pseudoTableReg==0 );
+  u.bc.pC = p->apCsr[pOp->p1];
+  assert( u.bc.pC!=0 );
+  assert( u.bc.pC->pseudoTableReg==0 );
   assert( OP_SeekLe == OP_SeekLt+1 );
   assert( OP_SeekGe == OP_SeekLt+2 );
   assert( OP_SeekGt == OP_SeekLt+3 );
-  assert( u.bb.pC->isOrdered );
-  if( ALWAYS(u.bb.pC->pCursor!=0) ){
-    u.bb.oc = pOp->opcode;
-    u.bb.pC->nullRow = 0;
-    if( u.bb.pC->isTable ){
+  assert( u.bc.pC->isOrdered );
+  if( ALWAYS(u.bc.pC->pCursor!=0) ){
+    u.bc.oc = pOp->opcode;
+    u.bc.pC->nullRow = 0;
+    if( u.bc.pC->isTable ){
       /* The input value in P3 might be of any type: integer, real, string,
       ** blob, or NULL.  But it needs to be an integer before we can do
       ** the seek, so covert it. */
       pIn3 = &aMem[pOp->p3];
       applyNumericAffinity(pIn3);
-      u.bb.iKey = sqlite3VdbeIntValue(pIn3);
-      u.bb.pC->rowidIsValid = 0;
+      u.bc.iKey = sqlite3VdbeIntValue(pIn3);
+      u.bc.pC->rowidIsValid = 0;
 
       /* If the P3 value could not be converted into an integer without
       ** loss of information, then special processing is required... */
@@ -66938,101 +68840,101 @@ case OP_SeekGt: {       /* jump, in3 */
         ** point number. */
         assert( (pIn3->flags & MEM_Real)!=0 );
 
-        if( u.bb.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bb.iKey || pIn3->r>0) ){
+        if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
           /* The P3 value is too large in magnitude to be expressed as an
           ** integer. */
-          u.bb.res = 1;
+          u.bc.res = 1;
           if( pIn3->r<0 ){
-            if( u.bb.oc>=OP_SeekGe ){  assert( u.bb.oc==OP_SeekGe || u.bb.oc==OP_SeekGt );
-              rc = sqlite3BtreeFirst(u.bb.pC->pCursor, &u.bb.res);
+            if( u.bc.oc>=OP_SeekGe ){  assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+              rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
               if( rc!=SQLITE_OK ) goto abort_due_to_error;
             }
           }else{
-            if( u.bb.oc<=OP_SeekLe ){  assert( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekLe );
-              rc = sqlite3BtreeLast(u.bb.pC->pCursor, &u.bb.res);
+            if( u.bc.oc<=OP_SeekLe ){  assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+              rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
               if( rc!=SQLITE_OK ) goto abort_due_to_error;
             }
           }
-          if( u.bb.res ){
+          if( u.bc.res ){
             pc = pOp->p2 - 1;
           }
           break;
-        }else if( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekGe ){
+        }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
           /* Use the ceiling() function to convert real->int */
-          if( pIn3->r > (double)u.bb.iKey ) u.bb.iKey++;
+          if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
         }else{
           /* Use the floor() function to convert real->int */
-          assert( u.bb.oc==OP_SeekLe || u.bb.oc==OP_SeekGt );
-          if( pIn3->r < (double)u.bb.iKey ) u.bb.iKey--;
+          assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
+          if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
         }
       }
-      rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, 0, (u64)u.bb.iKey, 0, &u.bb.res);
+      rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      if( u.bb.res==0 ){
-        u.bb.pC->rowidIsValid = 1;
-        u.bb.pC->lastRowid = u.bb.iKey;
+      if( u.bc.res==0 ){
+        u.bc.pC->rowidIsValid = 1;
+        u.bc.pC->lastRowid = u.bc.iKey;
       }
     }else{
-      u.bb.nField = pOp->p4.i;
+      u.bc.nField = pOp->p4.i;
       assert( pOp->p4type==P4_INT32 );
-      assert( u.bb.nField>0 );
-      u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
-      u.bb.r.nField = (u16)u.bb.nField;
+      assert( u.bc.nField>0 );
+      u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
+      u.bc.r.nField = (u16)u.bc.nField;
 
       /* The next line of code computes as follows, only faster:
-      **   if( u.bb.oc==OP_SeekGt || u.bb.oc==OP_SeekLe ){
-      **     u.bb.r.flags = UNPACKED_INCRKEY;
+      **   if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
+      **     u.bc.r.flags = UNPACKED_INCRKEY;
       **   }else{
-      **     u.bb.r.flags = 0;
+      **     u.bc.r.flags = 0;
       **   }
       */
-      u.bb.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bb.oc - OP_SeekLt)));
-      assert( u.bb.oc!=OP_SeekGt || u.bb.r.flags==UNPACKED_INCRKEY );
-      assert( u.bb.oc!=OP_SeekLe || u.bb.r.flags==UNPACKED_INCRKEY );
-      assert( u.bb.oc!=OP_SeekGe || u.bb.r.flags==0 );
-      assert( u.bb.oc!=OP_SeekLt || u.bb.r.flags==0 );
+      u.bc.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt)));
+      assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY );
+      assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY );
+      assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 );
+      assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 );
 
-      u.bb.r.aMem = &aMem[pOp->p3];
+      u.bc.r.aMem = &aMem[pOp->p3];
 #ifdef SQLITE_DEBUG
-      { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); }
+      { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
 #endif
-      ExpandBlob(u.bb.r.aMem);
-      rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, &u.bb.r, 0, 0, &u.bb.res);
+      ExpandBlob(u.bc.r.aMem);
+      rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      u.bb.pC->rowidIsValid = 0;
+      u.bc.pC->rowidIsValid = 0;
     }
-    u.bb.pC->deferredMoveto = 0;
-    u.bb.pC->cacheStatus = CACHE_STALE;
+    u.bc.pC->deferredMoveto = 0;
+    u.bc.pC->cacheStatus = CACHE_STALE;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
-    if( u.bb.oc>=OP_SeekGe ){  assert( u.bb.oc==OP_SeekGe || u.bb.oc==OP_SeekGt );
-      if( u.bb.res<0 || (u.bb.res==0 && u.bb.oc==OP_SeekGt) ){
-        rc = sqlite3BtreeNext(u.bb.pC->pCursor, &u.bb.res);
+    if( u.bc.oc>=OP_SeekGe ){  assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+      if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){
+        rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
-        u.bb.pC->rowidIsValid = 0;
+        u.bc.pC->rowidIsValid = 0;
       }else{
-        u.bb.res = 0;
+        u.bc.res = 0;
       }
     }else{
-      assert( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekLe );
-      if( u.bb.res>0 || (u.bb.res==0 && u.bb.oc==OP_SeekLt) ){
-        rc = sqlite3BtreePrevious(u.bb.pC->pCursor, &u.bb.res);
+      assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+      if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){
+        rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
-        u.bb.pC->rowidIsValid = 0;
+        u.bc.pC->rowidIsValid = 0;
       }else{
-        /* u.bb.res might be negative because the table is empty.  Check to
+        /* u.bc.res might be negative because the table is empty.  Check to
         ** see if this is the case.
         */
-        u.bb.res = sqlite3BtreeEof(u.bb.pC->pCursor);
+        u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
       }
     }
     assert( pOp->p2>0 );
-    if( u.bb.res ){
+    if( u.bc.res ){
       pc = pOp->p2 - 1;
     }
   }else{
@@ -67055,20 +68957,20 @@ case OP_SeekGt: {       /* jump, in3 */
 ** occur, no unnecessary I/O happens.
 */
 case OP_Seek: {    /* in2 */
-#if 0  /* local variables moved into u.bc */
+#if 0  /* local variables moved into u.bd */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bc */
+#endif /* local variables moved into u.bd */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bc.pC = p->apCsr[pOp->p1];
-  assert( u.bc.pC!=0 );
-  if( ALWAYS(u.bc.pC->pCursor!=0) ){
-    assert( u.bc.pC->isTable );
-    u.bc.pC->nullRow = 0;
+  u.bd.pC = p->apCsr[pOp->p1];
+  assert( u.bd.pC!=0 );
+  if( ALWAYS(u.bd.pC->pCursor!=0) ){
+    assert( u.bd.pC->isTable );
+    u.bd.pC->nullRow = 0;
     pIn2 = &aMem[pOp->p2];
-    u.bc.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
-    u.bc.pC->rowidIsValid = 0;
-    u.bc.pC->deferredMoveto = 1;
+    u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+    u.bd.pC->rowidIsValid = 0;
+    u.bd.pC->deferredMoveto = 1;
   }
   break;
 }
@@ -67100,7 +69002,7 @@ case OP_Seek: {    /* in2 */
 */
 case OP_NotFound:       /* jump, in3 */
 case OP_Found: {        /* jump, in3 */
-#if 0  /* local variables moved into u.bd */
+#if 0  /* local variables moved into u.be */
   int alreadyExists;
   VdbeCursor *pC;
   int res;
@@ -67108,55 +69010,55 @@ case OP_Found: {        /* jump, in3 */
   UnpackedRecord *pIdxKey;
   UnpackedRecord r;
   char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-#endif /* local variables moved into u.bd */
+#endif /* local variables moved into u.be */
 
 #ifdef SQLITE_TEST
   sqlite3_found_count++;
 #endif
 
-  u.bd.alreadyExists = 0;
+  u.be.alreadyExists = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p4type==P4_INT32 );
-  u.bd.pC = p->apCsr[pOp->p1];
-  assert( u.bd.pC!=0 );
+  u.be.pC = p->apCsr[pOp->p1];
+  assert( u.be.pC!=0 );
   pIn3 = &aMem[pOp->p3];
-  if( ALWAYS(u.bd.pC->pCursor!=0) ){
+  if( ALWAYS(u.be.pC->pCursor!=0) ){
 
-    assert( u.bd.pC->isTable==0 );
+    assert( u.be.pC->isTable==0 );
     if( pOp->p4.i>0 ){
-      u.bd.r.pKeyInfo = u.bd.pC->pKeyInfo;
-      u.bd.r.nField = (u16)pOp->p4.i;
-      u.bd.r.aMem = pIn3;
+      u.be.r.pKeyInfo = u.be.pC->pKeyInfo;
+      u.be.r.nField = (u16)pOp->p4.i;
+      u.be.r.aMem = pIn3;
 #ifdef SQLITE_DEBUG
-      { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
+      { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
 #endif
-      u.bd.r.flags = UNPACKED_PREFIX_MATCH;
-      u.bd.pIdxKey = &u.bd.r;
+      u.be.r.flags = UNPACKED_PREFIX_MATCH;
+      u.be.pIdxKey = &u.be.r;
     }else{
-      u.bd.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
-          u.bd.pC->pKeyInfo, u.bd.aTempRec, sizeof(u.bd.aTempRec), &u.bd.pFree
+      u.be.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+          u.be.pC->pKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree
       );
-      if( u.bd.pIdxKey==0 ) goto no_mem;
+      if( u.be.pIdxKey==0 ) goto no_mem;
       assert( pIn3->flags & MEM_Blob );
       assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
-      sqlite3VdbeRecordUnpack(u.bd.pC->pKeyInfo, pIn3->n, pIn3->z, u.bd.pIdxKey);
-      u.bd.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+      sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey);
+      u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
     }
-    rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, u.bd.pIdxKey, 0, 0, &u.bd.res);
+    rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
     if( pOp->p4.i==0 ){
-      sqlite3DbFree(db, u.bd.pFree);
+      sqlite3DbFree(db, u.be.pFree);
     }
     if( rc!=SQLITE_OK ){
       break;
     }
-    u.bd.alreadyExists = (u.bd.res==0);
-    u.bd.pC->deferredMoveto = 0;
-    u.bd.pC->cacheStatus = CACHE_STALE;
+    u.be.alreadyExists = (u.be.res==0);
+    u.be.pC->deferredMoveto = 0;
+    u.be.pC->cacheStatus = CACHE_STALE;
   }
   if( pOp->opcode==OP_Found ){
-    if( u.bd.alreadyExists ) pc = pOp->p2 - 1;
+    if( u.be.alreadyExists ) pc = pOp->p2 - 1;
   }else{
-    if( !u.bd.alreadyExists ) pc = pOp->p2 - 1;
+    if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
   }
   break;
 }
@@ -67188,7 +69090,7 @@ case OP_Found: {        /* jump, in3 */
 ** See also: NotFound, NotExists, Found
 */
 case OP_IsUnique: {        /* jump, in3 */
-#if 0  /* local variables moved into u.be */
+#if 0  /* local variables moved into u.bf */
   u16 ii;
   VdbeCursor *pCx;
   BtCursor *pCrsr;
@@ -67196,55 +69098,55 @@ case OP_IsUnique: {        /* jump, in3 */
   Mem *aMx;
   UnpackedRecord r;                  /* B-Tree index search key */
   i64 R;                             /* Rowid stored in register P3 */
-#endif /* local variables moved into u.be */
+#endif /* local variables moved into u.bf */
 
   pIn3 = &aMem[pOp->p3];
-  u.be.aMx = &aMem[pOp->p4.i];
+  u.bf.aMx = &aMem[pOp->p4.i];
   /* Assert that the values of parameters P1 and P4 are in range. */
   assert( pOp->p4type==P4_INT32 );
   assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
 
   /* Find the index cursor. */
-  u.be.pCx = p->apCsr[pOp->p1];
-  assert( u.be.pCx->deferredMoveto==0 );
-  u.be.pCx->seekResult = 0;
-  u.be.pCx->cacheStatus = CACHE_STALE;
-  u.be.pCrsr = u.be.pCx->pCursor;
+  u.bf.pCx = p->apCsr[pOp->p1];
+  assert( u.bf.pCx->deferredMoveto==0 );
+  u.bf.pCx->seekResult = 0;
+  u.bf.pCx->cacheStatus = CACHE_STALE;
+  u.bf.pCrsr = u.bf.pCx->pCursor;
 
   /* If any of the values are NULL, take the jump. */
-  u.be.nField = u.be.pCx->pKeyInfo->nField;
-  for(u.be.ii=0; u.be.ii<u.be.nField; u.be.ii++){
-    if( u.be.aMx[u.be.ii].flags & MEM_Null ){
+  u.bf.nField = u.bf.pCx->pKeyInfo->nField;
+  for(u.bf.ii=0; u.bf.ii<u.bf.nField; u.bf.ii++){
+    if( u.bf.aMx[u.bf.ii].flags & MEM_Null ){
       pc = pOp->p2 - 1;
-      u.be.pCrsr = 0;
+      u.bf.pCrsr = 0;
       break;
     }
   }
-  assert( (u.be.aMx[u.be.nField].flags & MEM_Null)==0 );
+  assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 );
 
-  if( u.be.pCrsr!=0 ){
+  if( u.bf.pCrsr!=0 ){
     /* Populate the index search key. */
-    u.be.r.pKeyInfo = u.be.pCx->pKeyInfo;
-    u.be.r.nField = u.be.nField + 1;
-    u.be.r.flags = UNPACKED_PREFIX_SEARCH;
-    u.be.r.aMem = u.be.aMx;
+    u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo;
+    u.bf.r.nField = u.bf.nField + 1;
+    u.bf.r.flags = UNPACKED_PREFIX_SEARCH;
+    u.bf.r.aMem = u.bf.aMx;
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
+    { int i; for(i=0; i<u.bf.r.nField; i++) assert( memIsValid(&u.bf.r.aMem[i]) ); }
 #endif
 
-    /* Extract the value of u.be.R from register P3. */
+    /* Extract the value of u.bf.R from register P3. */
     sqlite3VdbeMemIntegerify(pIn3);
-    u.be.R = pIn3->u.i;
+    u.bf.R = pIn3->u.i;
 
     /* Search the B-Tree index. If no conflicting record is found, jump
     ** to P2. Otherwise, copy the rowid of the conflicting record to
     ** register P3 and fall through to the next instruction.  */
-    rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, &u.be.r, 0, 0, &u.be.pCx->seekResult);
-    if( (u.be.r.flags & UNPACKED_PREFIX_SEARCH) || u.be.r.rowid==u.be.R ){
+    rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult);
+    if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){
       pc = pOp->p2 - 1;
     }else{
-      pIn3->u.i = u.be.r.rowid;
+      pIn3->u.i = u.bf.r.rowid;
     }
   }
   break;
@@ -67265,42 +69167,42 @@ case OP_IsUnique: {        /* jump, in3 */
 ** See also: Found, NotFound, IsUnique
 */
 case OP_NotExists: {        /* jump, in3 */
-#if 0  /* local variables moved into u.bf */
+#if 0  /* local variables moved into u.bg */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
   u64 iKey;
-#endif /* local variables moved into u.bf */
+#endif /* local variables moved into u.bg */
 
   pIn3 = &aMem[pOp->p3];
   assert( pIn3->flags & MEM_Int );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bf.pC = p->apCsr[pOp->p1];
-  assert( u.bf.pC!=0 );
-  assert( u.bf.pC->isTable );
-  assert( u.bf.pC->pseudoTableReg==0 );
-  u.bf.pCrsr = u.bf.pC->pCursor;
-  if( ALWAYS(u.bf.pCrsr!=0) ){
-    u.bf.res = 0;
-    u.bf.iKey = pIn3->u.i;
-    rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, 0, u.bf.iKey, 0, &u.bf.res);
-    u.bf.pC->lastRowid = pIn3->u.i;
-    u.bf.pC->rowidIsValid = u.bf.res==0 ?1:0;
-    u.bf.pC->nullRow = 0;
-    u.bf.pC->cacheStatus = CACHE_STALE;
-    u.bf.pC->deferredMoveto = 0;
-    if( u.bf.res!=0 ){
+  u.bg.pC = p->apCsr[pOp->p1];
+  assert( u.bg.pC!=0 );
+  assert( u.bg.pC->isTable );
+  assert( u.bg.pC->pseudoTableReg==0 );
+  u.bg.pCrsr = u.bg.pC->pCursor;
+  if( ALWAYS(u.bg.pCrsr!=0) ){
+    u.bg.res = 0;
+    u.bg.iKey = pIn3->u.i;
+    rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
+    u.bg.pC->lastRowid = pIn3->u.i;
+    u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
+    u.bg.pC->nullRow = 0;
+    u.bg.pC->cacheStatus = CACHE_STALE;
+    u.bg.pC->deferredMoveto = 0;
+    if( u.bg.res!=0 ){
       pc = pOp->p2 - 1;
-      assert( u.bf.pC->rowidIsValid==0 );
+      assert( u.bg.pC->rowidIsValid==0 );
     }
-    u.bf.pC->seekResult = u.bf.res;
+    u.bg.pC->seekResult = u.bg.res;
   }else{
     /* This happens when an attempt to open a read cursor on the
     ** sqlite_master table returns SQLITE_EMPTY.
     */
     pc = pOp->p2 - 1;
-    assert( u.bf.pC->rowidIsValid==0 );
-    u.bf.pC->seekResult = 0;
+    assert( u.bg.pC->rowidIsValid==0 );
+    u.bg.pC->seekResult = 0;
   }
   break;
 }
@@ -67335,21 +69237,21 @@ case OP_Sequence: {           /* out2-prerelease */
 ** AUTOINCREMENT feature.
 */
 case OP_NewRowid: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.bg */
+#if 0  /* local variables moved into u.bh */
   i64 v;                 /* The new rowid */
   VdbeCursor *pC;        /* Cursor of table to get the new rowid */
   int res;               /* Result of an sqlite3BtreeLast() */
   int cnt;               /* Counter to limit the number of searches */
   Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
   VdbeFrame *pFrame;     /* Root frame of VDBE */
-#endif /* local variables moved into u.bg */
+#endif /* local variables moved into u.bh */
 
-  u.bg.v = 0;
-  u.bg.res = 0;
+  u.bh.v = 0;
+  u.bh.res = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bg.pC = p->apCsr[pOp->p1];
-  assert( u.bg.pC!=0 );
-  if( NEVER(u.bg.pC->pCursor==0) ){
+  u.bh.pC = p->apCsr[pOp->p1];
+  assert( u.bh.pC!=0 );
+  if( NEVER(u.bh.pC->pCursor==0) ){
     /* The zero initialization above is all that is needed */
   }else{
     /* The next rowid or record number (different terms for the same
@@ -67365,7 +69267,7 @@ case OP_NewRowid: {           /* out2-prerelease */
     ** succeeded.  If the random rowid does exist, we select a new one
     ** and try again, up to 100 times.
     */
-    assert( u.bg.pC->isTable );
+    assert( u.bh.pC->isTable );
 
 #ifdef SQLITE_32BIT_ROWID
 #   define MAX_ROWID 0x7fffffff
@@ -67377,23 +69279,23 @@ case OP_NewRowid: {           /* out2-prerelease */
 #   define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
 #endif
 
-    if( !u.bg.pC->useRandomRowid ){
-      u.bg.v = sqlite3BtreeGetCachedRowid(u.bg.pC->pCursor);
-      if( u.bg.v==0 ){
-        rc = sqlite3BtreeLast(u.bg.pC->pCursor, &u.bg.res);
+    if( !u.bh.pC->useRandomRowid ){
+      u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor);
+      if( u.bh.v==0 ){
+        rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res);
         if( rc!=SQLITE_OK ){
           goto abort_due_to_error;
         }
-        if( u.bg.res ){
-          u.bg.v = 1;   /* IMP: R-61914-48074 */
+        if( u.bh.res ){
+          u.bh.v = 1;   /* IMP: R-61914-48074 */
         }else{
-          assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) );
-          rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v);
+          assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) );
+          rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
           assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
-          if( u.bg.v>=MAX_ROWID ){
-            u.bg.pC->useRandomRowid = 1;
+          if( u.bh.v>=MAX_ROWID ){
+            u.bh.pC->useRandomRowid = 1;
           }else{
-            u.bg.v++;   /* IMP: R-29538-34987 */
+            u.bh.v++;   /* IMP: R-29538-34987 */
           }
         }
       }
@@ -67403,35 +69305,35 @@ case OP_NewRowid: {           /* out2-prerelease */
         /* Assert that P3 is a valid memory cell. */
         assert( pOp->p3>0 );
         if( p->pFrame ){
-          for(u.bg.pFrame=p->pFrame; u.bg.pFrame->pParent; u.bg.pFrame=u.bg.pFrame->pParent);
+          for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
           /* Assert that P3 is a valid memory cell. */
-          assert( pOp->p3<=u.bg.pFrame->nMem );
-          u.bg.pMem = &u.bg.pFrame->aMem[pOp->p3];
+          assert( pOp->p3<=u.bh.pFrame->nMem );
+          u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
         }else{
           /* Assert that P3 is a valid memory cell. */
           assert( pOp->p3<=p->nMem );
-          u.bg.pMem = &aMem[pOp->p3];
-          memAboutToChange(p, u.bg.pMem);
+          u.bh.pMem = &aMem[pOp->p3];
+          memAboutToChange(p, u.bh.pMem);
         }
-        assert( memIsValid(u.bg.pMem) );
+        assert( memIsValid(u.bh.pMem) );
 
-        REGISTER_TRACE(pOp->p3, u.bg.pMem);
-        sqlite3VdbeMemIntegerify(u.bg.pMem);
-        assert( (u.bg.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
-        if( u.bg.pMem->u.i==MAX_ROWID || u.bg.pC->useRandomRowid ){
+        REGISTER_TRACE(pOp->p3, u.bh.pMem);
+        sqlite3VdbeMemIntegerify(u.bh.pMem);
+        assert( (u.bh.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
+        if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){
           rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
           goto abort_due_to_error;
         }
-        if( u.bg.v<u.bg.pMem->u.i+1 ){
-          u.bg.v = u.bg.pMem->u.i + 1;
+        if( u.bh.v<u.bh.pMem->u.i+1 ){
+          u.bh.v = u.bh.pMem->u.i + 1;
         }
-        u.bg.pMem->u.i = u.bg.v;
+        u.bh.pMem->u.i = u.bh.v;
       }
 #endif
 
-      sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, u.bg.v<MAX_ROWID ? u.bg.v+1 : 0);
+      sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.v<MAX_ROWID ? u.bh.v+1 : 0);
     }
-    if( u.bg.pC->useRandomRowid ){
+    if( u.bh.pC->useRandomRowid ){
       /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
       ** largest possible integer (9223372036854775807) then the database
       ** engine starts picking positive candidate ROWIDs at random until
@@ -67439,35 +69341,35 @@ case OP_NewRowid: {           /* out2-prerelease */
       assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                              ** an AUTOINCREMENT table. */
       /* on the first attempt, simply do one more than previous */
-      u.bg.v = lastRowid;
-      u.bg.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
-      u.bg.v++; /* ensure non-zero */
-      u.bg.cnt = 0;
-      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bg.pC->pCursor, 0, (u64)u.bg.v,
-                                                 0, &u.bg.res))==SQLITE_OK)
-            && (u.bg.res==0)
-            && (++u.bg.cnt<100)){
+      u.bh.v = lastRowid;
+      u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+      u.bh.v++; /* ensure non-zero */
+      u.bh.cnt = 0;
+      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v,
+                                                 0, &u.bh.res))==SQLITE_OK)
+            && (u.bh.res==0)
+            && (++u.bh.cnt<100)){
         /* collision - try another random rowid */
-        sqlite3_randomness(sizeof(u.bg.v), &u.bg.v);
-        if( u.bg.cnt<5 ){
+        sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
+        if( u.bh.cnt<5 ){
           /* try "small" random rowids for the initial attempts */
-          u.bg.v &= 0xffffff;
+          u.bh.v &= 0xffffff;
         }else{
-          u.bg.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+          u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
         }
-        u.bg.v++; /* ensure non-zero */
+        u.bh.v++; /* ensure non-zero */
       }
-      if( rc==SQLITE_OK && u.bg.res==0 ){
+      if( rc==SQLITE_OK && u.bh.res==0 ){
         rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
         goto abort_due_to_error;
       }
-      assert( u.bg.v>0 );  /* EV: R-40812-03570 */
+      assert( u.bh.v>0 );  /* EV: R-40812-03570 */
     }
-    u.bg.pC->rowidIsValid = 0;
-    u.bg.pC->deferredMoveto = 0;
-    u.bg.pC->cacheStatus = CACHE_STALE;
+    u.bh.pC->rowidIsValid = 0;
+    u.bh.pC->deferredMoveto = 0;
+    u.bh.pC->cacheStatus = CACHE_STALE;
   }
-  pOut->u.i = u.bg.v;
+  pOut->u.i = u.bh.v;
   break;
 }
 
@@ -67517,7 +69419,7 @@ case OP_NewRowid: {           /* out2-prerelease */
 */
 case OP_Insert: 
 case OP_InsertInt: {
-#if 0  /* local variables moved into u.bh */
+#if 0  /* local variables moved into u.bi */
   Mem *pData;       /* MEM cell holding data for the record to be inserted */
   Mem *pKey;        /* MEM cell holding key  for the record */
   i64 iKey;         /* The integer ROWID or key for the record to be inserted */
@@ -67527,60 +69429,60 @@ case OP_InsertInt: {
   const char *zDb;  /* database name - used by the update hook */
   const char *zTbl; /* Table name - used by the opdate hook */
   int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-#endif /* local variables moved into u.bh */
+#endif /* local variables moved into u.bi */
 
-  u.bh.pData = &aMem[pOp->p2];
+  u.bi.pData = &aMem[pOp->p2];
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  assert( memIsValid(u.bh.pData) );
-  u.bh.pC = p->apCsr[pOp->p1];
-  assert( u.bh.pC!=0 );
-  assert( u.bh.pC->pCursor!=0 );
-  assert( u.bh.pC->pseudoTableReg==0 );
-  assert( u.bh.pC->isTable );
-  REGISTER_TRACE(pOp->p2, u.bh.pData);
+  assert( memIsValid(u.bi.pData) );
+  u.bi.pC = p->apCsr[pOp->p1];
+  assert( u.bi.pC!=0 );
+  assert( u.bi.pC->pCursor!=0 );
+  assert( u.bi.pC->pseudoTableReg==0 );
+  assert( u.bi.pC->isTable );
+  REGISTER_TRACE(pOp->p2, u.bi.pData);
 
   if( pOp->opcode==OP_Insert ){
-    u.bh.pKey = &aMem[pOp->p3];
-    assert( u.bh.pKey->flags & MEM_Int );
-    assert( memIsValid(u.bh.pKey) );
-    REGISTER_TRACE(pOp->p3, u.bh.pKey);
-    u.bh.iKey = u.bh.pKey->u.i;
+    u.bi.pKey = &aMem[pOp->p3];
+    assert( u.bi.pKey->flags & MEM_Int );
+    assert( memIsValid(u.bi.pKey) );
+    REGISTER_TRACE(pOp->p3, u.bi.pKey);
+    u.bi.iKey = u.bi.pKey->u.i;
   }else{
     assert( pOp->opcode==OP_InsertInt );
-    u.bh.iKey = pOp->p3;
+    u.bi.iKey = pOp->p3;
   }
 
   if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
-  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bh.iKey;
-  if( u.bh.pData->flags & MEM_Null ){
-    u.bh.pData->z = 0;
-    u.bh.pData->n = 0;
+  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey;
+  if( u.bi.pData->flags & MEM_Null ){
+    u.bi.pData->z = 0;
+    u.bi.pData->n = 0;
   }else{
-    assert( u.bh.pData->flags & (MEM_Blob|MEM_Str) );
+    assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
   }
-  u.bh.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bh.pC->seekResult : 0);
-  if( u.bh.pData->flags & MEM_Zero ){
-    u.bh.nZero = u.bh.pData->u.nZero;
+  u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0);
+  if( u.bi.pData->flags & MEM_Zero ){
+    u.bi.nZero = u.bi.pData->u.nZero;
   }else{
-    u.bh.nZero = 0;
+    u.bi.nZero = 0;
   }
-  sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
-  rc = sqlite3BtreeInsert(u.bh.pC->pCursor, 0, u.bh.iKey,
-                          u.bh.pData->z, u.bh.pData->n, u.bh.nZero,
-                          pOp->p5 & OPFLAG_APPEND, u.bh.seekResult
+  sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
+  rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
+                          u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
+                          pOp->p5 & OPFLAG_APPEND, u.bi.seekResult
   );
-  u.bh.pC->rowidIsValid = 0;
-  u.bh.pC->deferredMoveto = 0;
-  u.bh.pC->cacheStatus = CACHE_STALE;
+  u.bi.pC->rowidIsValid = 0;
+  u.bi.pC->deferredMoveto = 0;
+  u.bi.pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    u.bh.zDb = db->aDb[u.bh.pC->iDb].zName;
-    u.bh.zTbl = pOp->p4.z;
-    u.bh.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
-    assert( u.bh.pC->isTable );
-    db->xUpdateCallback(db->pUpdateArg, u.bh.op, u.bh.zDb, u.bh.zTbl, u.bh.iKey);
-    assert( u.bh.pC->iDb>=0 );
+    u.bi.zDb = db->aDb[u.bi.pC->iDb].zName;
+    u.bi.zTbl = pOp->p4.z;
+    u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+    assert( u.bi.pC->isTable );
+    db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey);
+    assert( u.bi.pC->iDb>=0 );
   }
   break;
 }
@@ -67606,47 +69508,47 @@ case OP_InsertInt: {
 ** using OP_NotFound prior to invoking this opcode.
 */
 case OP_Delete: {
-#if 0  /* local variables moved into u.bi */
+#if 0  /* local variables moved into u.bj */
   i64 iKey;
   VdbeCursor *pC;
-#endif /* local variables moved into u.bi */
+#endif /* local variables moved into u.bj */
 
-  u.bi.iKey = 0;
+  u.bj.iKey = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bi.pC = p->apCsr[pOp->p1];
-  assert( u.bi.pC!=0 );
-  assert( u.bi.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
+  u.bj.pC = p->apCsr[pOp->p1];
+  assert( u.bj.pC!=0 );
+  assert( u.bj.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
 
-  /* If the update-hook will be invoked, set u.bi.iKey to the rowid of the
+  /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
   ** row being deleted.
   */
   if( db->xUpdateCallback && pOp->p4.z ){
-    assert( u.bi.pC->isTable );
-    assert( u.bi.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
-    u.bi.iKey = u.bi.pC->lastRowid;
+    assert( u.bj.pC->isTable );
+    assert( u.bj.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
+    u.bj.iKey = u.bj.pC->lastRowid;
   }
 
   /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
   ** OP_Column on the same table without any intervening operations that
-  ** might move or invalidate the cursor.  Hence cursor u.bi.pC is always pointing
+  ** might move or invalidate the cursor.  Hence cursor u.bj.pC is always pointing
   ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
   ** below is always a no-op and cannot fail.  We will run it anyhow, though,
   ** to guard against future changes to the code generator.
   **/
-  assert( u.bi.pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(u.bi.pC);
+  assert( u.bj.pC->deferredMoveto==0 );
+  rc = sqlite3VdbeCursorMoveto(u.bj.pC);
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
-  sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
-  rc = sqlite3BtreeDelete(u.bi.pC->pCursor);
-  u.bi.pC->cacheStatus = CACHE_STALE;
+  sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
+  rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
+  u.bj.pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    const char *zDb = db->aDb[u.bi.pC->iDb].zName;
+    const char *zDb = db->aDb[u.bj.pC->iDb].zName;
     const char *zTbl = pOp->p4.z;
-    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bi.iKey);
-    assert( u.bi.pC->iDb>=0 );
+    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
+    assert( u.bj.pC->iDb>=0 );
   }
   if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
   break;
@@ -67672,16 +69574,16 @@ case OP_ResetCount: {
 ** fall through to the next instruction. Otherwise, jump to instruction P2.
 */
 case OP_SorterCompare: {
-#if 0  /* local variables moved into u.bj */
+#if 0  /* local variables moved into u.bk */
   VdbeCursor *pC;
   int res;
-#endif /* local variables moved into u.bj */
+#endif /* local variables moved into u.bk */
 
-  u.bj.pC = p->apCsr[pOp->p1];
-  assert( isSorter(u.bj.pC) );
+  u.bk.pC = p->apCsr[pOp->p1];
+  assert( isSorter(u.bk.pC) );
   pIn3 = &aMem[pOp->p3];
-  rc = sqlite3VdbeSorterCompare(u.bj.pC, pIn3, &u.bj.res);
-  if( u.bj.res ){
+  rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res);
+  if( u.bk.res ){
     pc = pOp->p2-1;
   }
   break;
@@ -67692,18 +69594,14 @@ case OP_SorterCompare: {
 ** Write into register P2 the current sorter data for sorter cursor P1.
 */
 case OP_SorterData: {
-#if 0  /* local variables moved into u.bk */
+#if 0  /* local variables moved into u.bl */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bk */
-#ifndef SQLITE_OMIT_MERGE_SORT
+#endif /* local variables moved into u.bl */
+
   pOut = &aMem[pOp->p2];
-  u.bk.pC = p->apCsr[pOp->p1];
-  assert( u.bk.pC->isSorter );
-  rc = sqlite3VdbeSorterRowkey(u.bk.pC, pOut);
-#else
-  pOp->opcode = OP_RowKey;
-  pc--;
-#endif
+  u.bl.pC = p->apCsr[pOp->p1];
+  assert( u.bl.pC->isSorter );
+  rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
   break;
 }
 
@@ -67729,62 +69627,62 @@ case OP_SorterData: {
 */
 case OP_RowKey:
 case OP_RowData: {
-#if 0  /* local variables moved into u.bl */
+#if 0  /* local variables moved into u.bm */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   u32 n;
   i64 n64;
-#endif /* local variables moved into u.bl */
+#endif /* local variables moved into u.bm */
 
   pOut = &aMem[pOp->p2];
   memAboutToChange(p, pOut);
 
   /* Note that RowKey and RowData are really exactly the same instruction */
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bl.pC = p->apCsr[pOp->p1];
-  assert( u.bl.pC->isSorter==0 );
-  assert( u.bl.pC->isTable || pOp->opcode!=OP_RowData );
-  assert( u.bl.pC->isIndex || pOp->opcode==OP_RowData );
-  assert( u.bl.pC!=0 );
-  assert( u.bl.pC->nullRow==0 );
-  assert( u.bl.pC->pseudoTableReg==0 );
-  assert( u.bl.pC->pCursor!=0 );
-  u.bl.pCrsr = u.bl.pC->pCursor;
-  assert( sqlite3BtreeCursorIsValid(u.bl.pCrsr) );
+  u.bm.pC = p->apCsr[pOp->p1];
+  assert( u.bm.pC->isSorter==0 );
+  assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
+  assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData );
+  assert( u.bm.pC!=0 );
+  assert( u.bm.pC->nullRow==0 );
+  assert( u.bm.pC->pseudoTableReg==0 );
+  assert( u.bm.pC->pCursor!=0 );
+  u.bm.pCrsr = u.bm.pC->pCursor;
+  assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) );
 
   /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
   ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
   ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
   ** a no-op and can never fail.  But we leave it in place as a safety.
   */
-  assert( u.bl.pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(u.bl.pC);
+  assert( u.bm.pC->deferredMoveto==0 );
+  rc = sqlite3VdbeCursorMoveto(u.bm.pC);
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
-  if( u.bl.pC->isIndex ){
-    assert( !u.bl.pC->isTable );
-    VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bl.pCrsr, &u.bl.n64);
+  if( u.bm.pC->isIndex ){
+    assert( !u.bm.pC->isTable );
+    VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
     assert( rc==SQLITE_OK );    /* True because of CursorMoveto() call above */
-    if( u.bl.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+    if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
       goto too_big;
     }
-    u.bl.n = (u32)u.bl.n64;
+    u.bm.n = (u32)u.bm.n64;
   }else{
-    VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bl.pCrsr, &u.bl.n);
+    VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n);
     assert( rc==SQLITE_OK );    /* DataSize() cannot fail */
-    if( u.bl.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+    if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
       goto too_big;
     }
   }
-  if( sqlite3VdbeMemGrow(pOut, u.bl.n, 0) ){
+  if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){
     goto no_mem;
   }
-  pOut->n = u.bl.n;
+  pOut->n = u.bm.n;
   MemSetTypeFlag(pOut, MEM_Blob);
-  if( u.bl.pC->isIndex ){
-    rc = sqlite3BtreeKey(u.bl.pCrsr, 0, u.bl.n, pOut->z);
+  if( u.bm.pC->isIndex ){
+    rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
   }else{
-    rc = sqlite3BtreeData(u.bl.pCrsr, 0, u.bl.n, pOut->z);
+    rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
   UPDATE_MAX_BLOBSIZE(pOut);
@@ -67801,42 +69699,42 @@ case OP_RowData: {
 ** one opcode now works for both table types.
 */
 case OP_Rowid: {                 /* out2-prerelease */
-#if 0  /* local variables moved into u.bm */
+#if 0  /* local variables moved into u.bn */
   VdbeCursor *pC;
   i64 v;
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
-#endif /* local variables moved into u.bm */
+#endif /* local variables moved into u.bn */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bm.pC = p->apCsr[pOp->p1];
-  assert( u.bm.pC!=0 );
-  assert( u.bm.pC->pseudoTableReg==0 );
-  if( u.bm.pC->nullRow ){
+  u.bn.pC = p->apCsr[pOp->p1];
+  assert( u.bn.pC!=0 );
+  assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
+  if( u.bn.pC->nullRow ){
     pOut->flags = MEM_Null;
     break;
-  }else if( u.bm.pC->deferredMoveto ){
-    u.bm.v = u.bm.pC->movetoTarget;
+  }else if( u.bn.pC->deferredMoveto ){
+    u.bn.v = u.bn.pC->movetoTarget;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  }else if( u.bm.pC->pVtabCursor ){
-    u.bm.pVtab = u.bm.pC->pVtabCursor->pVtab;
-    u.bm.pModule = u.bm.pVtab->pModule;
-    assert( u.bm.pModule->xRowid );
-    rc = u.bm.pModule->xRowid(u.bm.pC->pVtabCursor, &u.bm.v);
-    importVtabErrMsg(p, u.bm.pVtab);
+  }else if( u.bn.pC->pVtabCursor ){
+    u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
+    u.bn.pModule = u.bn.pVtab->pModule;
+    assert( u.bn.pModule->xRowid );
+    rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
+    importVtabErrMsg(p, u.bn.pVtab);
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
   }else{
-    assert( u.bm.pC->pCursor!=0 );
-    rc = sqlite3VdbeCursorMoveto(u.bm.pC);
+    assert( u.bn.pC->pCursor!=0 );
+    rc = sqlite3VdbeCursorMoveto(u.bn.pC);
     if( rc ) goto abort_due_to_error;
-    if( u.bm.pC->rowidIsValid ){
-      u.bm.v = u.bm.pC->lastRowid;
+    if( u.bn.pC->rowidIsValid ){
+      u.bn.v = u.bn.pC->lastRowid;
     }else{
-      rc = sqlite3BtreeKeySize(u.bm.pC->pCursor, &u.bm.v);
+      rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v);
       assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
     }
   }
-  pOut->u.i = u.bm.v;
+  pOut->u.i = u.bn.v;
   break;
 }
 
@@ -67847,18 +69745,18 @@ case OP_Rowid: {                 /* out2-prerelease */
 ** write a NULL.
 */
 case OP_NullRow: {
-#if 0  /* local variables moved into u.bn */
+#if 0  /* local variables moved into u.bo */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bn */
+#endif /* local variables moved into u.bo */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bn.pC = p->apCsr[pOp->p1];
-  assert( u.bn.pC!=0 );
-  u.bn.pC->nullRow = 1;
-  u.bn.pC->rowidIsValid = 0;
-  assert( u.bn.pC->pCursor || u.bn.pC->pVtabCursor );
-  if( u.bn.pC->pCursor ){
-    sqlite3BtreeClearCursor(u.bn.pC->pCursor);
+  u.bo.pC = p->apCsr[pOp->p1];
+  assert( u.bo.pC!=0 );
+  u.bo.pC->nullRow = 1;
+  u.bo.pC->rowidIsValid = 0;
+  assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
+  if( u.bo.pC->pCursor ){
+    sqlite3BtreeClearCursor(u.bo.pC->pCursor);
   }
   break;
 }
@@ -67872,25 +69770,25 @@ case OP_NullRow: {
 ** to the following instruction.
 */
 case OP_Last: {        /* jump */
-#if 0  /* local variables moved into u.bo */
+#if 0  /* local variables moved into u.bp */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
-#endif /* local variables moved into u.bo */
+#endif /* local variables moved into u.bp */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bo.pC = p->apCsr[pOp->p1];
-  assert( u.bo.pC!=0 );
-  u.bo.pCrsr = u.bo.pC->pCursor;
-  u.bo.res = 0;
-  if( ALWAYS(u.bo.pCrsr!=0) ){
-    rc = sqlite3BtreeLast(u.bo.pCrsr, &u.bo.res);
+  u.bp.pC = p->apCsr[pOp->p1];
+  assert( u.bp.pC!=0 );
+  u.bp.pCrsr = u.bp.pC->pCursor;
+  u.bp.res = 0;
+  if( ALWAYS(u.bp.pCrsr!=0) ){
+    rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
   }
-  u.bo.pC->nullRow = (u8)u.bo.res;
-  u.bo.pC->deferredMoveto = 0;
-  u.bo.pC->rowidIsValid = 0;
-  u.bo.pC->cacheStatus = CACHE_STALE;
-  if( pOp->p2>0 && u.bo.res ){
+  u.bp.pC->nullRow = (u8)u.bp.res;
+  u.bp.pC->deferredMoveto = 0;
+  u.bp.pC->rowidIsValid = 0;
+  u.bp.pC->cacheStatus = CACHE_STALE;
+  if( pOp->p2>0 && u.bp.res ){
     pc = pOp->p2 - 1;
   }
   break;
@@ -67910,9 +69808,6 @@ case OP_Last: {        /* jump */
 ** correctly optimizing out sorts.
 */
 case OP_SorterSort:    /* jump */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  pOp->opcode = OP_Sort;
-#endif
 case OP_Sort: {        /* jump */
 #ifdef SQLITE_TEST
   sqlite3_sort_count++;
@@ -67930,31 +69825,31 @@ case OP_Sort: {        /* jump */
 ** to the following instruction.
 */
 case OP_Rewind: {        /* jump */
-#if 0  /* local variables moved into u.bp */
+#if 0  /* local variables moved into u.bq */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
-#endif /* local variables moved into u.bp */
+#endif /* local variables moved into u.bq */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bp.pC = p->apCsr[pOp->p1];
-  assert( u.bp.pC!=0 );
-  assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterSort) );
-  u.bp.res = 1;
-  if( isSorter(u.bp.pC) ){
-    rc = sqlite3VdbeSorterRewind(db, u.bp.pC, &u.bp.res);
-  }else{
-    u.bp.pCrsr = u.bp.pC->pCursor;
-    assert( u.bp.pCrsr );
-    rc = sqlite3BtreeFirst(u.bp.pCrsr, &u.bp.res);
-    u.bp.pC->atFirst = u.bp.res==0 ?1:0;
-    u.bp.pC->deferredMoveto = 0;
-    u.bp.pC->cacheStatus = CACHE_STALE;
-    u.bp.pC->rowidIsValid = 0;
+  u.bq.pC = p->apCsr[pOp->p1];
+  assert( u.bq.pC!=0 );
+  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) );
+  u.bq.res = 1;
+  if( isSorter(u.bq.pC) ){
+    rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
+  }else{
+    u.bq.pCrsr = u.bq.pC->pCursor;
+    assert( u.bq.pCrsr );
+    rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
+    u.bq.pC->atFirst = u.bq.res==0 ?1:0;
+    u.bq.pC->deferredMoveto = 0;
+    u.bq.pC->cacheStatus = CACHE_STALE;
+    u.bq.pC->rowidIsValid = 0;
   }
-  u.bp.pC->nullRow = (u8)u.bp.res;
+  u.bq.pC->nullRow = (u8)u.bq.res;
   assert( pOp->p2>0 && pOp->p2<p->nOp );
-  if( u.bp.res ){
+  if( u.bq.res ){
     pc = pOp->p2 - 1;
   }
   break;
@@ -67993,45 +69888,42 @@ case OP_Rewind: {        /* jump */
 ** number P5-1 in the prepared statement is incremented.
 */
 case OP_SorterNext:    /* jump */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  pOp->opcode = OP_Next;
-#endif
 case OP_Prev:          /* jump */
 case OP_Next: {        /* jump */
-#if 0  /* local variables moved into u.bq */
+#if 0  /* local variables moved into u.br */
   VdbeCursor *pC;
   int res;
-#endif /* local variables moved into u.bq */
+#endif /* local variables moved into u.br */
 
   CHECK_FOR_INTERRUPT;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p5<=ArraySize(p->aCounter) );
-  u.bq.pC = p->apCsr[pOp->p1];
-  if( u.bq.pC==0 ){
+  u.br.pC = p->apCsr[pOp->p1];
+  if( u.br.pC==0 ){
     break;  /* See ticket #2273 */
   }
-  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterNext) );
-  if( isSorter(u.bq.pC) ){
+  assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
+  if( isSorter(u.br.pC) ){
     assert( pOp->opcode==OP_SorterNext );
-    rc = sqlite3VdbeSorterNext(db, u.bq.pC, &u.bq.res);
+    rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
   }else{
-    u.bq.res = 1;
-    assert( u.bq.pC->deferredMoveto==0 );
-    assert( u.bq.pC->pCursor );
+    u.br.res = 1;
+    assert( u.br.pC->deferredMoveto==0 );
+    assert( u.br.pC->pCursor );
     assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
     assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
-    rc = pOp->p4.xAdvance(u.bq.pC->pCursor, &u.bq.res);
+    rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
   }
-  u.bq.pC->nullRow = (u8)u.bq.res;
-  u.bq.pC->cacheStatus = CACHE_STALE;
-  if( u.bq.res==0 ){
+  u.br.pC->nullRow = (u8)u.br.res;
+  u.br.pC->cacheStatus = CACHE_STALE;
+  if( u.br.res==0 ){
     pc = pOp->p2 - 1;
     if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
   }
-  u.bq.pC->rowidIsValid = 0;
+  u.br.pC->rowidIsValid = 0;
   break;
 }
 
@@ -68048,38 +69940,35 @@ case OP_Next: {        /* jump */
 ** for tables is OP_Insert.
 */
 case OP_SorterInsert:       /* in2 */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  pOp->opcode = OP_IdxInsert;
-#endif
 case OP_IdxInsert: {        /* in2 */
-#if 0  /* local variables moved into u.br */
+#if 0  /* local variables moved into u.bs */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int nKey;
   const char *zKey;
-#endif /* local variables moved into u.br */
+#endif /* local variables moved into u.bs */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.br.pC = p->apCsr[pOp->p1];
-  assert( u.br.pC!=0 );
-  assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
+  u.bs.pC = p->apCsr[pOp->p1];
+  assert( u.bs.pC!=0 );
+  assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
   pIn2 = &aMem[pOp->p2];
   assert( pIn2->flags & MEM_Blob );
-  u.br.pCrsr = u.br.pC->pCursor;
-  if( ALWAYS(u.br.pCrsr!=0) ){
-    assert( u.br.pC->isTable==0 );
+  u.bs.pCrsr = u.bs.pC->pCursor;
+  if( ALWAYS(u.bs.pCrsr!=0) ){
+    assert( u.bs.pC->isTable==0 );
     rc = ExpandBlob(pIn2);
     if( rc==SQLITE_OK ){
-      if( isSorter(u.br.pC) ){
-        rc = sqlite3VdbeSorterWrite(db, u.br.pC, pIn2);
+      if( isSorter(u.bs.pC) ){
+        rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
       }else{
-        u.br.nKey = pIn2->n;
-        u.br.zKey = pIn2->z;
-        rc = sqlite3BtreeInsert(u.br.pCrsr, u.br.zKey, u.br.nKey, "", 0, 0, pOp->p3,
-            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.br.pC->seekResult : 0)
+        u.bs.nKey = pIn2->n;
+        u.bs.zKey = pIn2->z;
+        rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
+            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
             );
-        assert( u.br.pC->deferredMoveto==0 );
-        u.br.pC->cacheStatus = CACHE_STALE;
+        assert( u.bs.pC->deferredMoveto==0 );
+        u.bs.pC->cacheStatus = CACHE_STALE;
       }
     }
   }
@@ -68093,33 +69982,33 @@ case OP_IdxInsert: {        /* in2 */
 ** index opened by cursor P1.
 */
 case OP_IdxDelete: {
-#if 0  /* local variables moved into u.bs */
+#if 0  /* local variables moved into u.bt */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
   UnpackedRecord r;
-#endif /* local variables moved into u.bs */
+#endif /* local variables moved into u.bt */
 
   assert( pOp->p3>0 );
   assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bs.pC = p->apCsr[pOp->p1];
-  assert( u.bs.pC!=0 );
-  u.bs.pCrsr = u.bs.pC->pCursor;
-  if( ALWAYS(u.bs.pCrsr!=0) ){
-    u.bs.r.pKeyInfo = u.bs.pC->pKeyInfo;
-    u.bs.r.nField = (u16)pOp->p3;
-    u.bs.r.flags = 0;
-    u.bs.r.aMem = &aMem[pOp->p2];
+  u.bt.pC = p->apCsr[pOp->p1];
+  assert( u.bt.pC!=0 );
+  u.bt.pCrsr = u.bt.pC->pCursor;
+  if( ALWAYS(u.bt.pCrsr!=0) ){
+    u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
+    u.bt.r.nField = (u16)pOp->p3;
+    u.bt.r.flags = 0;
+    u.bt.r.aMem = &aMem[pOp->p2];
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bs.r.nField; i++) assert( memIsValid(&u.bs.r.aMem[i]) ); }
+    { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
 #endif
-    rc = sqlite3BtreeMovetoUnpacked(u.bs.pCrsr, &u.bs.r, 0, 0, &u.bs.res);
-    if( rc==SQLITE_OK && u.bs.res==0 ){
-      rc = sqlite3BtreeDelete(u.bs.pCrsr);
+    rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
+    if( rc==SQLITE_OK && u.bt.res==0 ){
+      rc = sqlite3BtreeDelete(u.bt.pCrsr);
     }
-    assert( u.bs.pC->deferredMoveto==0 );
-    u.bs.pC->cacheStatus = CACHE_STALE;
+    assert( u.bt.pC->deferredMoveto==0 );
+    u.bt.pC->cacheStatus = CACHE_STALE;
   }
   break;
 }
@@ -68133,28 +70022,28 @@ case OP_IdxDelete: {
 ** See also: Rowid, MakeRecord.
 */
 case OP_IdxRowid: {              /* out2-prerelease */
-#if 0  /* local variables moved into u.bt */
+#if 0  /* local variables moved into u.bu */
   BtCursor *pCrsr;
   VdbeCursor *pC;
   i64 rowid;
-#endif /* local variables moved into u.bt */
+#endif /* local variables moved into u.bu */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bt.pC = p->apCsr[pOp->p1];
-  assert( u.bt.pC!=0 );
-  u.bt.pCrsr = u.bt.pC->pCursor;
+  u.bu.pC = p->apCsr[pOp->p1];
+  assert( u.bu.pC!=0 );
+  u.bu.pCrsr = u.bu.pC->pCursor;
   pOut->flags = MEM_Null;
-  if( ALWAYS(u.bt.pCrsr!=0) ){
-    rc = sqlite3VdbeCursorMoveto(u.bt.pC);
+  if( ALWAYS(u.bu.pCrsr!=0) ){
+    rc = sqlite3VdbeCursorMoveto(u.bu.pC);
     if( NEVER(rc) ) goto abort_due_to_error;
-    assert( u.bt.pC->deferredMoveto==0 );
-    assert( u.bt.pC->isTable==0 );
-    if( !u.bt.pC->nullRow ){
-      rc = sqlite3VdbeIdxRowid(db, u.bt.pCrsr, &u.bt.rowid);
+    assert( u.bu.pC->deferredMoveto==0 );
+    assert( u.bu.pC->isTable==0 );
+    if( !u.bu.pC->nullRow ){
+      rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      pOut->u.i = u.bt.rowid;
+      pOut->u.i = u.bu.rowid;
       pOut->flags = MEM_Int;
     }
   }
@@ -68189,39 +70078,39 @@ case OP_IdxRowid: {              /* out2-prerelease */
 */
 case OP_IdxLT:          /* jump */
 case OP_IdxGE: {        /* jump */
-#if 0  /* local variables moved into u.bu */
+#if 0  /* local variables moved into u.bv */
   VdbeCursor *pC;
   int res;
   UnpackedRecord r;
-#endif /* local variables moved into u.bu */
+#endif /* local variables moved into u.bv */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bu.pC = p->apCsr[pOp->p1];
-  assert( u.bu.pC!=0 );
-  assert( u.bu.pC->isOrdered );
-  if( ALWAYS(u.bu.pC->pCursor!=0) ){
-    assert( u.bu.pC->deferredMoveto==0 );
+  u.bv.pC = p->apCsr[pOp->p1];
+  assert( u.bv.pC!=0 );
+  assert( u.bv.pC->isOrdered );
+  if( ALWAYS(u.bv.pC->pCursor!=0) ){
+    assert( u.bv.pC->deferredMoveto==0 );
     assert( pOp->p5==0 || pOp->p5==1 );
     assert( pOp->p4type==P4_INT32 );
-    u.bu.r.pKeyInfo = u.bu.pC->pKeyInfo;
-    u.bu.r.nField = (u16)pOp->p4.i;
+    u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
+    u.bv.r.nField = (u16)pOp->p4.i;
     if( pOp->p5 ){
-      u.bu.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
+      u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
     }else{
-      u.bu.r.flags = UNPACKED_PREFIX_MATCH;
+      u.bv.r.flags = UNPACKED_PREFIX_MATCH;
     }
-    u.bu.r.aMem = &aMem[pOp->p3];
+    u.bv.r.aMem = &aMem[pOp->p3];
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bu.r.nField; i++) assert( memIsValid(&u.bu.r.aMem[i]) ); }
+    { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
 #endif
-    rc = sqlite3VdbeIdxKeyCompare(u.bu.pC, &u.bu.r, &u.bu.res);
+    rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
     if( pOp->opcode==OP_IdxLT ){
-      u.bu.res = -u.bu.res;
+      u.bv.res = -u.bv.res;
     }else{
       assert( pOp->opcode==OP_IdxGE );
-      u.bu.res++;
+      u.bv.res++;
     }
-    if( u.bu.res>0 ){
+    if( u.bv.res>0 ){
       pc = pOp->p2 - 1 ;
     }
   }
@@ -68249,39 +70138,40 @@ case OP_IdxGE: {        /* jump */
 ** See also: Clear
 */
 case OP_Destroy: {     /* out2-prerelease */
-#if 0  /* local variables moved into u.bv */
+#if 0  /* local variables moved into u.bw */
   int iMoved;
   int iCnt;
   Vdbe *pVdbe;
   int iDb;
-#endif /* local variables moved into u.bv */
+#endif /* local variables moved into u.bw */
+
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  u.bv.iCnt = 0;
-  for(u.bv.pVdbe=db->pVdbe; u.bv.pVdbe; u.bv.pVdbe = u.bv.pVdbe->pNext){
-    if( u.bv.pVdbe->magic==VDBE_MAGIC_RUN && u.bv.pVdbe->inVtabMethod<2 && u.bv.pVdbe->pc>=0 ){
-      u.bv.iCnt++;
+  u.bw.iCnt = 0;
+  for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
+    if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
+      u.bw.iCnt++;
     }
   }
 #else
-  u.bv.iCnt = db->activeVdbeCnt;
+  u.bw.iCnt = db->activeVdbeCnt;
 #endif
   pOut->flags = MEM_Null;
-  if( u.bv.iCnt>1 ){
+  if( u.bw.iCnt>1 ){
     rc = SQLITE_LOCKED;
     p->errorAction = OE_Abort;
   }else{
-    u.bv.iDb = pOp->p3;
-    assert( u.bv.iCnt==1 );
-    assert( (p->btreeMask & (((yDbMask)1)<<u.bv.iDb))!=0 );
-    rc = sqlite3BtreeDropTable(db->aDb[u.bv.iDb].pBt, pOp->p1, &u.bv.iMoved);
+    u.bw.iDb = pOp->p3;
+    assert( u.bw.iCnt==1 );
+    assert( (p->btreeMask & (((yDbMask)1)<<u.bw.iDb))!=0 );
+    rc = sqlite3BtreeDropTable(db->aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved);
     pOut->flags = MEM_Int;
-    pOut->u.i = u.bv.iMoved;
+    pOut->u.i = u.bw.iMoved;
 #ifndef SQLITE_OMIT_AUTOVACUUM
-    if( rc==SQLITE_OK && u.bv.iMoved!=0 ){
-      sqlite3RootPageMoved(db, u.bv.iDb, u.bv.iMoved, pOp->p1);
+    if( rc==SQLITE_OK && u.bw.iMoved!=0 ){
+      sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1);
       /* All OP_Destroy operations occur on the same btree */
-      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bv.iDb+1 );
-      resetSchemaOnFault = u.bv.iDb+1;
+      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 );
+      resetSchemaOnFault = u.bw.iDb+1;
     }
 #endif
   }
@@ -68307,21 +70197,21 @@ case OP_Destroy: {     /* out2-prerelease */
 ** See also: Destroy
 */
 case OP_Clear: {
-#if 0  /* local variables moved into u.bw */
+#if 0  /* local variables moved into u.bx */
   int nChange;
-#endif /* local variables moved into u.bw */
+#endif /* local variables moved into u.bx */
 
-  u.bw.nChange = 0;
+  u.bx.nChange = 0;
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
   rc = sqlite3BtreeClearTable(
-      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bw.nChange : 0)
+      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
   );
   if( pOp->p3 ){
-    p->nChange += u.bw.nChange;
+    p->nChange += u.bx.nChange;
     if( pOp->p3>0 ){
       assert( memIsValid(&aMem[pOp->p3]) );
       memAboutToChange(p, &aMem[pOp->p3]);
-      aMem[pOp->p3].u.i += u.bw.nChange;
+      aMem[pOp->p3].u.i += u.bx.nChange;
     }
   }
   break;
@@ -68351,25 +70241,25 @@ case OP_Clear: {
 */
 case OP_CreateIndex:            /* out2-prerelease */
 case OP_CreateTable: {          /* out2-prerelease */
-#if 0  /* local variables moved into u.bx */
+#if 0  /* local variables moved into u.by */
   int pgno;
   int flags;
   Db *pDb;
-#endif /* local variables moved into u.bx */
+#endif /* local variables moved into u.by */
 
-  u.bx.pgno = 0;
+  u.by.pgno = 0;
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.bx.pDb = &db->aDb[pOp->p1];
-  assert( u.bx.pDb->pBt!=0 );
+  u.by.pDb = &db->aDb[pOp->p1];
+  assert( u.by.pDb->pBt!=0 );
   if( pOp->opcode==OP_CreateTable ){
-    /* u.bx.flags = BTREE_INTKEY; */
-    u.bx.flags = BTREE_INTKEY;
+    /* u.by.flags = BTREE_INTKEY; */
+    u.by.flags = BTREE_INTKEY;
   }else{
-    u.bx.flags = BTREE_BLOBKEY;
+    u.by.flags = BTREE_BLOBKEY;
   }
-  rc = sqlite3BtreeCreateTable(u.bx.pDb->pBt, &u.bx.pgno, u.bx.flags);
-  pOut->u.i = u.bx.pgno;
+  rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags);
+  pOut->u.i = u.by.pgno;
   break;
 }
 
@@ -68382,44 +70272,44 @@ case OP_CreateTable: {          /* out2-prerelease */
 ** then runs the new virtual machine.  It is thus a re-entrant opcode.
 */
 case OP_ParseSchema: {
-#if 0  /* local variables moved into u.by */
+#if 0  /* local variables moved into u.bz */
   int iDb;
   const char *zMaster;
   char *zSql;
   InitData initData;
-#endif /* local variables moved into u.by */
+#endif /* local variables moved into u.bz */
 
   /* Any prepared statement that invokes this opcode will hold mutexes
   ** on every btree.  This is a prerequisite for invoking
   ** sqlite3InitCallback().
   */
 #ifdef SQLITE_DEBUG
-  for(u.by.iDb=0; u.by.iDb<db->nDb; u.by.iDb++){
-    assert( u.by.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.by.iDb].pBt) );
+  for(u.bz.iDb=0; u.bz.iDb<db->nDb; u.bz.iDb++){
+    assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) );
   }
 #endif
 
-  u.by.iDb = pOp->p1;
-  assert( u.by.iDb>=0 && u.by.iDb<db->nDb );
-  assert( DbHasProperty(db, u.by.iDb, DB_SchemaLoaded) );
+  u.bz.iDb = pOp->p1;
+  assert( u.bz.iDb>=0 && u.bz.iDb<db->nDb );
+  assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) );
   /* Used to be a conditional */ {
-    u.by.zMaster = SCHEMA_TABLE(u.by.iDb);
-    u.by.initData.db = db;
-    u.by.initData.iDb = pOp->p1;
-    u.by.initData.pzErrMsg = &p->zErrMsg;
-    u.by.zSql = sqlite3MPrintf(db,
+    u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb);
+    u.bz.initData.db = db;
+    u.bz.initData.iDb = pOp->p1;
+    u.bz.initData.pzErrMsg = &p->zErrMsg;
+    u.bz.zSql = sqlite3MPrintf(db,
        "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
-       db->aDb[u.by.iDb].zName, u.by.zMaster, pOp->p4.z);
-    if( u.by.zSql==0 ){
+       db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z);
+    if( u.bz.zSql==0 ){
       rc = SQLITE_NOMEM;
     }else{
       assert( db->init.busy==0 );
       db->init.busy = 1;
-      u.by.initData.rc = SQLITE_OK;
+      u.bz.initData.rc = SQLITE_OK;
       assert( !db->mallocFailed );
-      rc = sqlite3_exec(db, u.by.zSql, sqlite3InitCallback, &u.by.initData, 0);
-      if( rc==SQLITE_OK ) rc = u.by.initData.rc;
-      sqlite3DbFree(db, u.by.zSql);
+      rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0);
+      if( rc==SQLITE_OK ) rc = u.bz.initData.rc;
+      sqlite3DbFree(db, u.bz.zSql);
       db->init.busy = 0;
     }
   }
@@ -68503,41 +70393,41 @@ case OP_DropTrigger: {
 ** This opcode is used to implement the integrity_check pragma.
 */
 case OP_IntegrityCk: {
-#if 0  /* local variables moved into u.bz */
+#if 0  /* local variables moved into u.ca */
   int nRoot;      /* Number of tables to check.  (Number of root pages.) */
   int *aRoot;     /* Array of rootpage numbers for tables to be checked */
   int j;          /* Loop counter */
   int nErr;       /* Number of errors reported */
   char *z;        /* Text of the error report */
   Mem *pnErr;     /* Register keeping track of errors remaining */
-#endif /* local variables moved into u.bz */
+#endif /* local variables moved into u.ca */
 
-  u.bz.nRoot = pOp->p2;
-  assert( u.bz.nRoot>0 );
-  u.bz.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bz.nRoot+1) );
-  if( u.bz.aRoot==0 ) goto no_mem;
+  u.ca.nRoot = pOp->p2;
+  assert( u.ca.nRoot>0 );
+  u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
+  if( u.ca.aRoot==0 ) goto no_mem;
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.bz.pnErr = &aMem[pOp->p3];
-  assert( (u.bz.pnErr->flags & MEM_Int)!=0 );
-  assert( (u.bz.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+  u.ca.pnErr = &aMem[pOp->p3];
+  assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
+  assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
   pIn1 = &aMem[pOp->p1];
-  for(u.bz.j=0; u.bz.j<u.bz.nRoot; u.bz.j++){
-    u.bz.aRoot[u.bz.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bz.j]);
+  for(u.ca.j=0; u.ca.j<u.ca.nRoot; u.ca.j++){
+    u.ca.aRoot[u.ca.j] = (int)sqlite3VdbeIntValue(&pIn1[u.ca.j]);
   }
-  u.bz.aRoot[u.bz.j] = 0;
+  u.ca.aRoot[u.ca.j] = 0;
   assert( pOp->p5<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
-  u.bz.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bz.aRoot, u.bz.nRoot,
-                                 (int)u.bz.pnErr->u.i, &u.bz.nErr);
-  sqlite3DbFree(db, u.bz.aRoot);
-  u.bz.pnErr->u.i -= u.bz.nErr;
+  u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot,
+                                 (int)u.ca.pnErr->u.i, &u.ca.nErr);
+  sqlite3DbFree(db, u.ca.aRoot);
+  u.ca.pnErr->u.i -= u.ca.nErr;
   sqlite3VdbeMemSetNull(pIn1);
-  if( u.bz.nErr==0 ){
-    assert( u.bz.z==0 );
-  }else if( u.bz.z==0 ){
+  if( u.ca.nErr==0 ){
+    assert( u.ca.z==0 );
+  }else if( u.ca.z==0 ){
     goto no_mem;
   }else{
-    sqlite3VdbeMemSetStr(pIn1, u.bz.z, -1, SQLITE_UTF8, sqlite3_free);
+    sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free);
   }
   UPDATE_MAX_BLOBSIZE(pIn1);
   sqlite3VdbeChangeEncoding(pIn1, encoding);
@@ -68571,20 +70461,20 @@ case OP_RowSetAdd: {       /* in1, in2 */
 ** unchanged and jump to instruction P2.
 */
 case OP_RowSetRead: {       /* jump, in1, out3 */
-#if 0  /* local variables moved into u.ca */
+#if 0  /* local variables moved into u.cb */
   i64 val;
-#endif /* local variables moved into u.ca */
+#endif /* local variables moved into u.cb */
   CHECK_FOR_INTERRUPT;
   pIn1 = &aMem[pOp->p1];
   if( (pIn1->flags & MEM_RowSet)==0
-   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.ca.val)==0
+   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
   ){
     /* The boolean index is empty */
     sqlite3VdbeMemSetNull(pIn1);
     pc = pOp->p2 - 1;
   }else{
     /* A value was pulled from the index */
-    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.ca.val);
+    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
   }
   break;
 }
@@ -68613,14 +70503,14 @@ case OP_RowSetRead: {       /* jump, in1, out3 */
 ** inserted as part of some other set).
 */
 case OP_RowSetTest: {                     /* jump, in1, in3 */
-#if 0  /* local variables moved into u.cb */
+#if 0  /* local variables moved into u.cc */
   int iSet;
   int exists;
-#endif /* local variables moved into u.cb */
+#endif /* local variables moved into u.cc */
 
   pIn1 = &aMem[pOp->p1];
   pIn3 = &aMem[pOp->p3];
-  u.cb.iSet = pOp->p4.i;
+  u.cc.iSet = pOp->p4.i;
   assert( pIn3->flags&MEM_Int );
 
   /* If there is anything other than a rowset object in memory cell P1,
@@ -68632,17 +70522,17 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
   }
 
   assert( pOp->p4type==P4_INT32 );
-  assert( u.cb.iSet==-1 || u.cb.iSet>=0 );
-  if( u.cb.iSet ){
-    u.cb.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
-                               (u8)(u.cb.iSet>=0 ? u.cb.iSet & 0xf : 0xff),
+  assert( u.cc.iSet==-1 || u.cc.iSet>=0 );
+  if( u.cc.iSet ){
+    u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+                               (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff),
                                pIn3->u.i);
-    if( u.cb.exists ){
+    if( u.cc.exists ){
       pc = pOp->p2 - 1;
       break;
     }
   }
-  if( u.cb.iSet>=0 ){
+  if( u.cc.iSet>=0 ){
     sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
   }
   break;
@@ -68665,7 +70555,7 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
 ** P4 is a pointer to the VM containing the trigger program.
 */
 case OP_Program: {        /* jump */
-#if 0  /* local variables moved into u.cc */
+#if 0  /* local variables moved into u.cd */
   int nMem;               /* Number of memory registers for sub-program */
   int nByte;              /* Bytes of runtime space required for sub-program */
   Mem *pRt;               /* Register to allocate runtime space */
@@ -68674,11 +70564,11 @@ case OP_Program: {        /* jump */
   VdbeFrame *pFrame;      /* New vdbe frame to execute in */
   SubProgram *pProgram;   /* Sub-program to execute */
   void *t;                /* Token identifying trigger */
-#endif /* local variables moved into u.cc */
+#endif /* local variables moved into u.cd */
 
-  u.cc.pProgram = pOp->p4.pProgram;
-  u.cc.pRt = &aMem[pOp->p3];
-  assert( u.cc.pProgram->nOp>0 );
+  u.cd.pProgram = pOp->p4.pProgram;
+  u.cd.pRt = &aMem[pOp->p3];
+  assert( u.cd.pProgram->nOp>0 );
 
   /* If the p5 flag is clear, then recursive invocation of triggers is
   ** disabled for backwards compatibility (p5 is set if this sub-program
@@ -68692,9 +70582,9 @@ case OP_Program: {        /* jump */
   ** single trigger all have the same value for the SubProgram.token
   ** variable.  */
   if( pOp->p5 ){
-    u.cc.t = u.cc.pProgram->token;
-    for(u.cc.pFrame=p->pFrame; u.cc.pFrame && u.cc.pFrame->token!=u.cc.t; u.cc.pFrame=u.cc.pFrame->pParent);
-    if( u.cc.pFrame ) break;
+    u.cd.t = u.cd.pProgram->token;
+    for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent);
+    if( u.cd.pFrame ) break;
   }
 
   if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
@@ -68703,69 +70593,69 @@ case OP_Program: {        /* jump */
     break;
   }
 
-  /* Register u.cc.pRt is used to store the memory required to save the state
+  /* Register u.cd.pRt is used to store the memory required to save the state
   ** of the current program, and the memory required at runtime to execute
-  ** the trigger program. If this trigger has been fired before, then u.cc.pRt
+  ** the trigger program. If this trigger has been fired before, then u.cd.pRt
   ** is already allocated. Otherwise, it must be initialized.  */
-  if( (u.cc.pRt->flags&MEM_Frame)==0 ){
+  if( (u.cd.pRt->flags&MEM_Frame)==0 ){
     /* SubProgram.nMem is set to the number of memory cells used by the
     ** program stored in SubProgram.aOp. As well as these, one memory
     ** cell is required for each cursor used by the program. Set local
-    ** variable u.cc.nMem (and later, VdbeFrame.nChildMem) to this value.
+    ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value.
     */
-    u.cc.nMem = u.cc.pProgram->nMem + u.cc.pProgram->nCsr;
-    u.cc.nByte = ROUND8(sizeof(VdbeFrame))
-              + u.cc.nMem * sizeof(Mem)
-              + u.cc.pProgram->nCsr * sizeof(VdbeCursor *)
-              + u.cc.pProgram->nOnce * sizeof(u8);
-    u.cc.pFrame = sqlite3DbMallocZero(db, u.cc.nByte);
-    if( !u.cc.pFrame ){
+    u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr;
+    u.cd.nByte = ROUND8(sizeof(VdbeFrame))
+              + u.cd.nMem * sizeof(Mem)
+              + u.cd.pProgram->nCsr * sizeof(VdbeCursor *)
+              + u.cd.pProgram->nOnce * sizeof(u8);
+    u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte);
+    if( !u.cd.pFrame ){
       goto no_mem;
     }
-    sqlite3VdbeMemRelease(u.cc.pRt);
-    u.cc.pRt->flags = MEM_Frame;
-    u.cc.pRt->u.pFrame = u.cc.pFrame;
+    sqlite3VdbeMemRelease(u.cd.pRt);
+    u.cd.pRt->flags = MEM_Frame;
+    u.cd.pRt->u.pFrame = u.cd.pFrame;
 
-    u.cc.pFrame->v = p;
-    u.cc.pFrame->nChildMem = u.cc.nMem;
-    u.cc.pFrame->nChildCsr = u.cc.pProgram->nCsr;
-    u.cc.pFrame->pc = pc;
-    u.cc.pFrame->aMem = p->aMem;
-    u.cc.pFrame->nMem = p->nMem;
-    u.cc.pFrame->apCsr = p->apCsr;
-    u.cc.pFrame->nCursor = p->nCursor;
-    u.cc.pFrame->aOp = p->aOp;
-    u.cc.pFrame->nOp = p->nOp;
-    u.cc.pFrame->token = u.cc.pProgram->token;
-    u.cc.pFrame->aOnceFlag = p->aOnceFlag;
-    u.cc.pFrame->nOnceFlag = p->nOnceFlag;
+    u.cd.pFrame->v = p;
+    u.cd.pFrame->nChildMem = u.cd.nMem;
+    u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr;
+    u.cd.pFrame->pc = pc;
+    u.cd.pFrame->aMem = p->aMem;
+    u.cd.pFrame->nMem = p->nMem;
+    u.cd.pFrame->apCsr = p->apCsr;
+    u.cd.pFrame->nCursor = p->nCursor;
+    u.cd.pFrame->aOp = p->aOp;
+    u.cd.pFrame->nOp = p->nOp;
+    u.cd.pFrame->token = u.cd.pProgram->token;
+    u.cd.pFrame->aOnceFlag = p->aOnceFlag;
+    u.cd.pFrame->nOnceFlag = p->nOnceFlag;
 
-    u.cc.pEnd = &VdbeFrameMem(u.cc.pFrame)[u.cc.pFrame->nChildMem];
-    for(u.cc.pMem=VdbeFrameMem(u.cc.pFrame); u.cc.pMem!=u.cc.pEnd; u.cc.pMem++){
-      u.cc.pMem->flags = MEM_Invalid;
-      u.cc.pMem->db = db;
+    u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem];
+    for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){
+      u.cd.pMem->flags = MEM_Invalid;
+      u.cd.pMem->db = db;
     }
   }else{
-    u.cc.pFrame = u.cc.pRt->u.pFrame;
-    assert( u.cc.pProgram->nMem+u.cc.pProgram->nCsr==u.cc.pFrame->nChildMem );
-    assert( u.cc.pProgram->nCsr==u.cc.pFrame->nChildCsr );
-    assert( pc==u.cc.pFrame->pc );
+    u.cd.pFrame = u.cd.pRt->u.pFrame;
+    assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem );
+    assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr );
+    assert( pc==u.cd.pFrame->pc );
   }
 
   p->nFrame++;
-  u.cc.pFrame->pParent = p->pFrame;
-  u.cc.pFrame->lastRowid = lastRowid;
-  u.cc.pFrame->nChange = p->nChange;
+  u.cd.pFrame->pParent = p->pFrame;
+  u.cd.pFrame->lastRowid = lastRowid;
+  u.cd.pFrame->nChange = p->nChange;
   p->nChange = 0;
-  p->pFrame = u.cc.pFrame;
-  p->aMem = aMem = &VdbeFrameMem(u.cc.pFrame)[-1];
-  p->nMem = u.cc.pFrame->nChildMem;
-  p->nCursor = (u16)u.cc.pFrame->nChildCsr;
+  p->pFrame = u.cd.pFrame;
+  p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1];
+  p->nMem = u.cd.pFrame->nChildMem;
+  p->nCursor = (u16)u.cd.pFrame->nChildCsr;
   p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
-  p->aOp = aOp = u.cc.pProgram->aOp;
-  p->nOp = u.cc.pProgram->nOp;
+  p->aOp = aOp = u.cd.pProgram->aOp;
+  p->nOp = u.cd.pProgram->nOp;
   p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
-  p->nOnceFlag = u.cc.pProgram->nOnce;
+  p->nOnceFlag = u.cd.pProgram->nOnce;
   pc = -1;
   memset(p->aOnceFlag, 0, p->nOnceFlag);
 
@@ -68785,13 +70675,13 @@ case OP_Program: {        /* jump */
 ** calling OP_Program instruction.
 */
 case OP_Param: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.cd */
+#if 0  /* local variables moved into u.ce */
   VdbeFrame *pFrame;
   Mem *pIn;
-#endif /* local variables moved into u.cd */
-  u.cd.pFrame = p->pFrame;
-  u.cd.pIn = &u.cd.pFrame->aMem[pOp->p1 + u.cd.pFrame->aOp[u.cd.pFrame->pc].p1];
-  sqlite3VdbeMemShallowCopy(pOut, u.cd.pIn, MEM_Ephem);
+#endif /* local variables moved into u.ce */
+  u.ce.pFrame = p->pFrame;
+  u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1];
+  sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem);
   break;
 }
 
@@ -68847,22 +70737,22 @@ case OP_FkIfZero: {         /* jump */
 ** an integer.
 */
 case OP_MemMax: {        /* in2 */
-#if 0  /* local variables moved into u.ce */
+#if 0  /* local variables moved into u.cf */
   Mem *pIn1;
   VdbeFrame *pFrame;
-#endif /* local variables moved into u.ce */
+#endif /* local variables moved into u.cf */
   if( p->pFrame ){
-    for(u.ce.pFrame=p->pFrame; u.ce.pFrame->pParent; u.ce.pFrame=u.ce.pFrame->pParent);
-    u.ce.pIn1 = &u.ce.pFrame->aMem[pOp->p1];
+    for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent);
+    u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1];
   }else{
-    u.ce.pIn1 = &aMem[pOp->p1];
+    u.cf.pIn1 = &aMem[pOp->p1];
   }
-  assert( memIsValid(u.ce.pIn1) );
-  sqlite3VdbeMemIntegerify(u.ce.pIn1);
+  assert( memIsValid(u.cf.pIn1) );
+  sqlite3VdbeMemIntegerify(u.cf.pIn1);
   pIn2 = &aMem[pOp->p2];
   sqlite3VdbeMemIntegerify(pIn2);
-  if( u.ce.pIn1->u.i<pIn2->u.i){
-    u.ce.pIn1->u.i = pIn2->u.i;
+  if( u.cf.pIn1->u.i<pIn2->u.i){
+    u.cf.pIn1->u.i = pIn2->u.i;
   }
   break;
 }
@@ -68929,56 +70819,56 @@ case OP_IfZero: {        /* jump, in1 */
 ** successors.
 */
 case OP_AggStep: {
-#if 0  /* local variables moved into u.cf */
+#if 0  /* local variables moved into u.cg */
   int n;
   int i;
   Mem *pMem;
   Mem *pRec;
   sqlite3_context ctx;
   sqlite3_value **apVal;
-#endif /* local variables moved into u.cf */
+#endif /* local variables moved into u.cg */
 
-  u.cf.n = pOp->p5;
-  assert( u.cf.n>=0 );
-  u.cf.pRec = &aMem[pOp->p2];
-  u.cf.apVal = p->apArg;
-  assert( u.cf.apVal || u.cf.n==0 );
-  for(u.cf.i=0; u.cf.i<u.cf.n; u.cf.i++, u.cf.pRec++){
-    assert( memIsValid(u.cf.pRec) );
-    u.cf.apVal[u.cf.i] = u.cf.pRec;
-    memAboutToChange(p, u.cf.pRec);
-    sqlite3VdbeMemStoreType(u.cf.pRec);
-  }
-  u.cf.ctx.pFunc = pOp->p4.pFunc;
+  u.cg.n = pOp->p5;
+  assert( u.cg.n>=0 );
+  u.cg.pRec = &aMem[pOp->p2];
+  u.cg.apVal = p->apArg;
+  assert( u.cg.apVal || u.cg.n==0 );
+  for(u.cg.i=0; u.cg.i<u.cg.n; u.cg.i++, u.cg.pRec++){
+    assert( memIsValid(u.cg.pRec) );
+    u.cg.apVal[u.cg.i] = u.cg.pRec;
+    memAboutToChange(p, u.cg.pRec);
+    sqlite3VdbeMemStoreType(u.cg.pRec);
+  }
+  u.cg.ctx.pFunc = pOp->p4.pFunc;
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.cf.ctx.pMem = u.cf.pMem = &aMem[pOp->p3];
-  u.cf.pMem->n++;
-  u.cf.ctx.s.flags = MEM_Null;
-  u.cf.ctx.s.z = 0;
-  u.cf.ctx.s.zMalloc = 0;
-  u.cf.ctx.s.xDel = 0;
-  u.cf.ctx.s.db = db;
-  u.cf.ctx.isError = 0;
-  u.cf.ctx.pColl = 0;
-  u.cf.ctx.skipFlag = 0;
-  if( u.cf.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+  u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
+  u.cg.pMem->n++;
+  u.cg.ctx.s.flags = MEM_Null;
+  u.cg.ctx.s.z = 0;
+  u.cg.ctx.s.zMalloc = 0;
+  u.cg.ctx.s.xDel = 0;
+  u.cg.ctx.s.db = db;
+  u.cg.ctx.isError = 0;
+  u.cg.ctx.pColl = 0;
+  u.cg.ctx.skipFlag = 0;
+  if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
     assert( pOp>p->aOp );
     assert( pOp[-1].p4type==P4_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.cf.ctx.pColl = pOp[-1].p4.pColl;
+    u.cg.ctx.pColl = pOp[-1].p4.pColl;
   }
-  (u.cf.ctx.pFunc->xStep)(&u.cf.ctx, u.cf.n, u.cf.apVal); /* IMP: R-24505-23230 */
-  if( u.cf.ctx.isError ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cf.ctx.s));
-    rc = u.cf.ctx.isError;
+  (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */
+  if( u.cg.ctx.isError ){
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s));
+    rc = u.cg.ctx.isError;
   }
-  if( u.cf.ctx.skipFlag ){
+  if( u.cg.ctx.skipFlag ){
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.cf.i = pOp[-1].p1;
-    if( u.cf.i ) sqlite3VdbeMemSetInt64(&aMem[u.cf.i], 1);
+    u.cg.i = pOp[-1].p1;
+    if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1);
   }
 
-  sqlite3VdbeMemRelease(&u.cf.ctx.s);
+  sqlite3VdbeMemRelease(&u.cg.ctx.s);
 
   break;
 }
@@ -68996,19 +70886,19 @@ case OP_AggStep: {
 ** the step function was not previously called.
 */
 case OP_AggFinal: {
-#if 0  /* local variables moved into u.cg */
+#if 0  /* local variables moved into u.ch */
   Mem *pMem;
-#endif /* local variables moved into u.cg */
+#endif /* local variables moved into u.ch */
   assert( pOp->p1>0 && pOp->p1<=p->nMem );
-  u.cg.pMem = &aMem[pOp->p1];
-  assert( (u.cg.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
-  rc = sqlite3VdbeMemFinalize(u.cg.pMem, pOp->p4.pFunc);
+  u.ch.pMem = &aMem[pOp->p1];
+  assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+  rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
   if( rc ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cg.pMem));
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem));
   }
-  sqlite3VdbeChangeEncoding(u.cg.pMem, encoding);
-  UPDATE_MAX_BLOBSIZE(u.cg.pMem);
-  if( sqlite3VdbeMemTooBig(u.cg.pMem) ){
+  sqlite3VdbeChangeEncoding(u.ch.pMem, encoding);
+  UPDATE_MAX_BLOBSIZE(u.ch.pMem);
+  if( sqlite3VdbeMemTooBig(u.ch.pMem) ){
     goto too_big;
   }
   break;
@@ -69027,25 +70917,25 @@ case OP_AggFinal: {
 ** mem[P3+2] are initialized to -1.
 */
 case OP_Checkpoint: {
-#if 0  /* local variables moved into u.ch */
+#if 0  /* local variables moved into u.ci */
   int i;                          /* Loop counter */
   int aRes[3];                    /* Results */
   Mem *pMem;                      /* Write results here */
-#endif /* local variables moved into u.ch */
+#endif /* local variables moved into u.ci */
 
-  u.ch.aRes[0] = 0;
-  u.ch.aRes[1] = u.ch.aRes[2] = -1;
+  u.ci.aRes[0] = 0;
+  u.ci.aRes[1] = u.ci.aRes[2] = -1;
   assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
        || pOp->p2==SQLITE_CHECKPOINT_FULL
        || pOp->p2==SQLITE_CHECKPOINT_RESTART
   );
-  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ch.aRes[1], &u.ch.aRes[2]);
+  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]);
   if( rc==SQLITE_BUSY ){
     rc = SQLITE_OK;
-    u.ch.aRes[0] = 1;
+    u.ci.aRes[0] = 1;
   }
-  for(u.ch.i=0, u.ch.pMem = &aMem[pOp->p3]; u.ch.i<3; u.ch.i++, u.ch.pMem++){
-    sqlite3VdbeMemSetInt64(u.ch.pMem, (i64)u.ch.aRes[u.ch.i]);
+  for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){
+    sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]);
   }
   break;
 };  
@@ -69064,91 +70954,93 @@ case OP_Checkpoint: {
 ** Write a string containing the final journal-mode to register P2.
 */
 case OP_JournalMode: {    /* out2-prerelease */
-#if 0  /* local variables moved into u.ci */
+#if 0  /* local variables moved into u.cj */
   Btree *pBt;                     /* Btree to change journal mode of */
   Pager *pPager;                  /* Pager associated with pBt */
   int eNew;                       /* New journal mode */
   int eOld;                       /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
   const char *zFilename;          /* Name of database file for pPager */
-#endif /* local variables moved into u.ci */
+#endif
+#endif /* local variables moved into u.cj */
 
-  u.ci.eNew = pOp->p3;
-  assert( u.ci.eNew==PAGER_JOURNALMODE_DELETE
-       || u.ci.eNew==PAGER_JOURNALMODE_TRUNCATE
-       || u.ci.eNew==PAGER_JOURNALMODE_PERSIST
-       || u.ci.eNew==PAGER_JOURNALMODE_OFF
-       || u.ci.eNew==PAGER_JOURNALMODE_MEMORY
-       || u.ci.eNew==PAGER_JOURNALMODE_WAL
-       || u.ci.eNew==PAGER_JOURNALMODE_QUERY
+  u.cj.eNew = pOp->p3;
+  assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE
+       || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE
+       || u.cj.eNew==PAGER_JOURNALMODE_PERSIST
+       || u.cj.eNew==PAGER_JOURNALMODE_OFF
+       || u.cj.eNew==PAGER_JOURNALMODE_MEMORY
+       || u.cj.eNew==PAGER_JOURNALMODE_WAL
+       || u.cj.eNew==PAGER_JOURNALMODE_QUERY
   );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
 
-  u.ci.pBt = db->aDb[pOp->p1].pBt;
-  u.ci.pPager = sqlite3BtreePager(u.ci.pBt);
-  u.ci.eOld = sqlite3PagerGetJournalMode(u.ci.pPager);
-  if( u.ci.eNew==PAGER_JOURNALMODE_QUERY ) u.ci.eNew = u.ci.eOld;
-  if( !sqlite3PagerOkToChangeJournalMode(u.ci.pPager) ) u.ci.eNew = u.ci.eOld;
+  u.cj.pBt = db->aDb[pOp->p1].pBt;
+  u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
+  u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager);
+  if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld;
+  if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld;
 
 #ifndef SQLITE_OMIT_WAL
-  u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager, 1);
+  u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1);
 
   /* Do not allow a transition to journal_mode=WAL for a database
   ** in temporary storage or if the VFS does not support shared memory
   */
-  if( u.ci.eNew==PAGER_JOURNALMODE_WAL
-   && (sqlite3Strlen30(u.ci.zFilename)==0           /* Temp file */
-       || !sqlite3PagerWalSupported(u.ci.pPager))   /* No shared-memory support */
+  if( u.cj.eNew==PAGER_JOURNALMODE_WAL
+   && (sqlite3Strlen30(u.cj.zFilename)==0           /* Temp file */
+       || !sqlite3PagerWalSupported(u.cj.pPager))   /* No shared-memory support */
   ){
-    u.ci.eNew = u.ci.eOld;
+    u.cj.eNew = u.cj.eOld;
   }
 
-  if( (u.ci.eNew!=u.ci.eOld)
-   && (u.ci.eOld==PAGER_JOURNALMODE_WAL || u.ci.eNew==PAGER_JOURNALMODE_WAL)
+  if( (u.cj.eNew!=u.cj.eOld)
+   && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
   ){
     if( !db->autoCommit || db->activeVdbeCnt>1 ){
       rc = SQLITE_ERROR;
       sqlite3SetString(&p->zErrMsg, db,
           "cannot change %s wal mode from within a transaction",
-          (u.ci.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+          (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
       );
       break;
     }else{
 
-      if( u.ci.eOld==PAGER_JOURNALMODE_WAL ){
+      if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){
         /* If leaving WAL mode, close the log file. If successful, the call
         ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
         ** file. An EXCLUSIVE lock may still be held on the database file
         ** after a successful return.
         */
-        rc = sqlite3PagerCloseWal(u.ci.pPager);
+        rc = sqlite3PagerCloseWal(u.cj.pPager);
         if( rc==SQLITE_OK ){
-          sqlite3PagerSetJournalMode(u.ci.pPager, u.ci.eNew);
+          sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
         }
-      }else if( u.ci.eOld==PAGER_JOURNALMODE_MEMORY ){
+      }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){
         /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
         ** as an intermediate */
-        sqlite3PagerSetJournalMode(u.ci.pPager, PAGER_JOURNALMODE_OFF);
+        sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF);
       }
 
       /* Open a transaction on the database file. Regardless of the journal
       ** mode, this transaction always uses a rollback journal.
       */
-      assert( sqlite3BtreeIsInTrans(u.ci.pBt)==0 );
+      assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 );
       if( rc==SQLITE_OK ){
-        rc = sqlite3BtreeSetVersion(u.ci.pBt, (u.ci.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+        rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
       }
     }
   }
 #endif /* ifndef SQLITE_OMIT_WAL */
 
   if( rc ){
-    u.ci.eNew = u.ci.eOld;
+    u.cj.eNew = u.cj.eOld;
   }
-  u.ci.eNew = sqlite3PagerSetJournalMode(u.ci.pPager, u.ci.eNew);
+  u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
 
   pOut = &aMem[pOp->p2];
   pOut->flags = MEM_Str|MEM_Static|MEM_Term;
-  pOut->z = (char *)sqlite3JournalModename(u.ci.eNew);
+  pOut->z = (char *)sqlite3JournalModename(u.cj.eNew);
   pOut->n = sqlite3Strlen30(pOut->z);
   pOut->enc = SQLITE_UTF8;
   sqlite3VdbeChangeEncoding(pOut, encoding);
@@ -69177,14 +71069,14 @@ case OP_Vacuum: {
 ** P2. Otherwise, fall through to the next instruction.
 */
 case OP_IncrVacuum: {        /* jump */
-#if 0  /* local variables moved into u.cj */
+#if 0  /* local variables moved into u.ck */
   Btree *pBt;
-#endif /* local variables moved into u.cj */
+#endif /* local variables moved into u.ck */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.cj.pBt = db->aDb[pOp->p1].pBt;
-  rc = sqlite3BtreeIncrVacuum(u.cj.pBt);
+  u.ck.pBt = db->aDb[pOp->p1].pBt;
+  rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
   if( rc==SQLITE_DONE ){
     pc = pOp->p2 - 1;
     rc = SQLITE_OK;
@@ -69254,12 +71146,12 @@ case OP_TableLock: {
 ** code will be set to SQLITE_LOCKED.
 */
 case OP_VBegin: {
-#if 0  /* local variables moved into u.ck */
+#if 0  /* local variables moved into u.cl */
   VTable *pVTab;
-#endif /* local variables moved into u.ck */
-  u.ck.pVTab = pOp->p4.pVtab;
-  rc = sqlite3VtabBegin(db, u.ck.pVTab);
-  if( u.ck.pVTab ) importVtabErrMsg(p, u.ck.pVTab->pVtab);
+#endif /* local variables moved into u.cl */
+  u.cl.pVTab = pOp->p4.pVtab;
+  rc = sqlite3VtabBegin(db, u.cl.pVTab);
+  if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
   break;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69298,32 +71190,32 @@ case OP_VDestroy: {
 ** table and stores that cursor in P1.
 */
 case OP_VOpen: {
-#if 0  /* local variables moved into u.cl */
+#if 0  /* local variables moved into u.cm */
   VdbeCursor *pCur;
   sqlite3_vtab_cursor *pVtabCursor;
   sqlite3_vtab *pVtab;
   sqlite3_module *pModule;
-#endif /* local variables moved into u.cl */
+#endif /* local variables moved into u.cm */
 
-  u.cl.pCur = 0;
-  u.cl.pVtabCursor = 0;
-  u.cl.pVtab = pOp->p4.pVtab->pVtab;
-  u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule;
-  assert(u.cl.pVtab && u.cl.pModule);
-  rc = u.cl.pModule->xOpen(u.cl.pVtab, &u.cl.pVtabCursor);
-  importVtabErrMsg(p, u.cl.pVtab);
+  u.cm.pCur = 0;
+  u.cm.pVtabCursor = 0;
+  u.cm.pVtab = pOp->p4.pVtab->pVtab;
+  u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
+  assert(u.cm.pVtab && u.cm.pModule);
+  rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
+  importVtabErrMsg(p, u.cm.pVtab);
   if( SQLITE_OK==rc ){
     /* Initialize sqlite3_vtab_cursor base class */
-    u.cl.pVtabCursor->pVtab = u.cl.pVtab;
+    u.cm.pVtabCursor->pVtab = u.cm.pVtab;
 
-    /* Initialise vdbe cursor object */
-    u.cl.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
-    if( u.cl.pCur ){
-      u.cl.pCur->pVtabCursor = u.cl.pVtabCursor;
-      u.cl.pCur->pModule = u.cl.pVtabCursor->pVtab->pModule;
+    /* Initialize vdbe cursor object */
+    u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+    if( u.cm.pCur ){
+      u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
+      u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule;
     }else{
       db->mallocFailed = 1;
-      u.cl.pModule->xClose(u.cl.pVtabCursor);
+      u.cm.pModule->xClose(u.cm.pVtabCursor);
     }
   }
   break;
@@ -69350,7 +71242,7 @@ case OP_VOpen: {
 ** A jump is made to P2 if the result set after filtering would be empty.
 */
 case OP_VFilter: {   /* jump */
-#if 0  /* local variables moved into u.cm */
+#if 0  /* local variables moved into u.cn */
   int nArg;
   int iQuery;
   const sqlite3_module *pModule;
@@ -69362,45 +71254,45 @@ case OP_VFilter: {   /* jump */
   int res;
   int i;
   Mem **apArg;
-#endif /* local variables moved into u.cm */
+#endif /* local variables moved into u.cn */
 
-  u.cm.pQuery = &aMem[pOp->p3];
-  u.cm.pArgc = &u.cm.pQuery[1];
-  u.cm.pCur = p->apCsr[pOp->p1];
-  assert( memIsValid(u.cm.pQuery) );
-  REGISTER_TRACE(pOp->p3, u.cm.pQuery);
-  assert( u.cm.pCur->pVtabCursor );
-  u.cm.pVtabCursor = u.cm.pCur->pVtabCursor;
-  u.cm.pVtab = u.cm.pVtabCursor->pVtab;
-  u.cm.pModule = u.cm.pVtab->pModule;
+  u.cn.pQuery = &aMem[pOp->p3];
+  u.cn.pArgc = &u.cn.pQuery[1];
+  u.cn.pCur = p->apCsr[pOp->p1];
+  assert( memIsValid(u.cn.pQuery) );
+  REGISTER_TRACE(pOp->p3, u.cn.pQuery);
+  assert( u.cn.pCur->pVtabCursor );
+  u.cn.pVtabCursor = u.cn.pCur->pVtabCursor;
+  u.cn.pVtab = u.cn.pVtabCursor->pVtab;
+  u.cn.pModule = u.cn.pVtab->pModule;
 
   /* Grab the index number and argc parameters */
-  assert( (u.cm.pQuery->flags&MEM_Int)!=0 && u.cm.pArgc->flags==MEM_Int );
-  u.cm.nArg = (int)u.cm.pArgc->u.i;
-  u.cm.iQuery = (int)u.cm.pQuery->u.i;
+  assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int );
+  u.cn.nArg = (int)u.cn.pArgc->u.i;
+  u.cn.iQuery = (int)u.cn.pQuery->u.i;
 
   /* Invoke the xFilter method */
   {
-    u.cm.res = 0;
-    u.cm.apArg = p->apArg;
-    for(u.cm.i = 0; u.cm.i<u.cm.nArg; u.cm.i++){
-      u.cm.apArg[u.cm.i] = &u.cm.pArgc[u.cm.i+1];
-      sqlite3VdbeMemStoreType(u.cm.apArg[u.cm.i]);
+    u.cn.res = 0;
+    u.cn.apArg = p->apArg;
+    for(u.cn.i = 0; u.cn.i<u.cn.nArg; u.cn.i++){
+      u.cn.apArg[u.cn.i] = &u.cn.pArgc[u.cn.i+1];
+      sqlite3VdbeMemStoreType(u.cn.apArg[u.cn.i]);
     }
 
     p->inVtabMethod = 1;
-    rc = u.cm.pModule->xFilter(u.cm.pVtabCursor, u.cm.iQuery, pOp->p4.z, u.cm.nArg, u.cm.apArg);
+    rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
     p->inVtabMethod = 0;
-    importVtabErrMsg(p, u.cm.pVtab);
+    importVtabErrMsg(p, u.cn.pVtab);
     if( rc==SQLITE_OK ){
-      u.cm.res = u.cm.pModule->xEof(u.cm.pVtabCursor);
+      u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
     }
 
-    if( u.cm.res ){
+    if( u.cn.res ){
       pc = pOp->p2 - 1;
     }
   }
-  u.cm.pCur->nullRow = 0;
+  u.cn.pCur->nullRow = 0;
 
   break;
 }
@@ -69414,51 +71306,51 @@ case OP_VFilter: {   /* jump */
 ** P1 cursor is pointing to into register P3.
 */
 case OP_VColumn: {
-#if 0  /* local variables moved into u.cn */
+#if 0  /* local variables moved into u.co */
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
   Mem *pDest;
   sqlite3_context sContext;
-#endif /* local variables moved into u.cn */
+#endif /* local variables moved into u.co */
 
   VdbeCursor *pCur = p->apCsr[pOp->p1];
   assert( pCur->pVtabCursor );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.cn.pDest = &aMem[pOp->p3];
-  memAboutToChange(p, u.cn.pDest);
+  u.co.pDest = &aMem[pOp->p3];
+  memAboutToChange(p, u.co.pDest);
   if( pCur->nullRow ){
-    sqlite3VdbeMemSetNull(u.cn.pDest);
+    sqlite3VdbeMemSetNull(u.co.pDest);
     break;
   }
-  u.cn.pVtab = pCur->pVtabCursor->pVtab;
-  u.cn.pModule = u.cn.pVtab->pModule;
-  assert( u.cn.pModule->xColumn );
-  memset(&u.cn.sContext, 0, sizeof(u.cn.sContext));
+  u.co.pVtab = pCur->pVtabCursor->pVtab;
+  u.co.pModule = u.co.pVtab->pModule;
+  assert( u.co.pModule->xColumn );
+  memset(&u.co.sContext, 0, sizeof(u.co.sContext));
 
   /* The output cell may already have a buffer allocated. Move
-  ** the current contents to u.cn.sContext.s so in case the user-function
+  ** the current contents to u.co.sContext.s so in case the user-function
   ** can use the already allocated buffer instead of allocating a
   ** new one.
   */
-  sqlite3VdbeMemMove(&u.cn.sContext.s, u.cn.pDest);
-  MemSetTypeFlag(&u.cn.sContext.s, MEM_Null);
+  sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest);
+  MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
 
-  rc = u.cn.pModule->xColumn(pCur->pVtabCursor, &u.cn.sContext, pOp->p2);
-  importVtabErrMsg(p, u.cn.pVtab);
-  if( u.cn.sContext.isError ){
-    rc = u.cn.sContext.isError;
+  rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
+  importVtabErrMsg(p, u.co.pVtab);
+  if( u.co.sContext.isError ){
+    rc = u.co.sContext.isError;
   }
 
   /* Copy the result of the function to the P3 register. We
   ** do this regardless of whether or not an error occurred to ensure any
-  ** dynamic allocation in u.cn.sContext.s (a Mem struct) is  released.
+  ** dynamic allocation in u.co.sContext.s (a Mem struct) is  released.
   */
-  sqlite3VdbeChangeEncoding(&u.cn.sContext.s, encoding);
-  sqlite3VdbeMemMove(u.cn.pDest, &u.cn.sContext.s);
-  REGISTER_TRACE(pOp->p3, u.cn.pDest);
-  UPDATE_MAX_BLOBSIZE(u.cn.pDest);
+  sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding);
+  sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s);
+  REGISTER_TRACE(pOp->p3, u.co.pDest);
+  UPDATE_MAX_BLOBSIZE(u.co.pDest);
 
-  if( sqlite3VdbeMemTooBig(u.cn.pDest) ){
+  if( sqlite3VdbeMemTooBig(u.co.pDest) ){
     goto too_big;
   }
   break;
@@ -69473,22 +71365,22 @@ case OP_VColumn: {
 ** the end of its result set, then fall through to the next instruction.
 */
 case OP_VNext: {   /* jump */
-#if 0  /* local variables moved into u.co */
+#if 0  /* local variables moved into u.cp */
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
   int res;
   VdbeCursor *pCur;
-#endif /* local variables moved into u.co */
+#endif /* local variables moved into u.cp */
 
-  u.co.res = 0;
-  u.co.pCur = p->apCsr[pOp->p1];
-  assert( u.co.pCur->pVtabCursor );
-  if( u.co.pCur->nullRow ){
+  u.cp.res = 0;
+  u.cp.pCur = p->apCsr[pOp->p1];
+  assert( u.cp.pCur->pVtabCursor );
+  if( u.cp.pCur->nullRow ){
     break;
   }
-  u.co.pVtab = u.co.pCur->pVtabCursor->pVtab;
-  u.co.pModule = u.co.pVtab->pModule;
-  assert( u.co.pModule->xNext );
+  u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab;
+  u.cp.pModule = u.cp.pVtab->pModule;
+  assert( u.cp.pModule->xNext );
 
   /* Invoke the xNext() method of the module. There is no way for the
   ** underlying implementation to return an error if one occurs during
@@ -69497,14 +71389,14 @@ case OP_VNext: {   /* jump */
   ** some other method is next invoked on the save virtual table cursor.
   */
   p->inVtabMethod = 1;
-  rc = u.co.pModule->xNext(u.co.pCur->pVtabCursor);
+  rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
   p->inVtabMethod = 0;
-  importVtabErrMsg(p, u.co.pVtab);
+  importVtabErrMsg(p, u.cp.pVtab);
   if( rc==SQLITE_OK ){
-    u.co.res = u.co.pModule->xEof(u.co.pCur->pVtabCursor);
+    u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
   }
 
-  if( !u.co.res ){
+  if( !u.cp.res ){
     /* If there is data, jump to P2 */
     pc = pOp->p2 - 1;
   }
@@ -69520,24 +71412,24 @@ case OP_VNext: {   /* jump */
 ** in register P1 is passed as the zName argument to the xRename method.
 */
 case OP_VRename: {
-#if 0  /* local variables moved into u.cp */
+#if 0  /* local variables moved into u.cq */
   sqlite3_vtab *pVtab;
   Mem *pName;
-#endif /* local variables moved into u.cp */
+#endif /* local variables moved into u.cq */
 
-  u.cp.pVtab = pOp->p4.pVtab->pVtab;
-  u.cp.pName = &aMem[pOp->p1];
-  assert( u.cp.pVtab->pModule->xRename );
-  assert( memIsValid(u.cp.pName) );
-  REGISTER_TRACE(pOp->p1, u.cp.pName);
-  assert( u.cp.pName->flags & MEM_Str );
-  testcase( u.cp.pName->enc==SQLITE_UTF8 );
-  testcase( u.cp.pName->enc==SQLITE_UTF16BE );
-  testcase( u.cp.pName->enc==SQLITE_UTF16LE );
-  rc = sqlite3VdbeChangeEncoding(u.cp.pName, SQLITE_UTF8);
+  u.cq.pVtab = pOp->p4.pVtab->pVtab;
+  u.cq.pName = &aMem[pOp->p1];
+  assert( u.cq.pVtab->pModule->xRename );
+  assert( memIsValid(u.cq.pName) );
+  REGISTER_TRACE(pOp->p1, u.cq.pName);
+  assert( u.cq.pName->flags & MEM_Str );
+  testcase( u.cq.pName->enc==SQLITE_UTF8 );
+  testcase( u.cq.pName->enc==SQLITE_UTF16BE );
+  testcase( u.cq.pName->enc==SQLITE_UTF16LE );
+  rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
   if( rc==SQLITE_OK ){
-    rc = u.cp.pVtab->pModule->xRename(u.cp.pVtab, u.cp.pName->z);
-    importVtabErrMsg(p, u.cp.pVtab);
+    rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
+    importVtabErrMsg(p, u.cq.pVtab);
     p->expired = 0;
   }
   break;
@@ -69569,7 +71461,7 @@ case OP_VRename: {
 ** is set to the value of the rowid for the row just inserted.
 */
 case OP_VUpdate: {
-#if 0  /* local variables moved into u.cq */
+#if 0  /* local variables moved into u.cr */
   sqlite3_vtab *pVtab;
   sqlite3_module *pModule;
   int nArg;
@@ -69577,35 +71469,35 @@ case OP_VUpdate: {
   sqlite_int64 rowid;
   Mem **apArg;
   Mem *pX;
-#endif /* local variables moved into u.cq */
+#endif /* local variables moved into u.cr */
 
   assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback
        || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
   );
-  u.cq.pVtab = pOp->p4.pVtab->pVtab;
-  u.cq.pModule = (sqlite3_module *)u.cq.pVtab->pModule;
-  u.cq.nArg = pOp->p2;
+  u.cr.pVtab = pOp->p4.pVtab->pVtab;
+  u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
+  u.cr.nArg = pOp->p2;
   assert( pOp->p4type==P4_VTAB );
-  if( ALWAYS(u.cq.pModule->xUpdate) ){
+  if( ALWAYS(u.cr.pModule->xUpdate) ){
     u8 vtabOnConflict = db->vtabOnConflict;
-    u.cq.apArg = p->apArg;
-    u.cq.pX = &aMem[pOp->p3];
-    for(u.cq.i=0; u.cq.i<u.cq.nArg; u.cq.i++){
-      assert( memIsValid(u.cq.pX) );
-      memAboutToChange(p, u.cq.pX);
-      sqlite3VdbeMemStoreType(u.cq.pX);
-      u.cq.apArg[u.cq.i] = u.cq.pX;
-      u.cq.pX++;
+    u.cr.apArg = p->apArg;
+    u.cr.pX = &aMem[pOp->p3];
+    for(u.cr.i=0; u.cr.i<u.cr.nArg; u.cr.i++){
+      assert( memIsValid(u.cr.pX) );
+      memAboutToChange(p, u.cr.pX);
+      sqlite3VdbeMemStoreType(u.cr.pX);
+      u.cr.apArg[u.cr.i] = u.cr.pX;
+      u.cr.pX++;
     }
     db->vtabOnConflict = pOp->p5;
-    rc = u.cq.pModule->xUpdate(u.cq.pVtab, u.cq.nArg, u.cq.apArg, &u.cq.rowid);
+    rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
     db->vtabOnConflict = vtabOnConflict;
-    importVtabErrMsg(p, u.cq.pVtab);
+    importVtabErrMsg(p, u.cr.pVtab);
     if( rc==SQLITE_OK && pOp->p1 ){
-      assert( u.cq.nArg>1 && u.cq.apArg[0] && (u.cq.apArg[0]->flags&MEM_Null) );
-      db->lastRowid = lastRowid = u.cq.rowid;
+      assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
+      db->lastRowid = lastRowid = u.cr.rowid;
     }
-    if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
+    if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
       if( pOp->p5==OE_Ignore ){
         rc = SQLITE_OK;
       }else{
@@ -69663,21 +71555,24 @@ case OP_MaxPgcnt: {            /* out2-prerelease */
 ** the UTF-8 string contained in P4 is emitted on the trace callback.
 */
 case OP_Trace: {
-#if 0  /* local variables moved into u.cr */
+#if 0  /* local variables moved into u.cs */
   char *zTrace;
   char *z;
-#endif /* local variables moved into u.cr */
+#endif /* local variables moved into u.cs */
 
-  if( db->xTrace && (u.cr.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
-    u.cr.z = sqlite3VdbeExpandSql(p, u.cr.zTrace);
-    db->xTrace(db->pTraceArg, u.cr.z);
-    sqlite3DbFree(db, u.cr.z);
+  if( db->xTrace
+   && !p->doingRerun
+   && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+  ){
+    u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace);
+    db->xTrace(db->pTraceArg, u.cs.z);
+    sqlite3DbFree(db, u.cs.z);
   }
 #ifdef SQLITE_DEBUG
   if( (db->flags & SQLITE_SqlTrace)!=0
-   && (u.cr.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+   && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
   ){
-    sqlite3DebugPrintf("SQL-trace: %s\n", u.cr.zTrace);
+    sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace);
   }
 #endif /* SQLITE_DEBUG */
   break;
@@ -70120,7 +72015,7 @@ SQLITE_API int sqlite3_blob_open(
     }
     sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
     rc = blobSeekToRow(pBlob, iRow, &zErr);
-  } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA );
+  } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
 
 blob_open_out:
   if( rc==SQLITE_OK && db->mallocFailed==0 ){
@@ -70295,7 +72190,6 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
 */
 
 
-#ifndef SQLITE_OMIT_MERGE_SORT
 
 typedef struct VdbeSorterIter VdbeSorterIter;
 typedef struct SorterRecord SorterRecord;
@@ -70472,8 +72366,11 @@ static int vdbeSorterIterRead(
     int rc;                       /* sqlite3OsRead() return code */
 
     /* Determine how many bytes of data to read. */
-    nRead = (int)(p->iEof - p->iReadOff);
-    if( nRead>p->nBuffer ) nRead = p->nBuffer;
+    if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
+      nRead = p->nBuffer;
+    }else{
+      nRead = (int)(p->iEof - p->iReadOff);
+    }
     assert( nRead>0 );
 
     /* Read data from the file. Return early if an error occurs. */
@@ -71312,8 +73209,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
   return SQLITE_OK;
 }
 
-#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
-
 /************** End of vdbesort.c ********************************************/
 /************** Begin file journal.c *****************************************/
 /*
@@ -71376,6 +73271,14 @@ static int createFile(JournalFile *p){
         assert(p->iSize<=p->nBuf);
         rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
       }
+      if( rc!=SQLITE_OK ){
+        /* If an error occurred while writing to the file, close it before
+        ** returning. This way, SQLite uses the in-memory journal data to 
+        ** roll back changes made to the internal page-cache before this
+        ** function was called.  */
+        sqlite3OsClose(pReal);
+        p->pReal = 0;
+      }
     }
   }
   return rc;
@@ -71545,6 +73448,16 @@ SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
   return createFile((JournalFile *)p);
 }
 
+/*
+** The file-handle passed as the only argument is guaranteed to be an open
+** file. It may or may not be of class JournalFile. If the file is a
+** JournalFile, and the underlying file on disk has not yet been opened,
+** return 0. Otherwise, return 1.
+*/
+SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){
+  return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
+}
+
 /* 
 ** Return the number of bytes required to store a JournalFile that uses vfs
 ** pVfs to create the underlying on-disk files.
@@ -71787,7 +73700,9 @@ static const struct sqlite3_io_methods MemJournalMethods = {
   0,                /* xShmMap */
   0,                /* xShmLock */
   0,                /* xShmBarrier */
-  0                 /* xShmUnlock */
+  0,                /* xShmUnmap */
+  0,                /* xFetch */
+  0                 /* xUnfetch */
 };
 
 /* 
@@ -71931,7 +73846,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
 /*
 ** Call sqlite3WalkExpr() for every expression in Select statement p.
 ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
-** on the compound select chain, p->pPrior.
+** on the compound select chain, p->pPrior.  Invoke the xSelectCallback()
+** either before or after the walk of expressions and FROM clause, depending
+** on whether pWalker->bSelectDepthFirst is false or true, respectively.
 **
 ** Return WRC_Continue under normal conditions.  Return WRC_Abort if
 ** there is an abort request.
@@ -71945,14 +73862,23 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
   rc = WRC_Continue;
   pWalker->walkerDepth++;
   while( p ){
-    rc = pWalker->xSelectCallback(pWalker, p);
-    if( rc ) break;
+    if( !pWalker->bSelectDepthFirst ){
+       rc = pWalker->xSelectCallback(pWalker, p);
+       if( rc ) break;
+    }
     if( sqlite3WalkSelectExpr(pWalker, p)
      || sqlite3WalkSelectFrom(pWalker, p)
     ){
       pWalker->walkerDepth--;
       return WRC_Abort;
     }
+    if( pWalker->bSelectDepthFirst ){
+      rc = pWalker->xSelectCallback(pWalker, p);
+      /* Depth-first search is currently only used for
+      ** selectAddSubqueryTypeInfo() and that routine always returns
+      ** WRC_Continue (0).  So the following branch is never taken. */
+      if( NEVER(rc) ) break;
+    }
     p = p->pPrior;
   }
   pWalker->walkerDepth--;
@@ -72030,6 +73956,15 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
 ** from the result in the result-set.  We might fix this someday.  Or
 ** then again, we might not...
 **
+** If the reference is followed by a COLLATE operator, then make sure
+** the COLLATE operator is preserved.  For example:
+**
+**     SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
+**
+** Should be transformed into:
+**
+**     SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
+**
 ** The nSubquery parameter specifies how many levels of subquery the
 ** alias is removed from the original expression.  The usually value is
 ** zero but it might be more if the alias is contained within a subquery
@@ -72053,8 +73988,9 @@ static void resolveAlias(
   assert( pOrig!=0 );
   assert( pOrig->flags & EP_Resolved );
   db = pParse->db;
+  pDup = sqlite3ExprDup(db, pOrig, 0);
+  if( pDup==0 ) return;
   if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
-    pDup = sqlite3ExprDup(db, pOrig, 0);
     incrAggFunctionDepth(pDup, nSubquery);
     pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
     if( pDup==0 ) return;
@@ -72062,32 +73998,26 @@ static void resolveAlias(
       pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
     }
     pDup->iTable = pEList->a[iCol].iAlias;
-  }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
-    pDup = sqlite3ExprDup(db, pOrig, 0);
-    if( pDup==0 ) return;
-  }else{
-    char *zToken = pOrig->u.zToken;
-    assert( zToken!=0 );
-    pOrig->u.zToken = 0;
-    pDup = sqlite3ExprDup(db, pOrig, 0);
-    pOrig->u.zToken = zToken;
-    if( pDup==0 ) return;
-    assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
-    pDup->flags2 |= EP2_MallocedToken;
-    pDup->u.zToken = sqlite3DbStrDup(db, zToken);
   }
-  if( pExpr->flags & EP_ExpCollate ){
-    pDup->pColl = pExpr->pColl;
-    pDup->flags |= EP_ExpCollate;
+  if( pExpr->op==TK_COLLATE ){
+    pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
   }
 
   /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This 
   ** prevents ExprDelete() from deleting the Expr structure itself,
   ** allowing it to be repopulated by the memcpy() on the following line.
+  ** The pExpr->u.zToken might point into memory that will be freed by the
+  ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
+  ** make a copy of the token before doing the sqlite3DbFree().
   */
   ExprSetProperty(pExpr, EP_Static);
   sqlite3ExprDelete(db, pExpr);
   memcpy(pExpr, pDup, sizeof(*pExpr));
+  if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
+    assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
+    pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
+    pExpr->flags2 |= EP2_MallocedToken;
+  }
   sqlite3DbFree(db, pDup);
 }
 
@@ -72108,6 +74038,35 @@ static int nameInUsingClause(IdList *pUsing, const char *zCol){
   return 0;
 }
 
+/*
+** Subqueries stores the original database, table and column names for their
+** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
+** Check to see if the zSpan given to this routine matches the zDb, zTab,
+** and zCol.  If any of zDb, zTab, and zCol are NULL then those fields will
+** match anything.
+*/
+SQLITE_PRIVATE int sqlite3MatchSpanName(
+  const char *zSpan,
+  const char *zCol,
+  const char *zTab,
+  const char *zDb
+){
+  int n;
+  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+  if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
+    return 0;
+  }
+  zSpan += n+1;
+  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+  if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
+    return 0;
+  }
+  zSpan += n+1;
+  if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
+    return 0;
+  }
+  return 1;
+}
 
 /*
 ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
@@ -72157,13 +74116,27 @@ static int lookupName(
 
   assert( pNC );     /* the name context cannot be NULL. */
   assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
-  assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+  assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
 
   /* Initialize the node to no-match */
   pExpr->iTable = -1;
   pExpr->pTab = 0;
   ExprSetIrreducible(pExpr);
 
+  /* Translate the schema name in zDb into a pointer to the corresponding
+  ** schema.  If not found, pSchema will remain NULL and nothing will match
+  ** resulting in an appropriate error message toward the end of this routine
+  */
+  if( zDb ){
+    for(i=0; i<db->nDb; i++){
+      assert( db->aDb[i].zName );
+      if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+        pSchema = db->aDb[i].pSchema;
+        break;
+      }
+    }
+  }
+
   /* Start at the inner-most context and move outward until a match is found */
   while( pNC && cnt==0 ){
     ExprList *pEList;
@@ -72172,31 +74145,36 @@ static int lookupName(
     if( pSrcList ){
       for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
         Table *pTab;
-        int iDb;
         Column *pCol;
   
         pTab = pItem->pTab;
         assert( pTab!=0 && pTab->zName!=0 );
-        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
         assert( pTab->nCol>0 );
-        if( zTab ){
-          if( pItem->zAlias ){
-            char *zTabName = pItem->zAlias;
-            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-          }else{
-            char *zTabName = pTab->zName;
-            if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
-              continue;
-            }
-            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
-              continue;
+        if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
+          int hit = 0;
+          pEList = pItem->pSelect->pEList;
+          for(j=0; j<pEList->nExpr; j++){
+            if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
+              cnt++;
+              cntTab = 2;
+              pMatch = pItem;
+              pExpr->iColumn = j;
+              hit = 1;
             }
           }
+          if( hit || zTab==0 ) continue;
+        }
+        if( zDb && pTab->pSchema!=pSchema ){
+          continue;
+        }
+        if( zTab ){
+          const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
+          assert( zTabName!=0 );
+          if( sqlite3StrICmp(zTabName, zTab)!=0 ){
+            continue;
+          }
         }
         if( 0==(cntTab++) ){
-          pExpr->iTable = pItem->iCursor;
-          pExpr->pTab = pTab;
-          pSchema = pTab->pSchema;
           pMatch = pItem;
         }
         for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
@@ -72210,17 +74188,19 @@ static int lookupName(
               if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
             }
             cnt++;
-            pExpr->iTable = pItem->iCursor;
-            pExpr->pTab = pTab;
             pMatch = pItem;
-            pSchema = pTab->pSchema;
             /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
             pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
             break;
           }
         }
       }
-    }
+      if( pMatch ){
+        pExpr->iTable = pMatch->iCursor;
+        pExpr->pTab = pMatch->pTab;
+        pSchema = pExpr->pTab->pSchema;
+      }
+    } /* if( pSrcList ) */
 
 #ifndef SQLITE_OMIT_TRIGGER
     /* If we have not already resolved the name, then maybe 
@@ -72296,7 +74276,10 @@ static int lookupName(
     ** Note that the expression in the result set should have already been
     ** resolved by the time the WHERE clause is resolved.
     */
-    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
+    if( (pEList = pNC->pEList)!=0
+     && zTab==0
+     && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
+    ){
       for(j=0; j<pEList->nExpr; j++){
         char *zAs = pEList->a[j].zName;
         if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
@@ -72387,7 +74370,9 @@ static int lookupName(
 lookupname_end:
   if( cnt==1 ){
     assert( pNC!=0 );
-    sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+    if( pExpr->op!=TK_AS ){
+      sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+    }
     /* Increment the nRef value on all name contexts from TopNC up to
     ** the point where the name matched. */
     for(;;){
@@ -72555,7 +74540,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
         pNC->nErr++;
         is_agg = 0;
-      }else if( no_such_func ){
+      }else if( no_such_func && pParse->db->init.busy==0 ){
         sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
         pNC->nErr++;
       }else if( wrong_num_args ){
@@ -72774,7 +74759,7 @@ static int resolveCompoundOrderBy(
       int iCol = -1;
       Expr *pE, *pDup;
       if( pItem->done ) continue;
-      pE = pItem->pExpr;
+      pE = sqlite3ExprSkipCollate(pItem->pExpr);
       if( sqlite3ExprIsInteger(pE, &iCol) ){
         if( iCol<=0 || iCol>pEList->nExpr ){
           resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@@ -72792,14 +74777,20 @@ static int resolveCompoundOrderBy(
         }
       }
       if( iCol>0 ){
-        CollSeq *pColl = pE->pColl;
-        int flags = pE->flags & EP_ExpCollate;
+        /* Convert the ORDER BY term into an integer column number iCol,
+        ** taking care to preserve the COLLATE clause if it exists */
+        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+        if( pNew==0 ) return 1;
+        pNew->flags |= EP_IntValue;
+        pNew->u.iValue = iCol;
+        if( pItem->pExpr==pE ){
+          pItem->pExpr = pNew;
+        }else{
+          assert( pItem->pExpr->op==TK_COLLATE );
+          assert( pItem->pExpr->pLeft==pE );
+          pItem->pExpr->pLeft = pNew;
+        }
         sqlite3ExprDelete(db, pE);
-        pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
-        if( pE==0 ) return 1;
-        pE->pColl = pColl;
-        pE->flags |= EP_IntValue | flags;
-        pE->u.iValue = iCol;
         pItem->iOrderByCol = (u16)iCol;
         pItem->done = 1;
       }else{
@@ -72904,11 +74895,11 @@ static int resolveOrderGroupBy(
       pItem->iOrderByCol = (u16)iCol;
       continue;
     }
-    if( sqlite3ExprIsInteger(pE, &iCol) ){
+    if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
       /* The ORDER BY term is an integer constant.  Again, set the column
       ** number so that sqlite3ResolveOrderGroupBy() will convert the
       ** order-by term to a copy of the result-set expression */
-      if( iCol<1 ){
+      if( iCol<1 || iCol>0xffff ){
         resolveOutOfRangeError(pParse, zType, i+1, nResult);
         return 1;
       }
@@ -72985,23 +74976,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
       return WRC_Abort;
     }
   
-    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
-    ** resolve the result-set expression list.
-    */
-    sNC.ncFlags = NC_AllowAgg;
-    sNC.pSrcList = p->pSrc;
-    sNC.pNext = pOuterNC;
-  
-    /* Resolve names in the result set. */
-    pEList = p->pEList;
-    assert( pEList!=0 );
-    for(i=0; i<pEList->nExpr; i++){
-      Expr *pX = pEList->a[i].pExpr;
-      if( sqlite3ResolveExprNames(&sNC, pX) ){
-        return WRC_Abort;
-      }
-    }
-  
     /* Recursively resolve names in all subqueries
     */
     for(i=0; i<p->pSrc->nSrc; i++){
@@ -73029,6 +75003,23 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
       }
     }
   
+    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+    ** resolve the result-set expression list.
+    */
+    sNC.ncFlags = NC_AllowAgg;
+    sNC.pSrcList = p->pSrc;
+    sNC.pNext = pOuterNC;
+  
+    /* Resolve names in the result set. */
+    pEList = p->pEList;
+    assert( pEList!=0 );
+    for(i=0; i<pEList->nExpr; i++){
+      Expr *pX = pEList->a[i].pExpr;
+      if( sqlite3ResolveExprNames(&sNC, pX) ){
+        return WRC_Abort;
+      }
+    }
+  
     /* If there are no aggregate functions in the result-set, and no GROUP BY 
     ** expression, do not allow aggregates in any of the other expressions.
     */
@@ -73056,11 +75047,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
     ** re-evaluated for each reference to it.
     */
     sNC.pEList = p->pEList;
-    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||
-       sqlite3ResolveExprNames(&sNC, p->pHaving)
-    ){
-      return WRC_Abort;
-    }
+    sNC.ncFlags |= NC_AsMaybe;
+    if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
+    sNC.ncFlags &= ~NC_AsMaybe;
 
     /* The ORDER BY and GROUP BY clauses may not refer to terms in
     ** outer queries 
@@ -73181,6 +75171,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames(
 #endif
   savedHasAgg = pNC->ncFlags & NC_HasAgg;
   pNC->ncFlags &= ~NC_HasAgg;
+  memset(&w, 0, sizeof(w));
   w.xExprCallback = resolveExprStep;
   w.xSelectCallback = resolveSelectStep;
   w.pParse = pNC->pParse;
@@ -73221,6 +75212,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
   Walker w;
 
   assert( p!=0 );
+  memset(&w, 0, sizeof(w));
   w.xExprCallback = resolveExprStep;
   w.xSelectCallback = resolveSelectStep;
   w.pParse = pParse;
@@ -73262,7 +75254,9 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
 ** SELECT * FROM t1 WHERE (select a from t1);
 */
 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
-  int op = pExpr->op;
+  int op;
+  pExpr = sqlite3ExprSkipCollate(pExpr);
+  op = pExpr->op;
   if( op==TK_SELECT ){
     assert( pExpr->flags&EP_xIsSelect );
     return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
@@ -73287,66 +75281,89 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
 }
 
 /*
-** Set the explicit collating sequence for an expression to the
-** collating sequence supplied in the second argument.
+** Set the collating sequence for expression pExpr to be the collating
+** sequence named by pToken.   Return a pointer to a new Expr node that
+** implements the COLLATE operator.
+**
+** If a memory allocation error occurs, that fact is recorded in pParse->db
+** and the pExpr parameter is returned unchanged.
 */
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
-  if( pExpr && pColl ){
-    pExpr->pColl = pColl;
-    pExpr->flags |= EP_ExpCollate;
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
+  if( pCollName->n>0 ){
+    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
+    if( pNew ){
+      pNew->pLeft = pExpr;
+      pNew->flags |= EP_Collate;
+      pExpr = pNew;
+    }
   }
   return pExpr;
 }
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
+  Token s;
+  assert( zC!=0 );
+  s.z = zC;
+  s.n = sqlite3Strlen30(s.z);
+  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+}
 
 /*
-** Set the collating sequence for expression pExpr to be the collating
-** sequence named by pToken.   Return a pointer to the revised expression.
-** The collating sequence is marked as "explicit" using the EP_ExpCollate
-** flag.  An explicit collating sequence will override implicit
-** collating sequences.
+** Skip over any TK_COLLATE and/or TK_AS operators at the root of
+** an expression.
 */
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
-  char *zColl = 0;            /* Dequoted name of collation sequence */
-  CollSeq *pColl;
-  sqlite3 *db = pParse->db;
-  zColl = sqlite3NameFromToken(db, pCollName);
-  pColl = sqlite3LocateCollSeq(pParse, zColl);
-  sqlite3ExprSetColl(pExpr, pColl);
-  sqlite3DbFree(db, zColl);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
+  while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
+    pExpr = pExpr->pLeft;
+  }
   return pExpr;
 }
 
 /*
-** Return the default collation sequence for the expression pExpr. If
-** there is no default collation type, return 0.
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return NULL.
+**
+** The collating sequence might be determined by a COLLATE operator
+** or by the presence of a column with a defined collating sequence.
+** COLLATE operators take first precedence.  Left operands take
+** precedence over right operands.
 */
 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
+  sqlite3 *db = pParse->db;
   CollSeq *pColl = 0;
   Expr *p = pExpr;
   while( p ){
-    int op;
-    pColl = p->pColl;
-    if( pColl ) break;
-    op = p->op;
-    if( p->pTab!=0 && (
-        op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
-    )){
+    int op = p->op;
+    if( op==TK_CAST || op==TK_UPLUS ){
+      p = p->pLeft;
+      continue;
+    }
+    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
+    if( op==TK_COLLATE ){
+      pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
+      break;
+    }
+    if( p->pTab!=0
+     && (op==TK_AGG_COLUMN || op==TK_COLUMN
+          || op==TK_REGISTER || op==TK_TRIGGER)
+    ){
       /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
       ** a TK_COLUMN but was previously evaluated and cached in a register */
-      const char *zColl;
       int j = p->iColumn;
       if( j>=0 ){
-        sqlite3 *db = pParse->db;
-        zColl = p->pTab->aCol[j].zColl;
+        const char *zColl = p->pTab->aCol[j].zColl;
         pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
-        pExpr->pColl = pColl;
       }
       break;
     }
-    if( op!=TK_CAST && op!=TK_UPLUS ){
+    if( p->flags & EP_Collate ){
+      if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
+        p = p->pLeft;
+      }else{
+        p = p->pRight;
+      }
+    }else{
       break;
     }
-    p = p->pLeft;
   }
   if( sqlite3CheckCollSeq(pParse, pColl) ){ 
     pColl = 0;
@@ -73450,12 +75467,10 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
 ){
   CollSeq *pColl;
   assert( pLeft );
-  if( pLeft->flags & EP_ExpCollate ){
-    assert( pLeft->pColl );
-    pColl = pLeft->pColl;
-  }else if( pRight && pRight->flags & EP_ExpCollate ){
-    assert( pRight->pColl );
-    pColl = pRight->pColl;
+  if( pLeft->flags & EP_Collate ){
+    pColl = sqlite3ExprCollSeq(pParse, pLeft);
+  }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
+    pColl = sqlite3ExprCollSeq(pParse, pRight);
   }else{
     pColl = sqlite3ExprCollSeq(pParse, pLeft);
     if( !pColl ){
@@ -73685,17 +75700,11 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
   }else{
     if( pRight ){
       pRoot->pRight = pRight;
-      if( pRight->flags & EP_ExpCollate ){
-        pRoot->flags |= EP_ExpCollate;
-        pRoot->pColl = pRight->pColl;
-      }
+      pRoot->flags |= EP_Collate & pRight->flags;
     }
     if( pLeft ){
       pRoot->pLeft = pLeft;
-      if( pLeft->flags & EP_ExpCollate ){
-        pRoot->flags |= EP_ExpCollate;
-        pRoot->pColl = pLeft->pColl;
-      }
+      pRoot->flags |= EP_Collate & pLeft->flags;
     }
     exprSetHeight(pRoot);
   }
@@ -73847,7 +75856,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
       */
       ynVar i;
       for(i=0; i<pParse->nzVar; i++){
-        if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
+        if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
           pExpr->iColumn = x = (ynVar)i+1;
           break;
         }
@@ -73953,7 +75962,7 @@ static int dupedExprStructSize(Expr *p, int flags){
     assert( !ExprHasProperty(p, EP_FromJoin) ); 
     assert( (p->flags2 & EP2_MallocedToken)==0 );
     assert( (p->flags2 & EP2_Irreducible)==0 );
-    if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
+    if( p->pLeft || p->pRight || p->x.pList ){
       nSize = EXPR_REDUCEDSIZE | EP_Reduced;
     }else{
       nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
@@ -74161,6 +76170,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     struct SrcList_item *pNewItem = &pNew->a[i];
     struct SrcList_item *pOldItem = &p->a[i];
     Table *pTab;
+    pNewItem->pSchema = pOldItem->pSchema;
     pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
     pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
     pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
@@ -74169,6 +76179,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     pNewItem->addrFillSub = pOldItem->addrFillSub;
     pNewItem->regReturn = pOldItem->regReturn;
     pNewItem->isCorrelated = pOldItem->isCorrelated;
+    pNewItem->viaCoroutine = pOldItem->viaCoroutine;
     pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
     pNewItem->notIndexed = pOldItem->notIndexed;
     pNewItem->pIndex = pOldItem->pIndex;
@@ -74421,6 +76432,7 @@ static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
 }
 static int exprIsConst(Expr *p, int initFlag){
   Walker w;
+  memset(&w, 0, sizeof(w));
   w.u.i = initFlag;
   w.xExprCallback = exprNodeIsConstant;
   w.xSelectCallback = selectNodeIsConstant;
@@ -74651,24 +76663,34 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 
 /*
 ** This function is used by the implementation of the IN (...) operator.
-** It's job is to find or create a b-tree structure that may be used
-** either to test for membership of the (...) set or to iterate through
-** its members, skipping duplicates.
+** The pX parameter is the expression on the RHS of the IN operator, which
+** might be either a list of expressions or a subquery.
+**
+** The job of this routine is to find or create a b-tree object that can
+** be used either to test for membership in the RHS set or to iterate through
+** all members of the RHS set, skipping duplicates.
+**
+** A cursor is opened on the b-tree object that the RHS of the IN operator
+** and pX->iTable is set to the index of that cursor.
 **
-** The index of the cursor opened on the b-tree (database table, database index 
-** or ephermal table) is stored in pX->iTable before this function returns.
 ** The returned value of this function indicates the b-tree type, as follows:
 **
-**   IN_INDEX_ROWID - The cursor was opened on a database table.
-**   IN_INDEX_INDEX - The cursor was opened on a database index.
-**   IN_INDEX_EPH -   The cursor was opened on a specially created and
-**                    populated epheremal table.
+**   IN_INDEX_ROWID      - The cursor was opened on a database table.
+**   IN_INDEX_INDEX_ASC  - The cursor was opened on an ascending index.
+**   IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
+**   IN_INDEX_EPH        - The cursor was opened on a specially created and
+**                         populated epheremal table.
 **
-** An existing b-tree may only be used if the SELECT is of the simple
-** form:
+** An existing b-tree might be used if the RHS expression pX is a simple
+** subquery such as:
 **
 **     SELECT <column> FROM <table>
 **
+** If the RHS of the IN operator is a list or a more complex subquery, then
+** an ephemeral table might need to be generated from the RHS and then
+** pX->iTable made to point to the ephermeral table instead of an
+** existing table.  
+**
 ** If the prNotFound parameter is 0, then the b-tree will be used to iterate
 ** through the set members, skipping any duplicates. In this case an
 ** epheremal table must be used unless the selected <column> is guaranteed
@@ -74764,8 +76786,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
       ** comparison is the same as the affinity of the column. If
       ** it is not, it is not possible to use any index.
       */
-      char aff = comparisonAffinity(pX);
-      int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE);
+      int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
 
       for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
         if( (pIdx->aiColumn[0]==iCol)
@@ -74781,7 +76802,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
           sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                                pKey,P4_KEYINFO_HANDOFF);
           VdbeComment((v, "%s", pIdx->zName));
-          eType = IN_INDEX_INDEX;
+          assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
+          eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
 
           sqlite3VdbeJumpHere(v, iAddr);
           if( prNotFound && !pTab->aCol[iCol].notNull ){
@@ -74893,6 +76915,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
     case TK_IN: {
       char affinity;              /* Affinity of the LHS of the IN */
       KeyInfo keyInfo;            /* Keyinfo for the generated table */
+      static u8 sortOrder = 0;    /* Fake aSortOrder for keyInfo */
       int addr;                   /* Address of OP_OpenEphemeral instruction */
       Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
 
@@ -74920,6 +76943,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
       if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
       memset(&keyInfo, 0, sizeof(keyInfo));
       keyInfo.nField = 1;
+      keyInfo.aSortOrder = &sortOrder;
 
       if( ExprHasProperty(pExpr, EP_xIsSelect) ){
         /* Case 1:     expr IN (SELECT ...)
@@ -74960,6 +76984,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
           affinity = SQLITE_AFF_NONE;
         }
         keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+        keyInfo.aSortOrder = &sortOrder;
 
         /* Loop through each expression in <exprlist>. */
         r1 = sqlite3GetTempReg(pParse);
@@ -75286,7 +77311,7 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int
   ** for testing only - to verify that SQLite always gets the same answer
   ** with and without the column cache.
   */
-  if( pParse->db->flags & SQLITE_ColumnCache ) return;
+  if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
 
   /* First replace any existing entry.
   **
@@ -75483,8 +77508,8 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, in
 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
   int i;
   struct yColCache *p;
-  if( NEVER(iFrom==iTo) ) return;
-  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
+  assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
+  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     int x = p->iReg;
     if( x>=iFrom && x<iFrom+nReg ){
@@ -75493,18 +77518,6 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
   }
 }
 
-/*
-** Generate code to copy content from registers iFrom...iFrom+nReg-1
-** over to iTo..iTo+nReg-1.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){
-  int i;
-  if( NEVER(iFrom==iTo) ) return;
-  for(i=0; i<nReg; i++){
-    sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i);
-  }
-}
-
 #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
 /*
 ** Return true if any register in the range iFrom..iTo (inclusive)
@@ -75976,6 +77989,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       sqlite3ReleaseTempReg(pParse, r4);
       break;
     }
+    case TK_COLLATE: 
     case TK_UPLUS: {
       inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
       break;
@@ -76142,7 +78156,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
         sqlite3VdbeAddOp4(
             v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
       }else{
-        sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
+                              pExpr->affinity, pExpr->u.zToken, 0);
       }
 
       break;
@@ -76345,6 +78360,12 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
     case TK_ISNULL:  zUniOp = "ISNULL"; break;
     case TK_NOTNULL: zUniOp = "NOTNULL"; break;
 
+    case TK_COLLATE: {
+      sqlite3ExplainExpr(pOut, pExpr->pLeft);
+      sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
+      break;
+    }
+
     case TK_AGG_FUNCTION:
     case TK_CONST_FUNC:
     case TK_FUNCTION: {
@@ -76482,6 +78503,12 @@ SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
       sqlite3ExplainPush(pOut);
       sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
       sqlite3ExplainPop(pOut);
+      if( pList->a[i].zName ){
+        sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
+      }
+      if( pList->a[i].bSpanIsTab ){
+        sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
+      }
       if( i<pList->nExpr-1 ){
         sqlite3ExplainNL(pOut);
       }
@@ -76563,6 +78590,9 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
     case TK_REGISTER: {
       return WRC_Prune;
     }
+    case TK_COLLATE: {
+      return WRC_Continue;
+    }
     case TK_FUNCTION:
     case TK_AGG_FUNCTION:
     case TK_CONST_FUNC: {
@@ -76584,9 +78614,11 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
   }
   if( isAppropriateForFactoring(pExpr) ){
     int r1 = ++pParse->nMem;
-    int r2;
-    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
-    if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1);
+    int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+    /* If r2!=r1, it means that register r1 is never used.  That is harmless
+    ** but suboptimal, so we want to know about the situation to fix it.
+    ** Hence the following assert: */
+    assert( r2==r1 );
     pExpr->op2 = pExpr->op;
     pExpr->op = TK_REGISTER;
     pExpr->iTable = r2;
@@ -76614,9 +78646,9 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
 SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
   Walker w;
   if( pParse->cookieGoto ) return;
-  if( (pParse->db->flags & SQLITE_FactorOutConst)!=0 ) return;
+  if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
+  memset(&w, 0, sizeof(w));
   w.xExprCallback = evalConstExpr;
-  w.xSelectCallback = 0;
   w.pParse = pParse;
   sqlite3WalkExpr(&w, pExpr);
 }
@@ -76729,7 +78761,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
   int r1, r2;
 
   assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
-  if( NEVER(v==0) )     return;  /* Existance of VDBE checked by caller */
+  if( NEVER(v==0) )     return;  /* Existence of VDBE checked by caller */
   if( NEVER(pExpr==0) ) return;  /* No way this can happen */
   op = pExpr->op;
   switch( op ){
@@ -76849,7 +78881,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
   int r1, r2;
 
   assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
-  if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
+  if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
   if( pExpr==0 )    return;
 
   /* The value of pExpr->op and op are related as follows:
@@ -77003,7 +79035,15 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
     return 2;
   }
   if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
-  if( pA->op!=pB->op ) return 2;
+  if( pA->op!=pB->op ){
+    if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+      return 1;
+    }
+    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+      return 1;
+    }
+    return 2;
+  }
   if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
   if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
   if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
@@ -77015,11 +79055,9 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
   }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
     if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
     if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
-      return 2;
+      return pA->op==TK_COLLATE ? 1 : 2;
     }
   }
-  if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
-  if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
   return 0;
 }
 
@@ -77260,8 +79298,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         ExprSetIrreducible(pExpr);
         pExpr->iAgg = (i16)i;
         pExpr->pAggInfo = pAggInfo;
+        return WRC_Prune;
+      }else{
+        return WRC_Continue;
       }
-      return WRC_Prune;
     }
   }
   return WRC_Continue;
@@ -77273,9 +79313,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
 }
 
 /*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
+** Analyze the pExpr expression looking for aggregate functions and
+** for variables that need to be added to AggInfo object that pNC->pAggInfo
+** points to.  Additional entries are made on the AggInfo object as
+** necessary.
 **
 ** This routine should only be called after the expression has been
 ** analyzed by sqlite3ResolveExprNames().
@@ -77788,7 +79829,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
   assert( pSrc->nSrc==1 );
   assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
 
-  pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   if( !pTab ) goto exit_rename_table;
   iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
   zDb = db->aDb[iDb].zName;
@@ -78038,7 +80079,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
   ** If there is a NOT NULL constraint, then the default value for the
   ** column must not be NULL.
   */
-  if( pCol->isPrimKey ){
+  if( pCol->colFlags & COLFLAG_PRIMKEY ){
     sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
     return;
   }
@@ -78131,7 +80172,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
   assert( pParse->pNewTable==0 );
   assert( sqlite3BtreeHoldsAllMutexes(db) );
   if( db->mallocFailed ) goto exit_begin_add_column;
-  pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   if( !pTab ) goto exit_begin_add_column;
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -78675,7 +80716,7 @@ static void analyzeOneTable(
     /* Do not gather statistics on views or virtual tables */
     return;
   }
-  if( memcmp(pTab->zName, "sqlite_", 7)==0 ){
+  if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
     /* Do not gather statistics on system tables */
     return;
   }
@@ -79085,7 +81126,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
     if( pIndex==0 ) break;
     pIndex->aiRowEst[i] = v;
     if( *z==' ' ) z++;
-    if( memcmp(z, "unordered", 10)==0 ){
+    if( strcmp(z, "unordered")==0 ){
       pIndex->bUnordered = 1;
       break;
     }
@@ -79437,7 +81478,7 @@ static void attachFunc(
     }
   }
 
-  /* Allocate the new entry in the db->aDb[] array and initialise the schema
+  /* Allocate the new entry in the db->aDb[] array and initialize the schema
   ** hash tables.
   */
   if( db->aDb==db->aDbStatic ){
@@ -79454,7 +81495,7 @@ static void attachFunc(
 
   /* Open the database file. If the btree is successfully opened, use
   ** it to obtain the database schema. At this point the schema may
-  ** or may not be initialised.
+  ** or may not be initialized.
   */
   flags = db->openFlags;
   rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
@@ -79762,6 +81803,7 @@ SQLITE_PRIVATE int sqlite3FixInit(
   assert( db->nDb>iDb );
   pFix->pParse = pParse;
   pFix->zDb = db->aDb[iDb].zName;
+  pFix->pSchema = db->aDb[iDb].pSchema;
   pFix->zType = zType;
   pFix->pName = pName;
   return 1;
@@ -79792,14 +81834,15 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
   if( NEVER(pList==0) ) return 0;
   zDb = pFix->zDb;
   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
-    if( pItem->zDatabase==0 ){
-      pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
-    }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
+    if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
       sqlite3ErrorMsg(pFix->pParse,
          "%s %T cannot reference objects in database %s",
          pFix->zType, pFix->pName, pItem->zDatabase);
       return 1;
     }
+    sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
+    pItem->zDatabase = 0;
+    pItem->pSchema = pFix->pSchema;
 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
@@ -80265,6 +82308,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
   sqlite3 *db;
   Vdbe *v;
 
+  assert( pParse->pToplevel==0 );
   db = pParse->db;
   if( db->mallocFailed ) return;
   if( pParse->nested ) return;
@@ -80458,6 +82502,31 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
 }
 
 /*
+** Locate the table identified by *p.
+**
+** This is a wrapper around sqlite3LocateTable(). The difference between
+** sqlite3LocateTable() and this function is that this function restricts
+** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
+** non-NULL if it is part of a view or trigger program definition. See
+** sqlite3FixSrcList() for details.
+*/
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(
+  Parse *pParse, 
+  int isView, 
+  struct SrcList_item *p
+){
+  const char *zDb;
+  assert( p->pSchema==0 || p->zDatabase==0 );
+  if( p->pSchema ){
+    int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+    zDb = pParse->db->aDb[iDb].zName;
+  }else{
+    zDb = p->zDatabase;
+  }
+  return sqlite3LocateTable(pParse, isView, p->zName, zDb);
+}
+
+/*
 ** Locate the in-memory structure that describes 
 ** a particular index given the name of that index
 ** and the name of the database that contains the index.
@@ -81307,7 +83376,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
   pTab->tabFlags |= TF_HasPrimaryKey;
   if( pList==0 ){
     iCol = pTab->nCol - 1;
-    pTab->aCol[iCol].isPrimKey = 1;
+    pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
   }else{
     for(i=0; i<pList->nExpr; i++){
       for(iCol=0; iCol<pTab->nCol; iCol++){
@@ -81316,7 +83385,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
         }
       }
       if( iCol<pTab->nCol ){
-        pTab->aCol[iCol].isPrimKey = 1;
+        pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
       }
     }
     if( pList->nExpr>1 ) iCol = -1;
@@ -81433,10 +83502,7 @@ SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
 
   pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
   if( !initbusy && (!pColl || !pColl->xCmp) ){
-    pColl = sqlite3GetCollSeq(db, enc, pColl, zName);
-    if( !pColl ){
-      sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
-    }
+    pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
   }
 
   return pColl;
@@ -82135,6 +84201,7 @@ static void destroyTable(Parse *pParse, Table *pTab){
       return;
     }else{
       int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+      assert( iDb>=0 && iDb<pParse->db->nDb );
       destroyRootPage(pParse, iLargest, iDb);
       iDestroyed = iLargest;
     }
@@ -82214,7 +84281,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
   /* Drop all SQLITE_MASTER table and index entries that refer to the
   ** table. The program name loops through the master table and deletes
   ** every row that refers to a table of the same name as the one being
-  ** dropped. Triggers are handled seperately because a trigger can be
+  ** dropped. Triggers are handled separately because a trigger can be
   ** created in the temp database that refers to a table in another
   ** database.
   */
@@ -82252,8 +84319,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
   assert( pParse->nErr==0 );
   assert( pName->nSrc==1 );
   if( noErr ) db->suppressErr++;
-  pTab = sqlite3LocateTable(pParse, isView, 
-                            pName->a[0].zName, pName->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
   if( noErr ) db->suppressErr--;
 
   if( pTab==0 ){
@@ -82507,9 +84573,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   int tnum;                      /* Root page of index */
   Vdbe *v;                       /* Generate code into this virtual machine */
   KeyInfo *pKey;                 /* KeyInfo for index */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  int regIdxKey;                 /* Registers containing the index key */
-#endif
   int regRecord;                 /* Register holding assemblied index record */
   sqlite3 *db = pParse->db;      /* The database connection */
   int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
@@ -82537,13 +84600,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
                     (char *)pKey, P4_KEYINFO_HANDOFF);
   sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
 
-#ifndef SQLITE_OMIT_MERGE_SORT
   /* Open the sorter cursor if we are to use one. */
   iSorter = pParse->nTab++;
   sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
-#else
-  iSorter = iTab;
-#endif
 
   /* Open the table. Loop through all rows of the table, inserting index
   ** records into the sorter. */
@@ -82551,7 +84610,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
   regRecord = sqlite3GetTempReg(pParse);
 
-#ifndef SQLITE_OMIT_MERGE_SORT
   sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
   sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
   sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
@@ -82562,8 +84620,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
     sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
     addr2 = sqlite3VdbeCurrentAddr(v);
     sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+        OE_Abort, "indexed columns are not unique", P4_STATIC
     );
   }else{
     addr2 = sqlite3VdbeCurrentAddr(v);
@@ -82571,30 +84629,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
   sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
   sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-#else
-  regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
-  addr2 = addr1 + 1;
-  if( pIndex->onError!=OE_None ){
-    const int regRowid = regIdxKey + pIndex->nColumn;
-    const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
-    void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
-
-    /* The registers accessed by the OP_IsUnique opcode were allocated
-    ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
-    ** call above. Just before that function was freed they were released
-    ** (made available to the compiler for reuse) using 
-    ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
-    ** opcode use the values stored within seems dangerous. However, since
-    ** we can be sure that no other temp registers have been allocated
-    ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
-    */
-    sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
-  }
-  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
-  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-#endif
   sqlite3ReleaseTempReg(pParse, regRecord);
   sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
   sqlite3VdbeJumpHere(v, addr1);
@@ -82693,9 +84727,9 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
       ** sqlite3FixSrcList can never fail. */
       assert(0);
     }
-    pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName, 
-        pTblName->a[0].zDatabase);
-    if( !pTab || db->mallocFailed ) goto exit_create_index;
+    pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
+    assert( db->mallocFailed==0 || pTab==0 );
+    if( pTab==0 ) goto exit_create_index;
     assert( db->aDb[iDb].pSchema==pTab->pSchema );
   }else{
     assert( pName==0 );
@@ -82709,7 +84743,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   assert( pTab!=0 );
   assert( pParse->nErr==0 );
   if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 
-       && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){
+       && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
     sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
     goto exit_create_index;
   }
@@ -82806,12 +84840,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   for(i=0; i<pList->nExpr; i++){
     Expr *pExpr = pList->a[i].pExpr;
     if( pExpr ){
-      CollSeq *pColl = pExpr->pColl;
-      /* Either pColl!=0 or there was an OOM failure.  But if an OOM
-      ** failure we have quit before reaching this point. */
-      if( ALWAYS(pColl) ){
-        nExtra += (1 + sqlite3Strlen30(pColl->zName));
-      }
+      assert( pExpr->op==TK_COLLATE );
+      nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
     }
   }
 
@@ -82884,14 +84914,10 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
       goto exit_create_index;
     }
     pIndex->aiColumn[i] = j;
-    /* Justification of the ALWAYS(pListItem->pExpr->pColl):  Because of
-    ** the way the "idxlist" non-terminal is constructed by the parser,
-    ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
-    ** must exist or else there must have been an OOM error.  But if there
-    ** was an OOM error, we would never reach this point. */
-    if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
+    if( pListItem->pExpr ){
       int nColl;
-      zColl = pListItem->pExpr->pColl->zName;
+      assert( pListItem->pExpr->op==TK_COLLATE );
+      zColl = pListItem->pExpr->u.zToken;
       nColl = sqlite3Strlen30(zColl) + 1;
       assert( nExtra>=nColl );
       memcpy(zExtra, zColl, nColl);
@@ -82900,9 +84926,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
       nExtra -= nColl;
     }else{
       zColl = pTab->aCol[j].zColl;
-      if( !zColl ){
-        zColl = "BINARY";
-      }
+      if( !zColl ) zColl = "BINARY";
     }
     if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
       goto exit_create_index;
@@ -82958,7 +84982,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
           ** However the ON CONFLICT clauses are different. If both this 
           ** constraint and the previous equivalent constraint have explicit
           ** ON CONFLICT clauses this is an error. Otherwise, use the
-          ** explicitly specified behaviour for the index.
+          ** explicitly specified behavior for the index.
           */
           if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
             sqlite3ErrorMsg(pParse, 
@@ -83705,6 +85729,15 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
   Parse *pToplevel = sqlite3ParseToplevel(pParse);
 
+#ifndef SQLITE_OMIT_TRIGGER
+  if( pToplevel!=pParse ){
+    /* This branch is taken if a trigger is currently being coded. In this
+    ** case, set cookieGoto to a non-zero value to show that this function
+    ** has been called. This is used by the sqlite3ExprCodeConstants()
+    ** function. */
+    pParse->cookieGoto = -1;
+  }
+#endif
   if( pToplevel->cookieGoto==0 ){
     Vdbe *v = sqlite3GetVdbe(pToplevel);
     if( v==0 ) return;  /* This only happens if there was a prior error */
@@ -83802,12 +85835,19 @@ SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){
 ** error. The onError parameter determines which (if any) of the statement
 ** and/or current transaction is rolled back.
 */
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){
+SQLITE_PRIVATE void sqlite3HaltConstraint(
+  Parse *pParse,    /* Parsing context */
+  int errCode,      /* extended error code */
+  int onError,      /* Constraint type */
+  char *p4,         /* Error message */
+  int p4type        /* P4_STATIC or P4_TRANSIENT */
+){
   Vdbe *v = sqlite3GetVdbe(pParse);
+  assert( (errCode&0xff)==SQLITE_CONSTRAINT );
   if( onError==OE_Abort ){
     sqlite3MayAbort(pParse);
   }
-  sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type);
+  sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
 }
 
 /*
@@ -84054,17 +86094,18 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
 **
 ** The return value is either the collation sequence to be used in database
 ** db for collation type name zName, length nName, or NULL, if no collation
-** sequence can be found.
+** sequence can be found.  If no collation is found, leave an error message.
 **
 ** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
 */
 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
-  sqlite3* db,          /* The database connection */
+  Parse *pParse,        /* Parsing context */
   u8 enc,               /* The desired encoding for the collating sequence */
   CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */
   const char *zName     /* Collating sequence name */
 ){
   CollSeq *p;
+  sqlite3 *db = pParse->db;
 
   p = pColl;
   if( !p ){
@@ -84081,6 +86122,9 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
     p = 0;
   }
   assert( !p || p->xCmp );
+  if( p==0 ){
+    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
+  }
   return p;
 }
 
@@ -84099,10 +86143,8 @@ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
   if( pColl ){
     const char *zName = pColl->zName;
     sqlite3 *db = pParse->db;
-    CollSeq *p = sqlite3GetCollSeq(db, ENC(db), pColl, zName);
+    CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
     if( !p ){
-      sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
-      pParse->nErr++;
       return SQLITE_ERROR;
     }
     assert( p==pColl );
@@ -84489,7 +86531,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
   struct SrcList_item *pItem = pSrc->a;
   Table *pTab;
   assert( pItem && pSrc->nSrc==1 );
-  pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
   sqlite3DeleteTable(pParse->db, pItem->pTab);
   pItem->pTab = pTab;
   if( pTab ){
@@ -84550,29 +86592,28 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
   int iCur             /* Cursor number for ephemerial table */
 ){
   SelectDest dest;
-  Select *pDup;
+  Select *pSel;
+  SrcList *pFrom;
   sqlite3 *db = pParse->db;
+  int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
 
-  pDup = sqlite3SelectDup(db, pView->pSelect, 0);
-  if( pWhere ){
-    SrcList *pFrom;
-    
-    pWhere = sqlite3ExprDup(db, pWhere, 0);
-    pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
-    if( pFrom ){
-      assert( pFrom->nSrc==1 );
-      pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName);
-      pFrom->a[0].pSelect = pDup;
-      assert( pFrom->a[0].pOn==0 );
-      assert( pFrom->a[0].pUsing==0 );
-    }else{
-      sqlite3SelectDelete(db, pDup);
-    }
-    pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+  pWhere = sqlite3ExprDup(db, pWhere, 0);
+  pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
+
+  if( pFrom ){
+    assert( pFrom->nSrc==1 );
+    pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
+    pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
+    assert( pFrom->a[0].pOn==0 );
+    assert( pFrom->a[0].pUsing==0 );
   }
+
+  pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+  if( pSel ) pSel->selFlags |= SF_Materialize;
+
   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
-  sqlite3Select(pParse, pDup, &dest);
-  sqlite3SelectDelete(db, pDup);
+  sqlite3Select(pParse, pSel, &dest);
+  sqlite3SelectDelete(db, pSel);
 }
 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
 
@@ -85095,7 +87136,9 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
   }
   if( doMakeRec ){
     const char *zAff;
-    if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
+    if( pTab->pSelect
+     || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
+    ){
       zAff = 0;
     }else{
       zAff = sqlite3IndexAffinityStr(v, pIdx);
@@ -85278,6 +87321,56 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
 }
 
 /*
+** Implementation of the instr() function.
+**
+** instr(haystack,needle) finds the first occurrence of needle
+** in haystack and returns the number of previous characters plus 1,
+** or 0 if needle does not occur within haystack.
+**
+** If both haystack and needle are BLOBs, then the result is one more than
+** the number of bytes in haystack prior to the first occurrence of needle,
+** or 0 if needle never occurs in haystack.
+*/
+static void instrFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const unsigned char *zHaystack;
+  const unsigned char *zNeedle;
+  int nHaystack;
+  int nNeedle;
+  int typeHaystack, typeNeedle;
+  int N = 1;
+  int isText;
+
+  UNUSED_PARAMETER(argc);
+  typeHaystack = sqlite3_value_type(argv[0]);
+  typeNeedle = sqlite3_value_type(argv[1]);
+  if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
+  nHaystack = sqlite3_value_bytes(argv[0]);
+  nNeedle = sqlite3_value_bytes(argv[1]);
+  if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
+    zHaystack = sqlite3_value_blob(argv[0]);
+    zNeedle = sqlite3_value_blob(argv[1]);
+    isText = 0;
+  }else{
+    zHaystack = sqlite3_value_text(argv[0]);
+    zNeedle = sqlite3_value_text(argv[1]);
+    isText = 1;
+  }
+  while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+    N++;
+    do{
+      nHaystack--;
+      zHaystack++;
+    }while( isText && (zHaystack[0]&0xc0)==0x80 );
+  }
+  if( nNeedle>nHaystack ) N = 0;
+  sqlite3_result_int(context, N);
+}
+
+/*
 ** Implementation of the substr() function.
 **
 ** substr(x,p1,p2)  returns p2 characters of x[] beginning with p1.
@@ -85476,33 +87569,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   }
 }
 
-
-#if 0  /* This function is never used. */
-/*
-** The COALESCE() and IFNULL() functions used to be implemented as shown
-** here.  But now they are implemented as VDBE code so that unused arguments
-** do not have to be computed.  This legacy implementation is retained as
-** comment.
-*/
 /*
-** Implementation of the IFNULL(), NVL(), and COALESCE() functions.  
-** All three do the same thing.  They return the first non-NULL
-** argument.
+** The COALESCE() and IFNULL() functions are implemented as VDBE code so
+** that unused argument values do not have to be computed.  However, we
+** still need some kind of function implementation for this routines in
+** the function table.  That function implementation will never be called
+** so it doesn't matter what the implementation is.  We might as well use
+** the "version()" function as a substitute.
 */
-static void ifnullFunc(
-  sqlite3_context *context,
-  int argc,
-  sqlite3_value **argv
-){
-  int i;
-  for(i=0; i<argc; i++){
-    if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
-      sqlite3_result_value(context, argv[i]);
-      break;
-    }
-  }
-}
-#endif /* NOT USED */
 #define ifnullFunc versionFunc   /* Substitute function - never called */
 
 /*
@@ -85621,7 +87695,7 @@ struct compareInfo {
 ** whereas only characters less than 0x80 do in ASCII.
 */
 #if defined(SQLITE_EBCDIC)
-# define sqlite3Utf8Read(A,C)  (*(A++))
+# define sqlite3Utf8Read(A)    (*((*A)++))
 # define GlogUpperToLower(A)   A = sqlite3UpperToLower[A]
 #else
 # define GlogUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
@@ -85678,18 +87752,18 @@ static int patternCompare(
   u8 noCase = pInfo->noCase; 
   int prevEscape = 0;     /* True if the previous character was 'escape' */
 
-  while( (c = sqlite3Utf8Read(zPattern,&zPattern))!=0 ){
-    if( !prevEscape && c==matchAll ){
-      while( (c=sqlite3Utf8Read(zPattern,&zPattern)) == matchAll
+  while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
+    if( c==matchAll && !prevEscape ){
+      while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
                || c == matchOne ){
-        if( c==matchOne && sqlite3Utf8Read(zString, &zString)==0 ){
+        if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
           return 0;
         }
       }
       if( c==0 ){
         return 1;
       }else if( c==esc ){
-        c = sqlite3Utf8Read(zPattern, &zPattern);
+        c = sqlite3Utf8Read(&zPattern);
         if( c==0 ){
           return 0;
         }
@@ -85701,25 +87775,25 @@ static int patternCompare(
         }
         return *zString!=0;
       }
-      while( (c2 = sqlite3Utf8Read(zString,&zString))!=0 ){
+      while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
         if( noCase ){
           GlogUpperToLower(c2);
           GlogUpperToLower(c);
           while( c2 != 0 && c2 != c ){
-            c2 = sqlite3Utf8Read(zString, &zString);
+            c2 = sqlite3Utf8Read(&zString);
             GlogUpperToLower(c2);
           }
         }else{
           while( c2 != 0 && c2 != c ){
-            c2 = sqlite3Utf8Read(zString, &zString);
+            c2 = sqlite3Utf8Read(&zString);
           }
         }
         if( c2==0 ) return 0;
         if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
       }
       return 0;
-    }else if( !prevEscape && c==matchOne ){
-      if( sqlite3Utf8Read(zString, &zString)==0 ){
+    }else if( c==matchOne && !prevEscape ){
+      if( sqlite3Utf8Read(&zString)==0 ){
         return 0;
       }
     }else if( c==matchSet ){
@@ -85727,20 +87801,20 @@ static int patternCompare(
       assert( esc==0 );    /* This only occurs for GLOB, not LIKE */
       seen = 0;
       invert = 0;
-      c = sqlite3Utf8Read(zString, &zString);
+      c = sqlite3Utf8Read(&zString);
       if( c==0 ) return 0;
-      c2 = sqlite3Utf8Read(zPattern, &zPattern);
+      c2 = sqlite3Utf8Read(&zPattern);
       if( c2=='^' ){
         invert = 1;
-        c2 = sqlite3Utf8Read(zPattern, &zPattern);
+        c2 = sqlite3Utf8Read(&zPattern);
       }
       if( c2==']' ){
         if( c==']' ) seen = 1;
-        c2 = sqlite3Utf8Read(zPattern, &zPattern);
+        c2 = sqlite3Utf8Read(&zPattern);
       }
       while( c2 && c2!=']' ){
         if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
-          c2 = sqlite3Utf8Read(zPattern, &zPattern);
+          c2 = sqlite3Utf8Read(&zPattern);
           if( c>=prior_c && c<=c2 ) seen = 1;
           prior_c = 0;
         }else{
@@ -85749,7 +87823,7 @@ static int patternCompare(
           }
           prior_c = c2;
         }
-        c2 = sqlite3Utf8Read(zPattern, &zPattern);
+        c2 = sqlite3Utf8Read(&zPattern);
       }
       if( c2==0 || (seen ^ invert)==0 ){
         return 0;
@@ -85757,7 +87831,7 @@ static int patternCompare(
     }else if( esc==c && !prevEscape ){
       prevEscape = 1;
     }else{
-      c2 = sqlite3Utf8Read(zString, &zString);
+      c2 = sqlite3Utf8Read(&zString);
       if( noCase ){
         GlogUpperToLower(c);
         GlogUpperToLower(c2);
@@ -85772,6 +87846,13 @@ static int patternCompare(
 }
 
 /*
+** The sqlite3_strglob() interface.
+*/
+SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){
+  return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
+}
+
+/*
 ** Count the number of times that the LIKE operator (or GLOB which is
 ** just a variation of LIKE) gets called.  This is used for testing
 ** only.
@@ -85829,7 +87910,7 @@ static void likeFunc(
           "ESCAPE expression must be a single character", -1);
       return;
     }
-    escape = sqlite3Utf8Read(zEsc, &zEsc);
+    escape = sqlite3Utf8Read(&zEsc);
   }
   if( zA && zB ){
     struct compareInfo *pInfo = sqlite3_user_data(context);
@@ -86041,6 +88122,62 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
 }
 
 /*
+** The unicode() function.  Return the integer unicode code-point value
+** for the first character of the input string. 
+*/
+static void unicodeFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const unsigned char *z = sqlite3_value_text(argv[0]);
+  (void)argc;
+  if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
+}
+
+/*
+** The char() function takes zero or more arguments, each of which is
+** an integer.  It constructs a string where each character of the string
+** is the unicode character for the corresponding integer argument.
+*/
+static void charFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  unsigned char *z, *zOut;
+  int i;
+  zOut = z = sqlite3_malloc( argc*4 );
+  if( z==0 ){
+    sqlite3_result_error_nomem(context);
+    return;
+  }
+  for(i=0; i<argc; i++){
+    sqlite3_int64 x;
+    unsigned c;
+    x = sqlite3_value_int64(argv[i]);
+    if( x<0 || x>0x10ffff ) x = 0xfffd;
+    c = (unsigned)(x & 0x1fffff);
+    if( c<0x00080 ){
+      *zOut++ = (u8)(c&0xFF);
+    }else if( c<0x00800 ){
+      *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);
+      *zOut++ = 0x80 + (u8)(c & 0x3F);
+    }else if( c<0x10000 ){
+      *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);
+      *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+      *zOut++ = 0x80 + (u8)(c & 0x3F);
+    }else{
+      *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);
+      *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);
+      *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+      *zOut++ = 0x80 + (u8)(c & 0x3F);
+    }                                                    \
+  }
+  sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
+}
+
+/*
 ** The hex() function.  Interpret the argument as a blob.  Return
 ** a hexadecimal rendering as text.
 */
@@ -86664,8 +88801,11 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
     FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
     FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
+    FUNCTION(instr,              2, 0, 0, instrFunc        ),
     FUNCTION(substr,             2, 0, 0, substrFunc       ),
     FUNCTION(substr,             3, 0, 0, substrFunc       ),
+    FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),
+    FUNCTION(char,              -1, 0, 0, charFunc         ),
     FUNCTION(abs,                1, 0, 0, absFunc          ),
 #ifndef SQLITE_OMIT_FLOATING_POINT
     FUNCTION(round,              1, 0, 0, roundFunc        ),
@@ -86757,8 +88897,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** --------------------------
 **
 ** Foreign keys in SQLite come in two flavours: deferred and immediate.
-** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT
-** is returned and the current statement transaction rolled back. If a 
+** If an immediate foreign key constraint is violated,
+** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
+** statement transaction rolled back. If a 
 ** deferred foreign key constraint is violated, no action is taken 
 ** immediately. However if the application attempts to commit the 
 ** transaction before fixing the constraint violation, the attempt fails.
@@ -86822,7 +88963,8 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** Immediate constraints are usually handled similarly. The only difference 
 ** is that the counter used is stored as part of each individual statement
 ** object (struct Vdbe). If, after the statement has run, its immediate
-** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT
+** constraint counter is greater than zero,
+** it returns SQLITE_CONSTRAINT_FOREIGNKEY
 ** and the statement transaction is rolled back. An exception is an INSERT
 ** statement that inserts a single row only (no triggers). In this case,
 ** instead of using a counter, an exception is thrown immediately if the
@@ -86878,7 +89020,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** A foreign key constraint requires that the key columns in the parent
 ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
 ** Given that pParent is the parent table for foreign key constraint pFKey, 
-** search the schema a unique index on the parent key columns. 
+** search the schema for a unique index on the parent key columns. 
 **
 ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY 
 ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx 
@@ -86914,7 +89056,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** into pParse. If an OOM error occurs, non-zero is returned and the
 ** pParse->db->mallocFailed flag is set.
 */
-static int locateFkeyIndex(
+SQLITE_PRIVATE int sqlite3FkLocateIndex(
   Parse *pParse,                  /* Parse context to store any error in */
   Table *pParent,                 /* Parent table of FK constraint pFKey */
   FKey *pFKey,                    /* Foreign key to find index for */
@@ -87011,7 +89153,9 @@ static int locateFkeyIndex(
 
   if( !pIdx ){
     if( !pParse->disableTriggers ){
-      sqlite3ErrorMsg(pParse, "foreign key mismatch");
+      sqlite3ErrorMsg(pParse,
+           "foreign key mismatch - \"%w\" referencing \"%w\"",
+           pFKey->pFrom->zName, pFKey->zTo);
     }
     sqlite3DbFree(pParse->db, aiCol);
     return 1;
@@ -87160,8 +89304,8 @@ static void fkLookupParent(
     ** incrementing a counter. This is necessary as the VM code is being
     ** generated for will not open a statement transaction.  */
     assert( nIncr==1 );
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+        OE_Abort, "foreign key constraint failed", P4_STATIC
     );
   }else{
     if( nIncr>0 && pFKey->isDeferred==0 ){
@@ -87247,12 +89391,15 @@ static void fkScanChildren(
       ** expression to the parent key column defaults.  */
       if( pIdx ){
         Column *pCol;
+        const char *zColl;
         iCol = pIdx->aiColumn[i];
         pCol = &pTab->aCol[iCol];
         if( pTab->iPKey==iCol ) iCol = -1;
         pLeft->iTable = regData+iCol+1;
         pLeft->affinity = pCol->affinity;
-        pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
+        zColl = pCol->zColl;
+        if( zColl==0 ) zColl = db->pDfltColl->zName;
+        pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
       }else{
         pLeft->iTable = regData;
         pLeft->affinity = SQLITE_AFF_INTEGER;
@@ -87398,8 +89545,8 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
     ** any modifications to the schema are made. This is because statement
     ** transactions are not able to rollback schema changes.  */
     sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+        OE_Abort, "foreign key constraint failed", P4_STATIC
     );
 
     if( iSkip ){
@@ -87469,7 +89616,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
     }else{
       pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
     }
-    if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+    if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
       assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
       if( !isIgnoreErrors || db->mallocFailed ) return;
       if( pTo==0 ){
@@ -87549,7 +89696,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
       continue;
     }
 
-    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
+    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
       if( !isIgnoreErrors || db->mallocFailed ) return;
       continue;
     }
@@ -87604,7 +89751,7 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
     }
     for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
       Index *pIdx = 0;
-      locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
+      sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
       if( pIdx ){
         for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
       }
@@ -87661,7 +89808,8 @@ SQLITE_PRIVATE int sqlite3FkRequired(
           int iKey;
           for(iKey=0; iKey<pTab->nCol; iKey++){
             Column *pCol = &pTab->aCol[iKey];
-            if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) : pCol->isPrimKey) ){
+            if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey)
+                      : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){
               if( aChange[iKey]>=0 ) return 1;
               if( iKey==pTab->iPKey && chngRowid ) return 1;
             }
@@ -87729,7 +89877,7 @@ static Trigger *fkActionTrigger(
     int i;                        /* Iterator variable */
     Expr *pWhen = 0;              /* WHEN clause for the trigger */
 
-    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
+    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
     assert( aiCol || pFKey->nCol==1 );
 
     for(i=0; i<pFKey->nCol; i++){
@@ -87982,7 +90130,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
   int opcode      /* OP_OpenRead or OP_OpenWrite */
 ){
   Vdbe *v;
-  if( IsVirtual(pTab) ) return;
+  assert( !IsVirtual(pTab) );
   v = sqlite3GetVdbe(p);
   assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
   sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
@@ -88277,6 +90425,97 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
 #endif /* SQLITE_OMIT_AUTOINCREMENT */
 
 
+/*
+** Generate code for a co-routine that will evaluate a subquery one
+** row at a time.
+**
+** The pSelect parameter is the subquery that the co-routine will evaluation.
+** Information about the location of co-routine and the registers it will use
+** is returned by filling in the pDest object.
+**
+** Registers are allocated as follows:
+**
+**   pDest->iSDParm      The register holding the next entry-point of the
+**                       co-routine.  Run the co-routine to its next breakpoint
+**                       by calling "OP_Yield $X" where $X is pDest->iSDParm.
+**
+**   pDest->iSDParm+1    The register holding the "completed" flag for the
+**                       co-routine. This register is 0 if the previous Yield
+**                       generated a new result row, or 1 if the subquery
+**                       has completed.  If the Yield is called again
+**                       after this register becomes 1, then the VDBE will
+**                       halt with an SQLITE_INTERNAL error.
+**
+**   pDest->iSdst        First result register.
+**
+**   pDest->nSdst        Number of result registers.
+**
+** This routine handles all of the register allocation and fills in the
+** pDest structure appropriately.
+**
+** Here is a schematic of the generated code assuming that X is the 
+** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
+** completed flag reg[pDest->iSDParm+1], and R and S are the range of
+** registers that hold the result set, reg[pDest->iSdst] through
+** reg[pDest->iSdst+pDest->nSdst-1]:
+**
+**         X <- A
+**         EOF <- 0
+**         goto B
+**      A: setup for the SELECT
+**         loop rows in the SELECT
+**           load results into registers R..S
+**           yield X
+**         end loop
+**         cleanup after the SELECT
+**         EOF <- 1
+**         yield X
+**         halt-error
+**      B:
+**
+** To use this subroutine, the caller generates code as follows:
+**
+**         [ Co-routine generated by this subroutine, shown above ]
+**      S: yield X
+**         if EOF goto E
+**         if skip this row, goto C
+**         if terminate loop, goto E
+**         deal with this row
+**      C: goto S
+**      E:
+*/
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
+  int regYield;       /* Register holding co-routine entry-point */
+  int regEof;         /* Register holding co-routine completion flag */
+  int addrTop;        /* Top of the co-routine */
+  int j1;             /* Jump instruction */
+  int rc;             /* Result code */
+  Vdbe *v;            /* VDBE under construction */
+
+  regYield = ++pParse->nMem;
+  regEof = ++pParse->nMem;
+  v = sqlite3GetVdbe(pParse);
+  addrTop = sqlite3VdbeCurrentAddr(v);
+  sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
+  VdbeComment((v, "Co-routine entry point"));
+  sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);           /* EOF <- 0 */
+  VdbeComment((v, "Co-routine completion flag"));
+  sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
+  j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+  rc = sqlite3Select(pParse, pSelect, pDest);
+  assert( pParse->nErr==0 || rc );
+  if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
+  if( rc ) return rc;
+  sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);            /* EOF <- 1 */
+  sqlite3VdbeAddOp1(v, OP_Yield, regYield);   /* yield X */
+  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
+  VdbeComment((v, "End of coroutine"));
+  sqlite3VdbeJumpHere(v, j1);                             /* label B: */
+  return rc;
+}
+
+
+
 /* Forward declaration */
 static int xferOptimization(
   Parse *pParse,        /* Parser context */
@@ -88525,51 +90764,12 @@ SQLITE_PRIVATE void sqlite3Insert(
   ** co-routine is the common header to the 3rd and 4th templates.
   */
   if( pSelect ){
-    /* Data is coming from a SELECT.  Generate code to implement that SELECT
-    ** as a co-routine.  The code is common to both the 3rd and 4th
-    ** templates:
-    **
-    **         EOF <- 0
-    **         X <- A
-    **         goto B
-    **      A: setup for the SELECT
-    **         loop over the tables in the SELECT
-    **           load value into register R..R+n
-    **           yield X
-    **         end loop
-    **         cleanup after the SELECT
-    **         EOF <- 1
-    **         yield X
-    **         halt-error
-    **
-    ** On each invocation of the co-routine, it puts a single row of the
-    ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1.
-    ** (These output registers are allocated by sqlite3Select().)  When
-    ** the SELECT completes, it sets the EOF flag stored in regEof.
-    */
-    int rc, j1;
-
-    regEof = ++pParse->nMem;
-    sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);      /* EOF <- 0 */
-    VdbeComment((v, "SELECT eof flag"));
-    sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);
-    addrSelect = sqlite3VdbeCurrentAddr(v)+2;
-    sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iSDParm);
-    j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
-    VdbeComment((v, "Jump over SELECT coroutine"));
-
-    /* Resolve the expressions in the SELECT statement and execute it. */
-    rc = sqlite3Select(pParse, pSelect, &dest);
-    assert( pParse->nErr==0 || rc );
-    if( rc || NEVER(pParse->nErr) || db->mallocFailed ){
-      goto insert_cleanup;
-    }
-    sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);         /* EOF <- 1 */
-    sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);   /* yield X */
-    sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
-    VdbeComment((v, "End of SELECT coroutine"));
-    sqlite3VdbeJumpHere(v, j1);                          /* label B: */
+    /* Data is coming from a SELECT.  Generate a co-routine to run that
+    ** SELECT. */
+    int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
+    if( rc ) goto insert_cleanup;
 
+    regEof = dest.iSDParm + 1;
     regFromSelect = dest.iSdst;
     assert( pSelect->pEList );
     nColumn = pSelect->pEList->nExpr;
@@ -89150,7 +91350,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Fail: {
         char *zMsg;
         sqlite3VdbeAddOp3(v, OP_HaltIfNull,
-                                  SQLITE_CONSTRAINT, onError, regData+i);
+                          SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
         zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
                               pTab->zName, pTab->aCol[i].zName);
         sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
@@ -89190,7 +91390,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
         }else{
           zConsName = 0;
         }
-        sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
+                              onError, zConsName, P4_DYNAMIC);
       }
       sqlite3VdbeResolveLabel(v, allOk);
     }
@@ -89221,8 +91422,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Rollback:
       case OE_Abort:
       case OE_Fail: {
-        sqlite3HaltConstraint(
-          pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+           onError, "PRIMARY KEY must be unique", P4_STATIC);
         break;
       }
       case OE_Replace: {
@@ -89349,7 +91550,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
         sqlite3StrAccumAppend(&errMsg,
             pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
         zErr = sqlite3StrAccumFinish(&errMsg);
-        sqlite3HaltConstraint(pParse, onError, zErr, 0);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+                              onError, zErr, 0);
         sqlite3DbFree(errMsg.db, zErr);
         break;
       }
@@ -89648,7 +91850,7 @@ static int xferOptimization(
   ** we have to check the semantics.
   */
   pItem = pSelect->pSrc->a;
-  pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+  pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
   if( pSrc==0 ){
     return 0;   /* FROM clause does not contain a real table */
   }
@@ -89757,8 +91959,8 @@ static int xferOptimization(
   if( pDest->iPKey>=0 ){
     addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
     addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
-    sqlite3HaltConstraint(
-        pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+        onError, "PRIMARY KEY must be unique", P4_STATIC);
     sqlite3VdbeJumpHere(v, addr2);
     autoIncStep(pParse, regAutoinc, regRowid);
   }else if( pDest->pIndex==0 ){
@@ -89850,7 +92052,6 @@ SQLITE_API int sqlite3_exec(
   const char *zLeftover;      /* Tail of unprocessed SQL */
   sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
   char **azCols = 0;          /* Names of result columns */
-  int nRetry = 0;             /* Number of retry attempts */
   int callbackIsInit;         /* True if callback data is initialized */
 
   if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
@@ -89858,12 +92059,12 @@ SQLITE_API int sqlite3_exec(
 
   sqlite3_mutex_enter(db->mutex);
   sqlite3Error(db, SQLITE_OK, 0);
-  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
+  while( rc==SQLITE_OK && zSql[0] ){
     int nCol;
     char **azVals = 0;
 
     pStmt = 0;
-    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
+    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
     assert( rc==SQLITE_OK || pStmt==0 );
     if( rc!=SQLITE_OK ){
       continue;
@@ -89920,11 +92121,8 @@ SQLITE_API int sqlite3_exec(
       if( rc!=SQLITE_ROW ){
         rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
         pStmt = 0;
-        if( rc!=SQLITE_SCHEMA ){
-          nRetry = 0;
-          zSql = zLeftover;
-          while( sqlite3Isspace(zSql[0]) ) zSql++;
-        }
+        zSql = zLeftover;
+        while( sqlite3Isspace(zSql[0]) ) zSql++;
         break;
       }
     }
@@ -90215,6 +92413,20 @@ struct sqlite3_api_routines {
   int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
   int (*vtab_config)(sqlite3*,int op,...);
   int (*vtab_on_conflict)(sqlite3*);
+  /* Version 3.7.16 and later */
+  int (*close_v2)(sqlite3*);
+  const char *(*db_filename)(sqlite3*,const char*);
+  int (*db_readonly)(sqlite3*,const char*);
+  int (*db_release_memory)(sqlite3*);
+  const char *(*errstr)(int);
+  int (*stmt_busy)(sqlite3_stmt*);
+  int (*stmt_readonly)(sqlite3_stmt*);
+  int (*stricmp)(const char*,const char*);
+  int (*uri_boolean)(const char*,const char*,int);
+  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
+  const char *(*uri_parameter)(const char*,const char*);
+  char *(*vsnprintf)(int,char*,const char*,va_list);
+  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
 };
 
 /*
@@ -90418,10 +92630,33 @@ struct sqlite3_api_routines {
 #define sqlite3_blob_reopen            sqlite3_api->blob_reopen
 #define sqlite3_vtab_config            sqlite3_api->vtab_config
 #define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
+/* Version 3.7.16 and later */
+#define sqlite3_close_v2               sqlite3_api->close_v2
+#define sqlite3_db_filename            sqlite3_api->db_filename
+#define sqlite3_db_readonly            sqlite3_api->db_readonly
+#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
+#define sqlite3_errstr                 sqlite3_api->errstr
+#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
+#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
+#define sqlite3_stricmp                sqlite3_api->stricmp
+#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
+#define sqlite3_uri_int64              sqlite3_api->uri_int64
+#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
+#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
+#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
 #endif /* SQLITE_CORE */
 
-#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
-#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;
+#ifndef SQLITE_CORE
+  /* This case when the file really is being compiled as a loadable 
+  ** extension */
+# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
+# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
+#else
+  /* This case when the file is being statically linked into the 
+  ** application */
+# define SQLITE_EXTENSION_INIT1     /*no-op*/
+# define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
+#endif
 
 #endif /* _SQLITE3EXT_H_ */
 
@@ -90787,6 +93022,19 @@ static const sqlite3_api_routines sqlite3Apis = {
   sqlite3_blob_reopen,
   sqlite3_vtab_config,
   sqlite3_vtab_on_conflict,
+  sqlite3_close_v2,
+  sqlite3_db_filename,
+  sqlite3_db_readonly,
+  sqlite3_db_release_memory,
+  sqlite3_errstr,
+  sqlite3_stmt_busy,
+  sqlite3_stmt_readonly,
+  sqlite3_stricmp,
+  sqlite3_uri_boolean,
+  sqlite3_uri_int64,
+  sqlite3_uri_parameter,
+  sqlite3_vsnprintf,
+  sqlite3_wal_checkpoint_v2
 };
 
 /*
@@ -90811,8 +93059,23 @@ static int sqlite3LoadExtension(
   void *handle;
   int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
   char *zErrmsg = 0;
+  const char *zEntry;
+  char *zAltEntry = 0;
   void **aHandle;
   int nMsg = 300 + sqlite3Strlen30(zFile);
+  int ii;
+
+  /* Shared library endings to try if zFile cannot be loaded as written */
+  static const char *azEndings[] = {
+#if SQLITE_OS_WIN
+     "dll"   
+#elif defined(__APPLE__)
+     "dylib"
+#else
+     "so"
+#endif
+  };
+
 
   if( pzErrMsg ) *pzErrMsg = 0;
 
@@ -90829,11 +93092,17 @@ static int sqlite3LoadExtension(
     return SQLITE_ERROR;
   }
 
-  if( zProc==0 ){
-    zProc = "sqlite3_extension_init";
-  }
+  zEntry = zProc ? zProc : "sqlite3_extension_init";
 
   handle = sqlite3OsDlOpen(pVfs, zFile);
+#if SQLITE_OS_UNIX || SQLITE_OS_WIN
+  for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
+    char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]);
+    if( zAltFile==0 ) return SQLITE_NOMEM;
+    handle = sqlite3OsDlOpen(pVfs, zAltFile);
+    sqlite3_free(zAltFile);
+  }
+#endif
   if( handle==0 ){
     if( pzErrMsg ){
       *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
@@ -90846,20 +93115,57 @@ static int sqlite3LoadExtension(
     return SQLITE_ERROR;
   }
   xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
-                   sqlite3OsDlSym(pVfs, handle, zProc);
+                   sqlite3OsDlSym(pVfs, handle, zEntry);
+
+  /* If no entry point was specified and the default legacy
+  ** entry point name "sqlite3_extension_init" was not found, then
+  ** construct an entry point name "sqlite3_X_init" where the X is
+  ** replaced by the lowercase value of every ASCII alphabetic 
+  ** character in the filename after the last "/" upto the first ".",
+  ** and eliding the first three characters if they are "lib".  
+  ** Examples:
+  **
+  **    /usr/local/lib/libExample5.4.3.so ==>  sqlite3_example_init
+  **    C:/lib/mathfuncs.dll              ==>  sqlite3_mathfuncs_init
+  */
+  if( xInit==0 && zProc==0 ){
+    int iFile, iEntry, c;
+    int ncFile = sqlite3Strlen30(zFile);
+    zAltEntry = sqlite3_malloc(ncFile+30);
+    if( zAltEntry==0 ){
+      sqlite3OsDlClose(pVfs, handle);
+      return SQLITE_NOMEM;
+    }
+    memcpy(zAltEntry, "sqlite3_", 8);
+    for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
+    iFile++;
+    if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
+    for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
+      if( sqlite3Isalpha(c) ){
+        zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
+      }
+    }
+    memcpy(zAltEntry+iEntry, "_init", 6);
+    zEntry = zAltEntry;
+    xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
+                     sqlite3OsDlSym(pVfs, handle, zEntry);
+  }
   if( xInit==0 ){
     if( pzErrMsg ){
-      nMsg += sqlite3Strlen30(zProc);
+      nMsg += sqlite3Strlen30(zEntry);
       *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
       if( zErrmsg ){
         sqlite3_snprintf(nMsg, zErrmsg,
-            "no entry point [%s] in shared library [%s]", zProc,zFile);
+            "no entry point [%s] in shared library [%s]", zEntry, zFile);
         sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
       }
-      sqlite3OsDlClose(pVfs, handle);
     }
+    sqlite3OsDlClose(pVfs, handle);
+    sqlite3_free(zAltEntry);
     return SQLITE_ERROR;
-  }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){
+  }
+  sqlite3_free(zAltEntry);
+  if( xInit(db, &zErrmsg, &sqlite3Apis) ){
     if( pzErrMsg ){
       *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
     }
@@ -91253,6 +93559,9 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
     { "sql_trace",                SQLITE_SqlTrace      },
     { "vdbe_listing",             SQLITE_VdbeListing   },
     { "vdbe_trace",               SQLITE_VdbeTrace     },
+    { "vdbe_addoptrace",          SQLITE_VdbeAddopTrace},
+    { "vdbe_debug",    SQLITE_SqlTrace | SQLITE_VdbeListing
+                               | SQLITE_VdbeTrace      },
 #endif
 #ifndef SQLITE_OMIT_CHECK
     { "ignore_check_constraints", SQLITE_IgnoreChecks  },
@@ -91385,7 +93694,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   int rc;                      /* return value form SQLITE_FCNTL_PRAGMA */
   sqlite3 *db = pParse->db;    /* The database connection */
   Db *pDb;                     /* The specific database being pragmaed */
-  Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);  /* Prepared statement */
+  Vdbe *v = sqlite3GetVdbe(pParse);  /* Prepared statement */
 
   if( v==0 ) return;
   sqlite3VdbeRunOnlyOnce(v);
@@ -91426,6 +93735,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   aFcntl[1] = zLeft;
   aFcntl[2] = zRight;
   aFcntl[3] = 0;
+  db->busyHandler.nBusy = 0;
   rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
   if( rc==SQLITE_OK ){
     if( aFcntl[0] ){
@@ -91467,11 +93777,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
     static const VdbeOpList getCacheSize[] = {
       { OP_Transaction, 0, 0,        0},                         /* 0 */
       { OP_ReadCookie,  0, 1,        BTREE_DEFAULT_CACHE_SIZE},  /* 1 */
-      { OP_IfPos,       1, 7,        0},
+      { OP_IfPos,       1, 8,        0},
       { OP_Integer,     0, 2,        0},
       { OP_Subtract,    1, 2,        1},
-      { OP_IfPos,       1, 7,        0},
+      { OP_IfPos,       1, 8,        0},
       { OP_Integer,     0, 1,        0},                         /* 6 */
+      { OP_Noop,        0, 0,        0},
       { OP_ResultRow,   1, 1,        0},
     };
     int addr;
@@ -91810,6 +94121,43 @@ SQLITE_PRIVATE void sqlite3Pragma(
   }else
 
   /*
+  **  PRAGMA [database.]mmap_size(N)
+  **
+  ** Used to set mapping size limit. The mapping size limit is
+  ** used to limit the aggregate size of all memory mapped regions of the
+  ** database file. If this parameter is set to zero, then memory mapping
+  ** is not used at all.  If N is negative, then the default memory map
+  ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set.
+  ** The parameter N is measured in bytes.
+  **
+  ** This value is advisory.  The underlying VFS is free to memory map
+  ** as little or as much as it wants.  Except, if N is set to 0 then the
+  ** upper layers will never invoke the xFetch interfaces to the VFS.
+  */
+  if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
+    sqlite3_int64 sz;
+    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+    if( zRight ){
+      int ii;
+      sqlite3Atoi64(zRight, &sz, 1000, SQLITE_UTF8);
+      if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
+      if( pId2->n==0 ) db->szMmap = sz;
+      for(ii=db->nDb-1; ii>=0; ii--){
+        if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
+          sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
+        }
+      }
+    }
+    sz = -1;
+    if( sqlite3_file_control(db,zDb,SQLITE_FCNTL_MMAP_SIZE,&sz)==SQLITE_OK ){
+#if SQLITE_MAX_MMAP_SIZE==0
+      sz = 0;
+#endif
+      returnSingleInt(pParse, "mmap_size", sz);
+    }
+  }else
+
+  /*
   **   PRAGMA temp_store
   **   PRAGMA temp_store = "default"|"memory"|"file"
   **
@@ -92070,11 +94418,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
     if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pTab = sqlite3FindTable(db, zRight, zDb);
     if( pTab ){
-      int i;
+      int i, k;
       int nHidden = 0;
       Column *pCol;
+      Index *pPk;
+      for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
       sqlite3VdbeSetNumCols(v, 6);
       pParse->nMem = 6;
+      sqlite3CodeVerifySchema(pParse, iDb);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92097,7 +94448,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
         }else{
           sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
         }
-        sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6);
+        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
+          k = 0;
+        }else if( pPk==0 ){
+          k = 1;
+        }else{
+          for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
+        }
+        sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
       }
     }
@@ -92113,6 +94471,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
       pTab = pIdx->pTable;
       sqlite3VdbeSetNumCols(v, 3);
       pParse->nMem = 3;
+      sqlite3CodeVerifySchema(pParse, iDb);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
@@ -92139,6 +94498,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
         int i = 0; 
         sqlite3VdbeSetNumCols(v, 3);
         pParse->nMem = 3;
+        sqlite3CodeVerifySchema(pParse, iDb);
         sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
@@ -92202,6 +94562,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
         int i = 0; 
         sqlite3VdbeSetNumCols(v, 8);
         pParse->nMem = 8;
+        sqlite3CodeVerifySchema(pParse, iDb);
         sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
@@ -92235,6 +94596,122 @@ SQLITE_PRIVATE void sqlite3Pragma(
   }else
 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
 
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+#ifndef SQLITE_OMIT_TRIGGER
+  if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
+    FKey *pFK;             /* A foreign key constraint */
+    Table *pTab;           /* Child table contain "REFERENCES" keyword */
+    Table *pParent;        /* Parent table that child points to */
+    Index *pIdx;           /* Index in the parent table */
+    int i;                 /* Loop counter:  Foreign key number for pTab */
+    int j;                 /* Loop counter:  Field of the foreign key */
+    HashElem *k;           /* Loop counter:  Next table in schema */
+    int x;                 /* result variable */
+    int regResult;         /* 3 registers to hold a result row */
+    int regKey;            /* Register to hold key for checking the FK */
+    int regRow;            /* Registers to hold a row from pTab */
+    int addrTop;           /* Top of a loop checking foreign keys */
+    int addrOk;            /* Jump here if the key is OK */
+    int *aiCols;           /* child to parent column mapping */
+
+    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+    regResult = pParse->nMem+1;
+    pParse->nMem += 4;
+    regKey = ++pParse->nMem;
+    regRow = ++pParse->nMem;
+    v = sqlite3GetVdbe(pParse);
+    sqlite3VdbeSetNumCols(v, 4);
+    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
+    sqlite3CodeVerifySchema(pParse, iDb);
+    k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
+    while( k ){
+      if( zRight ){
+        pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
+        k = 0;
+      }else{
+        pTab = (Table*)sqliteHashData(k);
+        k = sqliteHashNext(k);
+      }
+      if( pTab==0 || pTab->pFKey==0 ) continue;
+      sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+      if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
+      sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
+      sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
+                        P4_TRANSIENT);
+      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+        if( pParent==0 ) break;
+        pIdx = 0;
+        sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
+        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
+        if( x==0 ){
+          if( pIdx==0 ){
+            sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
+          }else{
+            KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+            sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
+            sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+          }
+        }else{
+          k = 0;
+          break;
+        }
+      }
+      if( pFK ) break;
+      if( pParse->nTab<i ) pParse->nTab = i;
+      addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
+      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+        assert( pParent!=0 );
+        pIdx = 0;
+        aiCols = 0;
+        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
+        assert( x==0 );
+        addrOk = sqlite3VdbeMakeLabel(v);
+        if( pIdx==0 ){
+          int iKey = pFK->aCol[0].iFrom;
+          assert( iKey>=0 && iKey<pTab->nCol );
+          if( iKey!=pTab->iPKey ){
+            sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
+            sqlite3ColumnDefault(v, pTab, iKey, regRow);
+            sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
+            sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
+               sqlite3VdbeCurrentAddr(v)+3);
+          }else{
+            sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
+          }
+          sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
+          sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
+          sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+        }else{
+          for(j=0; j<pFK->nCol; j++){
+            sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
+                            aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
+            sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
+          }
+          sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
+          sqlite3VdbeChangeP4(v, -1,
+                   sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
+          sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+        }
+        sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
+        sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, 
+                          pFK->zTo, P4_TRANSIENT);
+        sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
+        sqlite3VdbeResolveLabel(v, addrOk);
+        sqlite3DbFree(db, aiCols);
+      }
+      sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
+      sqlite3VdbeJumpHere(v, addrTop);
+    }
+  }else
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+
 #ifndef NDEBUG
   if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
     if( zRight ){
@@ -92356,7 +94833,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
          sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
          P4_DYNAMIC);
-      sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
+      sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
       sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
       sqlite3VdbeJumpHere(v, addr);
@@ -92519,6 +94996,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
   **   PRAGMA [database.]user_version
   **   PRAGMA [database.]user_version = <integer>
   **
+  **   PRAGMA [database.]freelist_count = <integer>
+  **
+  **   PRAGMA [database.]application_id
+  **   PRAGMA [database.]application_id = <integer>
+  **
   ** The pragma's schema_version and user_version are used to set or get
   ** the value of the schema-version and user-version, respectively. Both
   ** the schema-version and the user-version are 32-bit signed integers
@@ -92540,10 +95022,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
   if( sqlite3StrICmp(zLeft, "schema_version")==0 
    || sqlite3StrICmp(zLeft, "user_version")==0 
    || sqlite3StrICmp(zLeft, "freelist_count")==0 
+   || sqlite3StrICmp(zLeft, "application_id")==0 
   ){
     int iCookie;   /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
     sqlite3VdbeUsesBtree(v, iDb);
     switch( zLeft[0] ){
+      case 'a': case 'A':
+        iCookie = BTREE_APPLICATION_ID;
+        break;
       case 'f': case 'F':
         iCookie = BTREE_FREE_PAGE_COUNT;
         break;
@@ -92659,6 +95145,22 @@ SQLITE_PRIVATE void sqlite3Pragma(
     sqlite3_db_release_memory(db);
   }else
 
+  /*
+  **   PRAGMA busy_timeout
+  **   PRAGMA busy_timeout = N
+  **
+  ** Call sqlite3_busy_timeout(db, N).  Return the current timeout value
+  ** if one is set.  If no busy handler or a different busy handler is set
+  ** then 0 is returned.  Setting the busy_timeout to 0 or negative
+  ** disables the timeout.
+  */
+  if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){
+    if( zRight ){
+      sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
+    }
+    returnSingleInt(pParse, "timeout",  db->busyTimeout);
+  }else
+
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   /*
   ** Report the current state of file logs for all databases
@@ -92674,13 +95176,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
     sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
     for(i=0; i<db->nDb; i++){
       Btree *pBt;
-      Pager *pPager;
       const char *zState = "unknown";
       int j;
       if( db->aDb[i].zName==0 ) continue;
       sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
       pBt = db->aDb[i].pBt;
-      if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
+      if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
         zState = "closed";
       }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, 
                                      SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
@@ -92717,7 +95218,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   }else
 #endif
 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
+  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
 #ifdef SQLITE_HAS_CODEC
     if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
       sqlite3_activate_see(&zRight[4]);
@@ -92889,7 +95390,9 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
 static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   int rc;
   int i;
+#ifndef SQLITE_OMIT_DEPRECATED
   int size;
+#endif
   Table *pTab;
   Db *pDb;
   char const *azArg[4];
@@ -92932,7 +95435,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
 
   /* zMasterSchema and zInitScript are set to point at the master schema
   ** and initialisation script appropriate for the database being
-  ** initialised. zMasterName is the name of the master table.
+  ** initialized. zMasterName is the name of the master table.
   */
   if( !OMIT_TEMPDB && iDb==1 ){
     zMasterSchema = temp_master_schema;
@@ -93012,11 +95515,15 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   */
   if( meta[BTREE_TEXT_ENCODING-1] ){  /* text encoding */
     if( iDb==0 ){
+#ifndef SQLITE_OMIT_UTF16
       u8 encoding;
       /* If opening the main database, set ENC(db). */
       encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
       if( encoding==0 ) encoding = SQLITE_UTF8;
       ENC(db) = encoding;
+#else
+      ENC(db) = SQLITE_UTF8;
+#endif
     }else{
       /* If opening an attached database, the encoding much match ENC(db) */
       if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
@@ -93153,7 +95660,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
     }
   }
 
-  /* Once all the other databases have been initialised, load the schema
+  /* Once all the other databases have been initialized, load the schema
   ** for the TEMP database. This is loaded last, as the TEMP database
   ** schema may contain references to objects in other databases.
   */
@@ -93176,7 +95683,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
 }
 
 /*
-** This routine is a no-op if the database schema is already initialised.
+** This routine is a no-op if the database schema is already initialized.
 ** Otherwise, the schema is loaded. An error code is returned.
 */
 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){
@@ -93403,7 +95910,6 @@ static int sqlite3Prepare(
   }
 #endif
 
-  assert( db->init.busy==0 || saveSqlFlag==0 );
   if( db->init.busy==0 ){
     Vdbe *pVdbe = pParse->pVdbe;
     sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
@@ -93674,7 +96180,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
   ExprList *pGroupBy,   /* the GROUP BY clause */
   Expr *pHaving,        /* the HAVING clause */
   ExprList *pOrderBy,   /* the ORDER BY clause */
-  int isDistinct,       /* true if the DISTINCT keyword is present */
+  u16 selFlags,         /* Flag parameters, such as SF_Distinct */
   Expr *pLimit,         /* LIMIT value.  NULL means not used */
   Expr *pOffset         /* OFFSET value.  NULL means no offset */
 ){
@@ -93698,7 +96204,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
   pNew->pGroupBy = pGroupBy;
   pNew->pHaving = pHaving;
   pNew->pOrderBy = pOrderBy;
-  pNew->selFlags = isDistinct ? SF_Distinct : 0;
+  pNew->selFlags = selFlags;
   pNew->op = TK_SELECT;
   pNew->pLimit = pLimit;
   pNew->pOffset = pOffset;
@@ -94145,6 +96651,19 @@ static int checkForMultiColumnSelectError(
 #endif
 
 /*
+** An instance of the following object is used to record information about
+** how to process the DISTINCT keyword, to simplify passing that information
+** into the selectInnerLoop() routine.
+*/
+typedef struct DistinctCtx DistinctCtx;
+struct DistinctCtx {
+  u8 isTnct;      /* True if the DISTINCT keyword is present */
+  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
+  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
+  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
+};
+
+/*
 ** This routine generates the code for the inside of the inner loop
 ** of a SELECT.
 **
@@ -94160,7 +96679,7 @@ static void selectInnerLoop(
   int srcTab,             /* Pull data from this table */
   int nColumn,            /* Number of columns in the source table */
   ExprList *pOrderBy,     /* If not NULL, sort results using this key */
-  int distinct,           /* If >=0, make sure results are distinct */
+  DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
   SelectDest *pDest,      /* How to dispose of the results */
   int iContinue,          /* Jump here to continue with next row */
   int iBreak              /* Jump here to break out of the inner loop */
@@ -94176,7 +96695,7 @@ static void selectInnerLoop(
   assert( v );
   if( NEVER(v==0) ) return;
   assert( pEList!=0 );
-  hasDistinct = distinct>=0;
+  hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
   if( pOrderBy==0 && !hasDistinct ){
     codeOffset(v, p, iContinue);
   }
@@ -94216,7 +96735,55 @@ static void selectInnerLoop(
   if( hasDistinct ){
     assert( pEList!=0 );
     assert( pEList->nExpr==nColumn );
-    codeDistinct(pParse, distinct, iContinue, nColumn, regResult);
+    switch( pDistinct->eTnctType ){
+      case WHERE_DISTINCT_ORDERED: {
+        VdbeOp *pOp;            /* No longer required OpenEphemeral instr. */
+        int iJump;              /* Jump destination */
+        int regPrev;            /* Previous row content */
+
+        /* Allocate space for the previous row */
+        regPrev = pParse->nMem+1;
+        pParse->nMem += nColumn;
+
+        /* Change the OP_OpenEphemeral coded earlier to an OP_Null
+        ** sets the MEM_Cleared bit on the first register of the
+        ** previous value.  This will cause the OP_Ne below to always
+        ** fail on the first iteration of the loop even if the first
+        ** row is all NULLs.
+        */
+        sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+        pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
+        pOp->opcode = OP_Null;
+        pOp->p1 = 1;
+        pOp->p2 = regPrev;
+
+        iJump = sqlite3VdbeCurrentAddr(v) + nColumn;
+        for(i=0; i<nColumn; i++){
+          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
+          if( i<nColumn-1 ){
+            sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
+          }else{
+            sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
+          }
+          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
+          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+        }
+        assert( sqlite3VdbeCurrentAddr(v)==iJump );
+        sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nColumn-1);
+        break;
+      }
+
+      case WHERE_DISTINCT_UNIQUE: {
+        sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+        break;
+      }
+
+      default: {
+        assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
+        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult);
+        break;
+      }
+    }
     if( pOrderBy==0 ){
       codeOffset(v, p, iContinue);
     }
@@ -94274,7 +96841,8 @@ static void selectInnerLoop(
     */
     case SRT_Set: {
       assert( nColumn==1 );
-      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
+      pDest->affSdst =
+                  sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
       if( pOrderBy ){
         /* At first glance you would think we could optimize out the
         ** ORDER BY in this case since the order of entries in the set
@@ -94283,7 +96851,7 @@ static void selectInnerLoop(
         pushOntoSorter(pParse, pOrderBy, p, regResult);
       }else{
         int r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
+        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
         sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
         sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
         sqlite3ReleaseTempReg(pParse, r1);
@@ -94550,7 +97118,8 @@ static void generateSortTail(
 #ifndef SQLITE_OMIT_SUBQUERY
     case SRT_Set: {
       assert( nColumn==1 );
-      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid,
+                        &pDest->affSdst, 1);
       sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
       sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
       break;
@@ -94865,7 +97434,7 @@ static void generateColumnNames(
 static int selectColumnsFromExprList(
   Parse *pParse,          /* Parsing context */
   ExprList *pEList,       /* Expr list from which to derive column names */
-  int *pnCol,             /* Write the number of columns here */
+  i16 *pnCol,             /* Write the number of columns here */
   Column **paCol          /* Write the new column list here */
 ){
   sqlite3 *db = pParse->db;   /* Database connection */
@@ -94891,9 +97460,7 @@ static int selectColumnsFromExprList(
   for(i=0, pCol=aCol; i<nCol; i++, pCol++){
     /* Get an appropriate name for the column
     */
-    p = pEList->a[i].pExpr;
-    assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
-               || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
+    p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
     if( (zName = pEList->a[i].zName)!=0 ){
       /* If the column contains an "AS <name>" phrase, use <name> as the name */
       zName = sqlite3DbStrDup(db, zName);
@@ -94931,6 +97498,9 @@ static int selectColumnsFromExprList(
     for(j=cnt=0; j<i; j++){
       if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
         char *zNewName;
+        int k;
+        for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
+        if( zName[k]==':' ) nName = k;
         zName[nName] = 0;
         zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
         sqlite3DbFree(db, zName);
@@ -95262,6 +97832,8 @@ static int multiSelect(
       int addr = 0;
       int nLimit;
       assert( !pPrior->pLimit );
+      pPrior->iLimit = p->iLimit;
+      pPrior->iOffset = p->iOffset;
       pPrior->pLimit = p->pLimit;
       pPrior->pOffset = p->pOffset;
       explainSetInteger(iSub1, pParse->iNextSelectId);
@@ -95387,7 +97959,7 @@ static int multiSelect(
         sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
         iStart = sqlite3VdbeCurrentAddr(v);
         selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
-                        0, -1, &dest, iCont, iBreak);
+                        0, 0, &dest, iCont, iBreak);
         sqlite3VdbeResolveLabel(v, iCont);
         sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);
         sqlite3VdbeResolveLabel(v, iBreak);
@@ -95465,7 +98037,7 @@ static int multiSelect(
       sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
       sqlite3ReleaseTempReg(pParse, r1);
       selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
-                      0, -1, &dest, iCont, iBreak);
+                      0, 0, &dest, iCont, iBreak);
       sqlite3VdbeResolveLabel(v, iCont);
       sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);
       sqlite3VdbeResolveLabel(v, iBreak);
@@ -95511,6 +98083,7 @@ static int multiSelect(
         *apColl = db->pDfltColl;
       }
     }
+    pKeyInfo->aSortOrder = (u8*)apColl;
 
     for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
       for(i=0; i<2; i++){
@@ -95584,7 +98157,7 @@ static int generateOutputSubroutine(
                               (char*)pKeyInfo, p4type);
     sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
     sqlite3VdbeJumpHere(v, j1);
-    sqlite3ExprCodeCopy(pParse, pIn->iSdst, regPrev+1, pIn->nSdst);
+    sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
     sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
   }
   if( pParse->db->mallocFailed ) return 0;
@@ -95619,10 +98192,10 @@ static int generateOutputSubroutine(
     case SRT_Set: {
       int r1;
       assert( pIn->nSdst==1 );
-      p->affinity = 
+      pDest->affSdst = 
          sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
       r1 = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &p->affinity, 1);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
       sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
       sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
       sqlite3ReleaseTempReg(pParse, r1);
@@ -95888,12 +98461,13 @@ static int multiSelectOrderBy(
       for(i=0; i<nOrderBy; i++){
         CollSeq *pColl;
         Expr *pTerm = pOrderBy->a[i].pExpr;
-        if( pTerm->flags & EP_ExpCollate ){
-          pColl = pTerm->pColl;
+        if( pTerm->flags & EP_Collate ){
+          pColl = sqlite3ExprCollSeq(pParse, pTerm);
         }else{
           pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
-          pTerm->flags |= EP_ExpCollate;
-          pTerm->pColl = pColl;
+          if( pColl==0 ) pColl = db->pDfltColl;
+          pOrderBy->a[i].pExpr =
+             sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
         }
         pKeyMerge->aColl[i] = pColl;
         pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
@@ -95917,7 +98491,8 @@ static int multiSelectOrderBy(
   }else{
     int nExpr = p->pEList->nExpr;
     assert( nOrderBy>=nExpr || db->mallocFailed );
-    regPrev = sqlite3GetTempRange(pParse, nExpr+1);
+    regPrev = pParse->nMem+1;
+    pParse->nMem += nExpr+1;
     sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
     pKeyDup = sqlite3DbMallocZero(db,
                   sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
@@ -96096,14 +98671,9 @@ static int multiSelectOrderBy(
   sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
   sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
                          (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
+  sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
   sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
 
-  /* Release temporary registers
-  */
-  if( regPrev ){
-    sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1);
-  }
-
   /* Jump to the this point in order to terminate the query.
   */
   sqlite3VdbeResolveLabel(v, labelEnd);
@@ -96163,9 +98733,6 @@ static Expr *substExpr(
       assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
       assert( pExpr->pLeft==0 && pExpr->pRight==0 );
       pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
-      if( pNew && pExpr->pColl ){
-        pNew->pColl = pExpr->pColl;
-      }
       sqlite3ExprDelete(db, pExpr);
       pExpr = pNew;
     }
@@ -96364,7 +98931,7 @@ static int flattenSubquery(
   */
   assert( p!=0 );
   assert( p->pPrior==0 );  /* Unable to flatten compound queries */
-  if( db->flags & SQLITE_QueryFlattener ) return 0;
+  if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
   pSrc = p->pSrc;
   assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
   pSubitem = &pSrc->a[iFrom];
@@ -96518,12 +99085,15 @@ static int flattenSubquery(
     Select *pNew;
     ExprList *pOrderBy = p->pOrderBy;
     Expr *pLimit = p->pLimit;
+    Expr *pOffset = p->pOffset;
     Select *pPrior = p->pPrior;
     p->pOrderBy = 0;
     p->pSrc = 0;
     p->pPrior = 0;
     p->pLimit = 0;
+    p->pOffset = 0;
     pNew = sqlite3SelectDup(db, p, 0);
+    p->pOffset = pOffset;
     p->pLimit = pLimit;
     p->pOrderBy = pOrderBy;
     p->pSrc = pSrc;
@@ -96653,10 +99223,9 @@ static int flattenSubquery(
     pList = pParent->pEList;
     for(i=0; i<pList->nExpr; i++){
       if( pList->a[i].zName==0 ){
-        const char *zSpan = pList->a[i].zSpan;
-        if( ALWAYS(zSpan) ){
-          pList->a[i].zName = sqlite3DbStrDup(db, zSpan);
-        }
+        char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
+        sqlite3Dequote(zName);
+        pList->a[i].zName = zName;
       }
     }
     substExprList(db, pParent->pEList, iParent, pSub->pEList);
@@ -96717,34 +99286,43 @@ static int flattenSubquery(
 #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
 
 /*
-** Analyze the SELECT statement passed as an argument to see if it
-** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if 
-** it is, or 0 otherwise. At present, a query is considered to be
-** a min()/max() query if:
+** Based on the contents of the AggInfo structure indicated by the first
+** argument, this function checks if the following are true:
 **
-**   1. There is a single object in the FROM clause.
+**    * the query contains just a single aggregate function,
+**    * the aggregate function is either min() or max(), and
+**    * the argument to the aggregate function is a column value.
 **
-**   2. There is a single expression in the result set, and it is
-**      either min(x) or max(x), where x is a column reference.
+** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
+** is returned as appropriate. Also, *ppMinMax is set to point to the 
+** list of arguments passed to the aggregate before returning.
+**
+** Or, if the conditions above are not met, *ppMinMax is set to 0 and
+** WHERE_ORDERBY_NORMAL is returned.
 */
-static u8 minMaxQuery(Select *p){
-  Expr *pExpr;
-  ExprList *pEList = p->pEList;
+static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
+  int eRet = WHERE_ORDERBY_NORMAL;          /* Return value */
 
-  if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
-  pExpr = pEList->a[0].pExpr;
-  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
-  if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
-  pEList = pExpr->x.pList;
-  if( pEList==0 || pEList->nExpr!=1 ) return 0;
-  if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
-  assert( !ExprHasProperty(pExpr, EP_IntValue) );
-  if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
-    return WHERE_ORDERBY_MIN;
-  }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
-    return WHERE_ORDERBY_MAX;
+  *ppMinMax = 0;
+  if( pAggInfo->nFunc==1 ){
+    Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
+    ExprList *pEList = pExpr->x.pList;      /* Arguments to agg function */
+
+    assert( pExpr->op==TK_AGG_FUNCTION );
+    if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
+      const char *zFunc = pExpr->u.zToken;
+      if( sqlite3StrICmp(zFunc, "min")==0 ){
+        eRet = WHERE_ORDERBY_MIN;
+        *ppMinMax = pEList;
+      }else if( sqlite3StrICmp(zFunc, "max")==0 ){
+        eRet = WHERE_ORDERBY_MAX;
+        *ppMinMax = pEList;
+      }
+    }
   }
-  return WHERE_ORDERBY_NORMAL;
+
+  assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
+  return eRet;
 }
 
 /*
@@ -96807,6 +99385,69 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pF
   }
   return SQLITE_OK;
 }
+/*
+** Detect compound SELECT statements that use an ORDER BY clause with 
+** an alternative collating sequence.
+**
+**    SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ...
+**
+** These are rewritten as a subquery:
+**
+**    SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2)
+**     ORDER BY ... COLLATE ...
+**
+** This transformation is necessary because the multiSelectOrderBy() routine
+** above that generates the code for a compound SELECT with an ORDER BY clause
+** uses a merge algorithm that requires the same collating sequence on the
+** result columns as on the ORDER BY clause.  See ticket
+** http://www.sqlite.org/src/info/6709574d2a
+**
+** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
+** The UNION ALL operator works fine with multiSelectOrderBy() even when
+** there are COLLATE terms in the ORDER BY.
+*/
+static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
+  int i;
+  Select *pNew;
+  Select *pX;
+  sqlite3 *db;
+  struct ExprList_item *a;
+  SrcList *pNewSrc;
+  Parse *pParse;
+  Token dummy;
+
+  if( p->pPrior==0 ) return WRC_Continue;
+  if( p->pOrderBy==0 ) return WRC_Continue;
+  for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){}
+  if( pX==0 ) return WRC_Continue;
+  a = p->pOrderBy->a;
+  for(i=p->pOrderBy->nExpr-1; i>=0; i--){
+    if( a[i].pExpr->flags & EP_Collate ) break;
+  }
+  if( i<0 ) return WRC_Continue;
+
+  /* If we reach this point, that means the transformation is required. */
+
+  pParse = pWalker->pParse;
+  db = pParse->db;
+  pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
+  if( pNew==0 ) return WRC_Abort;
+  memset(&dummy, 0, sizeof(dummy));
+  pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0);
+  if( pNewSrc==0 ) return WRC_Abort;
+  *pNew = *p;
+  p->pSrc = pNewSrc;
+  p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0));
+  p->op = TK_SELECT;
+  p->pWhere = 0;
+  pNew->pGroupBy = 0;
+  pNew->pHaving = 0;
+  pNew->pOrderBy = 0;
+  p->pPrior = 0;
+  pNew->pLimit = 0;
+  pNew->pOffset = 0;
+  return WRC_Continue;
+}
 
 /*
 ** This routine is a Walker callback for "expanding" a SELECT statement.
@@ -96839,14 +99480,16 @@ static int selectExpander(Walker *pWalker, Select *p){
   ExprList *pEList;
   struct SrcList_item *pFrom;
   sqlite3 *db = pParse->db;
+  Expr *pE, *pRight, *pExpr;
+  u16 selFlags = p->selFlags;
 
+  p->selFlags |= SF_Expanded;
   if( db->mallocFailed  ){
     return WRC_Abort;
   }
-  if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
+  if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
     return WRC_Prune;
   }
-  p->selFlags |= SF_Expanded;
   pTabList = p->pSrc;
   pEList = p->pEList;
 
@@ -96887,9 +99530,14 @@ static int selectExpander(Walker *pWalker, Select *p){
     }else{
       /* An ordinary table or view name in the FROM clause */
       assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
       if( pTab==0 ) return WRC_Abort;
+      if( pTab->nRef==0xffff ){
+        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
+           pTab->zName);
+        pFrom->pTab = 0;
+        return WRC_Abort;
+      }
       pTab->nRef++;
 #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
       if( pTab->pSelect || IsVirtual(pTab) ){
@@ -96925,7 +99573,7 @@ static int selectExpander(Walker *pWalker, Select *p){
   ** that need expanding.
   */
   for(k=0; k<pEList->nExpr; k++){
-    Expr *pE = pEList->a[k].pExpr;
+    pE = pEList->a[k].pExpr;
     if( pE->op==TK_ALL ) break;
     assert( pE->op!=TK_DOT || pE->pRight!=0 );
     assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
@@ -96943,10 +99591,18 @@ static int selectExpander(Walker *pWalker, Select *p){
     int longNames = (flags & SQLITE_FullColNames)!=0
                       && (flags & SQLITE_ShortColNames)==0;
 
+    /* When processing FROM-clause subqueries, it is always the case
+    ** that full_column_names=OFF and short_column_names=ON.  The
+    ** sqlite3ResultSetOfSelect() routine makes it so. */
+    assert( (p->selFlags & SF_NestedFrom)==0
+          || ((flags & SQLITE_FullColNames)==0 &&
+              (flags & SQLITE_ShortColNames)!=0) );
+
     for(k=0; k<pEList->nExpr; k++){
-      Expr *pE = a[k].pExpr;
-      assert( pE->op!=TK_DOT || pE->pRight!=0 );
-      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
+      pE = a[k].pExpr;
+      pRight = pE->pRight;
+      assert( pE->op!=TK_DOT || pRight!=0 );
+      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
         /* This particular expression does not need to be expanded.
         */
         pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
@@ -96961,32 +99617,43 @@ static int selectExpander(Walker *pWalker, Select *p){
         /* This expression is a "*" or a "TABLE.*" and needs to be
         ** expanded. */
         int tableSeen = 0;      /* Set to 1 when TABLE matches */
-        char *zTName;            /* text of name of TABLE */
+        char *zTName = 0;       /* text of name of TABLE */
         if( pE->op==TK_DOT ){
           assert( pE->pLeft!=0 );
           assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
           zTName = pE->pLeft->u.zToken;
-        }else{
-          zTName = 0;
         }
         for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
           Table *pTab = pFrom->pTab;
+          Select *pSub = pFrom->pSelect;
           char *zTabName = pFrom->zAlias;
+          const char *zSchemaName = 0;
+          int iDb;
           if( zTabName==0 ){
             zTabName = pTab->zName;
           }
           if( db->mallocFailed ) break;
-          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
-            continue;
+          if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
+            pSub = 0;
+            if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+              continue;
+            }
+            iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+            zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
           }
-          tableSeen = 1;
           for(j=0; j<pTab->nCol; j++){
-            Expr *pExpr, *pRight;
             char *zName = pTab->aCol[j].zName;
             char *zColname;  /* The computed column name */
             char *zToFree;   /* Malloced string that needs to be freed */
             Token sColname;  /* Computed column name as a token */
 
+            assert( zName );
+            if( zTName && pSub
+             && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+            ){
+              continue;
+            }
+
             /* If a column is marked as 'hidden' (currently only possible
             ** for virtual tables), do not include it in the expanded
             ** result-set list.
@@ -96995,6 +99662,7 @@ static int selectExpander(Walker *pWalker, Select *p){
               assert(IsVirtual(pTab));
               continue;
             }
+            tableSeen = 1;
 
             if( i>0 && zTName==0 ){
               if( (pFrom->jointype & JT_NATURAL)!=0
@@ -97017,6 +99685,10 @@ static int selectExpander(Walker *pWalker, Select *p){
               Expr *pLeft;
               pLeft = sqlite3Expr(db, TK_ID, zTabName);
               pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+              if( zSchemaName ){
+                pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
+                pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
+              }
               if( longNames ){
                 zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
                 zToFree = zColname;
@@ -97028,6 +99700,18 @@ static int selectExpander(Walker *pWalker, Select *p){
             sColname.z = zColname;
             sColname.n = sqlite3Strlen30(zColname);
             sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
+            if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
+              struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+              if( pSub ){
+                pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
+                testcase( pX->zSpan==0 );
+              }else{
+                pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+                                           zSchemaName, zTabName, zColname);
+                testcase( pX->zSpan==0 );
+              }
+              pX->bSpanIsTab = 1;
+            }
             sqlite3DbFree(db, zToFree);
           }
         }
@@ -97080,10 +99764,13 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
 */
 static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
   Walker w;
-  w.xSelectCallback = selectExpander;
+  memset(&w, 0, sizeof(w));
+  w.xSelectCallback = convertCompoundSelectToSubquery;
   w.xExprCallback = exprWalkNoop;
   w.pParse = pParse;
   sqlite3WalkSelect(&w, pSelect);
+  w.xSelectCallback = selectExpander;
+  sqlite3WalkSelect(&w, pSelect);
 }
 
 
@@ -97138,9 +99825,11 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
 static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
 #ifndef SQLITE_OMIT_SUBQUERY
   Walker w;
+  memset(&w, 0, sizeof(w));
   w.xSelectCallback = selectAddSubqueryTypeInfo;
   w.xExprCallback = exprWalkNoop;
   w.pParse = pParse;
+  w.bSelectDepthFirst = 1;
   sqlite3WalkSelect(&w, pSelect);
 #endif
 }
@@ -97166,6 +99855,7 @@ SQLITE_PRIVATE void sqlite3SelectPrep(
   sqlite3 *db;
   if( NEVER(p==0) ) return;
   db = pParse->db;
+  if( db->mallocFailed ) return;
   if( p->selFlags & SF_HasTypeInfo ) return;
   sqlite3SelectExpand(pParse, p);
   if( pParse->nErr || db->mallocFailed ) return;
@@ -97404,11 +100094,9 @@ SQLITE_PRIVATE int sqlite3Select(
   ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
   ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
   Expr *pHaving;         /* The HAVING clause.  May be NULL */
-  int isDistinct;        /* True if the DISTINCT keyword is present */
-  int distinct;          /* Table to use for the distinct set */
   int rc = 1;            /* Value to return from this function */
   int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
-  int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
+  DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
   AggInfo sAggInfo;      /* Information used by aggregate queries */
   int iEnd;              /* Address of the end of the query */
   sqlite3 *db;           /* The database connection */
@@ -97468,8 +100156,17 @@ SQLITE_PRIVATE int sqlite3Select(
     int isAggSub;
 
     if( pSub==0 ) continue;
+
+    /* Sometimes the code for a subquery will be generated more than
+    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
+    ** for example.  In that case, do not regenerate the code to manifest
+    ** a view or the co-routine to implement a view.  The first instance
+    ** is sufficient, though the subroutine to manifest the view does need
+    ** to be invoked again. */
     if( pItem->addrFillSub ){
-      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+      if( pItem->viaCoroutine==0 ){
+        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+      }
       continue;
     }
 
@@ -97490,6 +100187,44 @@ SQLITE_PRIVATE int sqlite3Select(
         p->selFlags |= SF_Aggregate;
       }
       i = -1;
+    }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
+      && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+    ){
+      /* Implement a co-routine that will return a single row of the result
+      ** set on each invocation.
+      */
+      int addrTop;
+      int addrEof;
+      pItem->regReturn = ++pParse->nMem;
+      addrEof = ++pParse->nMem;
+      /* Before coding the OP_Goto to jump to the start of the main routine,
+      ** ensure that the jump to the verify-schema routine has already
+      ** been coded. Otherwise, the verify-schema would likely be coded as 
+      ** part of the co-routine. If the main routine then accessed the 
+      ** database before invoking the co-routine for the first time (for 
+      ** example to initialize a LIMIT register from a sub-select), it would 
+      ** be doing so without having verified the schema version and obtained 
+      ** the required db locks. See ticket d6b36be38.  */
+      sqlite3CodeVerifySchema(pParse, -1);
+      sqlite3VdbeAddOp0(v, OP_Goto);
+      addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
+      sqlite3VdbeChangeP5(v, 1);
+      VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
+      pItem->addrFillSub = addrTop;
+      sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
+      sqlite3VdbeChangeP5(v, 1);
+      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+      sqlite3Select(pParse, pSub, &dest);
+      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+      pItem->viaCoroutine = 1;
+      sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
+      sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
+      sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
+      sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
+      VdbeComment((v, "end %s", pItem->pTab->zName));
+      sqlite3VdbeJumpHere(v, addrTop-1);
+      sqlite3ClearTempRegCache(pParse);
     }else{
       /* Generate a subroutine that will fill an ephemeral table with
       ** the content of this subquery.  pItem->addrFillSub will point
@@ -97505,7 +100240,7 @@ SQLITE_PRIVATE int sqlite3Select(
       pItem->addrFillSub = topAddr+1;
       VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
       if( pItem->isCorrelated==0 ){
-        /* If the subquery is no correlated and if we are not inside of
+        /* If the subquery is not correlated and if we are not inside of
         ** a trigger, then we only need to compute the value of the subquery
         ** once. */
         onceAddr = sqlite3CodeOnce(pParse);
@@ -97534,7 +100269,7 @@ SQLITE_PRIVATE int sqlite3Select(
   pWhere = p->pWhere;
   pGroupBy = p->pGroupBy;
   pHaving = p->pHaving;
-  isDistinct = (p->selFlags & SF_Distinct)!=0;
+  sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
 
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
   /* If there is are a sequence of queries, do the earlier ones first.
@@ -97569,7 +100304,7 @@ SQLITE_PRIVATE int sqlite3Select(
   ** to disable this optimization for testing purposes.
   */
   if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
-         && (db->flags & SQLITE_GroupByOrder)==0 ){
+         && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
     pOrderBy = 0;
   }
 
@@ -97595,6 +100330,10 @@ SQLITE_PRIVATE int sqlite3Select(
     p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
     pGroupBy = p->pGroupBy;
     pOrderBy = 0;
+    /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
+    ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
+    ** original setting of the SF_Distinct flag, not the current setting */
+    assert( sDistinct.isTnct );
   }
 
   /* If there is an ORDER BY clause, then this sorting
@@ -97635,24 +100374,27 @@ SQLITE_PRIVATE int sqlite3Select(
   /* Open a virtual index to use for the distinct set.
   */
   if( p->selFlags & SF_Distinct ){
-    KeyInfo *pKeyInfo;
-    distinct = pParse->nTab++;
-    pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
-    addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
-        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+    sDistinct.tabTnct = pParse->nTab++;
+    sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+                                sDistinct.tabTnct, 0, 0,
+                                (char*)keyInfoFromExprList(pParse, p->pEList),
+                                P4_KEYINFO_HANDOFF);
     sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+    sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
   }else{
-    distinct = addrDistinctIndex = -1;
+    sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
   }
 
-  /* Aggregate and non-aggregate queries are handled differently */
   if( !isAgg && pGroupBy==0 ){
-    ExprList *pDist = (isDistinct ? p->pEList : 0);
+    /* No aggregate functions and no GROUP BY clause */
+    ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
 
     /* Begin the database scan. */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0,0);
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
     if( pWInfo==0 ) goto select_end;
     if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
+    if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
+    if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
 
     /* If sorting index that was created by a prior OP_OpenEphemeral 
     ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -97663,59 +100405,16 @@ SQLITE_PRIVATE int sqlite3Select(
       p->addrOpenEphm[2] = -1;
     }
 
-    if( pWInfo->eDistinct ){
-      VdbeOp *pOp;                /* No longer required OpenEphemeral instr. */
-     
-      assert( addrDistinctIndex>=0 );
-      pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
-
-      assert( isDistinct );
-      assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED 
-           || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE 
-      );
-      distinct = -1;
-      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
-        int iJump;
-        int iExpr;
-        int iFlag = ++pParse->nMem;
-        int iBase = pParse->nMem+1;
-        int iBase2 = iBase + pEList->nExpr;
-        pParse->nMem += (pEList->nExpr*2);
-
-        /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
-        ** OP_Integer initializes the "first row" flag.  */
-        pOp->opcode = OP_Integer;
-        pOp->p1 = 1;
-        pOp->p2 = iFlag;
-
-        sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
-        iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
-        sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
-        for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
-          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
-          sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
-          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
-          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
-        }
-        sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
-
-        sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
-        assert( sqlite3VdbeCurrentAddr(v)==iJump );
-        sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
-      }else{
-        pOp->opcode = OP_Noop;
-      }
-    }
-
     /* Use the standard inner loop. */
-    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
+    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
                     pWInfo->iContinue, pWInfo->iBreak);
 
     /* End the database scan loop.
     */
     sqlite3WhereEnd(pWInfo);
   }else{
-    /* This is the processing for aggregate queries */
+    /* This case when there exist aggregate functions or a GROUP BY clause
+    ** or both */
     NameContext sNC;    /* Name context for processing aggregate information */
     int iAMem;          /* First Mem address for storing current GROUP BY */
     int iBMem;          /* First Mem address for previous GROUP BY */
@@ -97823,14 +100522,13 @@ SQLITE_PRIVATE int sqlite3Select(
       ** in the right order to begin with.
       */
       sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
-      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0);
+      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
       if( pWInfo==0 ) goto select_end;
-      if( pGroupBy==0 ){
+      if( pWInfo->nOBSat==pGroupBy->nExpr ){
         /* The optimizer is able to deliver rows in group by order so
         ** we do not have to sort.  The OP_OpenEphemeral table will be
         ** cancelled later because we still need to use the pKeyInfo
         */
-        pGroupBy = p->pGroupBy;
         groupBySort = 0;
       }else{
         /* Rows are coming out in undetermined order.  We have to push
@@ -97844,7 +100542,8 @@ SQLITE_PRIVATE int sqlite3Select(
         int nGroupBy;
 
         explainTempTable(pParse, 
-            isDistinct && !(p->selFlags&SF_Distinct)?"DISTINCT":"GROUP BY");
+            (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
+                    "DISTINCT" : "GROUP BY");
 
         groupBySort = 1;
         nGroupBy = pGroupBy->nExpr;
@@ -97976,7 +100675,7 @@ SQLITE_PRIVATE int sqlite3Select(
       finalizeAggFunctions(pParse, &sAggInfo);
       sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
       selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
-                      distinct, pDest,
+                      &sDistinct, pDest,
                       addrOutputRow+1, addrSetAbort);
       sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
       VdbeComment((v, "end groupby result generator"));
@@ -98064,7 +100763,7 @@ SQLITE_PRIVATE int sqlite3Select(
         ** value of x, the only row required).
         **
         ** A special flag must be passed to sqlite3WhereBegin() to slightly
-        ** modify behaviour as follows:
+        ** modify behavior as follows:
         **
         **   + If the query is a "SELECT min(x)", then the loop coded by
         **     where.c should not iterate over any values with a NULL value
@@ -98076,10 +100775,17 @@ SQLITE_PRIVATE int sqlite3Select(
         **     Refer to code and comments in where.c for details.
         */
         ExprList *pMinMax = 0;
-        u8 flag = minMaxQuery(p);
+        u8 flag = WHERE_ORDERBY_NORMAL;
+        
+        assert( p->pGroupBy==0 );
+        assert( flag==0 );
+        if( p->pHaving==0 ){
+          flag = minMaxQuery(&sAggInfo, &pMinMax);
+        }
+        assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
+
         if( flag ){
-          assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
-          pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
+          pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
           pDel = pMinMax;
           if( pMinMax && !db->mallocFailed ){
             pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
@@ -98092,13 +100798,14 @@ SQLITE_PRIVATE int sqlite3Select(
         ** of output.
         */
         resetAccumulator(pParse, &sAggInfo);
-        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0);
+        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
         if( pWInfo==0 ){
           sqlite3ExprListDelete(db, pDel);
           goto select_end;
         }
         updateAccumulator(pParse, &sAggInfo);
-        if( !pMinMax && flag ){
+        assert( pMinMax==0 || pMinMax->nExpr==1 );
+        if( pWInfo->nOBSat>0 ){
           sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
           VdbeComment((v, "%s() by index",
                 (flag==WHERE_ORDERBY_MIN?"min":"max")));
@@ -98109,7 +100816,7 @@ SQLITE_PRIVATE int sqlite3Select(
 
       pOrderBy = 0;
       sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
-      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, 
+      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0, 
                       pDest, addrEnd, addrEnd);
       sqlite3ExprListDelete(db, pDel);
     }
@@ -98117,7 +100824,7 @@ SQLITE_PRIVATE int sqlite3Select(
     
   } /* endif aggregate query */
 
-  if( distinct>=0 ){
+  if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
     explainTempTable(pParse, "DISTINCT");
   }
 
@@ -98234,7 +100941,10 @@ SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
     sqlite3ExplainPrintf(pVdbe, "(null-select)");
     return;
   }
-  while( p->pPrior ) p = p->pPrior;
+  while( p->pPrior ){
+    p->pPrior->pNext = p;
+    p = p->pPrior;
+  }
   sqlite3ExplainPush(pVdbe);
   while( p ){
     explainOneSelect(pVdbe, p);
@@ -99182,6 +101892,15 @@ static int codeTriggerProgram(
     */
     pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
 
+    /* Clear the cookieGoto flag. When coding triggers, the cookieGoto 
+    ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
+    ** that it is not safe to refactor constants (this happens after the
+    ** start of the first loop in the SQL statement is coded - at that 
+    ** point code may be conditionally executed, so it is no longer safe to 
+    ** initialize constant register values).  */
+    assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
+    pParse->cookieGoto = 0;
+
     switch( pStep->op ){
       case TK_UPDATE: {
         sqlite3Update(pParse, 
@@ -99787,6 +102506,7 @@ SQLITE_PRIVATE void sqlite3Update(
     }
     if( j>=pTab->nCol ){
       if( sqlite3IsRowid(pChanges->a[i].zName) ){
+        j = -1;
         chngRowid = 1;
         pRowidExpr = pChanges->a[i].pExpr;
       }else{
@@ -99799,7 +102519,8 @@ SQLITE_PRIVATE void sqlite3Update(
     {
       int rc;
       rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
-                           pTab->aCol[j].zName, db->aDb[iDb].zName);
+                            j<0 ? "ROWID" : pTab->aCol[j].zName,
+                            db->aDb[iDb].zName);
       if( rc==SQLITE_DENY ){
         goto update_cleanup;
       }else if( rc==SQLITE_IGNORE ){
@@ -100037,7 +102758,7 @@ SQLITE_PRIVATE void sqlite3Update(
 
     /* The row-trigger may have deleted the row being updated. In this
     ** case, jump to the next row. No updates or AFTER triggers are 
-    ** required. This behaviour - what happens when the row being updated
+    ** required. This behavior - what happens when the row being updated
     ** is deleted or renamed by a BEFORE trigger - is left undefined in the
     ** documentation.
     */
@@ -100338,6 +103059,7 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
   Vdbe *v = sqlite3GetVdbe(pParse);
   if( v ){
     sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
+    sqlite3VdbeUsesBtree(v, 0);
   }
   return;
 }
@@ -100541,6 +103263,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
        BTREE_DEFAULT_CACHE_SIZE, 0,  /* Preserve the default page cache size */
        BTREE_TEXT_ENCODING,      0,  /* Preserve the text encoding */
        BTREE_USER_VERSION,       0,  /* Preserve the user version */
+       BTREE_APPLICATION_ID,     0,  /* Preserve the application id */
     };
 
     assert( 1==sqlite3BtreeIsInTrans(pTemp) );
@@ -100866,7 +103589,7 @@ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
   if( p->azModuleArg ){
     int i;
     for(i=0; i<p->nModuleArg; i++){
-      sqlite3DbFree(db, p->azModuleArg[i]);
+      if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
     }
     sqlite3DbFree(db, p->azModuleArg);
   }
@@ -100926,7 +103649,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
   pTable->tabFlags |= TF_Virtual;
   pTable->nModuleArg = 0;
   addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
-  addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
+  addModuleArgument(db, pTable, 0);
   addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
   pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
 
@@ -101083,6 +103806,7 @@ static int vtabCallConstructor(
   int nArg = pTab->nModuleArg;
   char *zErr = 0;
   char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+  int iDb;
 
   if( !zModuleName ){
     return SQLITE_NOMEM;
@@ -101096,6 +103820,9 @@ static int vtabCallConstructor(
   pVTable->db = db;
   pVTable->pMod = pMod;
 
+  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+  pTab->azModuleArg[1] = db->aDb[iDb].zName;
+
   /* Invoke the virtual table constructor */
   assert( &db->pVtabCtx );
   assert( xConstruct );
@@ -101130,7 +103857,7 @@ static int vtabCallConstructor(
       /* If everything went according to plan, link the new VTable structure
       ** into the linked list headed by pTab->pVTable. Then loop through the 
       ** columns of the table to see if any of them contain the token "hidden".
-      ** If so, set the Column.isHidden flag and remove the token from
+      ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
       ** the type string.  */
       pVTable->pNext = pTab->pVTable;
       pTab->pVTable = pVTable;
@@ -101161,7 +103888,7 @@ static int vtabCallConstructor(
             assert(zType[i-1]==' ');
             zType[i-1] = '\0';
           }
-          pTab->aCol[iCol].isHidden = 1;
+          pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
         }
       }
     }
@@ -101722,9 +104449,10 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
 ** Trace output macros
 */
 #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-SQLITE_PRIVATE int sqlite3WhereTrace = 0;
+/***/ int sqlite3WhereTrace = 0;
 #endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+#if defined(SQLITE_DEBUG) \
+    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
 # define WHERETRACE(X)  if(sqlite3WhereTrace) sqlite3DebugPrintf X
 #else
 # define WHERETRACE(X)
@@ -101796,8 +104524,8 @@ struct WhereTerm {
   int leftCursor;         /* Cursor number of X in "X <op> <expr>" */
   union {
     int leftColumn;         /* Column number of X in "X <op> <expr>" */
-    WhereOrInfo *pOrInfo;   /* Extra information if eOperator==WO_OR */
-    WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */
+    WhereOrInfo *pOrInfo;   /* Extra information if (eOperator & WO_OR)!=0 */
+    WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
   } u;
   u16 eOperator;          /* A WO_xx value describing <op> */
   u8 wtFlags;             /* TERM_xxx bit flags.  See below */
@@ -101838,7 +104566,6 @@ struct WhereTerm {
 struct WhereClause {
   Parse *pParse;           /* The parser context */
   WhereMaskSet *pMaskSet;  /* Mapping of table cursor numbers to bitmasks */
-  Bitmask vmask;           /* Bitmask identifying virtual table cursors */
   WhereClause *pOuter;     /* Outer conjunction */
   u8 op;                   /* Split operator.  TK_AND or TK_OR */
   u16 wctrlFlags;          /* Might include WHERE_AND_ONLY */
@@ -101925,6 +104652,7 @@ struct WhereCost {
 #define WO_ISNULL 0x080
 #define WO_OR     0x100       /* Two or more OR-connected terms */
 #define WO_AND    0x200       /* Two or more AND-connected terms */
+#define WO_EQUIV  0x400       /* Of the form A==B, both columns */
 #define WO_NOOP   0x800       /* This term does not restrict search space */
 
 #define WO_ALL    0xfff       /* Mask of all possible WO_* values */
@@ -101951,18 +104679,55 @@ struct WhereCost {
 #define WHERE_COLUMN_NULL  0x00080000  /* x IS NULL */
 #define WHERE_INDEXED      0x000f0000  /* Anything that uses an index */
 #define WHERE_NOT_FULLSCAN 0x100f3000  /* Does not do a full table scan */
-#define WHERE_IN_ABLE      0x000f1000  /* Able to support an IN operator */
+#define WHERE_IN_ABLE      0x080f1000  /* Able to support an IN operator */
 #define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
 #define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
 #define WHERE_BOTH_LIMIT   0x00300000  /* Both x>EXPR and x<EXPR */
-#define WHERE_IDX_ONLY     0x00800000  /* Use index only - omit table */
-#define WHERE_ORDERBY      0x01000000  /* Output will appear in correct order */
-#define WHERE_REVERSE      0x02000000  /* Scan in reverse order */
-#define WHERE_UNIQUE       0x04000000  /* Selects no more than one row */
+#define WHERE_IDX_ONLY     0x00400000  /* Use index only - omit table */
+#define WHERE_ORDERED      0x00800000  /* Output will appear in correct order */
+#define WHERE_REVERSE      0x01000000  /* Scan in reverse order */
+#define WHERE_UNIQUE       0x02000000  /* Selects no more than one row */
+#define WHERE_ALL_UNIQUE   0x04000000  /* This and all prior have one row */
+#define WHERE_OB_UNIQUE    0x00004000  /* Values in ORDER BY columns are 
+                                       ** different for every output row */
 #define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
 #define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
 #define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */
 #define WHERE_DISTINCT     0x40000000  /* Correct order for DISTINCT */
+#define WHERE_COVER_SCAN   0x80000000  /* Full scan of a covering index */
+
+/*
+** This module contains many separate subroutines that work together to
+** find the best indices to use for accessing a particular table in a query.
+** An instance of the following structure holds context information about the
+** index search so that it can be more easily passed between the various
+** routines.
+*/
+typedef struct WhereBestIdx WhereBestIdx;
+struct WhereBestIdx {
+  Parse *pParse;                  /* Parser context */
+  WhereClause *pWC;               /* The WHERE clause */
+  struct SrcList_item *pSrc;      /* The FROM clause term to search */
+  Bitmask notReady;               /* Mask of cursors not available */
+  Bitmask notValid;               /* Cursors not available for any purpose */
+  ExprList *pOrderBy;             /* The ORDER BY clause */
+  ExprList *pDistinct;            /* The select-list if query is DISTINCT */
+  sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */
+  int i, n;                       /* Which loop is being coded; # of loops */
+  WhereLevel *aLevel;             /* Info about outer loops */
+  WhereCost cost;                 /* Lowest cost query plan */
+};
+
+/*
+** Return TRUE if the probe cost is less than the baseline cost
+*/
+static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
+  if( pProbe->rCost<pBaseline->rCost ) return 1;
+  if( pProbe->rCost>pBaseline->rCost ) return 0;
+  if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
+  if( pProbe->plan.nRow<pBaseline->plan.nRow ) return 1;
+  return 0;
+}
 
 /*
 ** Initialize a preallocated WhereClause structure.
@@ -101979,7 +104744,6 @@ static void whereClauseInit(
   pWC->nTerm = 0;
   pWC->nSlot = ArraySize(pWC->aStatic);
   pWC->a = pWC->aStatic;
-  pWC->vmask = 0;
   pWC->wctrlFlags = wctrlFlags;
 }
 
@@ -102066,7 +104830,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
     pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
   }
   pTerm = &pWC->a[idx = pWC->nTerm++];
-  pTerm->pExpr = p;
+  pTerm->pExpr = sqlite3ExprSkipCollate(p);
   pTerm->wtFlags = wtFlags;
   pTerm->pWC = pWC;
   pTerm->iParent = -1;
@@ -102226,23 +104990,32 @@ static int allowedOp(int op){
 ** Commute a comparison operator.  Expressions of the form "X op Y"
 ** are converted into "Y op X".
 **
-** If a collation sequence is associated with either the left or right
+** If left/right precedence rules come into play when determining the
+** collating
 ** side of the comparison, it remains associated with the same side after
 ** the commutation. So "Y collate NOCASE op X" becomes 
-** "X collate NOCASE op Y". This is because any collation sequence on
+** "X op Y". This is because any collation sequence on
 ** the left hand side of a comparison overrides any collation sequence 
-** attached to the right. For the same reason the EP_ExpCollate flag
+** attached to the right. For the same reason the EP_Collate flag
 ** is not commuted.
 */
 static void exprCommute(Parse *pParse, Expr *pExpr){
-  u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
-  u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
+  u16 expRight = (pExpr->pRight->flags & EP_Collate);
+  u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
   assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
-  pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
-  pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
-  SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
-  pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
-  pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
+  if( expRight==expLeft ){
+    /* Either X and Y both have COLLATE operator or neither do */
+    if( expRight ){
+      /* Both X and Y have COLLATE operators.  Make sure X is always
+      ** used by clearing the EP_Collate flag from Y. */
+      pExpr->pRight->flags &= ~EP_Collate;
+    }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
+      /* Neither X nor Y have COLLATE operators, but X has a non-default
+      ** collating sequence.  So add the EP_Collate marker on X to cause
+      ** it to be searched first. */
+      pExpr->pLeft->flags |= EP_Collate;
+    }
+  }
   SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
   if( pExpr->op>=TK_GT ){
     assert( TK_LT==TK_GT+2 );
@@ -102283,6 +105056,23 @@ static u16 operatorMask(int op){
 ** where X is a reference to the iColumn of table iCur and <op> is one of
 ** the WO_xx operator codes specified by the op parameter.
 ** Return a pointer to the term.  Return 0 if not found.
+**
+** The term returned might by Y=<expr> if there is another constraint in
+** the WHERE clause that specifies that X=Y.  Any such constraints will be
+** identified by the WO_EQUIV bit in the pTerm->eOperator field.  The
+** aEquiv[] array holds X and all its equivalents, with each SQL variable
+** taking up two slots in aEquiv[].  The first slot is for the cursor number
+** and the second is for the column number.  There are 22 slots in aEquiv[]
+** so that means we can look for X plus up to 10 other equivalent values.
+** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
+** and ... and A9=A10 and A10=<expr>.
+**
+** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
+** then try for the one with no dependencies on <expr> - in other words where
+** <expr> is a constant expression of some kind.  Only return entries of
+** the form "X <op> Y" where Y is a column in another table if no terms of
+** the form "X <op> <const-expr>" exist.   If no terms with a constant RHS
+** exist, try to return a term that does not use WO_EQUIV.
 */
 static WhereTerm *findTerm(
   WhereClause *pWC,     /* The WHERE clause to be searched */
@@ -102292,45 +105082,85 @@ static WhereTerm *findTerm(
   u32 op,               /* Mask of WO_xx values describing operator */
   Index *pIdx           /* Must be compatible with this index, if not NULL */
 ){
-  WhereTerm *pTerm;
-  int k;
+  WhereTerm *pTerm;            /* Term being examined as possible result */
+  WhereTerm *pResult = 0;      /* The answer to return */
+  WhereClause *pWCOrig = pWC;  /* Original pWC value */
+  int j, k;                    /* Loop counters */
+  Expr *pX;                /* Pointer to an expression */
+  Parse *pParse;           /* Parsing context */
+  int iOrigCol = iColumn;  /* Original value of iColumn */
+  int nEquiv = 2;          /* Number of entires in aEquiv[] */
+  int iEquiv = 2;          /* Number of entries of aEquiv[] processed so far */
+  int aEquiv[22];          /* iCur,iColumn and up to 10 other equivalents */
+
   assert( iCur>=0 );
-  op &= WO_ALL;
-  for(; pWC; pWC=pWC->pOuter){
-    for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
-      if( pTerm->leftCursor==iCur
-         && (pTerm->prereqRight & notReady)==0
-         && pTerm->u.leftColumn==iColumn
-         && (pTerm->eOperator & op)!=0
-      ){
-        if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
-          Expr *pX = pTerm->pExpr;
-          CollSeq *pColl;
-          char idxaff;
-          int j;
-          Parse *pParse = pWC->pParse;
-  
-          idxaff = pIdx->pTable->aCol[iColumn].affinity;
-          if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-  
-          /* Figure out the collation sequence required from an index for
-          ** it to be useful for optimising expression pX. Store this
-          ** value in variable pColl.
-          */
-          assert(pX->pLeft);
-          pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
-          assert(pColl || pParse->nErr);
-  
-          for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
-            if( NEVER(j>=pIdx->nColumn) ) return 0;
+  aEquiv[0] = iCur;
+  aEquiv[1] = iColumn;
+  for(;;){
+    for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
+      for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+        if( pTerm->leftCursor==iCur
+          && pTerm->u.leftColumn==iColumn
+        ){
+          if( (pTerm->prereqRight & notReady)==0
+           && (pTerm->eOperator & op & WO_ALL)!=0
+          ){
+            if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
+              CollSeq *pColl;
+              char idxaff;
+      
+              pX = pTerm->pExpr;
+              pParse = pWC->pParse;
+              idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
+              if( !sqlite3IndexAffinityOk(pX, idxaff) ){
+                continue;
+              }
+      
+              /* Figure out the collation sequence required from an index for
+              ** it to be useful for optimising expression pX. Store this
+              ** value in variable pColl.
+              */
+              assert(pX->pLeft);
+              pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
+              if( pColl==0 ) pColl = pParse->db->pDfltColl;
+      
+              for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
+                if( NEVER(j>=pIdx->nColumn) ) return 0;
+              }
+              if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
+                continue;
+              }
+            }
+            if( pTerm->prereqRight==0 && (pTerm->eOperator&WO_EQ)!=0 ){
+              pResult = pTerm;
+              goto findTerm_success;
+            }else if( pResult==0 ){
+              pResult = pTerm;
+            }
+          }
+          if( (pTerm->eOperator & WO_EQUIV)!=0
+           && nEquiv<ArraySize(aEquiv)
+          ){
+            pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
+            assert( pX->op==TK_COLUMN );
+            for(j=0; j<nEquiv; j+=2){
+              if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
+            }
+            if( j==nEquiv ){
+              aEquiv[j] = pX->iTable;
+              aEquiv[j+1] = pX->iColumn;
+              nEquiv += 2;
+            }
           }
-          if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
         }
-        return pTerm;
       }
     }
+    if( iEquiv>=nEquiv ) break;
+    iCur = aEquiv[iEquiv++];
+    iColumn = aEquiv[iEquiv++];
   }
-  return 0;
+findTerm_success:
+  return pResult;
 }
 
 /* Forward reference */
@@ -102516,7 +105346,7 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
 **
 ** CASE 1:
 **
-** If all subterms are of the form T.C=expr for some single column of C
+** If all subterms are of the form T.C=expr for some single column of C and
 ** a single table T (as shown in example B above) then create a new virtual
 ** term that is an equivalent IN expression.  In other words, if the term
 ** being analyzed is:
@@ -102604,11 +105434,10 @@ static void exprAnalyzeOrTerm(
   ** Compute the set of tables that might satisfy cases 1 or 2.
   */
   indexable = ~(Bitmask)0;
-  chngToIN = ~(pWC->vmask);
+  chngToIN = ~(Bitmask)0;
   for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
     if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
       WhereAndInfo *pAndInfo;
-      assert( pOrTerm->eOperator==0 );
       assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
       chngToIN = 0;
       pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
@@ -102647,7 +105476,7 @@ static void exprAnalyzeOrTerm(
         b |= getMask(pMaskSet, pOther->leftCursor);
       }
       indexable &= b;
-      if( pOrTerm->eOperator!=WO_EQ ){
+      if( (pOrTerm->eOperator & WO_EQ)==0 ){
         chngToIN = 0;
       }else{
         chngToIN &= b;
@@ -102698,7 +105527,7 @@ static void exprAnalyzeOrTerm(
     for(j=0; j<2 && !okToChngToIN; j++){
       pOrTerm = pOrWc->a;
       for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
-        assert( pOrTerm->eOperator==WO_EQ );
+        assert( pOrTerm->eOperator & WO_EQ );
         pOrTerm->wtFlags &= ~TERM_OR_OK;
         if( pOrTerm->leftCursor==iCursor ){
           /* This is the 2-bit case and we are on the second iteration and
@@ -102724,7 +105553,7 @@ static void exprAnalyzeOrTerm(
         /* No candidate table+column was found.  This can only occur
         ** on the second iteration */
         assert( j==1 );
-        assert( (chngToIN&(chngToIN-1))==0 );
+        assert( IsPowerOfTwo(chngToIN) );
         assert( chngToIN==getMask(pMaskSet, iCursor) );
         break;
       }
@@ -102734,7 +105563,7 @@ static void exprAnalyzeOrTerm(
       ** table and column is common to every term in the OR clause */
       okToChngToIN = 1;
       for(; i>=0 && okToChngToIN; i--, pOrTerm++){
-        assert( pOrTerm->eOperator==WO_EQ );
+        assert( pOrTerm->eOperator & WO_EQ );
         if( pOrTerm->leftCursor!=iCursor ){
           pOrTerm->wtFlags &= ~TERM_OR_OK;
         }else if( pOrTerm->u.leftColumn!=iColumn ){
@@ -102770,7 +105599,7 @@ static void exprAnalyzeOrTerm(
 
       for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
         if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
-        assert( pOrTerm->eOperator==WO_EQ );
+        assert( pOrTerm->eOperator & WO_EQ );
         assert( pOrTerm->leftCursor==iCursor );
         assert( pOrTerm->u.leftColumn==iColumn );
         pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
@@ -102800,7 +105629,6 @@ static void exprAnalyzeOrTerm(
 }
 #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
 
-
 /*
 ** The input to this routine is an WhereTerm structure with only the
 ** "pExpr" field filled in.  The job of this routine is to analyze the
@@ -102843,6 +105671,7 @@ static void exprAnalyze(
   pTerm = &pWC->a[idxTerm];
   pMaskSet = pWC->pMaskSet;
   pExpr = pTerm->pExpr;
+  assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
   prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
   op = pExpr->op;
   if( op==TK_IN ){
@@ -102868,17 +105697,19 @@ static void exprAnalyze(
   pTerm->leftCursor = -1;
   pTerm->iParent = -1;
   pTerm->eOperator = 0;
-  if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
-    Expr *pLeft = pExpr->pLeft;
-    Expr *pRight = pExpr->pRight;
+  if( allowedOp(op) ){
+    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
+    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
+    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
     if( pLeft->op==TK_COLUMN ){
       pTerm->leftCursor = pLeft->iTable;
       pTerm->u.leftColumn = pLeft->iColumn;
-      pTerm->eOperator = operatorMask(op);
+      pTerm->eOperator = operatorMask(op) & opMask;
     }
     if( pRight && pRight->op==TK_COLUMN ){
       WhereTerm *pNew;
       Expr *pDup;
+      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
       if( pTerm->leftCursor>=0 ){
         int idxNew;
         pDup = sqlite3ExprDup(db, pExpr, 0);
@@ -102893,18 +105724,25 @@ static void exprAnalyze(
         pTerm = &pWC->a[idxTerm];
         pTerm->nChild = 1;
         pTerm->wtFlags |= TERM_COPIED;
+        if( pExpr->op==TK_EQ
+         && !ExprHasProperty(pExpr, EP_FromJoin)
+         && OptimizationEnabled(db, SQLITE_Transitive)
+        ){
+          pTerm->eOperator |= WO_EQUIV;
+          eExtraOp = WO_EQUIV;
+        }
       }else{
         pDup = pExpr;
         pNew = pTerm;
       }
       exprCommute(pParse, pDup);
-      pLeft = pDup->pLeft;
+      pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
       pNew->leftCursor = pLeft->iTable;
       pNew->u.leftColumn = pLeft->iColumn;
       testcase( (prereqLeft | extraRight) != prereqLeft );
       pNew->prereqRight = prereqLeft | extraRight;
       pNew->prereqAll = prereqAll;
-      pNew->eOperator = operatorMask(pDup->op);
+      pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
     }
   }
 
@@ -102977,7 +105815,7 @@ static void exprAnalyze(
     Expr *pNewExpr2;
     int idxNew1;
     int idxNew2;
-    CollSeq *pColl;    /* Collating sequence to use */
+    Token sCollSeqName;  /* Name of collating sequence */
 
     pLeft = pExpr->x.pList->a[1].pExpr;
     pStr2 = sqlite3ExprDup(db, pStr1, 0);
@@ -102999,16 +105837,19 @@ static void exprAnalyze(
       }
       *pC = c + 1;
     }
-    pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
+    sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
+    sCollSeqName.n = 6;
+    pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
     pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
-                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
-                     pStr1, 0);
+           sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
+           pStr1, 0);
     idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew1==0 );
     exprAnalyze(pSrc, pWC, idxNew1);
+    pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
     pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
-                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
-                     pStr2, 0);
+           sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
+           pStr2, 0);
     idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew2==0 );
     exprAnalyze(pSrc, pWC, idxNew2);
@@ -103106,25 +105947,6 @@ static void exprAnalyze(
 }
 
 /*
-** Return TRUE if any of the expressions in pList->a[iFirst...] contain
-** a reference to any table other than the iBase table.
-*/
-static int referencesOtherTables(
-  ExprList *pList,          /* Search expressions in ths list */
-  WhereMaskSet *pMaskSet,   /* Mapping from tables to bitmaps */
-  int iFirst,               /* Be searching with the iFirst-th expression */
-  int iBase                 /* Ignore references to this table */
-){
-  Bitmask allowed = ~getMask(pMaskSet, iBase);
-  while( iFirst<pList->nExpr ){
-    if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
-      return 1;
-    }
-  }
-  return 0;
-}
-
-/*
 ** This function searches the expression list passed as the second argument
 ** for an expression of type TK_COLUMN that refers to the same column and
 ** uses the same collation sequence as the iCol'th column of index pIdx.
@@ -103145,12 +105967,12 @@ static int findIndexCol(
   const char *zColl = pIdx->azColl[iCol];
 
   for(i=0; i<pList->nExpr; i++){
-    Expr *p = pList->a[i].pExpr;
+    Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
     if( p->op==TK_COLUMN
      && p->iColumn==pIdx->aiColumn[iCol]
      && p->iTable==iBase
     ){
-      CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
+      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
       if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
         return i;
       }
@@ -103183,7 +106005,8 @@ static int isDistinctIndex(
   Bitmask mask = 0;               /* Mask of unaccounted for pDistinct exprs */
   int i;                          /* Iterator variable */
 
-  if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
+  assert( pDistinct!=0 );
+  if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
   testcase( pDistinct->nExpr==BMS-1 );
 
   /* Loop through all the expressions in the distinct list. If any of them
@@ -103196,7 +106019,7 @@ static int isDistinctIndex(
   */
   for(i=0; i<pDistinct->nExpr; i++){
     WhereTerm *pTerm;
-    Expr *p = pDistinct->a[i].pExpr;
+    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
     if( p->op!=TK_COLUMN ) return 0;
     pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
     if( pTerm ){
@@ -103248,7 +106071,7 @@ static int isDistinctRedundant(
   ** current SELECT is a correlated sub-query.
   */
   for(i=0; i<pDistinct->nExpr; i++){
-    Expr *p = pDistinct->a[i].pExpr;
+    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
     if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
   }
 
@@ -103286,165 +106109,6 @@ static int isDistinctRedundant(
 }
 
 /*
-** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause.  If it can, it returns 1.  If pIdx cannot satisfy the
-** ORDER BY clause, this routine returns 0.
-**
-** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the
-** left-most table in the FROM clause of that same SELECT statement and
-** the table has a cursor number of "base".  pIdx is an index on pTab.
-**
-** nEqCol is the number of columns of pIdx that are used as equality
-** constraints.  Any of these columns may be missing from the ORDER BY
-** clause and the match can still be a success.
-**
-** All terms of the ORDER BY that match against the index must be either
-** ASC or DESC.  (Terms of the ORDER BY clause past the end of a UNIQUE
-** index do not need to satisfy this constraint.)  The *pbRev value is
-** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
-** the ORDER BY clause is all ASC.
-*/
-static int isSortingIndex(
-  Parse *pParse,          /* Parsing context */
-  WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmaps */
-  Index *pIdx,            /* The index we are testing */
-  int base,               /* Cursor number for the table to be sorted */
-  ExprList *pOrderBy,     /* The ORDER BY clause */
-  int nEqCol,             /* Number of index columns with == constraints */
-  int wsFlags,            /* Index usages flags */
-  int *pbRev              /* Set to 1 if ORDER BY is DESC */
-){
-  int i, j;                       /* Loop counters */
-  int sortOrder = 0;              /* XOR of index and ORDER BY sort direction */
-  int nTerm;                      /* Number of ORDER BY terms */
-  struct ExprList_item *pTerm;    /* A term of the ORDER BY clause */
-  sqlite3 *db = pParse->db;
-
-  if( !pOrderBy ) return 0;
-  if( wsFlags & WHERE_COLUMN_IN ) return 0;
-  if( pIdx->bUnordered ) return 0;
-
-  nTerm = pOrderBy->nExpr;
-  assert( nTerm>0 );
-
-  /* Argument pIdx must either point to a 'real' named index structure, 
-  ** or an index structure allocated on the stack by bestBtreeIndex() to
-  ** represent the rowid index that is part of every table.  */
-  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
-
-  /* Match terms of the ORDER BY clause against columns of
-  ** the index.
-  **
-  ** Note that indices have pIdx->nColumn regular columns plus
-  ** one additional column containing the rowid.  The rowid column
-  ** of the index is also allowed to match against the ORDER BY
-  ** clause.
-  */
-  for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<=pIdx->nColumn; i++){
-    Expr *pExpr;       /* The expression of the ORDER BY pTerm */
-    CollSeq *pColl;    /* The collating sequence of pExpr */
-    int termSortOrder; /* Sort order for this term */
-    int iColumn;       /* The i-th column of the index.  -1 for rowid */
-    int iSortOrder;    /* 1 for DESC, 0 for ASC on the i-th index term */
-    const char *zColl; /* Name of the collating sequence for i-th index term */
-
-    pExpr = pTerm->pExpr;
-    if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
-      /* Can not use an index sort on anything that is not a column in the
-      ** left-most table of the FROM clause */
-      break;
-    }
-    pColl = sqlite3ExprCollSeq(pParse, pExpr);
-    if( !pColl ){
-      pColl = db->pDfltColl;
-    }
-    if( pIdx->zName && i<pIdx->nColumn ){
-      iColumn = pIdx->aiColumn[i];
-      if( iColumn==pIdx->pTable->iPKey ){
-        iColumn = -1;
-      }
-      iSortOrder = pIdx->aSortOrder[i];
-      zColl = pIdx->azColl[i];
-    }else{
-      iColumn = -1;
-      iSortOrder = 0;
-      zColl = pColl->zName;
-    }
-    if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){
-      /* Term j of the ORDER BY clause does not match column i of the index */
-      if( i<nEqCol ){
-        /* If an index column that is constrained by == fails to match an
-        ** ORDER BY term, that is OK.  Just ignore that column of the index
-        */
-        continue;
-      }else if( i==pIdx->nColumn ){
-        /* Index column i is the rowid.  All other terms match. */
-        break;
-      }else{
-        /* If an index column fails to match and is not constrained by ==
-        ** then the index cannot satisfy the ORDER BY constraint.
-        */
-        return 0;
-      }
-    }
-    assert( pIdx->aSortOrder!=0 || iColumn==-1 );
-    assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
-    assert( iSortOrder==0 || iSortOrder==1 );
-    termSortOrder = iSortOrder ^ pTerm->sortOrder;
-    if( i>nEqCol ){
-      if( termSortOrder!=sortOrder ){
-        /* Indices can only be used if all ORDER BY terms past the
-        ** equality constraints are all either DESC or ASC. */
-        return 0;
-      }
-    }else{
-      sortOrder = termSortOrder;
-    }
-    j++;
-    pTerm++;
-    if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
-      /* If the indexed column is the primary key and everything matches
-      ** so far and none of the ORDER BY terms to the right reference other
-      ** tables in the join, then we are assured that the index can be used 
-      ** to sort because the primary key is unique and so none of the other
-      ** columns will make any difference
-      */
-      j = nTerm;
-    }
-  }
-
-  *pbRev = sortOrder!=0;
-  if( j>=nTerm ){
-    /* All terms of the ORDER BY clause are covered by this index so
-    ** this index can be used for sorting. */
-    return 1;
-  }
-  if( pIdx->onError!=OE_None && i==pIdx->nColumn
-      && (wsFlags & WHERE_COLUMN_NULL)==0
-      && !referencesOtherTables(pOrderBy, pMaskSet, j, base) 
-  ){
-    Column *aCol = pIdx->pTable->aCol;
-
-    /* All terms of this index match some prefix of the ORDER BY clause,
-    ** the index is UNIQUE, and no terms on the tail of the ORDER BY
-    ** refer to other tables in a join. So, assuming that the index entries
-    ** visited contain no NULL values, then this index delivers rows in
-    ** the required order.
-    **
-    ** It is not possible for any of the first nEqCol index fields to be
-    ** NULL (since the corresponding "=" operator in the WHERE clause would 
-    ** not be true). So if all remaining index columns have NOT NULL 
-    ** constaints attached to them, we can be confident that the visited
-    ** index entries are free of NULLs.  */
-    for(i=nEqCol; i<pIdx->nColumn; i++){
-      if( aCol[pIdx->aiColumn[i]].notNull==0 ) break;
-    }
-    return (i==pIdx->nColumn);
-  }
-  return 0;
-}
-
-/*
 ** Prepare a crude estimate of the logarithm of the input value.
 ** The results need not be exact.  This is only used for estimating
 ** the total cost of performing operations with O(logN) or O(NlogN)
@@ -103508,9 +106172,7 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
 /* 
 ** Required because bestIndex() is called by bestOrClauseIndex() 
 */
-static void bestIndex(
-    Parse*, WhereClause*, struct SrcList_item*,
-    Bitmask, Bitmask, ExprList*, WhereCost*);
+static void bestIndex(WhereBestIdx*);
 
 /*
 ** This routine attempts to find an scanning strategy that can be used 
@@ -103519,20 +106181,14 @@ static void bestIndex(
 ** The table associated with FROM clause term pSrc may be either a
 ** regular B-Tree table or a virtual table.
 */
-static void bestOrClauseIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors not available for indexing */
-  Bitmask notValid,           /* Cursors not available for any purpose */
-  ExprList *pOrderBy,         /* The ORDER BY clause */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
+static void bestOrClauseIndex(WhereBestIdx *p){
 #ifndef SQLITE_OMIT_OR_OPTIMIZATION
-  const int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
+  WhereClause *pWC = p->pWC;           /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+  const int iCur = pSrc->iCursor;      /* The cursor of the table  */
   const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur);  /* Bitmask for pSrc */
   WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm];        /* End of pWC->a[] */
-  WhereTerm *pTerm;                 /* A single term of the WHERE clause */
+  WhereTerm *pTerm;                    /* A single term of the WHERE clause */
 
   /* The OR-clause optimization is disallowed if the INDEXED BY or
   ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
@@ -103545,8 +106201,8 @@ static void bestOrClauseIndex(
 
   /* Search the WHERE clause terms for a usable WO_OR term. */
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
-    if( pTerm->eOperator==WO_OR 
-     && ((pTerm->prereqAll & ~maskSrc) & notReady)==0
+    if( (pTerm->eOperator & WO_OR)!=0
+     && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
      && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 
     ){
       WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
@@ -103556,15 +106212,19 @@ static void bestOrClauseIndex(
       double rTotal = 0;
       double nRow = 0;
       Bitmask used = 0;
+      WhereBestIdx sBOI;
 
+      sBOI = *p;
+      sBOI.pOrderBy = 0;
+      sBOI.pDistinct = 0;
+      sBOI.ppIdxInfo = 0;
       for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
-        WhereCost sTermCost;
         WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
           (pOrTerm - pOrWC->a), (pTerm - pWC->a)
         ));
-        if( pOrTerm->eOperator==WO_AND ){
-          WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
-          bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost);
+        if( (pOrTerm->eOperator& WO_AND)!=0 ){
+          sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
+          bestIndex(&sBOI);
         }else if( pOrTerm->leftCursor==iCur ){
           WhereClause tempWC;
           tempWC.pParse = pWC->pParse;
@@ -103574,19 +106234,20 @@ static void bestOrClauseIndex(
           tempWC.a = pOrTerm;
           tempWC.wctrlFlags = 0;
           tempWC.nTerm = 1;
-          bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
+          sBOI.pWC = &tempWC;
+          bestIndex(&sBOI);
         }else{
           continue;
         }
-        rTotal += sTermCost.rCost;
-        nRow += sTermCost.plan.nRow;
-        used |= sTermCost.used;
-        if( rTotal>=pCost->rCost ) break;
+        rTotal += sBOI.cost.rCost;
+        nRow += sBOI.cost.plan.nRow;
+        used |= sBOI.cost.used;
+        if( rTotal>=p->cost.rCost ) break;
       }
 
       /* If there is an ORDER BY clause, increase the scan cost to account 
       ** for the cost of the sort. */
-      if( pOrderBy!=0 ){
+      if( p->pOrderBy!=0 ){
         WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
                     rTotal, rTotal+nRow*estLog(nRow)));
         rTotal += nRow*estLog(nRow);
@@ -103596,12 +106257,13 @@ static void bestOrClauseIndex(
       ** less than the current cost stored in pCost, replace the contents
       ** of pCost. */
       WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
-      if( rTotal<pCost->rCost ){
-        pCost->rCost = rTotal;
-        pCost->used = used;
-        pCost->plan.nRow = nRow;
-        pCost->plan.wsFlags = flags;
-        pCost->plan.u.pTerm = pTerm;
+      if( rTotal<p->cost.rCost ){
+        p->cost.rCost = rTotal;
+        p->cost.used = used;
+        p->cost.plan.nRow = nRow;
+        p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
+        p->cost.plan.wsFlags = flags;
+        p->cost.plan.u.pTerm = pTerm;
       }
     }
   }
@@ -103621,7 +106283,7 @@ static int termCanDriveIndex(
 ){
   char aff;
   if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
-  if( pTerm->eOperator!=WO_EQ ) return 0;
+  if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
   if( (pTerm->prereqRight & notReady)!=0 ) return 0;
   aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
   if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
@@ -103638,15 +106300,12 @@ static int termCanDriveIndex(
 ** is taken into account, then alter the query plan to use the
 ** transient index.
 */
-static void bestAutomaticIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors that are not available */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
-  double nTableRow;           /* Rows in the input table */
-  double logN;                /* log(nTableRow) */
+static void bestAutomaticIndex(WhereBestIdx *p){
+  Parse *pParse = p->pParse;            /* The parsing context */
+  WhereClause *pWC = p->pWC;            /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc;  /* The FROM clause term to search */
+  double nTableRow;                     /* Rows in the input table */
+  double logN;                          /* log(nTableRow) */
   double costTempIdx;         /* per-query cost of the transient index */
   WhereTerm *pTerm;           /* A single term of the WHERE clause */
   WhereTerm *pWCEnd;          /* End of pWC->a[] */
@@ -103660,10 +106319,16 @@ static void bestAutomaticIndex(
     /* Automatic indices are disabled at run-time */
     return;
   }
-  if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
+  if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
+   && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
+  ){
     /* We already have some kind of index in use for this query. */
     return;
   }
+  if( pSrc->viaCoroutine ){
+    /* Cannot index a co-routine */
+    return;
+  }
   if( pSrc->notIndexed ){
     /* The NOT INDEXED clause appears in the SQL. */
     return;
@@ -103678,7 +106343,7 @@ static void bestAutomaticIndex(
   nTableRow = pTable->nRowEst;
   logN = estLog(nTableRow);
   costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
-  if( costTempIdx>=pCost->rCost ){
+  if( costTempIdx>=p->cost.rCost ){
     /* The cost of creating the transient table would be greater than
     ** doing the full table scan */
     return;
@@ -103687,19 +106352,19 @@ static void bestAutomaticIndex(
   /* Search for any equality comparison term */
   pWCEnd = &pWC->a[pWC->nTerm];
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
-    if( termCanDriveIndex(pTerm, pSrc, notReady) ){
+    if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
       WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
-                    pCost->rCost, costTempIdx));
-      pCost->rCost = costTempIdx;
-      pCost->plan.nRow = logN + 1;
-      pCost->plan.wsFlags = WHERE_TEMP_INDEX;
-      pCost->used = pTerm->prereqRight;
+                    p->cost.rCost, costTempIdx));
+      p->cost.rCost = costTempIdx;
+      p->cost.plan.nRow = logN + 1;
+      p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
+      p->cost.used = pTerm->prereqRight;
       break;
     }
   }
 }
 #else
-# define bestAutomaticIndex(A,B,C,D,E)  /* no-op */
+# define bestAutomaticIndex(A)  /* no-op */
 #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
 
 
@@ -103860,12 +106525,11 @@ static void constructAutomaticIndex(
 ** responsibility of the caller to eventually release the structure
 ** by passing the pointer returned by this function to sqlite3_free().
 */
-static sqlite3_index_info *allocateIndexInfo(
-  Parse *pParse, 
-  WhereClause *pWC,
-  struct SrcList_item *pSrc,
-  ExprList *pOrderBy
-){
+static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
+  Parse *pParse = p->pParse; 
+  WhereClause *pWC = p->pWC;
+  struct SrcList_item *pSrc = p->pSrc;
+  ExprList *pOrderBy = p->pOrderBy;
   int i, j;
   int nTerm;
   struct sqlite3_index_constraint *pIdxCons;
@@ -103881,10 +106545,10 @@ static sqlite3_index_info *allocateIndexInfo(
   ** to this virtual table */
   for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
     if( pTerm->leftCursor != pSrc->iCursor ) continue;
-    assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
-    testcase( pTerm->eOperator==WO_IN );
-    testcase( pTerm->eOperator==WO_ISNULL );
-    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+    testcase( pTerm->eOperator & WO_IN );
+    testcase( pTerm->eOperator & WO_ISNULL );
+    if( pTerm->eOperator & (WO_ISNULL) ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     nTerm++;
   }
@@ -103895,12 +106559,13 @@ static sqlite3_index_info *allocateIndexInfo(
   */
   nOrderBy = 0;
   if( pOrderBy ){
-    for(i=0; i<pOrderBy->nExpr; i++){
+    int n = pOrderBy->nExpr;
+    for(i=0; i<n; i++){
       Expr *pExpr = pOrderBy->a[i].pExpr;
       if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
     }
-    if( i==pOrderBy->nExpr ){
-      nOrderBy = pOrderBy->nExpr;
+    if( i==n){
+      nOrderBy = n;
     }
   }
 
@@ -103931,15 +106596,18 @@ static sqlite3_index_info *allocateIndexInfo(
                                                                    pUsage;
 
   for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+    u8 op;
     if( pTerm->leftCursor != pSrc->iCursor ) continue;
-    assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
-    testcase( pTerm->eOperator==WO_IN );
-    testcase( pTerm->eOperator==WO_ISNULL );
-    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+    testcase( pTerm->eOperator & WO_IN );
+    testcase( pTerm->eOperator & WO_ISNULL );
+    if( pTerm->eOperator & (WO_ISNULL) ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     pIdxCons[j].iColumn = pTerm->u.leftColumn;
     pIdxCons[j].iTermOffset = i;
-    pIdxCons[j].op = (u8)pTerm->eOperator;
+    op = (u8)pTerm->eOperator & WO_ALL;
+    if( op==WO_IN ) op = WO_EQ;
+    pIdxCons[j].op = op;
     /* The direct assignment in the previous line is possible only because
     ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
     ** following asserts verify this fact. */
@@ -103949,7 +106617,7 @@ static sqlite3_index_info *allocateIndexInfo(
     assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
     assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
     assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
-    assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+    assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
     j++;
   }
   for(i=0; i<nOrderBy; i++){
@@ -104024,16 +106692,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
 ** routine takes care of freeing the sqlite3_index_info structure after
 ** everybody has finished with it.
 */
-static void bestVirtualIndex(
-  Parse *pParse,                  /* The parsing context */
-  WhereClause *pWC,               /* The WHERE clause */
-  struct SrcList_item *pSrc,      /* The FROM clause term to search */
-  Bitmask notReady,               /* Mask of cursors not available for index */
-  Bitmask notValid,               /* Cursors not valid for any purpose */
-  ExprList *pOrderBy,             /* The order by clause */
-  WhereCost *pCost,               /* Lowest cost query plan */
-  sqlite3_index_info **ppIdxInfo  /* Index information passed to xBestIndex */
-){
+static void bestVirtualIndex(WhereBestIdx *p){
+  Parse *pParse = p->pParse;      /* The parsing context */
+  WhereClause *pWC = p->pWC;      /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
   Table *pTab = pSrc->pTab;
   sqlite3_index_info *pIdxInfo;
   struct sqlite3_index_constraint *pIdxCons;
@@ -104041,21 +106703,22 @@ static void bestVirtualIndex(
   WhereTerm *pTerm;
   int i, j;
   int nOrderBy;
+  int bAllowIN;                   /* Allow IN optimizations */
   double rCost;
 
   /* Make sure wsFlags is initialized to some sane value. Otherwise, if the 
   ** malloc in allocateIndexInfo() fails and this function returns leaving
   ** wsFlags in an uninitialized state, the caller may behave unpredictably.
   */
-  memset(pCost, 0, sizeof(*pCost));
-  pCost->plan.wsFlags = WHERE_VIRTUALTABLE;
+  memset(&p->cost, 0, sizeof(p->cost));
+  p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
 
   /* If the sqlite3_index_info structure has not been previously
   ** allocated and initialized, then allocate and initialize it now.
   */
-  pIdxInfo = *ppIdxInfo;
+  pIdxInfo = *p->ppIdxInfo;
   if( pIdxInfo==0 ){
-    *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy);
+    *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
   }
   if( pIdxInfo==0 ){
     return;
@@ -104075,65 +106738,112 @@ static void bestVirtualIndex(
   assert( pTab->azModuleArg && pTab->azModuleArg[0] );
   assert( sqlite3GetVTable(pParse->db, pTab) );
 
-  /* Set the aConstraint[].usable fields and initialize all 
-  ** output variables to zero.
-  **
-  ** aConstraint[].usable is true for constraints where the right-hand
-  ** side contains only references to tables to the left of the current
-  ** table.  In other words, if the constraint is of the form:
-  **
-  **           column = expr
-  **
-  ** and we are evaluating a join, then the constraint on column is 
-  ** only valid if all tables referenced in expr occur to the left
-  ** of the table containing column.
-  **
-  ** The aConstraints[] array contains entries for all constraints
-  ** on the current table.  That way we only have to compute it once
-  ** even though we might try to pick the best index multiple times.
-  ** For each attempt at picking an index, the order of tables in the
-  ** join might be different so we have to recompute the usable flag
-  ** each time.
-  */
-  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
-  pUsage = pIdxInfo->aConstraintUsage;
-  for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
-    j = pIdxCons->iTermOffset;
-    pTerm = &pWC->a[j];
-    pIdxCons->usable = (pTerm->prereqRight&notReady) ? 0 : 1;
-  }
-  memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
-  if( pIdxInfo->needToFreeIdxStr ){
-    sqlite3_free(pIdxInfo->idxStr);
-  }
-  pIdxInfo->idxStr = 0;
-  pIdxInfo->idxNum = 0;
-  pIdxInfo->needToFreeIdxStr = 0;
-  pIdxInfo->orderByConsumed = 0;
-  /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
-  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
-  nOrderBy = pIdxInfo->nOrderBy;
-  if( !pOrderBy ){
-    pIdxInfo->nOrderBy = 0;
-  }
-
-  if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
-    return;
-  }
+  /* Try once or twice.  On the first attempt, allow IN optimizations.
+  ** If an IN optimization is accepted by the virtual table xBestIndex
+  ** method, but the  pInfo->aConstrainUsage.omit flag is not set, then
+  ** the query will not work because it might allow duplicate rows in
+  ** output.  In that case, run the xBestIndex method a second time
+  ** without the IN constraints.  Usually this loop only runs once.
+  ** The loop will exit using a "break" statement.
+  */
+  for(bAllowIN=1; 1; bAllowIN--){
+    assert( bAllowIN==0 || bAllowIN==1 );
 
-  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
-  for(i=0; i<pIdxInfo->nConstraint; i++){
-    if( pUsage[i].argvIndex>0 ){
-      pCost->used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
+    /* Set the aConstraint[].usable fields and initialize all 
+    ** output variables to zero.
+    **
+    ** aConstraint[].usable is true for constraints where the right-hand
+    ** side contains only references to tables to the left of the current
+    ** table.  In other words, if the constraint is of the form:
+    **
+    **           column = expr
+    **
+    ** and we are evaluating a join, then the constraint on column is 
+    ** only valid if all tables referenced in expr occur to the left
+    ** of the table containing column.
+    **
+    ** The aConstraints[] array contains entries for all constraints
+    ** on the current table.  That way we only have to compute it once
+    ** even though we might try to pick the best index multiple times.
+    ** For each attempt at picking an index, the order of tables in the
+    ** join might be different so we have to recompute the usable flag
+    ** each time.
+    */
+    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+    pUsage = pIdxInfo->aConstraintUsage;
+    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+      j = pIdxCons->iTermOffset;
+      pTerm = &pWC->a[j];
+      if( (pTerm->prereqRight&p->notReady)==0
+       && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
+      ){
+        pIdxCons->usable = 1;
+      }else{
+        pIdxCons->usable = 0;
+      }
+    }
+    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+    if( pIdxInfo->needToFreeIdxStr ){
+      sqlite3_free(pIdxInfo->idxStr);
+    }
+    pIdxInfo->idxStr = 0;
+    pIdxInfo->idxNum = 0;
+    pIdxInfo->needToFreeIdxStr = 0;
+    pIdxInfo->orderByConsumed = 0;
+    /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
+    pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
+    nOrderBy = pIdxInfo->nOrderBy;
+    if( !p->pOrderBy ){
+      pIdxInfo->nOrderBy = 0;
+    }
+  
+    if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
+      return;
+    }
+  
+    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+      if( pUsage[i].argvIndex>0 ){
+        j = pIdxCons->iTermOffset;
+        pTerm = &pWC->a[j];
+        p->cost.used |= pTerm->prereqRight;
+        if( (pTerm->eOperator & WO_IN)!=0 ){
+          if( pUsage[i].omit==0 ){
+            /* Do not attempt to use an IN constraint if the virtual table
+            ** says that the equivalent EQ constraint cannot be safely omitted.
+            ** If we do attempt to use such a constraint, some rows might be
+            ** repeated in the output. */
+            break;
+          }
+          /* A virtual table that is constrained by an IN clause may not
+          ** consume the ORDER BY clause because (1) the order of IN terms
+          ** is not necessarily related to the order of output terms and
+          ** (2) Multiple outputs from a single IN value will not merge
+          ** together.  */
+          pIdxInfo->orderByConsumed = 0;
+        }
+      }
     }
+    if( i>=pIdxInfo->nConstraint ) break;
   }
 
+  /* The orderByConsumed signal is only valid if all outer loops collectively
+  ** generate just a single row of output.
+  */
+  if( pIdxInfo->orderByConsumed ){
+    for(i=0; i<p->i; i++){
+      if( (p->aLevel[i].plan.wsFlags & WHERE_UNIQUE)==0 ){
+        pIdxInfo->orderByConsumed = 0;
+      }
+    }
+  }
+  
   /* If there is an ORDER BY clause, and the selected virtual table index
   ** does not satisfy it, increase the cost of the scan accordingly. This
   ** matches the processing for non-virtual tables in bestBtreeIndex().
   */
   rCost = pIdxInfo->estimatedCost;
-  if( pOrderBy && pIdxInfo->orderByConsumed==0 ){
+  if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
     rCost += estLog(rCost)*rCost;
   }
 
@@ -104145,21 +106855,24 @@ static void bestVirtualIndex(
   ** is defined.
   */
   if( (SQLITE_BIG_DBL/((double)2))<rCost ){
-    pCost->rCost = (SQLITE_BIG_DBL/((double)2));
+    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
   }else{
-    pCost->rCost = rCost;
+    p->cost.rCost = rCost;
   }
-  pCost->plan.u.pVtabIdx = pIdxInfo;
+  p->cost.plan.u.pVtabIdx = pIdxInfo;
   if( pIdxInfo->orderByConsumed ){
-    pCost->plan.wsFlags |= WHERE_ORDERBY;
+    p->cost.plan.wsFlags |= WHERE_ORDERED;
+    p->cost.plan.nOBSat = nOrderBy;
+  }else{
+    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
   }
-  pCost->plan.nEq = 0;
+  p->cost.plan.nEq = 0;
   pIdxInfo->nOrderBy = nOrderBy;
 
   /* Try to find a more efficient access pattern by using multiple indexes
   ** to optimize an OR expression within the WHERE clause. 
   */
-  bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
+  bestOrClauseIndex(p);
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
@@ -104247,10 +106960,8 @@ static int whereKeyStats(
         pColl = db->pDfltColl;
         assert( pColl->enc==SQLITE_UTF8 );
       }else{
-        pColl = sqlite3GetCollSeq(db, SQLITE_UTF8, 0, *pIdx->azColl);
+        pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
         if( pColl==0 ){
-          sqlite3ErrorMsg(pParse, "no such collation sequence: %s",
-                          *pIdx->azColl);
           return SQLITE_ERROR;
         }
         z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
@@ -104421,24 +107132,24 @@ static int whereRangeScanEst(
     if( pLower ){
       Expr *pExpr = pLower->pExpr->pRight;
       rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
-      assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
+      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
       if( rc==SQLITE_OK
        && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
       ){
         iLower = a[0];
-        if( pLower->eOperator==WO_GT ) iLower += a[1];
+        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
       }
       sqlite3ValueFree(pRangeVal);
     }
     if( rc==SQLITE_OK && pUpper ){
       Expr *pExpr = pUpper->pExpr->pRight;
       rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
-      assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
+      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
       if( rc==SQLITE_OK
        && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
       ){
         iUpper = a[0];
-        if( pUpper->eOperator==WO_LE ) iUpper += a[1];
+        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
       }
       sqlite3ValueFree(pRangeVal);
     }
@@ -104558,11 +107269,295 @@ static int whereInScanEst(
 }
 #endif /* defined(SQLITE_ENABLE_STAT3) */
 
+/*
+** Check to see if column iCol of the table with cursor iTab will appear
+** in sorted order according to the current query plan.
+**
+** Return values:
+**
+**    0   iCol is not ordered
+**    1   iCol has only a single value
+**    2   iCol is in ASC order
+**    3   iCol is in DESC order
+*/
+static int isOrderedColumn(
+  WhereBestIdx *p,
+  int iTab,
+  int iCol
+){
+  int i, j;
+  WhereLevel *pLevel = &p->aLevel[p->i-1];
+  Index *pIdx;
+  u8 sortOrder;
+  for(i=p->i-1; i>=0; i--, pLevel--){
+    if( pLevel->iTabCur!=iTab ) continue;
+    if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+      return 1;
+    }
+    assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
+    if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
+      if( iCol<0 ){
+        sortOrder = 0;
+        testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+      }else{
+        int n = pIdx->nColumn;
+        for(j=0; j<n; j++){
+          if( iCol==pIdx->aiColumn[j] ) break;
+        }
+        if( j>=n ) return 0;
+        sortOrder = pIdx->aSortOrder[j];
+        testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+      }
+    }else{
+      if( iCol!=(-1) ) return 0;
+      sortOrder = 0;
+      testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+    }
+    if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
+      assert( sortOrder==0 || sortOrder==1 );
+      testcase( sortOrder==1 );
+      sortOrder = 1 - sortOrder;
+    }
+    return sortOrder+2;
+  }
+  return 0;
+}
+
+/*
+** This routine decides if pIdx can be used to satisfy the ORDER BY
+** clause, either in whole or in part.  The return value is the 
+** cumulative number of terms in the ORDER BY clause that are satisfied
+** by the index pIdx and other indices in outer loops.
+**
+** The table being queried has a cursor number of "base".  pIdx is the
+** index that is postulated for use to access the table.
+**
+** The *pbRev value is set to 0 order 1 depending on whether or not
+** pIdx should be run in the forward order or in reverse order.
+*/
+static int isSortingIndex(
+  WhereBestIdx *p,    /* Best index search context */
+  Index *pIdx,        /* The index we are testing */
+  int base,           /* Cursor number for the table to be sorted */
+  int *pbRev,         /* Set to 1 for reverse-order scan of pIdx */
+  int *pbObUnique     /* ORDER BY column values will different in every row */
+){
+  int i;                        /* Number of pIdx terms used */
+  int j;                        /* Number of ORDER BY terms satisfied */
+  int sortOrder = 2;            /* 0: forward.  1: backward.  2: unknown */
+  int nTerm;                    /* Number of ORDER BY terms */
+  struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
+  Table *pTab = pIdx->pTable;   /* Table that owns index pIdx */
+  ExprList *pOrderBy;           /* The ORDER BY clause */
+  Parse *pParse = p->pParse;    /* Parser context */
+  sqlite3 *db = pParse->db;     /* Database connection */
+  int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
+  int seenRowid = 0;            /* True if an ORDER BY rowid term is seen */
+  int uniqueNotNull;            /* pIdx is UNIQUE with all terms are NOT NULL */
+  int outerObUnique;            /* Outer loops generate different values in
+                                ** every row for the ORDER BY columns */
+
+  if( p->i==0 ){
+    nPriorSat = 0;
+    outerObUnique = 1;
+  }else{
+    u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
+    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+    if( (wsFlags & WHERE_ORDERED)==0 ){
+      /* This loop cannot be ordered unless the next outer loop is
+      ** also ordered */
+      return nPriorSat;
+    }
+    if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
+      /* Only look at the outer-most loop if the OrderByIdxJoin
+      ** optimization is disabled */
+      return nPriorSat;
+    }
+    testcase( wsFlags & WHERE_OB_UNIQUE );
+    testcase( wsFlags & WHERE_ALL_UNIQUE );
+    outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
+  }
+  pOrderBy = p->pOrderBy;
+  assert( pOrderBy!=0 );
+  if( pIdx->bUnordered ){
+    /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
+    ** be used for sorting */
+    return nPriorSat;
+  }
+  nTerm = pOrderBy->nExpr;
+  uniqueNotNull = pIdx->onError!=OE_None;
+  assert( nTerm>0 );
+
+  /* Argument pIdx must either point to a 'real' named index structure, 
+  ** or an index structure allocated on the stack by bestBtreeIndex() to
+  ** represent the rowid index that is part of every table.  */
+  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
+
+  /* Match terms of the ORDER BY clause against columns of
+  ** the index.
+  **
+  ** Note that indices have pIdx->nColumn regular columns plus
+  ** one additional column containing the rowid.  The rowid column
+  ** of the index is also allowed to match against the ORDER BY
+  ** clause.
+  */
+  j = nPriorSat;
+  for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
+    Expr *pOBExpr;          /* The expression of the ORDER BY pOBItem */
+    CollSeq *pColl;         /* The collating sequence of pOBExpr */
+    int termSortOrder;      /* Sort order for this term */
+    int iColumn;            /* The i-th column of the index.  -1 for rowid */
+    int iSortOrder;         /* 1 for DESC, 0 for ASC on the i-th index term */
+    int isEq;               /* Subject to an == or IS NULL constraint */
+    int isMatch;            /* ORDER BY term matches the index term */
+    const char *zColl;      /* Name of collating sequence for i-th index term */
+    WhereTerm *pConstraint; /* A constraint in the WHERE clause */
+
+    /* If the next term of the ORDER BY clause refers to anything other than
+    ** a column in the "base" table, then this index will not be of any
+    ** further use in handling the ORDER BY. */
+    pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
+    if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
+      break;
+    }
+
+    /* Find column number and collating sequence for the next entry
+    ** in the index */
+    if( pIdx->zName && i<pIdx->nColumn ){
+      iColumn = pIdx->aiColumn[i];
+      if( iColumn==pIdx->pTable->iPKey ){
+        iColumn = -1;
+      }
+      iSortOrder = pIdx->aSortOrder[i];
+      zColl = pIdx->azColl[i];
+      assert( zColl!=0 );
+    }else{
+      iColumn = -1;
+      iSortOrder = 0;
+      zColl = 0;
+    }
+
+    /* Check to see if the column number and collating sequence of the
+    ** index match the column number and collating sequence of the ORDER BY
+    ** clause entry.  Set isMatch to 1 if they both match. */
+    if( pOBExpr->iColumn==iColumn ){
+      if( zColl ){
+        pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
+        if( !pColl ) pColl = db->pDfltColl;
+        isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
+      }else{
+        isMatch = 1;
+      }
+    }else{
+      isMatch = 0;
+    }
+
+    /* termSortOrder is 0 or 1 for whether or not the access loop should
+    ** run forward or backwards (respectively) in order to satisfy this 
+    ** term of the ORDER BY clause. */
+    assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
+    assert( iSortOrder==0 || iSortOrder==1 );
+    termSortOrder = iSortOrder ^ pOBItem->sortOrder;
+
+    /* If X is the column in the index and ORDER BY clause, check to see
+    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
+    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
+                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
+    if( pConstraint==0 ){
+      isEq = 0;
+    }else if( (pConstraint->eOperator & WO_IN)!=0 ){
+      isEq = 0;
+    }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
+      uniqueNotNull = 0;
+      isEq = 1;  /* "X IS NULL" means X has only a single value */
+    }else if( pConstraint->prereqRight==0 ){
+      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
+    }else{
+      Expr *pRight = pConstraint->pExpr->pRight;
+      if( pRight->op==TK_COLUMN ){
+        WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
+                    pRight->iTable, pRight->iColumn));
+        isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
+        WHERETRACE((" -> isEq=%d\n", isEq));
+
+        /* If the constraint is of the form X=Y where Y is an ordered value
+        ** in an outer loop, then make sure the sort order of Y matches the
+        ** sort order required for X. */
+        if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
+          testcase( isEq==2 );
+          testcase( isEq==3 );
+          break;
+        }
+      }else{
+        isEq = 0;  /* "X=expr" places no ordering constraints on X */
+      }
+    }
+    if( !isMatch ){
+      if( isEq==0 ){
+        break;
+      }else{
+        continue;
+      }
+    }else if( isEq!=1 ){
+      if( sortOrder==2 ){
+        sortOrder = termSortOrder;
+      }else if( termSortOrder!=sortOrder ){
+        break;
+      }
+    }
+    j++;
+    pOBItem++;
+    if( iColumn<0 ){
+      seenRowid = 1;
+      break;
+    }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
+      testcase( isEq==0 );
+      testcase( isEq==2 );
+      testcase( isEq==3 );
+      uniqueNotNull = 0;
+    }
+  }
+  if( seenRowid ){
+    uniqueNotNull = 1;
+  }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
+    uniqueNotNull = 0;
+  }
+
+  /* If we have not found at least one ORDER BY term that matches the
+  ** index, then show no progress. */
+  if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
+
+  /* Either the outer queries must generate rows where there are no two
+  ** rows with the same values in all ORDER BY columns, or else this
+  ** loop must generate just a single row of output.  Example:  Suppose
+  ** the outer loops generate A=1 and A=1, and this loop generates B=3
+  ** and B=4.  Then without the following test, ORDER BY A,B would 
+  ** generate the wrong order output: 1,3 1,4 1,3 1,4
+  */
+  if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
+  *pbObUnique = uniqueNotNull;
+
+  /* Return the necessary scan order back to the caller */
+  *pbRev = sortOrder & 1;
+
+  /* If there was an "ORDER BY rowid" term that matched, or it is only
+  ** possible for a single row from this table to match, then skip over
+  ** any additional ORDER BY terms dealing with this table.
+  */
+  if( uniqueNotNull ){
+    /* Advance j over additional ORDER BY terms associated with base */
+    WhereMaskSet *pMS = p->pWC->pMaskSet;
+    Bitmask m = ~getMask(pMS, base);
+    while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
+      j++;
+    }
+  }
+  return j;
+}
 
 /*
 ** Find the best query plan for accessing a particular table.  Write the
-** best query plan and its cost into the WhereCost object supplied as the
-** last parameter.
+** best query plan and its cost into the p->cost.
 **
 ** The lowest cost plan wins.  The cost is an estimate of the amount of
 ** CPU and disk I/O needed to process the requested result.
@@ -104582,21 +107577,15 @@ static int whereInScanEst(
 ** SQLITE_BIG_DBL. If a plan is found that uses the named index, 
 ** then the cost is calculated in the usual way.
 **
-** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table 
+** If a NOT INDEXED clause was attached to the table 
 ** in the SELECT statement, then no indexes are considered. However, the 
 ** selected plan may still take advantage of the built-in rowid primary key
 ** index.
 */
-static void bestBtreeIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors not available for indexing */
-  Bitmask notValid,           /* Cursors not available for any purpose */
-  ExprList *pOrderBy,         /* The ORDER BY clause */
-  ExprList *pDistinct,        /* The select-list if query is DISTINCT */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
+static void bestBtreeIndex(WhereBestIdx *p){
+  Parse *pParse = p->pParse;  /* The parsing context */
+  WhereClause *pWC = p->pWC;  /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
   int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
   Index *pProbe;              /* An index we are evaluating */
   Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
@@ -104605,11 +107594,16 @@ static void bestBtreeIndex(
   Index sPk;                  /* A fake index object for the primary key */
   tRowcnt aiRowEstPk[2];      /* The aiRowEst[] value for the sPk index */
   int aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
-  int wsFlagMask;             /* Allowed flags in pCost->plan.wsFlag */
+  int wsFlagMask;             /* Allowed flags in p->cost.plan.wsFlag */
+  int nPriorSat;              /* ORDER BY terms satisfied by outer loops */
+  int nOrderBy;               /* Number of ORDER BY terms */
+  char bSortInit;             /* Initializer for bSort in inner loop */
+  char bDistInit;             /* Initializer for bDist in inner loop */
+
 
   /* Initialize the cost to a worst-case value */
-  memset(pCost, 0, sizeof(*pCost));
-  pCost->rCost = SQLITE_BIG_DBL;
+  memset(&p->cost, 0, sizeof(p->cost));
+  p->cost.rCost = SQLITE_BIG_DBL;
 
   /* If the pSrc table is the right table of a LEFT JOIN then we may not
   ** use an index to satisfy IS NULL constraints on that table.  This is
@@ -104655,22 +107649,29 @@ static void bestBtreeIndex(
     pIdx = 0;
   }
 
+  nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
+  if( p->i ){
+    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+    bSortInit = nPriorSat<nOrderBy;
+    bDistInit = 0;
+  }else{
+    nPriorSat = 0;
+    bSortInit = nOrderBy>0;
+    bDistInit = p->pDistinct!=0;
+  }
+
   /* Loop over all indices looking for the best one to use
   */
   for(; pProbe; pIdx=pProbe=pProbe->pNext){
     const tRowcnt * const aiRowEst = pProbe->aiRowEst;
-    double cost;                /* Cost of using pProbe */
-    double nRow;                /* Estimated number of rows in result set */
+    WhereCost pc;               /* Cost of using pProbe */
     double log10N = (double)1;  /* base-10 logarithm of nRow (inexact) */
-    int rev;                    /* True to scan in reverse order */
-    int wsFlags = 0;
-    Bitmask used = 0;
 
     /* The following variables are populated based on the properties of
     ** index being evaluated. They are then used to determine the expected
     ** cost and number of rows returned.
     **
-    **  nEq: 
+    **  pc.plan.nEq: 
     **    Number of equality terms that can be implemented using the index.
     **    In other words, the number of initial fields in the index that
     **    are used in == or IN or NOT NULL constraints of the WHERE clause.
@@ -104713,6 +107714,10 @@ static void bestBtreeIndex(
     **    external sort (i.e. scanning the index being evaluated will not 
     **    correctly order records).
     **
+    **  bDist:
+    **    Boolean. True if there is a DISTINCT clause that will require an 
+    **    external btree.
+    **
     **  bLookup: 
     **    Boolean. True if a table lookup is required for each index entry
     **    visited.  In other words, true if this is not a covering index.
@@ -104728,29 +107733,35 @@ static void bestBtreeIndex(
     **             SELECT a, b    FROM tbl WHERE a = 1;
     **             SELECT a, b, c FROM tbl WHERE a = 1;
     */
-    int nEq;                      /* Number of == or IN terms matching index */
     int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
     int nInMul = 1;               /* Number of distinct equalities to lookup */
     double rangeDiv = (double)1;  /* Estimated reduction in search space */
     int nBound = 0;               /* Number of range constraints seen */
-    int bSort = !!pOrderBy;       /* True if external sort required */
-    int bDist = !!pDistinct;      /* True if index cannot help with DISTINCT */
-    int bLookup = 0;              /* True if not a covering index */
+    char bSort = bSortInit;       /* True if external sort required */
+    char bDist = bDistInit;       /* True if index cannot help with DISTINCT */
+    char bLookup = 0;             /* True if not a covering index */
     WhereTerm *pTerm;             /* A single term of the WHERE clause */
 #ifdef SQLITE_ENABLE_STAT3
     WhereTerm *pFirstTerm = 0;    /* First term matching the index */
 #endif
 
-    /* Determine the values of nEq and nInMul */
-    for(nEq=0; nEq<pProbe->nColumn; nEq++){
-      int j = pProbe->aiColumn[nEq];
-      pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
+    WHERETRACE((
+      "   %s(%s):\n",
+      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
+    ));
+    memset(&pc, 0, sizeof(pc));
+    pc.plan.nOBSat = nPriorSat;
+
+    /* Determine the values of pc.plan.nEq and nInMul */
+    for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
+      int j = pProbe->aiColumn[pc.plan.nEq];
+      pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
       if( pTerm==0 ) break;
-      wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
+      pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
       testcase( pTerm->pWC!=pWC );
       if( pTerm->eOperator & WO_IN ){
         Expr *pExpr = pTerm->pExpr;
-        wsFlags |= WHERE_COLUMN_IN;
+        pc.plan.wsFlags |= WHERE_COLUMN_IN;
         if( ExprHasProperty(pExpr, EP_xIsSelect) ){
           /* "x IN (SELECT ...)":  Assume the SELECT returns 25 rows */
           nInMul *= 25;
@@ -104760,12 +107771,12 @@ static void bestBtreeIndex(
           nInMul *= pExpr->x.pList->nExpr;
         }
       }else if( pTerm->eOperator & WO_ISNULL ){
-        wsFlags |= WHERE_COLUMN_NULL;
+        pc.plan.wsFlags |= WHERE_COLUMN_NULL;
       }
 #ifdef SQLITE_ENABLE_STAT3
-      if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
+      if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
 #endif
-      used |= pTerm->prereqRight;
+      pc.used |= pTerm->prereqRight;
     }
  
     /* If the index being considered is UNIQUE, and there is an equality 
@@ -104774,65 +107785,82 @@ static void bestBtreeIndex(
     ** indicate this to the caller.
     **
     ** Otherwise, if the search may find more than one row, test to see if
-    ** there is a range constraint on indexed column (nEq+1) that can be 
-    ** optimized using the index. 
+    ** there is a range constraint on indexed column (pc.plan.nEq+1) that
+    ** can be optimized using the index. 
     */
-    if( nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
-      testcase( wsFlags & WHERE_COLUMN_IN );
-      testcase( wsFlags & WHERE_COLUMN_NULL );
-      if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
-        wsFlags |= WHERE_UNIQUE;
+    if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
+      testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
+      testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
+      if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
+        pc.plan.wsFlags |= WHERE_UNIQUE;
+        if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+          pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
+        }
       }
     }else if( pProbe->bUnordered==0 ){
-      int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]);
-      if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
-        WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
-        WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
-        whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv);
+      int j;
+      j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
+      if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
+        WhereTerm *pTop, *pBtm;
+        pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
+        pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
+        whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
         if( pTop ){
           nBound = 1;
-          wsFlags |= WHERE_TOP_LIMIT;
-          used |= pTop->prereqRight;
+          pc.plan.wsFlags |= WHERE_TOP_LIMIT;
+          pc.used |= pTop->prereqRight;
           testcase( pTop->pWC!=pWC );
         }
         if( pBtm ){
           nBound++;
-          wsFlags |= WHERE_BTM_LIMIT;
-          used |= pBtm->prereqRight;
+          pc.plan.wsFlags |= WHERE_BTM_LIMIT;
+          pc.used |= pBtm->prereqRight;
           testcase( pBtm->pWC!=pWC );
         }
-        wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
+        pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
       }
     }
 
     /* If there is an ORDER BY clause and the index being considered will
     ** naturally scan rows in the required order, set the appropriate flags
-    ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
-    ** will scan rows in a different order, set the bSort variable.  */
-    if( isSortingIndex(
-          pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
-    ){
-      bSort = 0;
-      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
-      wsFlags |= (rev ? WHERE_REVERSE : 0);
+    ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
+    ** the index will scan rows in a different order, set the bSort
+    ** variable.  */
+    if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
+      int bRev = 2;
+      int bObUnique = 0;
+      WHERETRACE(("      --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
+      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
+      WHERETRACE(("      --> after  isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
+                  bRev, bObUnique, pc.plan.nOBSat));
+      if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+        pc.plan.wsFlags |= WHERE_ORDERED;
+        if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
+      }
+      if( nOrderBy==pc.plan.nOBSat ){
+        bSort = 0;
+        pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
+      }
+      if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
     }
 
     /* If there is a DISTINCT qualifier and this index will scan rows in
     ** order of the DISTINCT expressions, clear bDist and set the appropriate
-    ** flags in wsFlags. */
-    if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq)
-     && (wsFlags & WHERE_COLUMN_IN)==0
+    ** flags in pc.plan.wsFlags. */
+    if( bDist
+     && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
+     && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
     ){
       bDist = 0;
-      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
+      pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
     }
 
     /* If currently calculating the cost of using an index (not the IPK
     ** index), determine if all required column data may be obtained without 
     ** using the main table (i.e. if the index is a covering
     ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
-    ** wsFlags. Otherwise, set the bLookup variable to true.  */
-    if( pIdx && wsFlags ){
+    ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true.  */
+    if( pIdx ){
       Bitmask m = pSrc->colUsed;
       int j;
       for(j=0; j<pIdx->nColumn; j++){
@@ -104842,7 +107870,7 @@ static void bestBtreeIndex(
         }
       }
       if( m==0 ){
-        wsFlags |= WHERE_IDX_ONLY;
+        pc.plan.wsFlags |= WHERE_IDX_ONLY;
       }else{
         bLookup = 1;
       }
@@ -104852,10 +107880,10 @@ static void bestBtreeIndex(
     ** Estimate the number of rows of output.  For an "x IN (SELECT...)"
     ** constraint, do not let the estimate exceed half the rows in the table.
     */
-    nRow = (double)(aiRowEst[nEq] * nInMul);
-    if( bInEst && nRow*2>aiRowEst[0] ){
-      nRow = aiRowEst[0]/2;
-      nInMul = (int)(nRow / aiRowEst[nEq]);
+    pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
+    if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
+      pc.plan.nRow = aiRowEst[0]/2;
+      nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
     }
 
 #ifdef SQLITE_ENABLE_STAT3
@@ -104865,15 +107893,19 @@ static void bestBtreeIndex(
     ** to get a better estimate on the number of rows based on
     ** VALUE and how common that value is according to the histogram.
     */
-    if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
+    if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
+     && pFirstTerm!=0 && aiRowEst[1]>1 ){
       assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
       if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
-        testcase( pFirstTerm->eOperator==WO_EQ );
-        testcase( pFirstTerm->eOperator==WO_ISNULL );
-        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
+        testcase( pFirstTerm->eOperator & WO_EQ );
+        testcase( pFirstTerm->eOperator & WO_EQUIV );
+        testcase( pFirstTerm->eOperator & WO_ISNULL );
+        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
+                          &pc.plan.nRow);
       }else if( bInEst==0 ){
-        assert( pFirstTerm->eOperator==WO_IN );
-        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
+        assert( pFirstTerm->eOperator & WO_IN );
+        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
+                       &pc.plan.nRow);
       }
     }
 #endif /* SQLITE_ENABLE_STAT3 */
@@ -104881,8 +107913,8 @@ static void bestBtreeIndex(
     /* Adjust the number of output rows and downward to reflect rows
     ** that are excluded by range constraints.
     */
-    nRow = nRow/rangeDiv;
-    if( nRow<1 ) nRow = 1;
+    pc.plan.nRow = pc.plan.nRow/rangeDiv;
+    if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
 
     /* Experiments run on real SQLite databases show that the time needed
     ** to do a binary search to locate a row in a table or index is roughly
@@ -104897,7 +107929,19 @@ static void bestBtreeIndex(
     ** So this computation assumes table records are about twice as big
     ** as index records
     */
-    if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+    if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
+                                                              ==WHERE_IDX_ONLY
+     && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+     && sqlite3GlobalConfig.bUseCis
+     && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
+    ){
+      /* This index is not useful for indexing, but it is a covering index.
+      ** A full-scan of the index might be a little faster than a full-scan
+      ** of the table, so give this case a cost slightly less than a table
+      ** scan. */
+      pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
+      pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
+    }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
       /* The cost of a full table scan is a number of move operations equal
       ** to the number of rows in the table.
       **
@@ -104907,10 +107951,15 @@ static void bestBtreeIndex(
       ** decision and one which we expect to revisit in the future.  But
       ** it seems to be working well enough at the moment.
       */
-      cost = aiRowEst[0]*4;
+      pc.rCost = aiRowEst[0]*4;
+      pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
+      if( pIdx ){
+        pc.plan.wsFlags &= ~WHERE_ORDERED;
+        pc.plan.nOBSat = nPriorSat;
+      }
     }else{
       log10N = estLog(aiRowEst[0]);
-      cost = nRow;
+      pc.rCost = pc.plan.nRow;
       if( pIdx ){
         if( bLookup ){
           /* For an index lookup followed by a table lookup:
@@ -104918,20 +107967,20 @@ static void bestBtreeIndex(
           **  + nRow steps through the index
           **  + nRow table searches to lookup the table entry using the rowid
           */
-          cost += (nInMul + nRow)*log10N;
+          pc.rCost += (nInMul + pc.plan.nRow)*log10N;
         }else{
           /* For a covering index:
           **     nInMul index searches to find the initial entry 
           **   + nRow steps through the index
           */
-          cost += nInMul*log10N;
+          pc.rCost += nInMul*log10N;
         }
       }else{
         /* For a rowid primary key lookup:
         **    nInMult table searches to find the initial entry for each range
         **  + nRow steps through the table
         */
-        cost += nInMul*log10N;
+        pc.rCost += nInMul*log10N;
       }
     }
 
@@ -104942,10 +107991,12 @@ static void bestBtreeIndex(
     ** difference and select C of 3.0.
     */
     if( bSort ){
-      cost += nRow*estLog(nRow)*3;
+      double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
+      m *= (double)(pc.plan.nOBSat ? 2 : 3);
+      pc.rCost += pc.plan.nRow*m;
     }
     if( bDist ){
-      cost += nRow*estLog(nRow)*3;
+      pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
     }
 
     /**** Cost of using this index has now been computed ****/
@@ -104966,25 +108017,25 @@ static void bestBtreeIndex(
     ** might be selected even when there exists an optimal index that has
     ** no such dependency.
     */
-    if( nRow>2 && cost<=pCost->rCost ){
+    if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
       int k;                       /* Loop counter */
-      int nSkipEq = nEq;           /* Number of == constraints to skip */
+      int nSkipEq = pc.plan.nEq;   /* Number of == constraints to skip */
       int nSkipRange = nBound;     /* Number of < constraints to skip */
       Bitmask thisTab;             /* Bitmap for pSrc */
 
       thisTab = getMask(pWC->pMaskSet, iCur);
-      for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
+      for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
         if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
-        if( (pTerm->prereqAll & notValid)!=thisTab ) continue;
+        if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
         if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
           if( nSkipEq ){
-            /* Ignore the first nEq equality matches since the index
+            /* Ignore the first pc.plan.nEq equality matches since the index
             ** has already accounted for these */
             nSkipEq--;
           }else{
             /* Assume each additional equality match reduces the result
             ** set size by a factor of 10 */
-            nRow /= 10;
+            pc.plan.nRow /= 10;
           }
         }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
           if( nSkipRange ){
@@ -104998,37 +108049,33 @@ static void bestBtreeIndex(
             ** more selective intentionally because of the subjective 
             ** observation that indexed range constraints really are more
             ** selective in practice, on average. */
-            nRow /= 3;
+            pc.plan.nRow /= 3;
           }
-        }else if( pTerm->eOperator!=WO_NOOP ){
+        }else if( (pTerm->eOperator & WO_NOOP)==0 ){
           /* Any other expression lowers the output row count by half */
-          nRow /= 2;
+          pc.plan.nRow /= 2;
         }
       }
-      if( nRow<2 ) nRow = 2;
+      if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
     }
 
 
     WHERETRACE((
-      "%s(%s): nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
-      "         notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f used=0x%llx\n",
-      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), 
-      nEq, nInMul, (int)rangeDiv, bSort, bLookup, wsFlags,
-      notReady, log10N, nRow, cost, used
+      "      nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
+      "      notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
+      "      used=0x%llx nOBSat=%d\n",
+      pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
+      p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
+      pc.plan.nOBSat
     ));
 
     /* If this index is the best we have seen so far, then record this
-    ** index and its cost in the pCost structure.
+    ** index and its cost in the p->cost structure.
     */
-    if( (!pIdx || wsFlags)
-     && (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->plan.nRow))
-    ){
-      pCost->rCost = cost;
-      pCost->used = used;
-      pCost->plan.nRow = nRow;
-      pCost->plan.wsFlags = (wsFlags&wsFlagMask);
-      pCost->plan.nEq = nEq;
-      pCost->plan.u.pIdx = pIdx;
+    if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
+      p->cost = pc;
+      p->cost.plan.wsFlags &= wsFlagMask;
+      p->cost.plan.u.pIdx = pIdx;
     }
 
     /* If there was an INDEXED BY clause, then only that one index is
@@ -105043,27 +108090,26 @@ static void bestBtreeIndex(
   /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
   ** is set, then reverse the order that the index will be scanned
   ** in. This is used for application testing, to help find cases
-  ** where application behaviour depends on the (undefined) order that
+  ** where application behavior depends on the (undefined) order that
   ** SQLite outputs rows in in the absence of an ORDER BY clause.  */
-  if( !pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
-    pCost->plan.wsFlags |= WHERE_REVERSE;
+  if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
+    p->cost.plan.wsFlags |= WHERE_REVERSE;
   }
 
-  assert( pOrderBy || (pCost->plan.wsFlags&WHERE_ORDERBY)==0 );
-  assert( pCost->plan.u.pIdx==0 || (pCost->plan.wsFlags&WHERE_ROWID_EQ)==0 );
+  assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
+  assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
   assert( pSrc->pIndex==0 
-       || pCost->plan.u.pIdx==0 
-       || pCost->plan.u.pIdx==pSrc->pIndex 
+       || p->cost.plan.u.pIdx==0 
+       || p->cost.plan.u.pIdx==pSrc->pIndex 
   );
 
-  WHERETRACE(("best index is: %s\n", 
-    ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" : 
-         pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
-  ));
+  WHERETRACE(("   best index is %s cost=%.1f\n",
+         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
+         p->cost.rCost));
   
-  bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
-  bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
-  pCost->plan.wsFlags |= eqTermMask;
+  bestOrClauseIndex(p);
+  bestAutomaticIndex(p);
+  p->cost.plan.wsFlags |= eqTermMask;
 }
 
 /*
@@ -105071,28 +108117,28 @@ static void bestBtreeIndex(
 ** best query plan and its cost into the WhereCost object supplied 
 ** as the last parameter. This function may calculate the cost of
 ** both real and virtual table scans.
+**
+** This function does not take ORDER BY or DISTINCT into account.  Nor
+** does it remember the virtual table query plan.  All it does is compute
+** the cost while determining if an OR optimization is applicable.  The
+** details will be reconsidered later if the optimization is found to be
+** applicable.
 */
-static void bestIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors not available for indexing */
-  Bitmask notValid,           /* Cursors not available for any purpose */
-  ExprList *pOrderBy,         /* The ORDER BY clause */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
+static void bestIndex(WhereBestIdx *p){
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( IsVirtual(pSrc->pTab) ){
-    sqlite3_index_info *p = 0;
-    bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p);
-    if( p->needToFreeIdxStr ){
-      sqlite3_free(p->idxStr);
-    }
-    sqlite3DbFree(pParse->db, p);
+  if( IsVirtual(p->pSrc->pTab) ){
+    sqlite3_index_info *pIdxInfo = 0;
+    p->ppIdxInfo = &pIdxInfo;
+    bestVirtualIndex(p);
+    assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
+    if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
+      sqlite3_free(pIdxInfo->idxStr);
+    }
+    sqlite3DbFree(p->pParse->db, pIdxInfo);
   }else
 #endif
   {
-    bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
+    bestBtreeIndex(p);
   }
 }
 
@@ -105191,7 +108237,8 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
 static int codeEqualityTerm(
   Parse *pParse,      /* The parsing context */
   WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
-  WhereLevel *pLevel, /* When level of the FROM clause we are working on */
+  WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+  int iEq,            /* Index of the equality term within this level */
   int iTarget         /* Attempt to leave results in this register */
 ){
   Expr *pX = pTerm->pExpr;
@@ -105209,12 +108256,26 @@ static int codeEqualityTerm(
     int eType;
     int iTab;
     struct InLoop *pIn;
+    u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
 
+    if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 
+      && pLevel->plan.u.pIdx->aSortOrder[iEq]
+    ){
+      testcase( iEq==0 );
+      testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
+      testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
+      testcase( bRev );
+      bRev = !bRev;
+    }
     assert( pX->op==TK_IN );
     iReg = iTarget;
     eType = sqlite3FindInIndex(pParse, pX, 0);
+    if( eType==IN_INDEX_INDEX_DESC ){
+      testcase( bRev );
+      bRev = !bRev;
+    }
     iTab = pX->iTable;
-    sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
+    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
     assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
     if( pLevel->u.in.nIn==0 ){
       pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
@@ -105232,6 +108293,7 @@ static int codeEqualityTerm(
       }else{
         pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
       }
+      pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
       sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
     }else{
       pLevel->u.in.nIn = 0;
@@ -105326,7 +108388,7 @@ static int codeAllEqualityTerms(
     ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
     testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
     testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
+    r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
     if( r1!=regBase+j ){
       if( nReg==1 ){
         sqlite3ReleaseTempReg(pParse, regBase);
@@ -105536,6 +108598,7 @@ static Bitmask codeOneLoopStart(
   int addrCont;                   /* Jump here to continue with next cycle */
   int iRowidReg = 0;        /* Rowid is stored in this register, if not zero */
   int iReleaseReg = 0;      /* Temp register to free before returning */
+  Bitmask newNotReady;      /* Return value */
 
   pParse = pWInfo->pParse;
   v = pParse->pVdbe;
@@ -105546,6 +108609,7 @@ static Bitmask codeOneLoopStart(
   bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
   omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 
            && (wctrlFlags & WHERE_FORCE_TABLE)==0;
+  VdbeNoopComment((v, "Begin Join Loop %d", iLevel));
 
   /* Create labels for the "break" and "continue" instructions
   ** for the current loop.  Jump to addrBrk to break out of a loop.
@@ -105570,12 +108634,23 @@ static Bitmask codeOneLoopStart(
     VdbeComment((v, "init LEFT JOIN no-match flag"));
   }
 
+  /* Special case of a FROM clause subquery implemented as a co-routine */
+  if( pTabItem->viaCoroutine ){
+    int regYield = pTabItem->regReturn;
+    sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
+    pLevel->p2 =  sqlite3VdbeAddOp1(v, OP_Yield, regYield);
+    VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
+    sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
+    pLevel->op = OP_Goto;
+  }else
+
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   if(  (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
     /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
     **          to access the data.
     */
     int iReg;   /* P3 Value for OP_VFilter */
+    int addrNotFound;
     sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
     int nConstraint = pVtabIdx->nConstraint;
     struct sqlite3_index_constraint_usage *aUsage =
@@ -105585,11 +108660,18 @@ static Bitmask codeOneLoopStart(
 
     sqlite3ExprCachePush(pParse);
     iReg = sqlite3GetTempRange(pParse, nConstraint+2);
+    addrNotFound = pLevel->addrBrk;
     for(j=1; j<=nConstraint; j++){
       for(k=0; k<nConstraint; k++){
         if( aUsage[k].argvIndex==j ){
-          int iTerm = aConstraint[k].iTermOffset;
-          sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
+          int iTarget = iReg+j+1;
+          pTerm = &pWC->a[aConstraint[k].iTermOffset];
+          if( pTerm->eOperator & WO_IN ){
+            codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
+            addrNotFound = pLevel->addrNxt;
+          }else{
+            sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
+          }
           break;
         }
       }
@@ -105597,7 +108679,7 @@ static Bitmask codeOneLoopStart(
     }
     sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
     sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
-    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
+    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
                       pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
     pVtabIdx->needToFreeIdxStr = 0;
     for(j=0; j<nConstraint; j++){
@@ -105624,13 +108706,13 @@ static Bitmask codeOneLoopStart(
     pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
     assert( pTerm!=0 );
     assert( pTerm->pExpr!=0 );
-    assert( pTerm->leftCursor==iCur );
     assert( omitTable==0 );
     testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
+    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
     addrNxt = pLevel->addrNxt;
     sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
     sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
+    sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
     sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
     VdbeComment((v, "pk"));
     pLevel->op = OP_Noop;
@@ -105788,7 +108870,7 @@ static Bitmask codeOneLoopStart(
     ** this requires some special handling.
     */
     if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
-     && (pLevel->plan.wsFlags&WHERE_ORDERBY)
+     && (pLevel->plan.wsFlags&WHERE_ORDERED)
      && (pIdx->nColumn>nEq)
     ){
       /* assert( pOrderBy->nExpr==1 ); */
@@ -105951,6 +109033,11 @@ static Bitmask codeOneLoopStart(
       pLevel->op = OP_Next;
     }
     pLevel->p1 = iIdxCur;
+    if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
+      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+    }else{
+      assert( pLevel->p5==0 );
+    }
   }else
 
 #ifndef SQLITE_OMIT_OR_OPTIMIZATION
@@ -106010,7 +109097,7 @@ static Bitmask codeOneLoopStart(
    
     pTerm = pLevel->plan.u.pTerm;
     assert( pTerm!=0 );
-    assert( pTerm->eOperator==WO_OR );
+    assert( pTerm->eOperator & WO_OR );
     assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
     pOrWc = &pTerm->u.pOrInfo->wc;
     pLevel->op = OP_Return;
@@ -106065,6 +109152,10 @@ static Bitmask codeOneLoopStart(
     ** the "interesting" terms of z - terms that did not originate in the
     ** ON or USING clause of a LEFT JOIN, and terms that are usable as 
     ** indices.
+    **
+    ** This optimization also only applies if the (x1 OR x2 OR ...) term
+    ** is not contained in the ON clause of a LEFT JOIN.
+    ** See ticket http://www.sqlite.org/src/info/f2369304e4
     */
     if( pWC->nTerm>1 ){
       int iTerm;
@@ -106083,10 +109174,10 @@ static Bitmask codeOneLoopStart(
 
     for(ii=0; ii<pOrWc->nTerm; ii++){
       WhereTerm *pOrTerm = &pOrWc->a[ii];
-      if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
+      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
         WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
         Expr *pOrExpr = pOrTerm->pExpr;
-        if( pAndExpr ){
+        if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
           pAndExpr->pLeft = pOrExpr;
           pOrExpr = pAndExpr;
         }
@@ -106173,7 +109264,7 @@ static Bitmask codeOneLoopStart(
     pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
     pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
   }
-  notReady &= ~getMask(pWC->pMaskSet, iCur);
+  newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur);
 
   /* Insert code to test every subexpression that can be completely
   ** computed using the current set of tables.
@@ -106187,7 +109278,7 @@ static Bitmask codeOneLoopStart(
     testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
     testcase( pTerm->wtFlags & TERM_CODED );
     if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
-    if( (pTerm->prereqAll & notReady)!=0 ){
+    if( (pTerm->prereqAll & newNotReady)!=0 ){
       testcase( pWInfo->untestedTerms==0
                && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
       pWInfo->untestedTerms = 1;
@@ -106202,6 +109293,33 @@ static Bitmask codeOneLoopStart(
     pTerm->wtFlags |= TERM_CODED;
   }
 
+  /* Insert code to test for implied constraints based on transitivity
+  ** of the "==" operator.
+  **
+  ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
+  ** and we are coding the t1 loop and the t2 loop has not yet coded,
+  ** then we cannot use the "t1.a=t2.b" constraint, but we can code
+  ** the implied "t1.a=123" constraint.
+  */
+  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
+    Expr *pE;
+    WhereTerm *pAlt;
+    Expr sEq;
+    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+    if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
+    if( pTerm->leftCursor!=iCur ) continue;
+    pE = pTerm->pExpr;
+    assert( !ExprHasProperty(pE, EP_FromJoin) );
+    assert( (pTerm->prereqRight & newNotReady)!=0 );
+    pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
+    if( pAlt==0 ) continue;
+    if( pAlt->wtFlags & (TERM_CODED) ) continue;
+    VdbeNoopComment((v, "begin transitive constraint"));
+    sEq = *pAlt->pExpr;
+    sEq.pLeft = pE->pLeft;
+    sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL);
+  }
+
   /* For a LEFT OUTER JOIN, generate code that will record the fact that
   ** at least one row of the right table has matched the left table.  
   */
@@ -106214,7 +109332,7 @@ static Bitmask codeOneLoopStart(
       testcase( pTerm->wtFlags & TERM_VIRTUAL );  /* IMP: R-30575-11662 */
       testcase( pTerm->wtFlags & TERM_CODED );
       if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
-      if( (pTerm->prereqAll & notReady)!=0 ){
+      if( (pTerm->prereqAll & newNotReady)!=0 ){
         assert( pWInfo->untestedTerms );
         continue;
       }
@@ -106225,7 +109343,7 @@ static Bitmask codeOneLoopStart(
   }
   sqlite3ReleaseTempReg(pParse, iReleaseReg);
 
-  return notReady;
+  return newNotReady;
 }
 
 #if defined(SQLITE_TEST)
@@ -106345,42 +109463,46 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
 **
 ** ORDER BY CLAUSE PROCESSING
 **
-** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
 ** if there is one.  If there is no ORDER BY clause or if this routine
-** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
+** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
 **
 ** If an index can be used so that the natural output order of the table
 ** scan is correct for the ORDER BY clause, then that index is used and
-** *ppOrderBy is set to NULL.  This is an optimization that prevents an
-** unnecessary sort of the result set if an index appropriate for the
-** ORDER BY clause already exists.
+** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr.  This
+** is an optimization that prevents an unnecessary sort of the result set
+** if an index appropriate for the ORDER BY clause already exists.
 **
 ** If the where clause loops cannot be arranged to provide the correct
-** output order, then the *ppOrderBy is unchanged.
+** output order, then WhereInfo.nOBSat is 0.
 */
 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   Parse *pParse,        /* The parser context */
   SrcList *pTabList,    /* A list of all tables to be scanned */
   Expr *pWhere,         /* The WHERE clause */
-  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+  ExprList *pOrderBy,   /* An ORDER BY clause, or NULL */
   ExprList *pDistinct,  /* The select-list for DISTINCT queries - or NULL */
   u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
   int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
 ){
-  int i;                     /* Loop counter */
   int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
   int nTabList;              /* Number of elements in pTabList */
   WhereInfo *pWInfo;         /* Will become the return value of this function */
   Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
   Bitmask notReady;          /* Cursors that are not yet positioned */
+  WhereBestIdx sWBI;         /* Best index search context */
   WhereMaskSet *pMaskSet;    /* The expression mask set */
-  WhereClause *pWC;               /* Decomposition of the WHERE clause */
-  struct SrcList_item *pTabItem;  /* A single entry from pTabList */
-  WhereLevel *pLevel;             /* A single level in the pWInfo list */
-  int iFrom;                      /* First unused FROM clause element */
+  WhereLevel *pLevel;        /* A single level in pWInfo->a[] */
+  int iFrom;                 /* First unused FROM clause element */
   int andFlags;              /* AND-ed combination of all pWC->a[].wtFlags */
+  int ii;                    /* Loop counter */
   sqlite3 *db;               /* Database connection */
 
+
+  /* Variable initialization */
+  memset(&sWBI, 0, sizeof(sWBI));
+  sWBI.pParse = pParse;
+
   /* The number of tables in the FROM clause is limited by the number of
   ** bits in a Bitmask 
   */
@@ -106420,22 +109542,23 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   pWInfo->pParse = pParse;
   pWInfo->pTabList = pTabList;
   pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
-  pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
+  pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
   pWInfo->wctrlFlags = wctrlFlags;
   pWInfo->savedNQueryLoop = pParse->nQueryLoop;
-  pMaskSet = (WhereMaskSet*)&pWC[1];
+  pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
+  sWBI.aLevel = pWInfo->a;
 
   /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
   ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
-  if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
+  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
 
   /* Split the WHERE clause into separate subexpressions where each
   ** subexpression is separated by an AND operator.
   */
   initMaskSet(pMaskSet);
-  whereClauseInit(pWC, pParse, pMaskSet, wctrlFlags);
+  whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
   sqlite3ExprCodeConstants(pParse, pWhere);
-  whereSplit(pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
+  whereSplit(sWBI.pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
     
   /* Special case: a WHERE clause that is constant.  Evaluate the
   ** expression and either jump over all of the code or fall thru.
@@ -106456,30 +109579,19 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** bitmask for all tables to the left of the join.  Knowing the bitmask
   ** for all tables to the left of a left join is important.  Ticket #3015.
   **
-  ** Configure the WhereClause.vmask variable so that bits that correspond
-  ** to virtual table cursors are set. This is used to selectively disable 
-  ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful 
-  ** with virtual tables.
-  **
   ** Note that bitmasks are created for all pTabList->nSrc tables in
   ** pTabList, not just the first nTabList tables.  nTabList is normally
   ** equal to pTabList->nSrc but might be shortened to 1 if the
   ** WHERE_ONETABLE_ONLY flag is set.
   */
-  assert( pWC->vmask==0 && pMaskSet->n==0 );
-  for(i=0; i<pTabList->nSrc; i++){
-    createMask(pMaskSet, pTabList->a[i].iCursor);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-    if( ALWAYS(pTabList->a[i].pTab) && IsVirtual(pTabList->a[i].pTab) ){
-      pWC->vmask |= ((Bitmask)1 << i);
-    }
-#endif
+  for(ii=0; ii<pTabList->nSrc; ii++){
+    createMask(pMaskSet, pTabList->a[ii].iCursor);
   }
 #ifndef NDEBUG
   {
     Bitmask toTheLeft = 0;
-    for(i=0; i<pTabList->nSrc; i++){
-      Bitmask m = getMask(pMaskSet, pTabList->a[i].iCursor);
+    for(ii=0; ii<pTabList->nSrc; ii++){
+      Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
       assert( (m-1)==toTheLeft );
       toTheLeft |= m;
     }
@@ -106491,7 +109603,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** want to analyze these virtual terms, so start analyzing at the end
   ** and work forward so that the added virtual terms are never processed.
   */
-  exprAnalyzeAll(pTabList, pWC);
+  exprAnalyzeAll(pTabList, sWBI.pWC);
   if( db->mallocFailed ){
     goto whereBeginError;
   }
@@ -106500,7 +109612,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
   ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
   */
-  if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
+  if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
     pDistinct = 0;
     pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
   }
@@ -106520,22 +109632,26 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** This loop also figures out the nesting order of tables in the FROM
   ** clause.
   */
-  notReady = ~(Bitmask)0;
+  sWBI.notValid = ~(Bitmask)0;
+  sWBI.pOrderBy = pOrderBy;
+  sWBI.n = nTabList;
+  sWBI.pDistinct = pDistinct;
   andFlags = ~0;
   WHERETRACE(("*** Optimizer Start ***\n"));
-  for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
+  for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
     WhereCost bestPlan;         /* Most efficient plan seen so far */
     Index *pIdx;                /* Index for FROM table at pTabItem */
     int j;                      /* For looping over FROM tables */
     int bestJ = -1;             /* The value of j */
     Bitmask m;                  /* Bitmask value for j or bestJ */
     int isOptimal;              /* Iterator for optimal/non-optimal search */
+    int ckOptimal;              /* Do the optimal scan check */
     int nUnconstrained;         /* Number tables without INDEXED BY */
     Bitmask notIndexed;         /* Mask of tables that cannot use an index */
 
     memset(&bestPlan, 0, sizeof(bestPlan));
     bestPlan.rCost = SQLITE_BIG_DBL;
-    WHERETRACE(("*** Begin search for loop %d ***\n", i));
+    WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
 
     /* Loop through the remaining entries in the FROM clause to find the
     ** next nested loop. The loop tests all FROM clause entries
@@ -106551,8 +109667,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     ** by waiting for other tables to run first.  This "optimal" test works
     ** by first assuming that the FROM clause is on the inner loop and finding
     ** its query plan, then checking to see if that query plan uses any
-    ** other FROM clause terms that are notReady.  If no notReady terms are
-    ** used then the "optimal" query plan works.
+    ** other FROM clause terms that are sWBI.notValid.  If no notValid terms
+    ** are used then the "optimal" query plan works.
     **
     ** Note that the WhereCost.nRow parameter for an optimal scan might
     ** not be as small as it would be if the table really were the innermost
@@ -106564,10 +109680,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     ** strategies were found by the first iteration. This second iteration
     ** is used to search for the lowest cost scan overall.
     **
-    ** Previous versions of SQLite performed only the second iteration -
-    ** the next outermost loop was always that with the lowest overall
-    ** cost. However, this meant that SQLite could select the wrong plan
-    ** for scripts such as the following:
+    ** Without the optimal scan step (the first iteration) a suboptimal
+    ** plan might be chosen for queries like this:
     **   
     **   CREATE TABLE t1(a, b); 
     **   CREATE TABLE t2(c, d);
@@ -106582,59 +109696,89 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     */
     nUnconstrained = 0;
     notIndexed = 0;
-    for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
-      Bitmask mask;             /* Mask of tables not yet ready */
-      for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
-        int doNotReorder;    /* True if this table should not be reordered */
-        WhereCost sCost;     /* Cost information from best[Virtual]Index() */
-        ExprList *pOrderBy;  /* ORDER BY clause for index to optimize */
-        ExprList *pDist;     /* DISTINCT clause for index to optimize */
-  
-        doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
-        if( j!=iFrom && doNotReorder ) break;
-        m = getMask(pMaskSet, pTabItem->iCursor);
-        if( (m & notReady)==0 ){
+
+    /* The optimal scan check only occurs if there are two or more tables
+    ** available to be reordered */
+    if( iFrom==nTabList-1 ){
+      ckOptimal = 0;  /* Common case of just one table in the FROM clause */
+    }else{
+      ckOptimal = -1;
+      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
+        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+        if( (m & sWBI.notValid)==0 ){
           if( j==iFrom ) iFrom++;
           continue;
         }
-        mask = (isOptimal ? m : notReady);
-        pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
-        pDist = (i==0 ? pDistinct : 0);
-        if( pTabItem->pIndex==0 ) nUnconstrained++;
+        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
+        if( ++ckOptimal ) break;
+        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
+      }
+    }
+    assert( ckOptimal==0 || ckOptimal==1 );
+
+    for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
+      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
+        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
+          /* This break and one like it in the ckOptimal computation loop
+          ** above prevent table reordering across LEFT and CROSS JOINs.
+          ** The LEFT JOIN case is necessary for correctness.  The prohibition
+          ** against reordering across a CROSS JOIN is an SQLite feature that
+          ** allows the developer to control table reordering */
+          break;
+        }
+        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+        if( (m & sWBI.notValid)==0 ){
+          assert( j>iFrom );
+          continue;
+        }
+        sWBI.notReady = (isOptimal ? m : sWBI.notValid);
+        if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
   
-        WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
-                    j, isOptimal));
-        assert( pTabItem->pTab );
+        WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
+                    j, sWBI.pSrc->pTab->zName, isOptimal));
+        assert( sWBI.pSrc->pTab );
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-        if( IsVirtual(pTabItem->pTab) ){
-          sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
-          bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
-                           &sCost, pp);
+        if( IsVirtual(sWBI.pSrc->pTab) ){
+          sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
+          bestVirtualIndex(&sWBI);
         }else 
 #endif
         {
-          bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
-              pDist, &sCost);
+          bestBtreeIndex(&sWBI);
         }
-        assert( isOptimal || (sCost.used&notReady)==0 );
+        assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
 
         /* If an INDEXED BY clause is present, then the plan must use that
         ** index if it uses any index at all */
-        assert( pTabItem->pIndex==0 
-                  || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
-                  || sCost.plan.u.pIdx==pTabItem->pIndex );
+        assert( sWBI.pSrc->pIndex==0 
+                  || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
+                  || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
 
-        if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+        if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
           notIndexed |= m;
         }
+        if( isOptimal ){
+          pWInfo->a[j].rOptCost = sWBI.cost.rCost;
+        }else if( ckOptimal ){
+          /* If two or more tables have nearly the same outer loop cost, but
+          ** very different inner loop (optimal) cost, we want to choose
+          ** for the outer loop that table which benefits the least from
+          ** being in the inner loop.  The following code scales the 
+          ** outer loop cost estimate to accomplish that. */
+          WHERETRACE(("   scaling cost from %.1f to %.1f\n",
+                      sWBI.cost.rCost,
+                      sWBI.cost.rCost/pWInfo->a[j].rOptCost));
+          sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
+        }
 
         /* Conditions under which this table becomes the best so far:
         **
         **   (1) The table must not depend on other tables that have not
-        **       yet run.
+        **       yet run.  (In other words, it must not depend on tables
+        **       in inner loops.)
         **
-        **   (2) A full-table-scan plan cannot supercede indexed plan unless
-        **       the full-table-scan is an "optimal" plan as defined above.
+        **   (2) (This rule was removed on 2012-11-09.  The scaling of the
+        **       cost using the optimal scan cost made this rule obsolete.)
         **
         **   (3) All tables have an INDEXED BY clause or this table lacks an
         **       INDEXED BY clause or this table uses the specific
@@ -106645,43 +109789,47 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
         **       The NEVER() comes about because rule (2) above prevents
         **       An indexable full-table-scan from reaching rule (3).
         **
-        **   (4) The plan cost must be lower than prior plans or else the
-        **       cost must be the same and the number of rows must be lower.
+        **   (4) The plan cost must be lower than prior plans, where "cost"
+        **       is defined by the compareCost() function above. 
         */
-        if( (sCost.used&notReady)==0                       /* (1) */
-            && (bestJ<0 || (notIndexed&m)!=0               /* (2) */
-                || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
-                || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
-            && (nUnconstrained==0 || pTabItem->pIndex==0   /* (3) */
-                || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
-            && (bestJ<0 || sCost.rCost<bestPlan.rCost      /* (4) */
-                || (sCost.rCost<=bestPlan.rCost 
-                 && sCost.plan.nRow<bestPlan.plan.nRow))
+        if( (sWBI.cost.used&sWBI.notValid)==0                    /* (1) */
+            && (nUnconstrained==0 || sWBI.pSrc->pIndex==0        /* (3) */
+                || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
+            && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan))   /* (4) */
         ){
-          WHERETRACE(("=== table %d is best so far"
-                      " with cost=%g and nRow=%g\n",
-                      j, sCost.rCost, sCost.plan.nRow));
-          bestPlan = sCost;
+          WHERETRACE(("   === table %d (%s) is best so far\n"
+                      "       cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
+                      j, sWBI.pSrc->pTab->zName,
+                      sWBI.cost.rCost, sWBI.cost.plan.nRow,
+                      sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
+          bestPlan = sWBI.cost;
           bestJ = j;
         }
-        if( doNotReorder ) break;
+
+        /* In a join like "w JOIN x LEFT JOIN y JOIN z"  make sure that
+        ** table y (and not table z) is always the next inner loop inside
+        ** of table x. */
+        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
       }
     }
     assert( bestJ>=0 );
-    assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
-    WHERETRACE(("*** Optimizer selects table %d for loop %d"
-                " with cost=%g and nRow=%g\n",
-                bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
-    /* The ALWAYS() that follows was added to hush up clang scan-build */
-    if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 && ALWAYS(ppOrderBy) ){
-      *ppOrderBy = 0;
-    }
+    assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
+    assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
+    testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
+    testcase( bestJ>iFrom && bestJ<nTabList-1
+                          && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
+    WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
+                "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
+                bestJ, pTabList->a[bestJ].pTab->zName,
+                pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
+                bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
     if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
       assert( pWInfo->eDistinct==0 );
       pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
     }
     andFlags &= bestPlan.plan.wsFlags;
     pLevel->plan = bestPlan.plan;
+    pLevel->iTabCur = pTabList->a[bestJ].iCursor;
     testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
     testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
     if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
@@ -106695,7 +109843,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     }else{
       pLevel->iIdxCur = -1;
     }
-    notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
+    sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
     pLevel->iFrom = (u8)bestJ;
     if( bestPlan.plan.nRow>=(double)1 ){
       pParse->nQueryLoop *= bestPlan.plan.nRow;
@@ -106723,12 +109871,19 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   if( pParse->nErr || db->mallocFailed ){
     goto whereBeginError;
   }
+  if( nTabList ){
+    pLevel--;
+    pWInfo->nOBSat = pLevel->plan.nOBSat;
+  }else{
+    pWInfo->nOBSat = 0;
+  }
 
   /* If the total query only selects a single row, then the ORDER BY
   ** clause is irrelevant.
   */
-  if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){
-    *ppOrderBy = 0;
+  if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
+    assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
+    pWInfo->nOBSat = pOrderBy->nExpr;
   }
 
   /* If the caller is an UPDATE or DELETE statement that is requesting
@@ -106748,13 +109903,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
   notReady = ~(Bitmask)0;
   pWInfo->nRowOut = (double)1;
-  for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
+  for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
     Table *pTab;     /* Table to open */
     int iDb;         /* Index of database containing table/index */
+    struct SrcList_item *pTabItem;
 
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
-    pLevel->iTabCur = pTabItem->iCursor;
     pWInfo->nRowOut *= pLevel->plan.nRow;
     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
     if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
@@ -106765,6 +109920,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
       int iCur = pTabItem->iCursor;
       sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
+    }else if( IsVirtual(pTab) ){
+      /* noop */
     }else
 #endif
     if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
@@ -106786,7 +109943,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     }
 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
     if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
-      constructAutomaticIndex(pParse, pWC, pTabItem, notReady, pLevel);
+      constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
     }else
 #endif
     if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
@@ -106800,7 +109957,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       VdbeComment((v, "%s", pIx->zName));
     }
     sqlite3CodeVerifySchema(pParse, iDb);
-    notReady &= ~getMask(pWC->pMaskSet, pTabItem->iCursor);
+    notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
   }
   pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
   if( db->mallocFailed ) goto whereBeginError;
@@ -106810,10 +109967,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** program.
   */
   notReady = ~(Bitmask)0;
-  for(i=0; i<nTabList; i++){
-    pLevel = &pWInfo->a[i];
-    explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
-    notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
+  for(ii=0; ii<nTabList; ii++){
+    pLevel = &pWInfo->a[ii];
+    explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
+    notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
     pWInfo->iContinue = pLevel->addrCont;
   }
 
@@ -106824,16 +109981,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** the index is listed as "{}".  If the primary key is used the
   ** index name is '*'.
   */
-  for(i=0; i<nTabList; i++){
+  for(ii=0; ii<nTabList; ii++){
     char *z;
     int n;
-    pLevel = &pWInfo->a[i];
+    int w;
+    struct SrcList_item *pTabItem;
+
+    pLevel = &pWInfo->a[ii];
+    w = pLevel->plan.wsFlags;
     pTabItem = &pTabList->a[pLevel->iFrom];
     z = pTabItem->zAlias;
     if( z==0 ) z = pTabItem->pTab->zName;
     n = sqlite3Strlen30(z);
     if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
-      if( pLevel->plan.wsFlags & WHERE_IDX_ONLY ){
+      if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
         memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
         nQPlan += 2;
       }else{
@@ -106842,12 +110003,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       }
       sqlite3_query_plan[nQPlan++] = ' ';
     }
-    testcase( pLevel->plan.wsFlags & WHERE_ROWID_EQ );
-    testcase( pLevel->plan.wsFlags & WHERE_ROWID_RANGE );
-    if( pLevel->plan.wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+    testcase( w & WHERE_ROWID_EQ );
+    testcase( w & WHERE_ROWID_RANGE );
+    if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
       memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
       nQPlan += 2;
-    }else if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
+    }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
       n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
       if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
         memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
@@ -106908,7 +110069,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
       sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
       for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
         sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
-        sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop);
+        sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
         sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
       }
       sqlite3DbFree(db, pLevel->u.in.aInLoop);
@@ -107216,6 +110377,7 @@ typedef union {
   IdList* yy180;
   struct {int value; int mask;} yy207;
   u8 yy258;
+  u16 yy305;
   struct LikeOp yy318;
   TriggerStep* yy327;
   ExprSpan yy342;
@@ -109166,8 +112328,6 @@ static void yy_reduce(
       case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
       case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
       case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
-      case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
-      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
       case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
       case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
 {yygotominor.yy392 = 0;}
@@ -109177,7 +112337,6 @@ static void yy_reduce(
       case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
       case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
       case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
-      case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
       case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
       case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
 {yygotominor.yy392 = 1;}
@@ -109417,9 +112576,16 @@ static void yy_reduce(
         break;
       case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt 
orderby_opt limit_opt */
 {
-  yygotominor.yy159 = 
sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
+  yygotominor.yy159 = 
sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
 }
         break;
+      case 119: /* distinct ::= DISTINCT */
+{yygotominor.yy305 = SF_Distinct;}
+        break;
+      case 120: /* distinct ::= ALL */
+      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
+{yygotominor.yy305 = 0;}
+        break;
       case 122: /* sclp ::= selcollist COMMA */
       case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
 {yygotominor.yy442 = yymsp[-1].minor.yy442;}
@@ -109488,10 +112654,22 @@ static void yy_reduce(
 {
     if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && 
yymsp[0].minor.yy180==0 ){
       yygotominor.yy347 = yymsp[-4].minor.yy347;
+    }else if( yymsp[-4].minor.yy347->nSrc==1 ){
+      yygotominor.yy347 = 
sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+      if( yygotominor.yy347 ){
+        struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
+        struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
+        pNew->zName = pOld->zName;
+        pNew->zDatabase = pOld->zDatabase;
+        pNew->pSelect = pOld->pSelect;
+        pOld->zName = pOld->zDatabase = 0;
+        pOld->pSelect = 0;
+      }
+      sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
     }else{
       Select *pSubquery;
       sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
-      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
+      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
       yygotominor.yy347 = 
sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
     }
   }
@@ -109706,7 +112884,7 @@ static void yy_reduce(
         break;
       case 194: /* expr ::= expr COLLATE ids */
 {
-  yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, 
&yymsp[0].minor.yy0);
+  yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, 
&yymsp[0].minor.yy0);
   yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
   yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
@@ -109724,7 +112902,7 @@ static void yy_reduce(
   }
   yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
   spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
-  if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
+  if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
     yygotominor.yy342.pExpr->flags |= EP_Distinct;
   }
 }
@@ -109965,11 +113143,7 @@ static void yy_reduce(
         break;
       case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
 {
-  Expr *p = 0;
-  if( yymsp[-1].minor.yy0.n>0 ){
-    p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
-    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
-  }
+  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
   yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
   sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
   sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
@@ -109978,11 +113152,7 @@ static void yy_reduce(
         break;
       case 248: /* idxlist ::= nm collate sortorder */
 {
-  Expr *p = 0;
-  if( yymsp[-1].minor.yy0.n>0 ){
-    p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
-    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
-  }
+  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
   yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
   sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
   sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
@@ -110231,6 +113401,7 @@ static void yy_reduce(
       /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
         break;
   };
+  assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
   yygoto = yyRuleInfo[yyruleno].lhs;
   yysize = yyRuleInfo[yyruleno].nrhs;
   yypParser->yyidx -= yysize;
@@ -111796,6 +114967,13 @@ SQLITE_API int sqlite3_initialize(void){
   */
   if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
 
+#ifdef SQLITE_ENABLE_SQLLOG
+  {
+    extern void sqlite3_init_sqllog(void);
+    sqlite3_init_sqllog();
+  }
+#endif
+
   /* Make sure the mutex subsystem is initialized.  If unable to 
   ** initialize the mutex subsystem, return early with the error.
   ** If the system is so sick that we are unable to allocate a mutex,
@@ -112139,6 +115317,33 @@ SQLITE_API int sqlite3_config(int op, ...){
       break;
     }
 
+    case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
+      sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
+      break;
+    }
+
+#ifdef SQLITE_ENABLE_SQLLOG
+    case SQLITE_CONFIG_SQLLOG: {
+      typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
+      sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
+      sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
+      break;
+    }
+#endif
+
+    case SQLITE_CONFIG_MMAP_SIZE: {
+      sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64);
+      sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64);
+      if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
+        mxMmap = SQLITE_MAX_MMAP_SIZE;
+      }
+      sqlite3GlobalConfig.mxMmap = mxMmap;
+      if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
+      if( szMmap>mxMmap) szMmap = mxMmap;
+      sqlite3GlobalConfig.szMmap = szMmap;
+      break;
+    }
+
     default: {
       rc = SQLITE_ERROR;
       break;
@@ -112478,6 +115683,13 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
     return SQLITE_BUSY;
   }
 
+#ifdef SQLITE_ENABLE_SQLLOG
+  if( sqlite3GlobalConfig.xSqllog ){
+    /* Closing the handle. Fourth parameter is passed the value 2. */
+    sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
+  }
+#endif
+
   /* Convert the connection into a zombie and then close it.
   */
   db->magic = SQLITE_MAGIC_ZOMBIE;
@@ -112521,10 +115733,16 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
 
   /* If we reach this point, it means that the database connection has
   ** closed all sqlite3_stmt and sqlite3_backup objects and has been
-  ** pased to sqlite3_close (meaning that it is a zombie).  Therefore,
+  ** passed to sqlite3_close (meaning that it is a zombie).  Therefore,
   ** go ahead and free all resources.
   */
 
+  /* If a transaction is open, roll it back. This also ensures that if
+  ** any database schemas have been modified by an uncommitted transaction
+  ** they are reset. And that the required b-tree mutex is held to make
+  ** the pager rollback and schema reset an atomic operation. */
+  sqlite3RollbackAll(db, SQLITE_OK);
+
   /* Free any outstanding Savepoint structures. */
   sqlite3CloseSavepoints(db);
 
@@ -112625,6 +115843,15 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
   int inTrans = 0;
   assert( sqlite3_mutex_held(db->mutex) );
   sqlite3BeginBenignMalloc();
+
+  /* Obtain all b-tree mutexes before making any calls to BtreeRollback(). 
+  ** This is important in case the transaction being rolled back has
+  ** modified the database schema. If the b-tree mutexes are not taken
+  ** here, then another shared-cache connection might sneak in between
+  ** the database rollback and schema reset, which can cause false
+  ** corruption reports in some cases.  */
+  sqlite3BtreeEnterAll(db);
+
   for(i=0; i<db->nDb; i++){
     Btree *p = db->aDb[i].pBt;
     if( p ){
@@ -112638,10 +115865,11 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
   sqlite3VtabRollback(db);
   sqlite3EndBenignMalloc();
 
-  if( db->flags&SQLITE_InternChanges ){
+  if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
     sqlite3ExpirePreparedStatements(db);
     sqlite3ResetAllSchemasOfConnection(db);
   }
+  sqlite3BtreeLeaveAll(db);
 
   /* Any deferred constraint violations have now been resolved. */
   db->nDeferredCons = 0;
@@ -112653,6 +115881,110 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
 }
 
 /*
+** Return a static string containing the name corresponding to the error code
+** specified in the argument.
+*/
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
+    defined(SQLITE_DEBUG_OS_TRACE)
+SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
+  const char *zName = 0;
+  int i, origRc = rc;
+  for(i=0; i<2 && zName==0; i++, rc &= 0xff){
+    switch( rc ){
+      case SQLITE_OK:                 zName = "SQLITE_OK";                break;
+      case SQLITE_ERROR:              zName = "SQLITE_ERROR";             break;
+      case SQLITE_INTERNAL:           zName = "SQLITE_INTERNAL";          break;
+      case SQLITE_PERM:               zName = "SQLITE_PERM";              break;
+      case SQLITE_ABORT:              zName = "SQLITE_ABORT";             break;
+      case SQLITE_ABORT_ROLLBACK:     zName = "SQLITE_ABORT_ROLLBACK";    break;
+      case SQLITE_BUSY:               zName = "SQLITE_BUSY";              break;
+      case SQLITE_BUSY_RECOVERY:      zName = "SQLITE_BUSY_RECOVERY";     break;
+      case SQLITE_LOCKED:             zName = "SQLITE_LOCKED";            break;
+      case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
+      case SQLITE_NOMEM:              zName = "SQLITE_NOMEM";             break;
+      case SQLITE_READONLY:           zName = "SQLITE_READONLY";          break;
+      case SQLITE_READONLY_RECOVERY:  zName = "SQLITE_READONLY_RECOVERY"; break;
+      case SQLITE_READONLY_CANTLOCK:  zName = "SQLITE_READONLY_CANTLOCK"; break;
+      case SQLITE_READONLY_ROLLBACK:  zName = "SQLITE_READONLY_ROLLBACK"; break;
+      case SQLITE_INTERRUPT:          zName = "SQLITE_INTERRUPT";         break;
+      case SQLITE_IOERR:              zName = "SQLITE_IOERR";             break;
+      case SQLITE_IOERR_READ:         zName = "SQLITE_IOERR_READ";        break;
+      case SQLITE_IOERR_SHORT_READ:   zName = "SQLITE_IOERR_SHORT_READ";  break;
+      case SQLITE_IOERR_WRITE:        zName = "SQLITE_IOERR_WRITE";       break;
+      case SQLITE_IOERR_FSYNC:        zName = "SQLITE_IOERR_FSYNC";       break;
+      case SQLITE_IOERR_DIR_FSYNC:    zName = "SQLITE_IOERR_DIR_FSYNC";   break;
+      case SQLITE_IOERR_TRUNCATE:     zName = "SQLITE_IOERR_TRUNCATE";    break;
+      case SQLITE_IOERR_FSTAT:        zName = "SQLITE_IOERR_FSTAT";       break;
+      case SQLITE_IOERR_UNLOCK:       zName = "SQLITE_IOERR_UNLOCK";      break;
+      case SQLITE_IOERR_RDLOCK:       zName = "SQLITE_IOERR_RDLOCK";      break;
+      case SQLITE_IOERR_DELETE:       zName = "SQLITE_IOERR_DELETE";      break;
+      case SQLITE_IOERR_BLOCKED:      zName = "SQLITE_IOERR_BLOCKED";     break;
+      case SQLITE_IOERR_NOMEM:        zName = "SQLITE_IOERR_NOMEM";       break;
+      case SQLITE_IOERR_ACCESS:       zName = "SQLITE_IOERR_ACCESS";      break;
+      case SQLITE_IOERR_CHECKRESERVEDLOCK:
+                                zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
+      case SQLITE_IOERR_LOCK:         zName = "SQLITE_IOERR_LOCK";        break;
+      case SQLITE_IOERR_CLOSE:        zName = "SQLITE_IOERR_CLOSE";       break;
+      case SQLITE_IOERR_DIR_CLOSE:    zName = "SQLITE_IOERR_DIR_CLOSE";   break;
+      case SQLITE_IOERR_SHMOPEN:      zName = "SQLITE_IOERR_SHMOPEN";     break;
+      case SQLITE_IOERR_SHMSIZE:      zName = "SQLITE_IOERR_SHMSIZE";     break;
+      case SQLITE_IOERR_SHMLOCK:      zName = "SQLITE_IOERR_SHMLOCK";     break;
+      case SQLITE_IOERR_SHMMAP:       zName = "SQLITE_IOERR_SHMMAP";      break;
+      case SQLITE_IOERR_SEEK:         zName = "SQLITE_IOERR_SEEK";        break;
+      case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break;
+      case SQLITE_IOERR_MMAP:         zName = "SQLITE_IOERR_MMAP";        break;
+      case SQLITE_CORRUPT:            zName = "SQLITE_CORRUPT";           break;
+      case SQLITE_CORRUPT_VTAB:       zName = "SQLITE_CORRUPT_VTAB";      break;
+      case SQLITE_NOTFOUND:           zName = "SQLITE_NOTFOUND";          break;
+      case SQLITE_FULL:               zName = "SQLITE_FULL";              break;
+      case SQLITE_CANTOPEN:           zName = "SQLITE_CANTOPEN";          break;
+      case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break;
+      case SQLITE_CANTOPEN_ISDIR:     zName = "SQLITE_CANTOPEN_ISDIR";    break;
+      case SQLITE_CANTOPEN_FULLPATH:  zName = "SQLITE_CANTOPEN_FULLPATH"; break;
+      case SQLITE_PROTOCOL:           zName = "SQLITE_PROTOCOL";          break;
+      case SQLITE_EMPTY:              zName = "SQLITE_EMPTY";             break;
+      case SQLITE_SCHEMA:             zName = "SQLITE_SCHEMA";            break;
+      case SQLITE_TOOBIG:             zName = "SQLITE_TOOBIG";            break;
+      case SQLITE_CONSTRAINT:         zName = "SQLITE_CONSTRAINT";        break;
+      case SQLITE_CONSTRAINT_UNIQUE:  zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
+      case SQLITE_CONSTRAINT_TRIGGER: zName = "SQLITE_CONSTRAINT_TRIGGER";break;
+      case SQLITE_CONSTRAINT_FOREIGNKEY:
+                                zName = "SQLITE_CONSTRAINT_FOREIGNKEY";   break;
+      case SQLITE_CONSTRAINT_CHECK:   zName = "SQLITE_CONSTRAINT_CHECK";  break;
+      case SQLITE_CONSTRAINT_PRIMARYKEY:
+                                zName = "SQLITE_CONSTRAINT_PRIMARYKEY";   break;
+      case SQLITE_CONSTRAINT_NOTNULL: zName = "SQLITE_CONSTRAINT_NOTNULL";break;
+      case SQLITE_CONSTRAINT_COMMITHOOK:
+                                zName = "SQLITE_CONSTRAINT_COMMITHOOK";   break;
+      case SQLITE_CONSTRAINT_VTAB:    zName = "SQLITE_CONSTRAINT_VTAB";   break;
+      case SQLITE_CONSTRAINT_FUNCTION:
+                                zName = "SQLITE_CONSTRAINT_FUNCTION";     break;
+      case SQLITE_MISMATCH:           zName = "SQLITE_MISMATCH";          break;
+      case SQLITE_MISUSE:             zName = "SQLITE_MISUSE";            break;
+      case SQLITE_NOLFS:              zName = "SQLITE_NOLFS";             break;
+      case SQLITE_AUTH:               zName = "SQLITE_AUTH";              break;
+      case SQLITE_FORMAT:             zName = "SQLITE_FORMAT";            break;
+      case SQLITE_RANGE:              zName = "SQLITE_RANGE";             break;
+      case SQLITE_NOTADB:             zName = "SQLITE_NOTADB";            break;
+      case SQLITE_ROW:                zName = "SQLITE_ROW";               break;
+      case SQLITE_NOTICE:             zName = "SQLITE_NOTICE";            break;
+      case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break;
+      case SQLITE_NOTICE_RECOVER_ROLLBACK:
+                                zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
+      case SQLITE_WARNING:            zName = "SQLITE_WARNING";           break;
+      case SQLITE_DONE:               zName = "SQLITE_DONE";              break;
+    }
+  }
+  if( zName==0 ){
+    static char zBuf[50];
+    sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc);
+    zName = zBuf;
+  }
+  return zName;
+}
+#endif
+
+/*
 ** Return a static string that describes the kind of error specified in the
 ** argument.
 */
@@ -112780,6 +116112,7 @@ SQLITE_API int sqlite3_busy_handler(
   db->busyHandler.xFunc = xBusy;
   db->busyHandler.pArg = pArg;
   db->busyHandler.nBusy = 0;
+  db->busyTimeout = 0;
   sqlite3_mutex_leave(db->mutex);
   return SQLITE_OK;
 }
@@ -112817,8 +116150,8 @@ SQLITE_API void sqlite3_progress_handler(
 */
 SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
   if( ms>0 ){
-    db->busyTimeout = ms;
     sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+    db->busyTimeout = ms;
   }else{
     sqlite3_busy_handler(db, 0, 0);
   }
@@ -113432,6 +116765,15 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
 }
 
 /*
+** Return a string that describes the kind of error specified in the
+** argument.  For now, this simply calls the internal sqlite3ErrStr()
+** function.
+*/
+SQLITE_API const char *sqlite3_errstr(int rc){
+  return sqlite3ErrStr(rc);
+}
+
+/*
 ** Create a new collating function for database "db".  The name is zName
 ** and the encoding is enc.
 */
@@ -113942,6 +117284,7 @@ static int openDatabase(
   memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
   db->autoCommit = 1;
   db->nextAutovac = -1;
+  db->szMmap = sqlite3GlobalConfig.szMmap;
   db->nextPagesize = 0;
   db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
 #if SQLITE_DEFAULT_FILE_FORMAT<4
@@ -114100,6 +117443,13 @@ opendb_out:
     db->magic = SQLITE_MAGIC_SICK;
   }
   *ppDb = db;
+#ifdef SQLITE_ENABLE_SQLLOG
+  if( sqlite3GlobalConfig.xSqllog ){
+    /* Opening a db handle. Fourth parameter is passed 0. */
+    void *pArg = sqlite3GlobalConfig.pSqllogArg;
+    sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
+  }
+#endif
   return sqlite3ApiExit(0, rc);
 }
 
@@ -114405,7 +117755,7 @@ SQLITE_API int sqlite3_table_column_metadata(
     zDataType = pCol->zType;
     zCollSeq = pCol->zColl;
     notnull = pCol->notNull!=0;
-    primarykey  = pCol->isPrimKey!=0;
+    primarykey  = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
     autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
   }else{
     zDataType = "INTEGER";
@@ -114668,8 +118018,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
     */
     case SQLITE_TESTCTRL_OPTIMIZATIONS: {
       sqlite3 *db = va_arg(ap, sqlite3*);
-      int x = va_arg(ap,int);
-      db->flags = (x & SQLITE_OptMask) | (db->flags & ~SQLITE_OptMask);
+      db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
       break;
     }
 
@@ -115557,7 +118906,7 @@ struct sqlite3_tokenizer_module {
   ** This method should return either SQLITE_OK (0), or an SQLite error 
   ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
   ** to point at the newly created tokenizer structure. The generic
-  ** sqlite3_tokenizer.pModule variable should not be initialised by
+  ** sqlite3_tokenizer.pModule variable should not be initialized by
   ** this callback. The caller will do so.
   */
   int (*xCreate)(
@@ -115662,7 +119011,7 @@ int fts3_term_cnt(int iTerm, int iCol);
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This is the header file for the generic hash-table implemenation
+** This is the header file for the generic hash-table implementation
 ** used in SQLite.  We've modified it slightly to serve as a standalone
 ** hash table implementation for the full-text indexing module.
 **
@@ -116252,7 +119601,7 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const
 
 /* fts3_expr.c */
 SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
-  char **, int, int, int, const char *, int, Fts3Expr **
+  char **, int, int, int, const char *, int, Fts3Expr **, char **
 );
 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
 #ifdef SQLITE_TEST
@@ -116277,6 +119626,9 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iC
 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
 SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
 
+/* fts3_tokenize_vtab.c */
+SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
+
 /* fts3_unicode2.c (functions generated by parsing unicode text files) */
 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
 SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
@@ -117569,7 +120921,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
       }else{
         rc = sqlite3_reset(pCsr->pStmt);
         if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
-          /* If no row was found and no error has occured, then the %_content
+          /* If no row was found and no error has occurred, then the %_content
           ** table is missing a row that is present in the full-text index.
           ** The data structures are corrupt.  */
           rc = FTS_CORRUPT_VTAB;
@@ -118809,7 +122161,7 @@ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
 }
 
 /*
-** This function retreives the doclist for the specified term (or term
+** This function retrieves the doclist for the specified term (or term
 ** prefix) from the database.
 */
 static int fts3TermSelect(
@@ -118973,14 +122325,12 @@ static int fts3FilterMethod(
     pCsr->iLangid = 0;
     if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
 
+    assert( p->base.zErrMsg==0 );
     rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
-        p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
+        p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, 
+        &p->base.zErrMsg
     );
     if( rc!=SQLITE_OK ){
-      if( rc==SQLITE_ERROR ){
-        static const char *zErr = "malformed MATCH expression: [%s]";
-        p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
-      }
       return rc;
     }
 
@@ -119560,7 +122910,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const
 #endif
 
 /*
-** Initialise the fts3 extension. If this extension is built as part
+** Initialize the fts3 extension. If this extension is built as part
 ** of the sqlite library, then this function is called directly by
 ** SQLite. If fts3 is built as a dynamically loadable extension, this
 ** function is called by the sqlite3_extension_init() entry point.
@@ -119594,7 +122944,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
   sqlite3Fts3SimpleTokenizerModule(&pSimple);
   sqlite3Fts3PorterTokenizerModule(&pPorter);
 
-  /* Allocate and initialise the hash-table used to store tokenizers. */
+  /* Allocate and initialize the hash-table used to store tokenizers. */
   pHash = sqlite3_malloc(sizeof(Fts3Hash));
   if( !pHash ){
     rc = SQLITE_NOMEM;
@@ -119644,9 +122994,13 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
           db, "fts4", &fts3Module, (void *)pHash, 0
       );
     }
+    if( rc==SQLITE_OK ){
+      rc = sqlite3Fts3InitTok(db, (void *)pHash);
+    }
     return rc;
   }
 
+
   /* An error has occurred. Delete the hash table and return the error code. */
   assert( rc!=SQLITE_OK );
   if( pHash ){
@@ -120741,35 +124095,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
       nTmp += p->pRight->pPhrase->doclist.nList;
     }
     nTmp += p->pPhrase->doclist.nList;
-    aTmp = sqlite3_malloc(nTmp*2);
-    if( !aTmp ){
-      *pRc = SQLITE_NOMEM;
+    if( nTmp==0 ){
       res = 0;
     }else{
-      char *aPoslist = p->pPhrase->doclist.pList;
-      int nToken = p->pPhrase->nToken;
+      aTmp = sqlite3_malloc(nTmp*2);
+      if( !aTmp ){
+        *pRc = SQLITE_NOMEM;
+        res = 0;
+      }else{
+        char *aPoslist = p->pPhrase->doclist.pList;
+        int nToken = p->pPhrase->nToken;
 
-      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
-        Fts3Phrase *pPhrase = p->pRight->pPhrase;
-        int nNear = p->nNear;
-        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
-      }
-  
-      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
-      nToken = pExpr->pRight->pPhrase->nToken;
-      for(p=pExpr->pLeft; p && res; p=p->pLeft){
-        int nNear;
-        Fts3Phrase *pPhrase;
-        assert( p->pParent && p->pParent->pLeft==p );
-        nNear = p->pParent->nNear;
-        pPhrase = (
-            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
-        );
-        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+        for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
+          Fts3Phrase *pPhrase = p->pRight->pPhrase;
+          int nNear = p->nNear;
+          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+        }
+
+        aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+        nToken = pExpr->pRight->pPhrase->nToken;
+        for(p=pExpr->pLeft; p && res; p=p->pLeft){
+          int nNear;
+          Fts3Phrase *pPhrase;
+          assert( p->pParent && p->pParent->pLeft==p );
+          nNear = p->pParent->nNear;
+          pPhrase = (
+              p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+              );
+          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+        }
       }
-    }
 
-    sqlite3_free(aTmp);
+      sqlite3_free(aTmp);
+    }
   }
 
   return res;
@@ -121189,7 +124547,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
 ** of the current row. 
 **
 ** More specifically, the returned buffer contains 1 varint for each 
-** occurence of the phrase in the column, stored using the normal (delta+2) 
+** occurrence of the phrase in the column, stored using the normal (delta+2) 
 ** compression and is terminated by either an 0x01 or 0x00 byte. For example,
 ** if the requested column contains "a b X c d X X" and the position-list
 ** for 'X' is requested, the buffer returned may contain:
@@ -121416,17 +124774,26 @@ static int fts3auxConnectMethod(
 
   UNUSED_PARAMETER(pUnused);
 
-  /* The user should specify a single argument - the name of an fts3 table. */
-  if( argc!=4 ){
-    *pzErr = sqlite3_mprintf(
-        "wrong number of arguments to fts4aux constructor"
-    );
-    return SQLITE_ERROR;
-  }
+  /* The user should invoke this in one of two forms:
+  **
+  **     CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table);
+  **     CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table);
+  */
+  if( argc!=4 && argc!=5 ) goto bad_args;
 
   zDb = argv[1]; 
   nDb = (int)strlen(zDb);
-  zFts3 = argv[3];
+  if( argc==5 ){
+    if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
+      zDb = argv[3]; 
+      nDb = (int)strlen(zDb);
+      zFts3 = argv[4];
+    }else{
+      goto bad_args;
+    }
+  }else{
+    zFts3 = argv[3];
+  }
   nFts3 = (int)strlen(zFts3);
 
   rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
@@ -121449,6 +124816,10 @@ static int fts3auxConnectMethod(
 
   *ppVtab = (sqlite3_vtab *)p;
   return SQLITE_OK;
+
+ bad_args:
+  *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
+  return SQLITE_ERROR;
 }
 
 /*
@@ -121928,7 +125299,7 @@ struct ParseContext {
 ** This function is equivalent to the standard isspace() function. 
 **
 ** The standard isspace() can be awkward to use safely, because although it
-** is defined to accept an argument of type int, its behaviour when passed
+** is defined to accept an argument of type int, its behavior when passed
 ** an integer that falls outside of the range of the unsigned char type
 ** is undefined (and sometimes, "undefined" means segfault). This wrapper
 ** is defined to accept an argument of type char, and always returns 0 for
@@ -122007,7 +125378,7 @@ static int getNextToken(
   rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
   if( rc==SQLITE_OK ){
     const char *zToken;
-    int nToken, iStart, iEnd, iPosition;
+    int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
     int nByte;                               /* total space to allocate */
 
     rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
@@ -122122,7 +125493,7 @@ static int getNextString(
     int ii;
     for(ii=0; rc==SQLITE_OK; ii++){
       const char *zByte;
-      int nByte, iBegin, iEnd, iPos;
+      int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
       rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
       if( rc==SQLITE_OK ){
         Fts3PhraseToken *pToken;
@@ -122462,8 +125833,10 @@ static int fts3ExprParse(
         }
         pNot->eType = FTSQUERY_NOT;
         pNot->pRight = p;
+        p->pParent = pNot;
         if( pNotBranch ){
           pNot->pLeft = pNotBranch;
+          pNotBranch->pParent = pNot;
         }
         pNotBranch = pNot;
         p = pPrev;
@@ -122551,6 +125924,7 @@ static int fts3ExprParse(
           pIter = pIter->pLeft;
         }
         pIter->pLeft = pRet;
+        pRet->pParent = pIter;
         pRet = pNotBranch;
       }
     }
@@ -122568,30 +125942,184 @@ exprparse_out:
 }
 
 /*
-** Parameters z and n contain a pointer to and length of a buffer containing
-** an fts3 query expression, respectively. This function attempts to parse the
-** query expression and create a tree of Fts3Expr structures representing the
-** parsed expression. If successful, *ppExpr is set to point to the head
-** of the parsed expression tree and SQLITE_OK is returned. If an error
-** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse
-** error) is returned and *ppExpr is set to 0.
+** Return SQLITE_ERROR if the maximum depth of the expression tree passed 
+** as the only argument is more than nMaxDepth.
+*/
+static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){
+  int rc = SQLITE_OK;
+  if( p ){
+    if( nMaxDepth<0 ){ 
+      rc = SQLITE_TOOBIG;
+    }else{
+      rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1);
+      if( rc==SQLITE_OK ){
+        rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1);
+      }
+    }
+  }
+  return rc;
+}
+
+/*
+** This function attempts to transform the expression tree at (*pp) to
+** an equivalent but more balanced form. The tree is modified in place.
+** If successful, SQLITE_OK is returned and (*pp) set to point to the 
+** new root expression node. 
 **
-** If parameter n is a negative number, then z is assumed to point to a
-** nul-terminated string and the length is determined using strlen().
+** nMaxDepth is the maximum allowable depth of the balanced sub-tree.
 **
-** The first parameter, pTokenizer, is passed the fts3 tokenizer module to
-** use to normalize query tokens while parsing the expression. The azCol[]
-** array, which is assumed to contain nCol entries, should contain the names
-** of each column in the target fts3 table, in order from left to right. 
-** Column names must be nul-terminated strings.
+** Otherwise, if an error occurs, an SQLite error code is returned and 
+** expression (*pp) freed.
+*/
+static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
+  int rc = SQLITE_OK;             /* Return code */
+  Fts3Expr *pRoot = *pp;          /* Initial root node */
+  Fts3Expr *pFree = 0;            /* List of free nodes. Linked by pParent. */
+  int eType = pRoot->eType;       /* Type of node in this tree */
+
+  if( nMaxDepth==0 ){
+    rc = SQLITE_ERROR;
+  }
+
+  if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
+    Fts3Expr **apLeaf;
+    apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
+    if( 0==apLeaf ){
+      rc = SQLITE_NOMEM;
+    }else{
+      memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
+    }
+
+    if( rc==SQLITE_OK ){
+      int i;
+      Fts3Expr *p;
+
+      /* Set $p to point to the left-most leaf in the tree of eType nodes. */
+      for(p=pRoot; p->eType==eType; p=p->pLeft){
+        assert( p->pParent==0 || p->pParent->pLeft==p );
+        assert( p->pLeft && p->pRight );
+      }
+
+      /* This loop runs once for each leaf in the tree of eType nodes. */
+      while( 1 ){
+        int iLvl;
+        Fts3Expr *pParent = p->pParent;     /* Current parent of p */
+
+        assert( pParent==0 || pParent->pLeft==p );
+        p->pParent = 0;
+        if( pParent ){
+          pParent->pLeft = 0;
+        }else{
+          pRoot = 0;
+        }
+        rc = fts3ExprBalance(&p, nMaxDepth-1);
+        if( rc!=SQLITE_OK ) break;
+
+        for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
+          if( apLeaf[iLvl]==0 ){
+            apLeaf[iLvl] = p;
+            p = 0;
+          }else{
+            assert( pFree );
+            pFree->pLeft = apLeaf[iLvl];
+            pFree->pRight = p;
+            pFree->pLeft->pParent = pFree;
+            pFree->pRight->pParent = pFree;
+
+            p = pFree;
+            pFree = pFree->pParent;
+            p->pParent = 0;
+            apLeaf[iLvl] = 0;
+          }
+        }
+        if( p ){
+          sqlite3Fts3ExprFree(p);
+          rc = SQLITE_TOOBIG;
+          break;
+        }
+
+        /* If that was the last leaf node, break out of the loop */
+        if( pParent==0 ) break;
+
+        /* Set $p to point to the next leaf in the tree of eType nodes */
+        for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
+
+        /* Remove pParent from the original tree. */
+        assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
+        pParent->pRight->pParent = pParent->pParent;
+        if( pParent->pParent ){
+          pParent->pParent->pLeft = pParent->pRight;
+        }else{
+          assert( pParent==pRoot );
+          pRoot = pParent->pRight;
+        }
+
+        /* Link pParent into the free node list. It will be used as an
+        ** internal node of the new tree.  */
+        pParent->pParent = pFree;
+        pFree = pParent;
+      }
+
+      if( rc==SQLITE_OK ){
+        p = 0;
+        for(i=0; i<nMaxDepth; i++){
+          if( apLeaf[i] ){
+            if( p==0 ){
+              p = apLeaf[i];
+              p->pParent = 0;
+            }else{
+              assert( pFree!=0 );
+              pFree->pRight = p;
+              pFree->pLeft = apLeaf[i];
+              pFree->pLeft->pParent = pFree;
+              pFree->pRight->pParent = pFree;
+
+              p = pFree;
+              pFree = pFree->pParent;
+              p->pParent = 0;
+            }
+          }
+        }
+        pRoot = p;
+      }else{
+        /* An error occurred. Delete the contents of the apLeaf[] array 
+        ** and pFree list. Everything else is cleaned up by the call to
+        ** sqlite3Fts3ExprFree(pRoot) below.  */
+        Fts3Expr *pDel;
+        for(i=0; i<nMaxDepth; i++){
+          sqlite3Fts3ExprFree(apLeaf[i]);
+        }
+        while( (pDel=pFree)!=0 ){
+          pFree = pDel->pParent;
+          sqlite3_free(pDel);
+        }
+      }
+
+      assert( pFree==0 );
+      sqlite3_free( apLeaf );
+    }
+  }
+
+  if( rc!=SQLITE_OK ){
+    sqlite3Fts3ExprFree(pRoot);
+    pRoot = 0;
+  }
+  *pp = pRoot;
+  return rc;
+}
+
+/*
+** This function is similar to sqlite3Fts3ExprParse(), with the following
+** differences:
 **
-** The iDefaultCol parameter should be passed the index of the table column
-** that appears on the left-hand-side of the MATCH operator (the default
-** column to match against for tokens for which a column name is not explicitly
-** specified as part of the query string), or -1 if tokens may by default
-** match any table column.
+**   1. It does not do expression rebalancing.
+**   2. It does not check that the expression does not exceed the 
+**      maximum allowable depth.
+**   3. Even if it fails, *ppExpr may still be set to point to an 
+**      expression tree. It should be deleted using sqlite3Fts3ExprFree()
+**      in this case.
 */
-SQLITE_PRIVATE int sqlite3Fts3ExprParse(
+static int fts3ExprParseUnbalanced(
   sqlite3_tokenizer *pTokenizer,      /* Tokenizer module */
   int iLangid,                        /* Language id for tokenizer */
   char **azCol,                       /* Array of column names for fts3 table */
@@ -122620,28 +126148,116 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
     n = (int)strlen(z);
   }
   rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed);
+  assert( rc==SQLITE_OK || *ppExpr==0 );
 
   /* Check for mismatched parenthesis */
   if( rc==SQLITE_OK && sParse.nNest ){
     rc = SQLITE_ERROR;
+  }
+  
+  return rc;
+}
+
+/*
+** Parameters z and n contain a pointer to and length of a buffer containing
+** an fts3 query expression, respectively. This function attempts to parse the
+** query expression and create a tree of Fts3Expr structures representing the
+** parsed expression. If successful, *ppExpr is set to point to the head
+** of the parsed expression tree and SQLITE_OK is returned. If an error
+** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse
+** error) is returned and *ppExpr is set to 0.
+**
+** If parameter n is a negative number, then z is assumed to point to a
+** nul-terminated string and the length is determined using strlen().
+**
+** The first parameter, pTokenizer, is passed the fts3 tokenizer module to
+** use to normalize query tokens while parsing the expression. The azCol[]
+** array, which is assumed to contain nCol entries, should contain the names
+** of each column in the target fts3 table, in order from left to right. 
+** Column names must be nul-terminated strings.
+**
+** The iDefaultCol parameter should be passed the index of the table column
+** that appears on the left-hand-side of the MATCH operator (the default
+** column to match against for tokens for which a column name is not explicitly
+** specified as part of the query string), or -1 if tokens may by default
+** match any table column.
+*/
+SQLITE_PRIVATE int sqlite3Fts3ExprParse(
+  sqlite3_tokenizer *pTokenizer,      /* Tokenizer module */
+  int iLangid,                        /* Language id for tokenizer */
+  char **azCol,                       /* Array of column names for fts3 table */
+  int bFts4,                          /* True to allow FTS4-only syntax */
+  int nCol,                           /* Number of entries in azCol[] */
+  int iDefaultCol,                    /* Default column to query */
+  const char *z, int n,               /* Text of MATCH query */
+  Fts3Expr **ppExpr,                  /* OUT: Parsed query structure */
+  char **pzErr                        /* OUT: Error message (sqlite3_malloc) */
+){
+  static const int MAX_EXPR_DEPTH = 12;
+  int rc = fts3ExprParseUnbalanced(
+      pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
+  );
+  
+  /* Rebalance the expression. And check that its depth does not exceed
+  ** MAX_EXPR_DEPTH.  */
+  if( rc==SQLITE_OK && *ppExpr ){
+    rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH);
+    if( rc==SQLITE_OK ){
+      rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH);
+    }
+  }
+
+  if( rc!=SQLITE_OK ){
     sqlite3Fts3ExprFree(*ppExpr);
     *ppExpr = 0;
+    if( rc==SQLITE_TOOBIG ){
+      *pzErr = sqlite3_mprintf(
+          "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH
+      );
+      rc = SQLITE_ERROR;
+    }else if( rc==SQLITE_ERROR ){
+      *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z);
+    }
   }
 
   return rc;
 }
 
 /*
+** Free a single node of an expression tree.
+*/
+static void fts3FreeExprNode(Fts3Expr *p){
+  assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
+  sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
+  sqlite3_free(p->aMI);
+  sqlite3_free(p);
+}
+
+/*
 ** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
+**
+** This function would be simpler if it recursively called itself. But
+** that would mean passing a sufficiently large expression to ExprParse()
+** could cause a stack overflow.
 */
-SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
-  if( p ){
-    assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
-    sqlite3Fts3ExprFree(p->pLeft);
-    sqlite3Fts3ExprFree(p->pRight);
-    sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
-    sqlite3_free(p->aMI);
-    sqlite3_free(p);
+SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *pDel){
+  Fts3Expr *p;
+  assert( pDel==0 || pDel->pParent==0 );
+  for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){
+    assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft );
+  }
+  while( p ){
+    Fts3Expr *pParent = p->pParent;
+    fts3FreeExprNode(p);
+    if( pParent && p==pParent->pLeft && pParent->pRight ){
+      p = pParent->pRight;
+      while( p && (p->pLeft || p->pRight) ){
+        assert( p==p->pParent->pRight || p==p->pParent->pLeft );
+        p = (p->pLeft ? p->pLeft : p->pRight);
+      }
+    }else{
+      p = pParent;
+    }
   }
 }
 
@@ -122693,6 +126309,9 @@ static int queryTestTokenizer(
 ** the returned expression text and then freed using sqlite3_free().
 */
 static char *exprToString(Fts3Expr *pExpr, char *zBuf){
+  if( pExpr==0 ){
+    return sqlite3_mprintf("");
+  }
   switch( pExpr->eType ){
     case FTSQUERY_PHRASE: {
       Fts3Phrase *pPhrase = pExpr->pPhrase;
@@ -122800,10 +126419,21 @@ static void fts3ExprTest(
     azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
   }
 
-  rc = sqlite3Fts3ExprParse(
-      pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
-  );
+  if( sqlite3_user_data(context) ){
+    char *zDummy = 0;
+    rc = sqlite3Fts3ExprParse(
+        pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy
+    );
+    assert( rc==SQLITE_OK || pExpr==0 );
+    sqlite3_free(zDummy);
+  }else{
+    rc = fts3ExprParseUnbalanced(
+        pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
+    );
+  }
+
   if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
+    sqlite3Fts3ExprFree(pExpr);
     sqlite3_result_error(context, "Error parsing expression", -1);
   }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
     sqlite3_result_error_nomem(context);
@@ -122826,9 +126456,15 @@ exprtest_out:
 ** with database connection db. 
 */
 SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
-  return sqlite3_create_function(
+  int rc = sqlite3_create_function(
       db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
   );
+  if( rc==SQLITE_OK ){
+    rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", 
+        -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0
+    );
+  }
+  return rc;
 }
 
 #endif
@@ -124119,10 +127755,10 @@ static void testFunc(
   const char *azArg[64];
 
   const char *zToken;
-  int nToken;
-  int iStart;
-  int iEnd;
-  int iPos;
+  int nToken = 0;
+  int iStart = 0;
+  int iEnd = 0;
+  int iPos = 0;
   int i;
 
   Tcl_Obj *pRet;
@@ -124296,7 +127932,7 @@ static void intTestFunc(
 /*
 ** Set up SQL objects in database db used to access the contents of
 ** the hash table pointed to by argument pHash. The hash table must
-** been initialised to use string keys, and to take a private copy 
+** been initialized to use string keys, and to take a private copy 
 ** of the key when a value is inserted. i.e. by a call similar to:
 **
 **    sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
@@ -124591,6 +128227,462 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(
 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
 
 /************** End of fts3_tokenizer1.c *************************************/
+/************** Begin file fts3_tokenize_vtab.c ******************************/
+/*
+** 2013 Apr 22
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains code for the "fts3tokenize" virtual table module.
+** An fts3tokenize virtual table is created as follows:
+**
+**   CREATE VIRTUAL TABLE <tbl> USING fts3tokenize(
+**       <tokenizer-name>, <arg-1>, ...
+**   );
+**
+** The table created has the following schema:
+**
+**   CREATE TABLE <tbl>(input, token, start, end, position)
+**
+** When queried, the query must include a WHERE clause of type:
+**
+**   input = <string>
+**
+** The virtual table module tokenizes this <string>, using the FTS3 
+** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE 
+** statement and returns one row for each token in the result. With
+** fields set as follows:
+**
+**   input:   Always set to a copy of <string>
+**   token:   A token from the input.
+**   start:   Byte offset of the token within the input <string>.
+**   end:     Byte offset of the byte immediately following the end of the
+**            token within the input string.
+**   pos:     Token offset of token within input.
+**
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <string.h> */
+/* #include <assert.h> */
+
+typedef struct Fts3tokTable Fts3tokTable;
+typedef struct Fts3tokCursor Fts3tokCursor;
+
+/*
+** Virtual table structure.
+*/
+struct Fts3tokTable {
+  sqlite3_vtab base;              /* Base class used by SQLite core */
+  const sqlite3_tokenizer_module *pMod;
+  sqlite3_tokenizer *pTok;
+};
+
+/*
+** Virtual table cursor structure.
+*/
+struct Fts3tokCursor {
+  sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
+  char *zInput;                   /* Input string */
+  sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */
+  int iRowid;                     /* Current 'rowid' value */
+  const char *zToken;             /* Current 'token' value */
+  int nToken;                     /* Size of zToken in bytes */
+  int iStart;                     /* Current 'start' value */
+  int iEnd;                       /* Current 'end' value */
+  int iPos;                       /* Current 'pos' value */
+};
+
+/*
+** Query FTS for the tokenizer implementation named zName.
+*/
+static int fts3tokQueryTokenizer(
+  Fts3Hash *pHash,
+  const char *zName,
+  const sqlite3_tokenizer_module **pp,
+  char **pzErr
+){
+  sqlite3_tokenizer_module *p;
+  int nName = (int)strlen(zName);
+
+  p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
+  if( !p ){
+    *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
+    return SQLITE_ERROR;
+  }
+
+  *pp = p;
+  return SQLITE_OK;
+}
+
+/*
+** The second argument, argv[], is an array of pointers to nul-terminated
+** strings. This function makes a copy of the array and strings into a 
+** single block of memory. It then dequotes any of the strings that appear
+** to be quoted.
+**
+** If successful, output parameter *pazDequote is set to point at the
+** array of dequoted strings and SQLITE_OK is returned. The caller is
+** responsible for eventually calling sqlite3_free() to free the array
+** in this case. Or, if an error occurs, an SQLite error code is returned.
+** The final value of *pazDequote is undefined in this case.
+*/
+static int fts3tokDequoteArray(
+  int argc,                       /* Number of elements in argv[] */
+  const char * const *argv,       /* Input array */
+  char ***pazDequote              /* Output array */
+){
+  int rc = SQLITE_OK;             /* Return code */
+  if( argc==0 ){
+    *pazDequote = 0;
+  }else{
+    int i;
+    int nByte = 0;
+    char **azDequote;
+
+    for(i=0; i<argc; i++){
+      nByte += (int)(strlen(argv[i]) + 1);
+    }
+
+    *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
+    if( azDequote==0 ){
+      rc = SQLITE_NOMEM;
+    }else{
+      char *pSpace = (char *)&azDequote[argc];
+      for(i=0; i<argc; i++){
+        int n = (int)strlen(argv[i]);
+        azDequote[i] = pSpace;
+        memcpy(pSpace, argv[i], n+1);
+        sqlite3Fts3Dequote(pSpace);
+        pSpace += (n+1);
+      }
+    }
+  }
+
+  return rc;
+}
+
+/*
+** Schema of the tokenizer table.
+*/
+#define FTS3_TOK_SCHEMA "CREATE TABLE x(input, token, start, end, position)"
+
+/*
+** This function does all the work for both the xConnect and xCreate methods.
+** These tables have no persistent representation of their own, so xConnect
+** and xCreate are identical operations.
+**
+**   argv[0]: module name
+**   argv[1]: database name 
+**   argv[2]: table name
+**   argv[3]: first argument (tokenizer name)
+*/
+static int fts3tokConnectMethod(
+  sqlite3 *db,                    /* Database connection */
+  void *pHash,                    /* Hash table of tokenizers */
+  int argc,                       /* Number of elements in argv array */
+  const char * const *argv,       /* xCreate/xConnect argument array */
+  sqlite3_vtab **ppVtab,          /* OUT: New sqlite3_vtab object */
+  char **pzErr                    /* OUT: sqlite3_malloc'd error message */
+){
+  Fts3tokTable *pTab;
+  const sqlite3_tokenizer_module *pMod = 0;
+  sqlite3_tokenizer *pTok = 0;
+  int rc;
+  char **azDequote = 0;
+  int nDequote;
+
+  rc = sqlite3_declare_vtab(db, FTS3_TOK_SCHEMA);
+  if( rc!=SQLITE_OK ) return rc;
+
+  nDequote = argc-3;
+  rc = fts3tokDequoteArray(nDequote, &argv[3], &azDequote);
+
+  if( rc==SQLITE_OK ){
+    const char *zModule;
+    if( nDequote<1 ){
+      zModule = "simple";
+    }else{
+      zModule = azDequote[0];
+    }
+    rc = fts3tokQueryTokenizer((Fts3Hash*)pHash, zModule, &pMod, pzErr);
+  }
+
+  assert( (rc==SQLITE_OK)==(pMod!=0) );
+  if( rc==SQLITE_OK ){
+    const char * const *azArg = (const char * const *)&azDequote[1];
+    rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
+  }
+
+  if( rc==SQLITE_OK ){
+    pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable));
+    if( pTab==0 ){
+      rc = SQLITE_NOMEM;
+    }
+  }
+
+  if( rc==SQLITE_OK ){
+    memset(pTab, 0, sizeof(Fts3tokTable));
+    pTab->pMod = pMod;
+    pTab->pTok = pTok;
+    *ppVtab = &pTab->base;
+  }else{
+    if( pTok ){
+      pMod->xDestroy(pTok);
+    }
+  }
+
+  sqlite3_free(azDequote);
+  return rc;
+}
+
+/*
+** This function does the work for both the xDisconnect and xDestroy methods.
+** These tables have no persistent representation of their own, so xDisconnect
+** and xDestroy are identical operations.
+*/
+static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){
+  Fts3tokTable *pTab = (Fts3tokTable *)pVtab;
+
+  pTab->pMod->xDestroy(pTab->pTok);
+  sqlite3_free(pTab);
+  return SQLITE_OK;
+}
+
+/*
+** xBestIndex - Analyze a WHERE and ORDER BY clause.
+*/
+static int fts3tokBestIndexMethod(
+  sqlite3_vtab *pVTab, 
+  sqlite3_index_info *pInfo
+){
+  int i;
+  UNUSED_PARAMETER(pVTab);
+
+  for(i=0; i<pInfo->nConstraint; i++){
+    if( pInfo->aConstraint[i].usable 
+     && pInfo->aConstraint[i].iColumn==0 
+     && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ 
+    ){
+      pInfo->idxNum = 1;
+      pInfo->aConstraintUsage[i].argvIndex = 1;
+      pInfo->aConstraintUsage[i].omit = 1;
+      pInfo->estimatedCost = 1;
+      return SQLITE_OK;
+    }
+  }
+
+  pInfo->idxNum = 0;
+  assert( pInfo->estimatedCost>1000000.0 );
+
+  return SQLITE_OK;
+}
+
+/*
+** xOpen - Open a cursor.
+*/
+static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
+  Fts3tokCursor *pCsr;
+  UNUSED_PARAMETER(pVTab);
+
+  pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor));
+  if( pCsr==0 ){
+    return SQLITE_NOMEM;
+  }
+  memset(pCsr, 0, sizeof(Fts3tokCursor));
+
+  *ppCsr = (sqlite3_vtab_cursor *)pCsr;
+  return SQLITE_OK;
+}
+
+/*
+** Reset the tokenizer cursor passed as the only argument. As if it had
+** just been returned by fts3tokOpenMethod().
+*/
+static void fts3tokResetCursor(Fts3tokCursor *pCsr){
+  if( pCsr->pCsr ){
+    Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab);
+    pTab->pMod->xClose(pCsr->pCsr);
+    pCsr->pCsr = 0;
+  }
+  sqlite3_free(pCsr->zInput);
+  pCsr->zInput = 0;
+  pCsr->zToken = 0;
+  pCsr->nToken = 0;
+  pCsr->iStart = 0;
+  pCsr->iEnd = 0;
+  pCsr->iPos = 0;
+  pCsr->iRowid = 0;
+}
+
+/*
+** xClose - Close a cursor.
+*/
+static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){
+  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
+
+  fts3tokResetCursor(pCsr);
+  sqlite3_free(pCsr);
+  return SQLITE_OK;
+}
+
+/*
+** xNext - Advance the cursor to the next row, if any.
+*/
+static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){
+  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
+  Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
+  int rc;                         /* Return code */
+
+  pCsr->iRowid++;
+  rc = pTab->pMod->xNext(pCsr->pCsr,
+      &pCsr->zToken, &pCsr->nToken,
+      &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos
+  );
+
+  if( rc!=SQLITE_OK ){
+    fts3tokResetCursor(pCsr);
+    if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+  }
+
+  return rc;
+}
+
+/*
+** xFilter - Initialize a cursor to point at the start of its data.
+*/
+static int fts3tokFilterMethod(
+  sqlite3_vtab_cursor *pCursor,   /* The cursor used for this query */
+  int idxNum,                     /* Strategy index */
+  const char *idxStr,             /* Unused */
+  int nVal,                       /* Number of elements in apVal */
+  sqlite3_value **apVal           /* Arguments for the indexing scheme */
+){
+  int rc = SQLITE_ERROR;
+  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
+  Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
+  UNUSED_PARAMETER(idxStr);
+  UNUSED_PARAMETER(nVal);
+
+  fts3tokResetCursor(pCsr);
+  if( idxNum==1 ){
+    const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
+    int nByte = sqlite3_value_bytes(apVal[0]);
+    pCsr->zInput = sqlite3_malloc(nByte+1);
+    if( pCsr->zInput==0 ){
+      rc = SQLITE_NOMEM;
+    }else{
+      memcpy(pCsr->zInput, zByte, nByte);
+      pCsr->zInput[nByte] = 0;
+      rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
+      if( rc==SQLITE_OK ){
+        pCsr->pCsr->pTokenizer = pTab->pTok;
+      }
+    }
+  }
+
+  if( rc!=SQLITE_OK ) return rc;
+  return fts3tokNextMethod(pCursor);
+}
+
+/*
+** xEof - Return true if the cursor is at EOF, or false otherwise.
+*/
+static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){
+  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
+  return (pCsr->zToken==0);
+}
+
+/*
+** xColumn - Return a column value.
+*/
+static int fts3tokColumnMethod(
+  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
+  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
+  int iCol                        /* Index of column to read value from */
+){
+  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
+
+  /* CREATE TABLE x(input, token, start, end, position) */
+  switch( iCol ){
+    case 0:
+      sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT);
+      break;
+    case 1:
+      sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT);
+      break;
+    case 2:
+      sqlite3_result_int(pCtx, pCsr->iStart);
+      break;
+    case 3:
+      sqlite3_result_int(pCtx, pCsr->iEnd);
+      break;
+    default:
+      assert( iCol==4 );
+      sqlite3_result_int(pCtx, pCsr->iPos);
+      break;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** xRowid - Return the current rowid for the cursor.
+*/
+static int fts3tokRowidMethod(
+  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
+  sqlite_int64 *pRowid            /* OUT: Rowid value */
+){
+  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
+  *pRowid = (sqlite3_int64)pCsr->iRowid;
+  return SQLITE_OK;
+}
+
+/*
+** Register the fts3tok module with database connection db. Return SQLITE_OK
+** if successful or an error code if sqlite3_create_module() fails.
+*/
+SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
+  static const sqlite3_module fts3tok_module = {
+     0,                           /* iVersion      */
+     fts3tokConnectMethod,        /* xCreate       */
+     fts3tokConnectMethod,        /* xConnect      */
+     fts3tokBestIndexMethod,      /* xBestIndex    */
+     fts3tokDisconnectMethod,     /* xDisconnect   */
+     fts3tokDisconnectMethod,     /* xDestroy      */
+     fts3tokOpenMethod,           /* xOpen         */
+     fts3tokCloseMethod,          /* xClose        */
+     fts3tokFilterMethod,         /* xFilter       */
+     fts3tokNextMethod,           /* xNext         */
+     fts3tokEofMethod,            /* xEof          */
+     fts3tokColumnMethod,         /* xColumn       */
+     fts3tokRowidMethod,          /* xRowid        */
+     0,                           /* xUpdate       */
+     0,                           /* xBegin        */
+     0,                           /* xSync         */
+     0,                           /* xCommit       */
+     0,                           /* xRollback     */
+     0,                           /* xFindFunction */
+     0,                           /* xRename       */
+     0,                           /* xSavepoint    */
+     0,                           /* xRelease      */
+     0                            /* xRollbackTo   */
+  };
+  int rc;                         /* Return code */
+
+  rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
+  return rc;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_tokenize_vtab.c **********************************/
 /************** Begin file fts3_write.c **************************************/
 /*
 ** 2009 Oct 23
@@ -125369,16 +129461,16 @@ static int fts3PendingTermsAdd(
   int iLangid,                    /* Language id to use */
   const char *zText,              /* Text of document to be inserted */
   int iCol,                       /* Column into which text is being inserted */
-  u32 *pnWord                     /* OUT: Number of tokens inserted */
+  u32 *pnWord                     /* IN/OUT: Incr. by number tokens inserted */
 ){
   int rc;
-  int iStart;
-  int iEnd;
-  int iPos;
+  int iStart = 0;
+  int iEnd = 0;
+  int iPos = 0;
   int nWord = 0;
 
   char const *zToken;
-  int nToken;
+  int nToken = 0;
 
   sqlite3_tokenizer *pTokenizer = p->pTokenizer;
   sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
@@ -125433,7 +129525,7 @@ static int fts3PendingTermsAdd(
   }
 
   pModule->xClose(pCsr);
-  *pnWord = nWord;
+  *pnWord += nWord;
   return (rc==SQLITE_DONE ? SQLITE_OK : rc);
 }
 
@@ -125637,11 +129729,13 @@ static void fts3DeleteTerms(
   int *pRC,               /* Result code */
   Fts3Table *p,           /* The FTS table to delete from */
   sqlite3_value *pRowid,  /* The docid to be deleted */
-  u32 *aSz                /* Sizes of deleted document written here */
+  u32 *aSz,               /* Sizes of deleted document written here */
+  int *pbFound            /* OUT: Set to true if row really does exist */
 ){
   int rc;
   sqlite3_stmt *pSelect;
 
+  assert( *pbFound==0 );
   if( *pRC ) return;
   rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
   if( rc==SQLITE_OK ){
@@ -125659,6 +129753,7 @@ static void fts3DeleteTerms(
         *pRC = rc;
         return;
       }
+      *pbFound = 1;
     }
     rc = sqlite3_reset(pSelect);
   }else{
@@ -126072,6 +130167,7 @@ static int fts3SegReaderNextDocid(
       *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
     }
 
+    /* List may have been edited in place by fts3EvalNearTrim() */
     while( p<pEnd && *p==0 ) p++;
   
     /* If there are no more entries in the doclist, set pOffsetList to
@@ -127087,9 +131183,13 @@ static int fts3DeleteSegdir(
 **
 ** If there are no entries in the input position list for column iCol, then
 ** *pnList is set to zero before returning.
+**
+** If parameter bZero is non-zero, then any part of the input list following
+** the end of the output list is zeroed before returning.
 */
 static void fts3ColumnFilter(
   int iCol,                       /* Column to filter on */
+  int bZero,                      /* Zero out anything following *ppList */
   char **ppList,                  /* IN/OUT: Pointer to position list */
   int *pnList                     /* IN/OUT: Size of buffer *ppList in bytes */
 ){
@@ -127118,6 +131218,9 @@ static void fts3ColumnFilter(
     p += sqlite3Fts3GetVarint32(p, &iCurrent);
   }
 
+  if( bZero && &pList[nList]!=pEnd ){
+    memset(&pList[nList], 0, pEnd - &pList[nList]);
+  }
   *ppList = pList;
   *pnList = nList;
 }
@@ -127191,19 +131294,19 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
       if( rc!=SQLITE_OK ) return rc;
       fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
 
+      if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
+        rc = fts3MsrBufferData(pMsr, pList, nList+1);
+        if( rc!=SQLITE_OK ) return rc;
+        assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
+        pList = pMsr->aBuffer;
+      }
+
       if( pMsr->iColFilter>=0 ){
-        fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
+        fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
       }
 
       if( nList>0 ){
-        if( fts3SegReaderIsPending(apSegment[0]) ){
-          rc = fts3MsrBufferData(pMsr, pList, nList+1);
-          if( rc!=SQLITE_OK ) return rc;
-          *paPoslist = pMsr->aBuffer;
-          assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
-        }else{
-          *paPoslist = pList;
-        }
+        *paPoslist = pList;
         *piDocid = iDocid;
         *pnPoslist = nList;
         break;
@@ -127446,7 +131549,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
         }
 
         if( isColFilter ){
-          fts3ColumnFilter(pFilter->iCol, &pList, &nList);
+          fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
         }
 
         if( !isIgnoreEmpty || nList>0 ){
@@ -127883,7 +131986,7 @@ static int fts3DoRebuild(Fts3Table *p){
       int iCol;
       int iLangid = langidFromSelect(p, pStmt);
       rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
-      aSz[p->nColumn] = 0;
+      memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
       for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
         const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
         rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
@@ -129527,9 +133630,9 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
         rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
         while( rc==SQLITE_OK ){
           char const *zToken;       /* Buffer containing token */
-          int nToken;               /* Number of bytes in token */
-          int iDum1, iDum2;         /* Dummy variables */
-          int iPos;                 /* Position of token in zText */
+          int nToken = 0;           /* Number of bytes in token */
+          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+          int iPos = 0;             /* Position of token in zText */
 
           rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
           if( rc==SQLITE_OK ){
@@ -129696,9 +133799,9 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
       rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
       while( rc==SQLITE_OK ){
         char const *zToken;       /* Buffer containing token */
-        int nToken;               /* Number of bytes in token */
-        int iDum1, iDum2;         /* Dummy variables */
-        int iPos;                 /* Position of token in zText */
+        int nToken = 0;           /* Number of bytes in token */
+        int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+        int iPos = 0;             /* Position of token in zText */
   
         rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
         for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
@@ -129787,28 +133890,32 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
 static int fts3DeleteByRowid(
   Fts3Table *p, 
   sqlite3_value *pRowid, 
-  int *pnDoc,
+  int *pnChng,                    /* IN/OUT: Decrement if row is deleted */
   u32 *aSzDel
 ){
-  int isEmpty = 0;
-  int rc = fts3IsEmpty(p, pRowid, &isEmpty);
-  if( rc==SQLITE_OK ){
-    if( isEmpty ){
-      /* Deleting this row means the whole table is empty. In this case
-      ** delete the contents of all three tables and throw away any
-      ** data in the pendingTerms hash table.  */
-      rc = fts3DeleteAll(p, 1);
-      *pnDoc = *pnDoc - 1;
-    }else{
-      fts3DeleteTerms(&rc, p, pRowid, aSzDel);
-      if( p->zContentTbl==0 ){
-        fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
-        if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
+  int rc = SQLITE_OK;             /* Return code */
+  int bFound = 0;                 /* True if *pRowid really is in the table */
+
+  fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
+  if( bFound && rc==SQLITE_OK ){
+    int isEmpty = 0;              /* Deleting *pRowid leaves the table empty */
+    rc = fts3IsEmpty(p, pRowid, &isEmpty);
+    if( rc==SQLITE_OK ){
+      if( isEmpty ){
+        /* Deleting this row means the whole table is empty. In this case
+        ** delete the contents of all three tables and throw away any
+        ** data in the pendingTerms hash table.  */
+        rc = fts3DeleteAll(p, 1);
+        *pnChng = 0;
+        memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
       }else{
-        *pnDoc = *pnDoc - 1;
-      }
-      if( p->bHasDocsize ){
-        fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+        *pnChng = *pnChng - 1;
+        if( p->zContentTbl==0 ){
+          fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
+        }
+        if( p->bHasDocsize ){
+          fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+        }
       }
     }
   }
@@ -129839,7 +133946,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   int rc = SQLITE_OK;             /* Return Code */
   int isRemove = 0;               /* True for an UPDATE or DELETE */
   u32 *aSzIns = 0;                /* Sizes of inserted documents */
-  u32 *aSzDel;                    /* Sizes of deleted documents */
+  u32 *aSzDel = 0;                /* Sizes of deleted documents */
   int nChng = 0;                  /* Net change in number of documents */
   int bInsertDone = 0;
 
@@ -129867,13 +133974,13 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   }
 
   /* Allocate space to hold the change in document sizes */
-  aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
-  if( aSzIns==0 ){
+  aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
+  if( aSzDel==0 ){
     rc = SQLITE_NOMEM;
     goto update_out;
   }
-  aSzDel = &aSzIns[p->nColumn+1];
-  memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
+  aSzIns = &aSzDel[p->nColumn+1];
+  memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
 
   /* If this is an INSERT operation, or an UPDATE that modifies the rowid
   ** value, then this operation requires constraint handling.
@@ -129958,7 +134065,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   }
 
  update_out:
-  sqlite3_free(aSzIns);
+  sqlite3_free(aSzDel);
   sqlite3Fts3SegmentsClose(p);
   return rc;
 }
@@ -130379,9 +134486,9 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
 ** is the snippet with the highest score, where scores are calculated
 ** by adding:
 **
-**   (a) +1 point for each occurence of a matchable phrase in the snippet.
+**   (a) +1 point for each occurrence of a matchable phrase in the snippet.
 **
-**   (b) +1000 points for the first occurence of each matchable phrase in 
+**   (b) +1000 points for the first occurrence of each matchable phrase in 
 **       the snippet for which the corresponding mCovered bit is not set.
 **
 ** The selected snippet parameters are stored in structure *pFragment before
@@ -130566,7 +134673,7 @@ static int fts3SnippetShift(
         return rc;
       }
       while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
-        const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
+        const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
         rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
       }
       pMod->xClose(pC);
@@ -130610,8 +134717,6 @@ static int fts3SnippetText(
   int iCol = pFragment->iCol+1;   /* Query column to extract text from */
   sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
   sqlite3_tokenizer_cursor *pC;   /* Tokenizer cursor open on zDoc/nDoc */
-  const char *ZDUMMY;             /* Dummy argument used with tokenizer */
-  int DUMMY1;                     /* Dummy argument used with tokenizer */
   
   zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
   if( zDoc==0 ){
@@ -130630,10 +134735,23 @@ static int fts3SnippetText(
   }
 
   while( rc==SQLITE_OK ){
-    int iBegin;                   /* Offset in zDoc of start of token */
-    int iFin;                     /* Offset in zDoc of end of token */
-    int isHighlight;              /* True for highlighted terms */
-
+    const char *ZDUMMY;           /* Dummy argument used with tokenizer */
+    int DUMMY1 = -1;              /* Dummy argument used with tokenizer */
+    int iBegin = 0;               /* Offset in zDoc of start of token */
+    int iFin = 0;                 /* Offset in zDoc of end of token */
+    int isHighlight = 0;          /* True for highlighted terms */
+
+    /* Variable DUMMY1 is initialized to a negative value above. Elsewhere
+    ** in the FTS code the variable that the third argument to xNext points to
+    ** is initialized to zero before the first (*but not necessarily
+    ** subsequent*) call to xNext(). This is done for a particular application
+    ** that needs to know whether or not the tokenizer is being used for
+    ** snippet generation or for some other purpose.
+    **
+    ** Extreme care is required when writing code to depend on this
+    ** initialization. It is not a documented part of the tokenizer interface.
+    ** If a tokenizer is used directly by any code outside of FTS, this
+    ** convention might not be respected.  */
     rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
     if( rc!=SQLITE_OK ){
       if( rc==SQLITE_DONE ){
@@ -131323,8 +135441,6 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
 ){
   Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
   sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
-  const char *ZDUMMY;             /* Dummy argument used with xNext() */
-  int NDUMMY;                     /* Dummy argument used with xNext() */
   int rc;                         /* Return Code */
   int nToken;                     /* Number of tokens in query */
   int iCol;                       /* Column currently being processed */
@@ -131357,9 +135473,11 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
   */
   for(iCol=0; iCol<pTab->nColumn; iCol++){
     sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
-    int iStart;
-    int iEnd;
-    int iCurrent;
+    const char *ZDUMMY;           /* Dummy argument used with xNext() */
+    int NDUMMY = 0;               /* Dummy argument used with xNext() */
+    int iStart = 0;
+    int iEnd = 0;
+    int iCurrent = 0;
     const char *zDoc;
     int nDoc;
 
@@ -131625,7 +135743,7 @@ static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
 **
 ** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
 ** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
-** It is not possible to change the behaviour of the tokenizer with respect
+** It is not possible to change the behavior of the tokenizer with respect
 ** to these codepoints.
 */
 static int unicodeAddExceptions(
@@ -134923,12 +139041,12 @@ static int newRowid(Rtree *pRtree, i64 *piRowid){
 */
 static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
   int rc;                         /* Return code */
-  RtreeNode *pLeaf;               /* Leaf node containing record iDelete */
+  RtreeNode *pLeaf = 0;           /* Leaf node containing record iDelete */
   int iCell;                      /* Index of iDelete cell in pLeaf */
   RtreeNode *pRoot;               /* Root node of rtree structure */
 
 
-  /* Obtain a reference to the root node to initialise Rtree.iDepth */
+  /* Obtain a reference to the root node to initialize Rtree.iDepth */
   rc = nodeAcquire(pRtree, 1, 0, &pRoot);
 
   /* Obtain a reference to the leaf node that contains the entry 
@@ -135126,7 +139244,7 @@ static int rtreeUpdate(
   */
   if( rc==SQLITE_OK && nData>1 ){
     /* Insert the new record into the r-tree */
-    RtreeNode *pLeaf;
+    RtreeNode *pLeaf = 0;
 
     /* Figure out the rowid of the new row. */
     if( bHaveRowid==0 ){
@@ -135312,7 +139430,8 @@ static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
 static int getNodeSize(
   sqlite3 *db,                    /* Database handle */
   Rtree *pRtree,                  /* Rtree handle */
-  int isCreate                    /* True for xCreate, false for xConnect */
+  int isCreate,                   /* True for xCreate, false for xConnect */
+  char **pzErr                    /* OUT: Error message, if any */
 ){
   int rc;
   char *zSql;
@@ -135325,6 +139444,8 @@ static int getNodeSize(
       if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
         pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
       }
+    }else{
+      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
     }
   }else{
     zSql = sqlite3_mprintf(
@@ -135332,6 +139453,9 @@ static int getNodeSize(
         pRtree->zDb, pRtree->zName
     );
     rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
+    if( rc!=SQLITE_OK ){
+      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+    }
   }
 
   sqlite3_free(zSql);
@@ -135395,7 +139519,7 @@ static int rtreeInit(
   memcpy(pRtree->zName, argv[2], nName);
 
   /* Figure out the node size to use. */
-  rc = getNodeSize(db, pRtree, isCreate);
+  rc = getNodeSize(db, pRtree, isCreate, pzErr);
 
   /* Create/Connect to the underlying relational database schema. If
   ** that is successful, call sqlite3_declare_vtab() to configure
@@ -136242,7 +140366,7 @@ static int icuOpen(
   nChar = nInput+1;
   pCsr = (IcuCursor *)sqlite3_malloc(
       sizeof(IcuCursor) +                /* IcuCursor */
-      nChar * sizeof(UChar) +            /* IcuCursor.aChar[] */
+      ((nChar+3)&~3) * sizeof(UChar) +   /* IcuCursor.aChar[] */
       (nChar+1) * sizeof(int)            /* IcuCursor.aOffset[] */
   );
   if( !pCsr ){
@@ -136250,7 +140374,7 @@ static int icuOpen(
   }
   memset(pCsr, 0, sizeof(IcuCursor));
   pCsr->aChar = (UChar *)&pCsr[1];
-  pCsr->aOffset = (int *)&pCsr->aChar[nChar];
+  pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
 
   pCsr->aOffset[iOut] = iInput;
   U8_NEXT(zInput, iInput, nInput, c); 
diff --git a/libgda/sqlite/sqlite-src/sqlite3.h b/libgda/sqlite/sqlite-src/sqlite3.h
index 5a1f9d4..e398838 100644
--- a/libgda/sqlite/sqlite-src/sqlite3.h
+++ b/libgda/sqlite/sqlite-src/sqlite3.h
@@ -107,9 +107,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.14.1"
-#define SQLITE_VERSION_NUMBER 3007014
-#define SQLITE_SOURCE_ID      "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
+#define SQLITE_VERSION        "3.7.17"
+#define SQLITE_VERSION_NUMBER 3007017
+#define SQLITE_SOURCE_ID      "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -288,7 +288,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** [sqlite3_blob_close | close] all [BLOB handles], and 
 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
-** sqlite3_close() is called on a [database connection] that still has
+** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
 ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
@@ -425,6 +425,8 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_FORMAT      24   /* Auxiliary database format error */
 #define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
 #define SQLITE_NOTADB      26   /* File opened that is not a database file */
+#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
+#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
 #define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
 #define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
 /* end-of-error-codes */
@@ -474,14 +476,29 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
 #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
+#define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
 #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
 #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
+#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
+#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -721,6 +738,9 @@ struct sqlite3_io_methods {
   void (*xShmBarrier)(sqlite3_file*);
   int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
   /* Methods above are valid for version 2 */
+  int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
+  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
+  /* Methods above are valid for version 3 */
   /* Additional methods may be added in future releases */
 };
 
@@ -855,6 +875,38 @@ struct sqlite3_io_methods {
 ** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
 ** file control occurs at the beginning of pragma statement analysis and so
 ** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^The [SQLITE_FCNTL_BUSYHANDLER]
+** file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
+** to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses.  The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()].  The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
+** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
+** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
+** maximum number of bytes that will be used for memory-mapped I/O.
+** The argument is a pointer to a value of type sqlite3_int64 that
+** is an advisory maximum number of bytes in the file to memory map.  The
+** pointer is overwritten with the old value.  The limit is not changed if
+** the value originally pointed to is negative, and so the current limit 
+** can be queried by passing in a pointer to a negative number.  This
+** file-control is used internally to implement [PRAGMA mmap_size].
+**
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -871,6 +923,9 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_VFSNAME                12
 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
 #define SQLITE_FCNTL_PRAGMA                 14
+#define SQLITE_FCNTL_BUSYHANDLER            15
+#define SQLITE_FCNTL_TEMPFILENAME           16
+#define SQLITE_FCNTL_MMAP_SIZE              18
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -1537,7 +1592,9 @@ struct sqlite3_mem_methods {
 ** page cache implementation into that object.)^ </dd>
 **
 ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
-** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
+** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
+** global [error log].
+** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
 ** function with a call signature of void(*)(void*,int,const char*), 
 ** and a pointer to void. ^If the function pointer is not NULL, it is
 ** invoked by [sqlite3_log()] to process each logging event.  ^If the
@@ -1567,10 +1624,54 @@ struct sqlite3_mem_methods {
 ** disabled. The default value may be changed by compiling with the
 ** [SQLITE_USE_URI] symbol defined.
 **
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer.  The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled.  Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
 ** <dd> These options are obsolete and should not be used by new code.
 ** They are retained for backwards compatibility but are now no-ops.
+** </dd>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.  An example of using this
+** configuration option can be seen in the "test_sqllog.c" source file in
+** the canonical SQLite source tree.</dd>
+**
+** [[SQLITE_CONFIG_MMAP_SIZE]]
+** <dt>SQLITE_CONFIG_MMAP_SIZE
+** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
+** that are the default mmap size limit (the default setting for
+** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
+** The default setting can be overridden by each database connection using
+** either the [PRAGMA mmap_size] command, or by using the
+** [SQLITE_FCNTL_MMAP_SIZE] file control.  The maximum allowed mmap size
+** cannot be changed at run-time.  Nor may the maximum allowed mmap size
+** exceed the compile-time maximum mmap size set by the
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.  
+** If either argument to this option is negative, then that argument is
+** changed to its compile-time default.
 ** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -1592,6 +1693,9 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_URI          17  /* int */
 #define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
 #define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
+#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
+#define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -2425,6 +2529,9 @@ SQLITE_API int sqlite3_set_authorizer(
 ** as each triggered subprogram is entered.  The callbacks for triggers
 ** contain a UTF-8 SQL comment that identifies the trigger.)^
 **
+** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit
+** the length of [bound parameter] expansion in the output of sqlite3_trace().
+**
 ** ^The callback function registered by sqlite3_profile() is invoked
 ** as each SQL statement finishes.  ^The profile callback contains
 ** the original statement text and an estimate of wall-clock time
@@ -2600,7 +2707,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     an error)^. 
 **     ^If "ro" is specified, then the database is opened for read-only 
 **     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
-**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
+**     third argument to sqlite3_open_v2(). ^If the mode option is set to 
 **     "rw", then the database is opened for read-write (but not create) 
 **     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
 **     been set. ^Value "rwc" is equivalent to setting both 
@@ -2616,7 +2723,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
 **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
-**     a URI filename, its value overrides any behaviour requested by setting
+**     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
 ** </ul>
 **
@@ -2752,6 +2859,11 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
 ** However, the error string might be overwritten or deallocated by
 ** subsequent calls to other SQLite interface functions.)^
 **
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
 ** When the serialized [threading mode] is in use, it might be the
 ** case that a second error occurs on a separate thread in between
 ** the time of the first error and the call to these interfaces.
@@ -2770,6 +2882,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db);
 SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
 SQLITE_API const char *sqlite3_errmsg(sqlite3*);
 SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
 
 /*
 ** CAPI3REF: SQL Statement Object
@@ -2957,7 +3070,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** <li>
 ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
 ** always used to do, [sqlite3_step()] will automatically recompile the SQL
-** statement and try to run it again.
+** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY]
+** retries will occur before sqlite3_step() gives up and returns an error.
 ** </li>
 **
 ** <li>
@@ -3161,6 +3275,9 @@ typedef struct sqlite3_context sqlite3_context;
 ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
 **
 ** ^The third argument is the value to bind to the parameter.
+** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
+** is ignored and the end result is the same as sqlite3_bind_null().
 **
 ** ^(In those routines that have a fourth argument, its value is the
 ** number of bytes in the parameter.  To be clear: the value is the
@@ -3928,7 +4045,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
 SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+                      void*,sqlite3_int64);
 #endif
 
 /*
@@ -4008,14 +4126,17 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** In those cases, sqlite3_aggregate_context() might be called for the
 ** first time from within xFinal().)^
 **
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is
-** less than or equal to zero or if a memory allocate error occurs.
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
 **
 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
 ** determined by the N parameter on first successful call.  Changing the
 ** value of N in subsequent call to sqlite3_aggregate_context() within
 ** the same aggregate function instance will not resize the memory
-** allocation.)^
+** allocation.)^  Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
+** pointless memory allocations occur.
 **
 ** ^SQLite automatically frees the memory allocated by 
 ** sqlite3_aggregate_context() when the aggregate query concludes.
@@ -4113,7 +4234,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
 ** the content before returning.
 **
 ** The typedef is necessary to work around problems in certain
-** C++ compilers.  See ticket #2191.
+** C++ compilers.
 */
 typedef void (*sqlite3_destructor_type)(void*);
 #define SQLITE_STATIC      ((sqlite3_destructor_type)0)
@@ -4732,6 +4853,9 @@ SQLITE_API void *sqlite3_update_hook(
 ** future releases of SQLite.  Applications that care about shared
 ** cache setting should set it explicitly.
 **
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
 ** See Also:  [SQLite Shared-Cache Mode]
 */
 SQLITE_API int sqlite3_enable_shared_cache(int);
@@ -4909,11 +5033,20 @@ SQLITE_API int sqlite3_table_column_metadata(
 ** ^This interface loads an SQLite extension library from the named file.
 **
 ** ^The sqlite3_load_extension() interface attempts to load an
-** SQLite extension library contained in the file zFile.
+** [SQLite extension] library contained in the file zFile.  If
+** the file cannot be loaded directly, attempts are made to load
+** with various operating-system specific extensions added.
+** So for example, if "samplelib" cannot be loaded, then names like
+** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
+** be tried also.
 **
 ** ^The entry point is zProc.
-** ^zProc may be 0, in which case the name of the entry point
-** defaults to "sqlite3_extension_init".
+** ^(zProc may be 0, in which case SQLite will try to come up with an
+** entry point name on its own.  It first tries "sqlite3_extension_init".
+** If that does not work, it constructs a name "sqlite3_X_init" where the
+** X is consists of the lower-case equivalent of all ASCII alphabetic
+** characters in the filename from the last "/" to the first following
+** "." and omitting any initial "lib".)^
 ** ^The sqlite3_load_extension() interface returns
 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
 ** ^If an error occurs and pzErrMsg is not 0, then the
@@ -4939,11 +5072,11 @@ SQLITE_API int sqlite3_load_extension(
 ** CAPI3REF: Enable Or Disable Extension Loading
 **
 ** ^So as not to open security holes in older applications that are
-** unprepared to deal with extension loading, and as a means of disabling
-** extension loading while evaluating user-entered SQL, the following API
+** unprepared to deal with [extension loading], and as a means of disabling
+** [extension loading] while evaluating user-entered SQL, the following API
 ** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
 **
-** ^Extension loading is off by default. See ticket #1863.
+** ^Extension loading is off by default.
 ** ^Call the sqlite3_enable_load_extension() routine with onoff==1
 ** to turn extension loading on and call it with onoff==0 to turn
 ** it back off again.
@@ -4955,7 +5088,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
 **
 ** ^This interface causes the xEntryPoint() function to be invoked for
 ** each new [database connection] that is created.  The idea here is that
-** xEntryPoint() is the entry point for a statically linked SQLite extension
+** xEntryPoint() is the entry point for a statically linked [SQLite extension]
 ** that is to be automatically loaded into all new database connections.
 **
 ** ^(Even though the function prototype shows that xEntryPoint() takes
@@ -6306,7 +6439,7 @@ struct sqlite3_pcache_page {
 ** parameter to help it determined what action to take:
 **
 ** <table border=1 width=85% align=center>
-** <tr><th> createFlag <th> Behaviour when page is not already in cache
+** <tr><th> createFlag <th> Behavior when page is not already in cache
 ** <tr><td> 0 <td> Do not allocate a new page.  Return NULL.
 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
 **                 Otherwise return NULL.
@@ -6736,9 +6869,24 @@ SQLITE_API int sqlite3_stricmp(const char *, const char *);
 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
 
 /*
+** CAPI3REF: String Globbing
+*
+** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches
+** the glob pattern P, and it returns non-zero if string X does not match
+** the glob pattern P.  ^The definition of glob pattern matching used in
+** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
+** SQL dialect used by SQLite.  ^The sqlite3_strglob(P,X) function is case
+** sensitive.
+**
+** Note that this routine returns zero on a match and non-zero if the strings
+** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
+*/
+SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
+
+/*
 ** CAPI3REF: Error Logging Interface
 **
-** ^The [sqlite3_log()] interface writes a message into the error log
+** ^The [sqlite3_log()] interface writes a message into the [error log]
 ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
 ** ^If logging is enabled, the zFormat string and subsequent arguments are
 ** used with [sqlite3_snprintf()] to generate the final output string.
diff --git a/providers/sqlcipher/sqlcipher.patch b/providers/sqlcipher/sqlcipher.patch
index 81128dc..047ef67 100644
--- a/providers/sqlcipher/sqlcipher.patch
+++ b/providers/sqlcipher/sqlcipher.patch
@@ -1,6 +1,6 @@
---- sqlite3.c.sqlite   2012-12-22 18:15:17.484622846 +0100
-+++ sqlite3.c  2012-12-22 18:14:44.407175450 +0100
-@@ -12317,9 +12317,47 @@
+--- sqlite3.c.sqlite   2013-06-30 15:20:58.230969175 +0200
++++ sqlite3.c  2013-06-30 15:14:57.082959321 +0200
+@@ -12585,9 +12585,45 @@
  #endif /* _SQLITEINT_H_ */
  
  /************** End of sqliteInt.h *******************************************/
@@ -8,11 +8,9 @@
 +/************** Begin file crypto.c ******************************************/
 +/* 
 +** SQLCipher
-+** crypto.c developed by Stephen Lombardo (Zetetic LLC) 
-+** sjlombardo at zetetic dot net
-+** http://zetetic.net
++** http://sqlcipher.net
 +** 
-+** Copyright (c) 2009, ZETETIC LLC
++** Copyright (c) 2008 - 2013, ZETETIC LLC
 +** All rights reserved.
 +** 
 +** Redistribution and use in source and binary forms, with or without
@@ -38,7 +36,7 @@
 +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +**  
 +*/
-+/* BEGIN CRYPTO */
++/* BEGIN SQLCIPHER */
 +#ifdef SQLITE_HAS_CODEC
 +
 +/* #include <assert.h> */
@@ -50,7 +48,7 @@
  **
  ** The author disclaims copyright to this source code.  In place of
  ** a legal notice, here is a blessing:
-@@ -12329,220 +12367,2496 @@
+@@ -12597,3032 +12633,3163 @@
  **    May you share freely, never taking more than you give.
  **
  *************************************************************************
@@ -337,7 +335,7 @@
 -  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 28..2f    ()*+,-./ */
 -  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,  /* 30..37    01234567 */
 -  0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 38..3f    89:;<=>? */
- 
+-
 -  0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02,  /* 40..47    @ABCDEFG */
 -  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  /* 48..4f    HIJKLMNO */
 -  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  /* 50..57    PQRSTUVW */
@@ -355,10 +353,6 @@
 -  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* a8..af    ........ */
 -  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* b0..b7    ........ */
 -  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* b8..bf    ........ */
-+/* The following value is the maximum cell size assuming a maximum page
-+** size give above.
-+*/
-+#define MX_CELL_SIZE(pBt)  ((int)(pBt->pageSize-8))
  
 -  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* c0..c7    ........ */
 -  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* c8..cf    ........ */
@@ -370,6 +364,14 @@
 -  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
 -};
 -#endif
++/* The following value is the maximum cell size assuming a maximum page
++** size give above.
++*/
++#define MX_CELL_SIZE(pBt)  ((int)(pBt->pageSize-8))
+ 
+-#ifndef SQLITE_USE_URI
+-# define  SQLITE_USE_URI 0
+-#endif
 +/* The maximum number of cells on a single page of the database.  This
 +** assumes a minimum cell size of 6 bytes  (4 bytes for the cell itself
 +** plus 2 bytes for the index to the cell in the page header).  Such
@@ -377,13 +379,16 @@
 +*/
 +#define MX_CELL(pBt) ((pBt->pageSize-8)/6)
  
--#ifndef SQLITE_USE_URI
--# define  SQLITE_USE_URI 0
+-#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+-# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+-#endif
 +/* Forward declarations */
 +typedef struct MemPage MemPage;
 +typedef struct BtLock BtLock;
-+
-+/*
+ 
+ /*
+-** The following singleton contains the global configuration for
+-** the SQLite library.
 +** This is a magic string that appears at the beginning of every
 +** SQLite database in order to identify the file as a real database.
 +**
@@ -394,22 +399,13 @@
 +** the header, then your custom library will not be able to read 
 +** databases generated by the standard tools and the standard tools
 +** will not be able to read databases created by your custom library.
-+*/
-+#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
-+#  define SQLITE_FILE_HEADER "SQLite format 3"
- #endif
- 
- /*
--** The following singleton contains the global configuration for
--** the SQLite library.
-+** Page type flags.  An ORed combination of these flags appear as the
-+** first byte of on-disk image of every BTree page.
  */
 -SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
 -   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
 -   1,                         /* bCoreMutex */
 -   SQLITE_THREADSAFE==1,      /* bFullMutex */
 -   SQLITE_USE_URI,            /* bOpenUri */
+-   SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
 -   0x7ffffffe,                /* mxStrlen */
 -   128,                       /* szLookaside */
 -   500,                       /* nLookaside */
@@ -419,6 +415,8 @@
 -   (void*)0,                  /* pHeap */
 -   0,                         /* nHeap */
 -   0, 0,                      /* mnHeap, mxHeap */
+-   SQLITE_DEFAULT_MMAP_SIZE,  /* szMmap */
+-   SQLITE_MAX_MMAP_SIZE,      /* mxMmap */
 -   (void*)0,                  /* pScratch */
 -   0,                         /* szScratch */
 -   0,                         /* nScratch */
@@ -438,13 +436,30 @@
 -   0,                         /* xLog */
 -   0,                         /* pLogArg */
 -   0,                         /* bLocaltimeFault */
+-#ifdef SQLITE_ENABLE_SQLLOG
+-   0,                         /* xSqllog */
+-   0                          /* pSqllogArg */
++#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
++#  define SQLITE_FILE_HEADER "SQLite format 3"
+ #endif
 -};
+-
+ 
+ /*
+-** Hash table for global functions - functions common to all
+-** database connections.  After initialization, this table is
+-** read-only.
++** Page type flags.  An ORed combination of these flags appear as the
++** first byte of on-disk image of every BTree page.
+ */
+-SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
 +#define PTF_INTKEY    0x01
 +#define PTF_ZERODATA  0x02
 +#define PTF_LEAFDATA  0x04
 +#define PTF_LEAF      0x08
  
-+/*
+ /*
+-** Constant tokens for values 0 and 1.
 +** As each page of the file is loaded into memory, an instance of the following
 +** structure is appended and initialized to zero.  This structure stores
 +** information about the page that is decoded from the raw file page.
@@ -456,7 +471,10 @@
 +**
 +** Access to all fields of this structure is controlled by the mutex
 +** stored in MemPage.pBt->mutex.
-+*/
+ */
+-SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
+-   { "0", 1 },
+-   { "1", 1 }
 +struct MemPage {
 +  u8 isInit;           /* True if previously initialized. MUST BE FIRST! */
 +  u8 nOverflow;        /* Number of overflow cell bodies in aCell[] */
@@ -481,79 +499,95 @@
 +  u8 *aCellIdx;        /* The cell index area */
 +  DbPage *pDbPage;     /* Pager page handle */
 +  Pgno pgno;           /* Page number for this page */
-+};
+ };
  
+-
  /*
--** Hash table for global functions - functions common to all
--** database connections.  After initialization, this table is
--** read-only.
+-** The value of the "pending" byte must be 0x40000000 (1 byte past the
+-** 1-gibabyte boundary) in a compatible database.  SQLite never uses
+-** the database page that contains the pending byte.  It never attempts
+-** to read or write that page.  The pending byte page is set assign
+-** for use by the VFS layers as space for managing file locks.
+-**
+-** During testing, it is often desirable to move the pending byte to
+-** a different position in the file.  This allows code that has to
+-** deal with the pending byte to run on files that are much smaller
+-** than 1 GiB.  The sqlite3_test_control() interface can be used to
+-** move the pending byte.
+-**
+-** IMPORTANT:  Changing the pending byte to any value other than
+-** 0x40000000 results in an incompatible database file format!
+-** Changing the pending byte during operating results in undefined
+-** and dileterious behavior.
 +** The in-memory image of a disk page has the auxiliary information appended
 +** to the end.  EXTRA_SIZE is the number of bytes of space needed to hold
 +** that extra information.
  */
--SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
+-#ifndef SQLITE_OMIT_WSD
+-SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
+-#endif
 +#define EXTRA_SIZE sizeof(MemPage)
  
  /*
--** Constant tokens for values 0 and 1.
+-** Properties of opcodes.  The OPFLG_INITIALIZER macro is
+-** created by mkopcodeh.awk during compilation.  Data is obtained
+-** from the comments following the "case OP_xxxx:" statements in
+-** the vdbe.c file.  
 +** A linked list of the following structures is stored at BtShared.pLock.
 +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor 
 +** is opened on the table with root page BtShared.iTable. Locks are removed
 +** from this list when a transaction is committed or rolled back, or when
 +** a btree handle is closed.
  */
--SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
--   { "0", 1 },
--   { "1", 1 }
+-SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
 +struct BtLock {
 +  Btree *pBtree;        /* Btree handle holding this lock */
 +  Pgno iTable;          /* Root page of table */
 +  u8 eLock;             /* READ_LOCK or WRITE_LOCK */
 +  BtLock *pNext;        /* Next in BtShared.pLock list */
- };
++};
  
+-/************** End of global.c **********************************************/
+-/************** Begin file ctime.c *******************************************/
+-/*
+-** 2010 February 23
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
 +/* Candidate values for BtLock.eLock */
 +#define READ_LOCK     1
 +#define WRITE_LOCK    2
- 
--/*
--** The value of the "pending" byte must be 0x40000000 (1 byte past the
--** 1-gibabyte boundary) in a compatible database.  SQLite never uses
--** the database page that contains the pending byte.  It never attempts
--** to read or write that page.  The pending byte page is set assign
--** for use by the VFS layers as space for managing file locks.
++
 +/* A Btree handle
  **
--** During testing, it is often desirable to move the pending byte to
--** a different position in the file.  This allows code that has to
--** deal with the pending byte to run on files that are much smaller
--** than 1 GiB.  The sqlite3_test_control() interface can be used to
--** move the pending byte.
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
 +** A database connection contains a pointer to an instance of
 +** this object for every database file that it has open.  This structure
 +** is opaque to the database connection.  The database connection cannot
 +** see the internals of this structure and only deals with pointers to
 +** this structure.
  **
--** IMPORTANT:  Changing the pending byte to any value other than
--** 0x40000000 results in an incompatible database file format!
--** Changing the pending byte during operating results in undefined
--** and dileterious behavior.
+-*************************************************************************
 +** For some database files, the same underlying database cache might be 
 +** shared between multiple connections.  In that case, each connection
 +** has it own instance of this object.  But each instance of this object
 +** points to the same BtShared object.  The database cache and the
 +** schema associated with the database file are all contained within
 +** the BtShared object.
-+**
+ **
+-** This file implements routines used to report what compile-time options
+-** SQLite was built with.
 +** All fields in this structure are accessed under sqlite3.mutex.
 +** The pBt pointer itself may not be changed while there exists cursors 
 +** in the referenced BtShared that point back to this Btree since those
 +** cursors have to go through this Btree to find their BtShared and
 +** they often do so without holding sqlite3.mutex.
  */
--#ifndef SQLITE_OMIT_WSD
--SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
+-
+-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+-
 +struct Btree {
 +  sqlite3 *db;       /* The database connection holding this btree */
 +  BtShared *pBt;     /* Sharable content of this btree */
@@ -566,30 +600,112 @@
 +  Btree *pPrev;      /* Back pointer of the same list */
 +#ifndef SQLITE_OMIT_SHARED_CACHE
 +  BtLock lock;       /* Object used to lock page 1 */
- #endif
++#endif
 +};
  
  /*
--** Properties of opcodes.  The OPFLG_INITIALIZER macro is
--** created by mkopcodeh.awk during compilation.  Data is obtained
--** from the comments following the "case OP_xxxx:" statements in
--** the vdbe.c file.  
+-** An array of names of all compile-time options.  This array should 
+-** be sorted A-Z.
 +** Btree.inTrans may take one of the following values.
-+**
+ **
+-** This array looks large, but in a typical installation actually uses
+-** only a handful of compile-time options, so most times this array is usually
+-** rather short and uses little memory space.
 +** If the shared-data extension is enabled, there may be multiple users
 +** of the Btree structure. At most one of these may open a write transaction,
 +** but any number may have active read transactions.
  */
--SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
+-static const char * const azCompileOpt[] = {
+-
+-/* These macros are provided to "stringify" the value of the define
+-** for those options in which the value is meaningful. */
+-#define CTIMEOPT_VAL_(opt) #opt
+-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
 +#define TRANS_NONE  0
 +#define TRANS_READ  1
 +#define TRANS_WRITE 2
  
--/************** End of global.c **********************************************/
--/************** Begin file ctime.c *******************************************/
- /*
--** 2010 February 23
--**
+-#ifdef SQLITE_32BIT_ROWID
+-  "32BIT_ROWID",
+-#endif
+-#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+-  "4_BYTE_ALIGNED_MALLOC",
+-#endif
+-#ifdef SQLITE_CASE_SENSITIVE_LIKE
+-  "CASE_SENSITIVE_LIKE",
+-#endif
+-#ifdef SQLITE_CHECK_PAGES
+-  "CHECK_PAGES",
+-#endif
+-#ifdef SQLITE_COVERAGE_TEST
+-  "COVERAGE_TEST",
+-#endif
+-#ifdef SQLITE_DEBUG
+-  "DEBUG",
+-#endif
+-#ifdef SQLITE_DEFAULT_LOCKING_MODE
+-  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
+-#endif
+-#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
+-  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
+-#endif
+-#ifdef SQLITE_DISABLE_DIRSYNC
+-  "DISABLE_DIRSYNC",
+-#endif
+-#ifdef SQLITE_DISABLE_LFS
+-  "DISABLE_LFS",
+-#endif
+-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+-  "ENABLE_ATOMIC_WRITE",
+-#endif
+-#ifdef SQLITE_ENABLE_CEROD
+-  "ENABLE_CEROD",
+-#endif
+-#ifdef SQLITE_ENABLE_COLUMN_METADATA
+-  "ENABLE_COLUMN_METADATA",
+-#endif
+-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+-  "ENABLE_EXPENSIVE_ASSERT",
+-#endif
+-#ifdef SQLITE_ENABLE_FTS1
+-  "ENABLE_FTS1",
+-#endif
+-#ifdef SQLITE_ENABLE_FTS2
+-  "ENABLE_FTS2",
+-#endif
+-#ifdef SQLITE_ENABLE_FTS3
+-  "ENABLE_FTS3",
+-#endif
+-#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+-  "ENABLE_FTS3_PARENTHESIS",
+-#endif
+-#ifdef SQLITE_ENABLE_FTS4
+-  "ENABLE_FTS4",
+-#endif
+-#ifdef SQLITE_ENABLE_ICU
+-  "ENABLE_ICU",
+-#endif
+-#ifdef SQLITE_ENABLE_IOTRACE
+-  "ENABLE_IOTRACE",
+-#endif
+-#ifdef SQLITE_ENABLE_LOAD_EXTENSION
+-  "ENABLE_LOAD_EXTENSION",
+-#endif
+-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+-  "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
+-#endif
+-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+-  "ENABLE_MEMORY_MANAGEMENT",
+-#endif
+-#ifdef SQLITE_ENABLE_MEMSYS3
+-  "ENABLE_MEMSYS3",
+-#endif
+-#ifdef SQLITE_ENABLE_MEMSYS5
+-  "ENABLE_MEMSYS5",
+-#endif
+-#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
+-  "ENABLE_OVERSIZE_CELL_CHECK",
++/*
 +** An instance of this object represents a single database file.
 +** 
 +** A single database file can be in use at the same time by two
@@ -633,7 +749,10 @@
 +#ifndef SQLITE_OMIT_AUTOVACUUM
 +  u8 autoVacuum;        /* True if auto-vacuum is enabled */
 +  u8 incrVacuum;        /* True if incr-vacuum is enabled */
-+#endif
++  u8 bDoTruncate;       /* True to truncate db on commit */
+ #endif
+-#ifdef SQLITE_ENABLE_RTREE
+-  "ENABLE_RTREE",
 +  u8 inTransaction;     /* Transaction state */
 +  u8 max1bytePayload;   /* Maximum first byte of cell for a 1-byte payload */
 +  u16 btsFlags;         /* Boolean parameters.  See BTS_* macros below */
@@ -654,7 +773,9 @@
 +  BtShared *pNext;      /* Next on a list of sharable BtShared structs */
 +  BtLock *pLock;        /* List of locks held on this shared-btree struct */
 +  Btree *pWriter;       /* Btree with currently open write transaction */
-+#endif
+ #endif
+-#ifdef SQLITE_ENABLE_STAT3
+-  "ENABLE_STAT3",
 +  u8 *pTmpSpace;        /* BtShared.pageSize bytes of space for tmp use */
 +};
 +
@@ -718,7 +839,9 @@
 +  struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
 +#ifndef SQLITE_OMIT_INCRBLOB
 +  Pgno *aOverflow;          /* Cache of overflow page locations */
-+#endif
+ #endif
+-#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+-  "ENABLE_UNLOCK_NOTIFY",
 +  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 */
@@ -731,7 +854,9 @@
 +  u8 eState;                /* One of the CURSOR_XXX constants (see below) */
 +#ifndef SQLITE_OMIT_INCRBLOB
 +  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
-+#endif
+ #endif
+-#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+-  "ENABLE_UPDATE_DELETE_LIMIT",
 +  u8 hints;                             /* As configured by CursorSetHints() */
 +  i16 iPage;                            /* Index of current page in apPage */
 +  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
@@ -848,7 +973,7 @@
 +#define ISAUTOVACUUM (pBt->autoVacuum)
 +#else
 +#define ISAUTOVACUUM 0
-+#endif
+ #endif
 +
 +
 +/*
@@ -917,20 +1042,51 @@
 +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +**  
 +*/
-+/* BEGIN CRYPTO */
-+#ifdef SQLITE_HAS_CODEC
++/* BEGIN SQLCIPHER */
+ #ifdef SQLITE_HAS_CODEC
+-  "HAS_CODEC",
+-#endif
+-#ifdef SQLITE_HAVE_ISNAN
+-  "HAVE_ISNAN",
+-#endif
+-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+-  "HOMEGROWN_RECURSIVE_MUTEX",
+-#endif
+-#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+-  "IGNORE_AFP_LOCK_ERRORS",
+-#endif
+-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+-  "IGNORE_FLOCK_LOCK_ERRORS",
+-#endif
+-#ifdef SQLITE_INT64_TYPE
+-  "INT64_TYPE",
+-#endif
+-#ifdef SQLITE_LOCK_TRACE
+-  "LOCK_TRACE",
 +#ifndef CRYPTO_H
 +#define CRYPTO_H
 +
++#if !defined (SQLCIPHER_CRYPTO_CC) \
++   && !defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT) \
++   && !defined (SQLCIPHER_CRYPTO_OPENSSL)
++#define SQLCIPHER_CRYPTO_OPENSSL
+ #endif
+-#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
+-  "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
++
 +#define FILE_HEADER_SZ 16
 +
 +#ifndef CIPHER_VERSION
-+#define CIPHER_VERSION "2.1.1"
-+#endif
++#define CIPHER_VERSION "2.2.0"
+ #endif
+-#ifdef SQLITE_MAX_SCHEMA_RETRY
+-  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
 +
 +#ifndef CIPHER
 +#define CIPHER "aes-256-cbc"
-+#endif
+ #endif
+-#ifdef SQLITE_MEMDEBUG
+-  "MEMDEBUG",
 +
 +#define CIPHER_DECRYPT 0
 +#define CIPHER_ENCRYPT 1
@@ -941,7 +1097,9 @@
 +
 +#ifndef PBKDF2_ITER
 +#define PBKDF2_ITER 4000
-+#endif
+ #endif
+-#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+-  "MIXED_ENDIAN_64BIT_FLOAT",
 +
 +/* possible flags for cipher_ctx->flags */
 +#define CIPHER_FLAG_HMAC          0x01
@@ -950,7 +1108,9 @@
 +
 +#ifndef DEFAULT_CIPHER_FLAGS
 +#define DEFAULT_CIPHER_FLAGS CIPHER_FLAG_HMAC | CIPHER_FLAG_LE_PGNO
-+#endif
+ #endif
+-#ifdef SQLITE_NO_SYNC
+-  "NO_SYNC",
 +
 +
 +/* by default, sqlcipher will use a reduced number of iterations to generate
@@ -958,7 +1118,9 @@
 +   */
 +#ifndef FAST_PBKDF2_ITER
 +#define FAST_PBKDF2_ITER 2
-+#endif
+ #endif
+-#ifdef SQLITE_OMIT_ALTERTABLE
+-  "OMIT_ALTERTABLE",
 +
 +/* this if a fixed random array that will be xor'd with the database salt to ensure that the
 +   salt passed to the HMAC key derivation function is not the same as that used to derive
@@ -967,13 +1129,30 @@
 +   will likely allow this to be defined at runtime via pragma */ 
 +#ifndef HMAC_SALT_MASK
 +#define HMAC_SALT_MASK 0x3a
-+#endif
+ #endif
+-#ifdef SQLITE_OMIT_ANALYZE
+-  "OMIT_ANALYZE",
++
++#ifndef CIPHER_MAX_IV_SZ
++#define CIPHER_MAX_IV_SZ 16
+ #endif
+-#ifdef SQLITE_OMIT_ATTACH
+-  "OMIT_ATTACH",
++
++#ifndef CIPHER_MAX_KEY_SZ
++#define CIPHER_MAX_KEY_SZ 64
+ #endif
+-#ifdef SQLITE_OMIT_AUTHORIZATION
+-  "OMIT_AUTHORIZATION",
++
 +
 +#ifdef CODEC_DEBUG
 +#define CODEC_TRACE(X)  {printf X;fflush(stdout);}
 +#else
 +#define CODEC_TRACE(X)
-+#endif
+ #endif
+-#ifdef SQLITE_OMIT_AUTOINCREMENT
+-  "OMIT_AUTOINCREMENT",
 +
 +#ifdef CODEC_DEBUG_PAGEDATA
 +#define CODEC_HEXDUMP(DESC,BUFFER,LEN)  \
@@ -989,7 +1168,9 @@
 +  }
 +#else
 +#define CODEC_HEXDUMP(DESC,BUFFER,LEN)
-+#endif
+ #endif
+-#ifdef SQLITE_OMIT_AUTOINIT
+-  "OMIT_AUTOINIT",
 +
 +/* extensions defined in pager.c */ 
 +SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx);
@@ -1022,16 +1203,8 @@
 +}
 +
 +/* extensions defined in crypto_impl.c */
-+
 +typedef struct codec_ctx codec_ctx;
 +
-+/* utility functions */
-+void* sqlcipher_memset(void *v, unsigned char value, int len);
-+int sqlcipher_ismemset(const void *v, unsigned char value, int len);
-+int sqlcipher_memcmp(const void *v0, const void *v1, int len);
-+int sqlcipher_pseudorandom(void *, int);
-+void sqlcipher_free(void *, int);
-+
 +/* activation and initialization */
 +void sqlcipher_activate();
 +void sqlcipher_deactivate();
@@ -1081,21 +1254,221 @@
 +int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag);
 +int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx);
 +
-+/* end extensions defined in crypto_impl.c */
-+
-+#endif
-+#endif
-+/* END CRYPTO */
-+
++const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
+ #endif
+-#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
+-  "OMIT_AUTOMATIC_INDEX",
+ #endif
+-#ifdef SQLITE_OMIT_AUTORESET
+-  "OMIT_AUTORESET",
+-#endif
+-#ifdef SQLITE_OMIT_AUTOVACUUM
+-  "OMIT_AUTOVACUUM",
+-#endif
+-#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+-  "OMIT_BETWEEN_OPTIMIZATION",
+-#endif
+-#ifdef SQLITE_OMIT_BLOB_LITERAL
+-  "OMIT_BLOB_LITERAL",
+-#endif
+-#ifdef SQLITE_OMIT_BTREECOUNT
+-  "OMIT_BTREECOUNT",
+-#endif
+-#ifdef SQLITE_OMIT_BUILTIN_TEST
+-  "OMIT_BUILTIN_TEST",
+-#endif
+-#ifdef SQLITE_OMIT_CAST
+-  "OMIT_CAST",
+-#endif
+-#ifdef SQLITE_OMIT_CHECK
+-  "OMIT_CHECK",
+-#endif
+-#ifdef SQLITE_OMIT_COMPLETE
+-  "OMIT_COMPLETE",
+-#endif
+-#ifdef SQLITE_OMIT_COMPOUND_SELECT
+-  "OMIT_COMPOUND_SELECT",
+-#endif
+-#ifdef SQLITE_OMIT_DATETIME_FUNCS
+-  "OMIT_DATETIME_FUNCS",
+-#endif
+-#ifdef SQLITE_OMIT_DECLTYPE
+-  "OMIT_DECLTYPE",
+-#endif
+-#ifdef SQLITE_OMIT_DEPRECATED
+-  "OMIT_DEPRECATED",
+-#endif
+-#ifdef SQLITE_OMIT_DISKIO
+-  "OMIT_DISKIO",
+-#endif
+-#ifdef SQLITE_OMIT_EXPLAIN
+-  "OMIT_EXPLAIN",
+-#endif
+-#ifdef SQLITE_OMIT_FLAG_PRAGMAS
+-  "OMIT_FLAG_PRAGMAS",
+-#endif
+-#ifdef SQLITE_OMIT_FLOATING_POINT
+-  "OMIT_FLOATING_POINT",
+-#endif
+-#ifdef SQLITE_OMIT_FOREIGN_KEY
+-  "OMIT_FOREIGN_KEY",
+-#endif
+-#ifdef SQLITE_OMIT_GET_TABLE
+-  "OMIT_GET_TABLE",
+-#endif
+-#ifdef SQLITE_OMIT_INCRBLOB
+-  "OMIT_INCRBLOB",
+-#endif
+-#ifdef SQLITE_OMIT_INTEGRITY_CHECK
+-  "OMIT_INTEGRITY_CHECK",
+-#endif
+-#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
+-  "OMIT_LIKE_OPTIMIZATION",
+-#endif
+-#ifdef SQLITE_OMIT_LOAD_EXTENSION
+-  "OMIT_LOAD_EXTENSION",
+-#endif
+-#ifdef SQLITE_OMIT_LOCALTIME
+-  "OMIT_LOCALTIME",
+-#endif
+-#ifdef SQLITE_OMIT_LOOKASIDE
+-  "OMIT_LOOKASIDE",
+-#endif
+-#ifdef SQLITE_OMIT_MEMORYDB
+-  "OMIT_MEMORYDB",
+-#endif
+-#ifdef SQLITE_OMIT_OR_OPTIMIZATION
+-  "OMIT_OR_OPTIMIZATION",
+-#endif
+-#ifdef SQLITE_OMIT_PAGER_PRAGMAS
+-  "OMIT_PAGER_PRAGMAS",
+-#endif
+-#ifdef SQLITE_OMIT_PRAGMA
+-  "OMIT_PRAGMA",
+-#endif
+-#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+-  "OMIT_PROGRESS_CALLBACK",
+-#endif
+-#ifdef SQLITE_OMIT_QUICKBALANCE
+-  "OMIT_QUICKBALANCE",
+-#endif
+-#ifdef SQLITE_OMIT_REINDEX
+-  "OMIT_REINDEX",
+-#endif
+-#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
+-  "OMIT_SCHEMA_PRAGMAS",
+-#endif
+-#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+-  "OMIT_SCHEMA_VERSION_PRAGMAS",
+-#endif
+-#ifdef SQLITE_OMIT_SHARED_CACHE
+-  "OMIT_SHARED_CACHE",
+-#endif
+-#ifdef SQLITE_OMIT_SUBQUERY
+-  "OMIT_SUBQUERY",
+-#endif
+-#ifdef SQLITE_OMIT_TCL_VARIABLE
+-  "OMIT_TCL_VARIABLE",
+-#endif
+-#ifdef SQLITE_OMIT_TEMPDB
+-  "OMIT_TEMPDB",
+-#endif
+-#ifdef SQLITE_OMIT_TRACE
+-  "OMIT_TRACE",
+-#endif
+-#ifdef SQLITE_OMIT_TRIGGER
+-  "OMIT_TRIGGER",
+-#endif
+-#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+-  "OMIT_TRUNCATE_OPTIMIZATION",
+-#endif
+-#ifdef SQLITE_OMIT_UTF16
+-  "OMIT_UTF16",
+-#endif
+-#ifdef SQLITE_OMIT_VACUUM
+-  "OMIT_VACUUM",
+-#endif
+-#ifdef SQLITE_OMIT_VIEW
+-  "OMIT_VIEW",
+-#endif
+-#ifdef SQLITE_OMIT_VIRTUALTABLE
+-  "OMIT_VIRTUALTABLE",
+-#endif
+-#ifdef SQLITE_OMIT_WAL
+-  "OMIT_WAL",
+-#endif
+-#ifdef SQLITE_OMIT_WSD
+-  "OMIT_WSD",
+-#endif
+-#ifdef SQLITE_OMIT_XFER_OPT
+-  "OMIT_XFER_OPT",
+-#endif
+-#ifdef SQLITE_PERFORMANCE_TRACE
+-  "PERFORMANCE_TRACE",
+-#endif
+-#ifdef SQLITE_PROXY_DEBUG
+-  "PROXY_DEBUG",
+-#endif
+-#ifdef SQLITE_RTREE_INT_ONLY
+-  "RTREE_INT_ONLY",
+-#endif
+-#ifdef SQLITE_SECURE_DELETE
+-  "SECURE_DELETE",
+-#endif
+-#ifdef SQLITE_SMALL_STACK
+-  "SMALL_STACK",
+-#endif
+-#ifdef SQLITE_SOUNDEX
+-  "SOUNDEX",
+-#endif
+-#ifdef SQLITE_TCL
+-  "TCL",
+-#endif
+-#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
+-  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
+-#endif
+-#ifdef SQLITE_TEST
+-  "TEST",
+-#endif
+-#if defined(SQLITE_THREADSAFE)
+-  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
+-#endif
+-#ifdef SQLITE_USE_ALLOCA
+-  "USE_ALLOCA",
+-#endif
+-#ifdef SQLITE_ZERO_MALLOC
+-  "ZERO_MALLOC"
+-#endif
+-};
++/* END SQLCIPHER */
+ 
+-/*
+-** Given the name of a compile-time option, return true if that option
+-** was used and false if not.
+-**
+-** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
+-** is not required for a match.
+-*/
+-SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
+-  int i, n;
+-  if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
+-  n = sqlite3Strlen30(zOptName);
 +/************** End of crypto.h **********************************************/
 +/************** Continuing where we left off in crypto.c *********************/
-+
-+const char* codec_get_cipher_version() {
+ 
+-  /* Since ArraySize(azCompileOpt) is normally in single digits, a
+-  ** linear search is adequate.  No need for a binary search. */
+-  for(i=0; i<ArraySize(azCompileOpt); i++){
+-    if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
+-     && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
+-    ){
+-      return 1;
++static const char* codec_get_cipher_version() {
 +  return CIPHER_VERSION;
 +}
 +
 +/* Generate code to return a string value */
-+void codec_vdbe_return_static_string(Parse *pParse, const char *zLabel, const char *value){
++static void codec_vdbe_return_static_string(Parse *pParse, const char *zLabel, const char *value){
 +  Vdbe *v = sqlite3GetVdbe(pParse);
 +  sqlite3VdbeSetNumCols(v, 1);
 +  sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
@@ -1121,7 +1494,7 @@
 +  return rc;
 +}
 +
-+int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
++static int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
 +  struct Db *pDb = &db->aDb[nDb];
 +  CODEC_TRACE(("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char 
*)zKey, nKey, for_ctx));
 +  if(pDb->pBt) {
@@ -1143,6 +1516,11 @@
 +
 +  CODEC_TRACE(("codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, 
zLeft, zRight, ctx));
 +
++  if( sqlite3StrICmp(zLeft, "cipher_provider")==0 && !zRight ){
++    if(ctx) { codec_vdbe_return_static_string(pParse, "cipher_provider",
++                                              sqlcipher_codec_get_cipher_provider(ctx));
++    }
++  } else
 +  if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){
 +    codec_vdbe_return_static_string(pParse, "cipher_version", codec_get_cipher_version());
 +  }else
@@ -1262,14 +1640,21 @@
 +          codec_vdbe_return_static_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask);
 +          sqlite3_free(hmac_salt_mask);
 +      }
-+    }
+     }
 +  }else {
 +    return 0;
-+  }
+   }
+-  return 0;
 +  return 1;
-+}
-+
-+/*
+ }
+ 
+ /*
+-** Return the N-th compile-time option string.  If N is out of range,
+-** return a NULL pointer.
+-*/
+-SQLITE_API const char *sqlite3_compileoption_get(int N){
+-  if( N>=0 && N<ArraySize(azCompileOpt) ){
+-    return azCompileOpt[N];
 + * sqlite3Codec can be called in multiple modes.
 + * encrypt mode - expected to return a pointer to the 
 + *   encrypted data without altering pData.
@@ -1319,9 +1704,11 @@
 +    default:
 +      return pData;
 +      break;
-+  }
-+}
-+
+   }
+-  return 0;
+ }
+ 
+-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
 +SQLITE_PRIVATE void sqlite3FreeCodecArg(void *pCodecArg) {
 +  codec_ctx *ctx = (codec_ctx *) pCodecArg;
 +  if(pCodecArg == NULL) return;
@@ -1343,13 +1730,13 @@
 +
 +    sqlcipher_activate(); /* perform internal initialization for sqlcipher */
 +
++    sqlite3_mutex_enter(db->mutex);
++
 +    /* point the internal codec argument against the contet to be prepared */
 +    rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey); 
 +
 +    if(rc != SQLITE_OK) return rc; /* initialization failed, do not attach potentially corrupted context */
 +
-+    sqlite3_mutex_enter(db->mutex);
-+
 +    sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, 
(void *) ctx);
 +
 +    codec_set_btree_to_codec_pagesize(db, pDb, ctx);
@@ -1475,19 +1862,336 @@
 +  }
 +}
 +
++#ifndef OMIT_EXPORT
+ 
+-/************** End of ctime.c ***********************************************/
+-/************** Begin file status.c ******************************************/
+ /*
+-** 2008 June 18
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-**
+-** This module implements the sqlite3_status() interface and related
+-** functionality.
+-*/
+-/************** Include vdbeInt.h in the middle of status.c ******************/
+-/************** Begin file vdbeInt.h *****************************************/
++ * Implementation of an "export" function that allows a caller
++ * to duplicate the main database to an attached database. This is intended
++ * as a conveneince for users who need to:
++ * 
++ *   1. migrate from an non-encrypted database to an encrypted database
++ *   2. move from an encrypted database to a non-encrypted database
++ *   3. convert beween the various flavors of encrypted databases.  
++ *
++ * This implementation is based heavily on the procedure and code used
++ * in vacuum.c, but is exposed as a function that allows export to any
++ * named attached database.
++ */
 +
-+/* END CRYPTO */
-+#endif
+ /*
+-** 2003 September 6
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-** This is the header file for information that is private to the
+-** VDBE.  This information used to all be at the top of the single
+-** source code file "vdbe.c".  When that file became too big (over
+-** 6000 lines long) it was split up into several smaller files and
+-** this header information was factored out.
++** Finalize a prepared statement.  If there was an error, store the
++** text of the error message in *pzErrMsg.  Return the result code.
++** 
++** Based on vacuumFinalize from vacuum.c
+ */
+-#ifndef _VDBEINT_H_
+-#define _VDBEINT_H_
++static int sqlcipher_finalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
++  int rc;
++  rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
++  if( rc ){
++    sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
++  }
++  return rc;
++}
+ 
+ /*
+-** The maximum number of times that a statement will try to reparse
+-** itself before giving up and returning SQLITE_SCHEMA.
++** Execute zSql on database db. Return an error code.
++** 
++** Based on execSql from vacuum.c
+ */
+-#ifndef SQLITE_MAX_SCHEMA_RETRY
+-# define SQLITE_MAX_SCHEMA_RETRY 50
+-#endif
++static int sqlcipher_execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
++  sqlite3_stmt *pStmt;
++  VVA_ONLY( int rc; )
++  if( !zSql ){
++    return SQLITE_NOMEM;
++  }
++  if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
++    sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
++    return sqlite3_errcode(db);
++  }
++  VVA_ONLY( rc = ) sqlite3_step(pStmt);
++  assert( rc!=SQLITE_ROW );
++  return sqlcipher_finalize(db, pStmt, pzErrMsg);
++}
+ 
+ /*
+-** SQL is translated into a sequence of instructions to be
+-** executed by a virtual machine.  Each instruction is an instance
+-** of the following structure.
++** Execute zSql on database db. The statement returns exactly
++** one column. Execute this as SQL on the same database.
++** 
++** Based on execExecSql from vacuum.c
+ */
+-typedef struct VdbeOp Op;
++static int sqlcipher_execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
++  sqlite3_stmt *pStmt;
++  int rc;
++
++  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
++  if( rc!=SQLITE_OK ) return rc;
++
++  while( SQLITE_ROW==sqlite3_step(pStmt) ){
++    rc = sqlcipher_execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
++    if( rc!=SQLITE_OK ){
++      sqlcipher_finalize(db, pStmt, pzErrMsg);
++      return rc;
++    }
++  }
++
++  return sqlcipher_finalize(db, pStmt, pzErrMsg);
++}
+ 
+ /*
+-** Boolean values
++ * copy database and schema from the main database to an attached database
++ * 
++ * Based on sqlite3RunVacuum from vacuum.c
+ */
+-typedef unsigned char Bool;
++void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
++  sqlite3 *db = sqlite3_context_db_handle(context);
++  const char* attachedDb = (const char*) sqlite3_value_text(argv[0]);
++  int saved_flags;        /* Saved value of the db->flags */
++  int saved_nChange;      /* Saved value of db->nChange */
++  int saved_nTotalChange; /* Saved value of db->nTotalChange */
++  void (*saved_xTrace)(void*,const char*);  /* Saved db->xTrace */
++  int rc = SQLITE_OK;     /* Return code from service routines */
++  char *zSql = NULL;         /* SQL statements */
++  char *pzErrMsg = NULL;
++  
++  saved_flags = db->flags;
++  saved_nChange = db->nChange;
++  saved_nTotalChange = db->nTotalChange;
++  saved_xTrace = db->xTrace;
++  db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
++  db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
++  db->xTrace = 0;
++
++  /* Query the schema of the main database. Create a mirror schema
++  ** in the temporary database.
++  */
++  zSql = sqlite3_mprintf(
++    "SELECT 'CREATE TABLE %s.' || substr(sql,14) "
++    "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
++    "   AND rootpage>0"
++  , attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
++
++  zSql = sqlite3_mprintf(
++    "SELECT 'CREATE INDEX %s.' || substr(sql,14)"
++    "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %%' "
++  , attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
++
++  zSql = sqlite3_mprintf(
++    "SELECT 'CREATE UNIQUE INDEX %s.' || substr(sql,21) "
++    "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %%'"
++  , attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
++
++  /* Loop through the tables in the main database. For each, do
++  ** an "INSERT INTO rekey_db.xxx SELECT * FROM main.xxx;" to copy
++  ** the contents to the temporary database.
++  */
++  zSql = sqlite3_mprintf(
++    "SELECT 'INSERT INTO %s.' || quote(name) "
++    "|| ' SELECT * FROM main.' || quote(name) || ';'"
++    "FROM main.sqlite_master "
++    "WHERE type = 'table' AND name!='sqlite_sequence' "
++    "  AND rootpage>0"
++  , attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
 +
++  /* Copy over the sequence table
++  */
++  zSql = sqlite3_mprintf(
++    "SELECT 'DELETE FROM %s.' || quote(name) || ';' "
++    "FROM %s.sqlite_master WHERE name='sqlite_sequence' "
++  , attachedDb, attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
++
++  zSql = sqlite3_mprintf(
++    "SELECT 'INSERT INTO %s.' || quote(name) "
++    "|| ' SELECT * FROM main.' || quote(name) || ';' "
++    "FROM %s.sqlite_master WHERE name=='sqlite_sequence';"
++  , attachedDb, attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
++
++  /* Copy the triggers, views, and virtual tables from the main database
++  ** over to the temporary database.  None of these objects has any
++  ** associated storage, so all we have to do is copy their entries
++  ** from the SQLITE_MASTER table.
++  */
++  zSql = sqlite3_mprintf(
++    "INSERT INTO %s.sqlite_master "
++    "  SELECT type, name, tbl_name, rootpage, sql"
++    "    FROM main.sqlite_master"
++    "   WHERE type='view' OR type='trigger'"
++    "      OR (type='table' AND rootpage=0)"
++  , attachedDb);
++  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execSql(db, &pzErrMsg, zSql); 
++  if( rc!=SQLITE_OK ) goto end_of_export;
++  sqlite3_free(zSql);
++
++  zSql = NULL;
++end_of_export:
++  db->flags = saved_flags;
++  db->nChange = saved_nChange;
++  db->nTotalChange = saved_nTotalChange;
++  db->xTrace = saved_xTrace;
++
++  sqlite3_free(zSql);
++
++  if(rc) {
++    if(pzErrMsg != NULL) {
++      sqlite3_result_error(context, pzErrMsg, -1);
++      sqlite3DbFree(db, pzErrMsg);
++    } else {
++      sqlite3_result_error(context, sqlite3ErrStr(rc), -1);
++    }
++  }
++}
+ 
+-/* Opaque type used by code in vdbesort.c */
+-typedef struct VdbeSorter VdbeSorter;
++#endif
+ 
+-/* Opaque type used by the explainer */
+-typedef struct Explain Explain;
++/* END SQLCIPHER */
++#endif
+ 
+-/*
+-** A cursor is a pointer into a single BTree within a database file.
+-** The cursor can seek to a BTree entry with a particular key, or
+-** loop over all entries of the Btree.  You can also insert new BTree
+-** entries or retrieve the key or data from the entry that the cursor
+-** is currently pointing to.
 +/************** End of crypto.c **********************************************/
 +/************** Begin file crypto_impl.c *************************************/
 +/* 
 +** SQLCipher
-+** crypto_impl.c developed by Stephen Lombardo (Zetetic LLC) 
++** http://sqlcipher.net
+ ** 
+-** Every cursor that the virtual machine has open is represented by an
+-** instance of the following structure.
++** Copyright (c) 2008 - 2013, ZETETIC LLC
++** All rights reserved.
++** 
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++**     * Redistributions of source code must retain the above copyright
++**       notice, this list of conditions and the following disclaimer.
++**     * Redistributions in binary form must reproduce the above copyright
++**       notice, this list of conditions and the following disclaimer in the
++**       documentation and/or other materials provided with the distribution.
++**     * Neither the name of the ZETETIC LLC nor the
++**       names of its contributors may be used to endorse or promote products
++**       derived from this software without specific prior written permission.
++** 
++** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
++** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
++** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++**  
+ */
+-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) */
+-  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 */
+-  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
+-  Bool nullRow;         /* True if pointing to a row with no data */
+-  Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
+-  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 */
+-  Bool isSorter;        /* True if a new-style sorter */
+-  Bool multiPseudo;     /* Multi-register pseudo-cursor */
+-  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 */
+-  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
+ 
+-  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
+-  ** OP_IsUnique opcode on this cursor. */
+-  int seekResult;
++/************** Include sqlcipher.h in the middle of crypto_impl.c ***********/
++/************** Begin file sqlcipher.h ***************************************/
++/* 
++** SQLCipher
++** sqlcipher.h developed by Stephen Lombardo (Zetetic LLC) 
 +** sjlombardo at zetetic dot net
 +** http://zetetic.net
 +** 
-+** Copyright (c) 2011, ZETETIC LLC
++** Copyright (c) 2008, ZETETIC LLC
 +** All rights reserved.
 +** 
 +** Redistribution and use in source and binary forms, with or without
@@ -1513,12 +2217,66 @@
 +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +**  
 +*/
-+/* BEGIN CRYPTO */
++/* BEGIN SQLCIPHER */
 +#ifdef SQLITE_HAS_CODEC
++#ifndef SQLCIPHER_H
++#define SQLCIPHER_H
+ 
+-  /* Cached information about the header for the data record that the
+-  ** cursor is currently pointing to.  Only valid if cacheStatus matches
+-  ** Vdbe.cacheCtr.  Vdbe.cacheCtr will never take on the value of
+-  ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
+-  ** the cache is out of date.
+-  **
+-  ** aRow might point to (ephemeral) data for the current row, or it might
+-  ** be NULL.
+-  */
+-  u32 cacheStatus;      /* Cache is valid if this matches Vdbe.cacheCtr */
+-  int payloadSize;      /* Total number of bytes in the record */
+-  u32 *aType;           /* Type values for all entries in the record */
+-  u32 *aOffset;         /* Cached offsets to the start of each columns data */
+-  u8 *aRow;             /* Data for the current row, if all on one page */
 +
-+#include <openssl/rand.h>
-+#include <openssl/evp.h>
-+#include <openssl/hmac.h>
++typedef struct {
++  int (*activate)(void *ctx);
++  int (*deactivate)(void *ctx);
++  const char* (*get_provider_name)(void *ctx);
++  int (*add_random)(void *ctx, void *buffer, int length);
++  int (*random)(void *ctx, void *buffer, int length);
++  int (*hmac)(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char 
*in2, int in2_sz, unsigned char *out);
++  int (*kdf)(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, 
int key_sz, unsigned char *key);
++  int (*cipher)(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, 
int in_sz, unsigned char *out);
++  int (*set_cipher)(void *ctx, const char *cipher_name);
++  const char* (*get_cipher)(void *ctx);
++  int (*get_key_sz)(void *ctx);
++  int (*get_iv_sz)(void *ctx);
++  int (*get_block_sz)(void *ctx);
++  int (*get_hmac_sz)(void *ctx);
++  int (*ctx_copy)(void *target_ctx, void *source_ctx);
++  int (*ctx_cmp)(void *c1, void *c2);
++  int (*ctx_init)(void **ctx);
++  int (*ctx_free)(void **ctx);
++} sqlcipher_provider;
++
++/* utility functions */
++void sqlcipher_free(void *ptr, int sz);
++void* sqlcipher_malloc(int sz);
++void* sqlcipher_memset(void *v, unsigned char value, int len);
++int sqlcipher_ismemset(const void *v, unsigned char value, int len);
++int sqlcipher_memcmp(const void *v0, const void *v1, int len);
++void sqlcipher_free(void *, int);
++
++/* provider interfaces */
++int sqlcipher_register_provider(sqlcipher_provider *p);
++sqlcipher_provider* sqlcipher_get_provider();
++
++#endif
++#endif
++/* END SQLCIPHER */
++
++
++/************** End of sqlcipher.h *******************************************/
++/************** Continuing where we left off in crypto_impl.c ****************/
 +#ifndef OMIT_MEMLOCK
 +#if defined(__unix__) || defined(__APPLE__) 
 +#include <sys/mman.h>
@@ -1532,9 +2290,6 @@
 +   struct and associated functions are defined here */
 +typedef struct {
 +  int derive_key;
-+  EVP_CIPHER *evp_cipher;
-+  EVP_CIPHER_CTX ectx;
-+  HMAC_CTX hctx;
 +  int kdf_iter;
 +  int fast_kdf_iter;
 +  int key_sz;
@@ -1547,23 +2302,14 @@
 +  unsigned char *key;
 +  unsigned char *hmac_key;
 +  char *pass;
++  sqlcipher_provider *provider;
++  void *provider_ctx;
 +} cipher_ctx;
 +
-+void sqlcipher_cipher_ctx_free(cipher_ctx **);
-+int sqlcipher_cipher_ctx_cmp(cipher_ctx *, cipher_ctx *);
-+int sqlcipher_cipher_ctx_copy(cipher_ctx *, cipher_ctx *);
-+int sqlcipher_cipher_ctx_init(cipher_ctx **);
-+int sqlcipher_cipher_ctx_set_pass(cipher_ctx *, const void *, int);
-+int sqlcipher_cipher_ctx_key_derive(codec_ctx *, cipher_ctx *);
-+
-+/* prototype for pager HMAC function */
-+int sqlcipher_page_hmac(cipher_ctx *, Pgno, unsigned char *, int, unsigned char *);
-+
 +static unsigned int default_flags = DEFAULT_CIPHER_FLAGS;
 +static unsigned char hmac_salt_mask = HMAC_SALT_MASK;
 +
-+static unsigned int openssl_external_init = 0;
-+static unsigned int openssl_init_count = 0;
++static sqlcipher_provider *default_provider = NULL;
 +
 +struct codec_ctx {
 +  int kdf_salt_sz;
@@ -1574,90 +2320,328 @@
 +  Btree *pBt;
 +  cipher_ctx *read_ctx;
 +  cipher_ctx *write_ctx;
-+};
-+
-+/* activate and initialize sqlcipher. Most importantly, this will automatically
-+   intialize OpenSSL's EVP system if it hasn't already be externally. Note that 
-+   this function may be called multiple times as new codecs are intiialized. 
-+   Thus it performs some basic counting to ensure that only the last and final
-+   sqlcipher_deactivate() will free the EVP structures. 
-+*/
+ };
+-typedef struct VdbeCursor VdbeCursor;
+ 
+-/*
+-** When a sub-program is executed (OP_Program), a structure of this type
+-** is allocated to store the current value of the program counter, as
+-** well as the current memory cell array and various other frame specific
+-** values stored in the Vdbe struct. When the sub-program is finished, 
+-** these values are copied back to the Vdbe from the VdbeFrame structure,
+-** restoring the state of the VM to as it was before the sub-program
+-** began executing.
+-**
+-** The memory for a VdbeFrame object is allocated and managed by a memory
+-** cell in the parent (calling) frame. When the memory cell is deleted or
+-** overwritten, the VdbeFrame object is not freed immediately. Instead, it
+-** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
+-** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
+-** this instead of deleting the VdbeFrame immediately is to avoid recursive
+-** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
+-** child frame are released.
+-**
+-** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
+-** set to NULL if the currently executing frame is the main program.
+-*/
+-typedef struct VdbeFrame VdbeFrame;
+-struct VdbeFrame {
+-  Vdbe *v;                /* VM this frame belongs to */
+-  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
+-  Op *aOp;                /* Program instructions for parent frame */
+-  Mem *aMem;              /* Array of memory cells for parent frame */
+-  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
+-  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
+-  void *token;            /* Copy of SubProgram.token */
+-  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
+-  int nCursor;            /* Number of entries in apCsr */
+-  int pc;                 /* Program Counter in parent (calling) frame */
+-  int nOp;                /* Size of aOp array */
+-  int nMem;               /* Number of entries in aMem */
+-  int nOnceFlag;          /* Number of entries in aOnceFlag */
+-  int nChildMem;          /* Number of memory cells for child frame */
+-  int nChildCsr;          /* Number of cursors for child frame */
+-  int nChange;            /* Statement changes (Vdbe.nChanges)     */
+-};
+-
+-#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
++int sqlcipher_register_provider(sqlcipher_provider *p) {
++  if(default_provider != NULL && default_provider != p) {
++    /* only free the current registerd provider if it has been initialized
++       and it isn't a pointer to the same provider passed to the function
++       (i.e. protect against a caller calling register twice for the same provider) */
++    sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
++  }
++  default_provider = p;   
++  return SQLITE_OK;
++}
+ 
+-/*
+-** A value for VdbeCursor.cacheValid that means the cache is always invalid.
+-*/
+-#define CACHE_STALE 0
++/* return a pointer to the currently registered provider. This will
++   allow an application to fetch the current registered provider and
++   make minor changes to it */
++sqlcipher_provider* sqlcipher_get_provider() {
++  return default_provider;
++}
+ 
+-/*
+-** 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.
+-*/
+-struct Mem {
+-  sqlite3 *db;        /* The associated database connection */
+-  char *z;            /* String or BLOB value */
+-  double r;           /* Real value */
+-  union {
+-    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;
+-  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 */
+-  u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
+-#ifdef SQLITE_DEBUG
+-  Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
+-  void *pFiller;      /* So that sizeof(Mem) is a multiple of 8 */
 +void sqlcipher_activate() {
++  sqlcipher_provider *p;
 +  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+
-+  /* we'll initialize openssl and increment the internal init counter
-+     but only if it hasn't been initalized outside of SQLCipher by this program 
-+     e.g. on startup */
-+  if(openssl_init_count == 0 && EVP_get_cipherbyname(CIPHER) != NULL) {
-+    openssl_external_init = 1;
++  p = sqlcipher_malloc(sizeof(sqlcipher_provider));
++  {
++#if defined (SQLCIPHER_CRYPTO_CC)
++  extern int sqlcipher_cc_setup(sqlcipher_provider *p);
++  sqlcipher_cc_setup(p);
++#elif defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT)
++  extern int sqlcipher_ltc_setup(sqlcipher_provider *p);
++  sqlcipher_ltc_setup(p);
++#elif defined (SQLCIPHER_CRYPTO_OPENSSL)
++  extern int sqlcipher_openssl_setup(sqlcipher_provider *p);
++  sqlcipher_openssl_setup(p);
++#else
++#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED"
+ #endif
+-  void (*xDel)(void *);  /* If not null, call this function to delete Mem.z */
+-  char *zMalloc;      /* Dynamic buffer allocated by sqlite3_malloc() */
+-};
 +  }
-+
-+  if(openssl_external_init == 0) {
-+    if(openssl_init_count == 0)  {
-+      OpenSSL_add_all_algorithms();
-+    }
-+    openssl_init_count++; 
-+  } 
++  sqlcipher_register_provider(p);
+ 
+-/* One or more of the following flags are set to indicate the validOK
+-** representations of the value stored in the Mem struct.
+-**
+-** If the MEM_Null flag is set, then the value is an SQL NULL value.
+-** No other flags may be set in this case.
+-**
+-** If the MEM_Str flag is set then Mem.z points at a string representation.
+-** Usually this is encoded in the same unicode encoding as the main
+-** 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.
+-*/
+-#define MEM_Null      0x0001   /* Value is NULL */
+-#define MEM_Str       0x0002   /* Value is a string */
+-#define MEM_Int       0x0004   /* Value is an integer */
+-#define MEM_Real      0x0008   /* Value is a real number */
+-#define MEM_Blob      0x0010   /* Value is a BLOB */
+-#define MEM_RowSet    0x0020   /* Value is a RowSet object */
+-#define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
+-#define MEM_Invalid   0x0080   /* Value is undefined */
+-#define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
+-#define MEM_TypeMask  0x01ff   /* Mask of type bits */
 +  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 +}
-+
-+/* deactivate SQLCipher, most imporantly decremeting the activation count and
-+   freeing the EVP structures on the final deactivation to ensure that 
-+   OpenSSL memory is cleaned up */
+ 
 +void sqlcipher_deactivate() {
 +  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+  /* If it is initialized externally, then the init counter should never be greater than zero.
-+     This should prevent SQLCipher from "cleaning up" openssl 
-+     when something else in the program might be using it. */
-+  if(openssl_external_init == 0) {
-+    openssl_init_count--;
-+    /* if the counter reaches zero after it's decremented release EVP memory
-+       Note: this code will only be reached if OpensSSL_add_all_algorithms()
-+       is called by SQLCipher internally. */
-+    if(openssl_init_count == 0) {
-+      EVP_cleanup();
-+    }
++  if(default_provider != NULL) {
++    sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
++    default_provider = NULL;
 +  }
 +  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 +}
-+
+ 
+-/* Whenever Mem contains a valid string or blob representation, one of
+-** the following flags must be set to determine the memory management
+-** policy for Mem.z.  The MEM_Term flag tells us whether or not the
+-** string is \000 or \u0000 terminated
 +/* constant time memset using volitile to avoid having the memset
 +   optimized out by the compiler. 
 +   Note: As suggested by Joachim Schipper (joachim schipper fox-it com)
-+*/
+ */
+-#define MEM_Term      0x0200   /* String rep is nul terminated */
+-#define MEM_Dyn       0x0400   /* Need to call sqliteFree() on Mem.z */
+-#define MEM_Static    0x0800   /* Mem.z points to a static string */
+-#define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
+-#define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
+-#define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
+-#ifdef SQLITE_OMIT_INCRBLOB
+-  #undef MEM_Zero
+-  #define MEM_Zero 0x0000
+-#endif
 +void* sqlcipher_memset(void *v, unsigned char value, int len) {
 +  int i = 0;
 +  volatile unsigned char *a = v;
-+
+ 
+-/*
+-** Clear any existing type flags from a Mem and replace them with f
+-*/
+-#define MemSetTypeFlag(p, f) \
+-   ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
 +  if (v == NULL) return v;
-+
+ 
+-/*
+-** Return true if a memory cell is not marked as invalid.  This macro
+-** is for use inside assert() statements only.
+-*/
+-#ifdef SQLITE_DEBUG
+-#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
+-#endif
 +  for(i = 0; i < len; i++) {
 +    a[i] = value;
 +  }
-+
+ 
 +  return v;
 +}
-+
+ 
+-/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
+-** additional information about auxiliary information bound to arguments
+-** of the function.  This is used to implement the sqlite3_get_auxdata()
+-** and sqlite3_set_auxdata() APIs.  The "auxdata" is some auxiliary data
+-** that can be associated with a constant argument to a function.  This
+-** allows functions such as "regexp" to compile their constant regular
+-** expression argument once and reused the compiled code for multiple
+-** invocations.
+-*/
+-struct VdbeFunc {
+-  FuncDef *pFunc;               /* The definition of the function */
+-  int nAux;                     /* Number of entries allocated for apAux[] */
+-  struct AuxData {
+-    void *pAux;                   /* Aux data for the i-th argument */
+-    void (*xDelete)(void *);      /* Destructor for the aux data */
+-  } apAux[1];                   /* One slot for each function argument */
+-};
 +/* constant time memory check tests every position of a memory segement
 +   matches a single value (i.e. the memory is all zeros)
 +   returns 0 if match, 1 of no match */
 +int sqlcipher_ismemset(const void *v, unsigned char value, int len) {
 +  const unsigned char *a = v;
 +  int i = 0, result = 0;
-+
+ 
+-/*
+-** The "context" argument for a installable function.  A pointer to an
+-** instance of this structure is the first argument to the routines used
+-** implement the SQL functions.
+-**
+-** There is a typedef for this structure in sqlite.h.  So all routines,
+-** even the public interface to SQLite, can use a pointer to this structure.
+-** But this file is the only place where the internal details of this
+-** structure are known.
+-**
+-** This structure is defined inside of vdbeInt.h because it uses substructures
+-** (Mem) which are only defined there.
+-*/
+-struct sqlite3_context {
+-  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
+-  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
+-  Mem s;                /* The return value is stored here */
+-  Mem *pMem;            /* Memory cell used to store aggregate context */
+-  CollSeq *pColl;       /* Collating sequence */
+-  int isError;          /* Error code returned by the function. */
+-  int skipFlag;         /* Skip skip accumulator loading if true */
+-};
 +  for(i = 0; i < len; i++) {
 +    result |= a[i] ^ value;
 +  }
-+
+ 
+-/*
+-** An Explain object accumulates indented output which is helpful
+-** in describing recursive data structures.
+-*/
+-struct Explain {
+-  Vdbe *pVdbe;       /* Attach the explanation to this Vdbe */
+-  StrAccum str;      /* The string being accumulated */
+-  int nIndent;       /* Number of elements in aIndent */
+-  u16 aIndent[100];  /* Levels of indentation */
+-  char zBase[100];   /* Initial space */
+-};
 +  return (result != 0);
 +}
-+
+ 
+-/* A bitfield type for use inside of structures.  Always follow with :N where
+-** N is the number of bits.
+-*/
+-typedef unsigned bft;  /* Bit Field Type */
 +/* constant time memory comparison routine. 
 +   returns 0 if match, 1 if no match */
 +int sqlcipher_memcmp(const void *v0, const void *v1, int len) {
 +  const unsigned char *a0 = v0, *a1 = v1;
 +  int i = 0, result = 0;
-+
+ 
+-/*
+-** 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_prepare()
+-** is really a pointer to an instance of this structure.
+-**
+-** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
+-** any virtual table method invocations made by the vdbe program. It is
+-** set to 2 for xDestroy method calls and 1 for all other methods. This
+-** variable is used for two purposes: to allow xDestroy methods to execute
+-** "DROP TABLE" statements and to prevent some nasty side effects of
+-** malloc failure when SQLite is invoked recursively by a virtual table 
+-** method function.
+-*/
+-struct Vdbe {
+-  sqlite3 *db;            /* The database connection that owns this statement */
+-  Op *aOp;                /* Space to hold the virtual machine's program */
+-  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 *aLabel;            /* Space to hold the labels */
+-  u16 nResColumn;         /* Number of columns in one row of the result set */
+-  int 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 */
+-  Mem *aVar;              /* Values for the OP_Variable opcode. */
+-  char **azVar;           /* Name of variables */
+-  ynVar nVar;             /* Number of entries in aVar[] */
+-  ynVar nzVar;            /* Number of entries in azVar[] */
+-  u32 cacheCtr;           /* VdbeCursor row cache generation counter */
+-  int pc;                 /* The program counter */
+-  int rc;                 /* Value to return */
+-  u8 errorAction;         /* Recovery action to do in case of an error */
+-  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
+-  bft explain:2;          /* True if EXPLAIN present on SQL command */
+-  bft inVtabMethod:2;     /* See comments above */
+-  bft changeCntOn:1;      /* True to update the change-counter */
+-  bft expired:1;          /* True if the VM needs to be recompiled */
+-  bft runOnlyOnce:1;      /* Automatically expire on reset */
+-  bft usesStmtJournal:1;  /* True if uses a statement journal */
+-  bft readOnly:1;         /* True for read-only statements */
+-  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
+-  bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
+-  int nChange;            /* Number of db changes made since last reset */
+-  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
+-  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
+-  int iStatement;         /* Statement number (or 0 if has not opened stmt) */
+-  int aCounter[3];        /* Counters used by sqlite3_stmt_status() */
+-#ifndef SQLITE_OMIT_TRACE
+-  i64 startTime;          /* Time when query started - used for profiling */
 +  for(i = 0; i < len; i++) {
 +    result |= a0[i] ^ a1[i];
 +  }
@@ -1665,11 +2649,6 @@
 +  return (result != 0);
 +}
 +
-+/* generate a defined number of pseudorandom bytes */
-+int sqlcipher_random (void *buffer, int length) {
-+  return RAND_bytes((unsigned char *)buffer, length);
-+}
-+
 +/**
 +  * Free and wipe memory. Uses SQLites internal sqlite3_free so that memory
 +  * can be countend and memory leak detection works in the test suite. 
@@ -1687,8 +2666,17 @@
 +      munlock(ptr, sz);
 +#elif defined(_WIN32)
 +      VirtualUnlock(ptr, sz);
-+#endif
-+#endif
+ #endif
+-  i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
+-  i64 nStmtDefCons;       /* Number of def. constraints when stmt started */
+-  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
+-#ifdef SQLITE_ENABLE_TREE_EXPLAIN
+-  Explain *pExplain;      /* The explainer */
+-  char *zExplain;         /* Explanation of data structures */
 +    }
 +    sqlite3_free(ptr);
 +  }
@@ -1708,13 +2696,42 @@
 +    mlock(ptr, sz);
 +#elif defined(_WIN32)
 +    VirtualLock(ptr, sz);
-+#endif
+ #endif
+-  VdbeFrame *pFrame;      /* Parent frame */
+-  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
+-  int nFrame;             /* Number of frames in pFrame list */
+-  u32 expmask;            /* Binding to these vars invalidates VM */
+-  SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */
+-  int nOnceFlag;          /* Size of array aOnceFlag[] */
+-  u8 *aOnceFlag;          /* Flags for OP_Once */
+-};
 +  }
 +#endif
 +  return ptr;
 +}
-+
-+
+ 
+-/*
+-** The following are allowed values for Vdbe.magic
+-*/
+-#define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
+-#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */
+-#define VDBE_MAGIC_HALT     0x519c2973    /* VDBE has completed execution */
+-#define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */
+ 
+-/*
+-** Function prototypes
+-*/
+-SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
+-void sqliteVdbePopStack(Vdbe*,int);
+-SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*);
+-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
+-#endif
+-SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
+-SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
+-SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
+-SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
+-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
 +/**
 +  * Initialize new cipher_ctx struct. This function will allocate memory
 +  * for the cipher context and for the key
@@ -1722,29 +2739,96 @@
 +  * returns SQLITE_OK if initialization was successful
 +  * returns SQLITE_NOMEM if an error occured allocating memory
 +  */
-+int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) {
++static int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) {
++  int rc;
 +  cipher_ctx *ctx;
 +  *iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx));
 +  ctx = *iCtx;
 +  if(ctx == NULL) return SQLITE_NOMEM;
 +
-+  ctx->key = (unsigned char *) sqlcipher_malloc(EVP_MAX_KEY_LENGTH);
-+  ctx->hmac_key = (unsigned char *) sqlcipher_malloc(EVP_MAX_KEY_LENGTH);
++  ctx->provider = (sqlcipher_provider *) sqlcipher_malloc(sizeof(sqlcipher_provider));
++  if(ctx->provider == NULL) return SQLITE_NOMEM;
++  memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider));
++
++  if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) return rc;
++  ctx->key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ);
++  ctx->hmac_key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ);
 +  if(ctx->key == NULL) return SQLITE_NOMEM;
 +  if(ctx->hmac_key == NULL) return SQLITE_NOMEM;
-+
+ 
+-int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
+-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
+-SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
+-SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
+-SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
+-SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
+-SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
+-SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
+-SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
+-SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
+-SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
+-SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
+-#ifdef SQLITE_OMIT_FLOATING_POINT
+-# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
+-#else
+-SQLITE_PRIVATE   void sqlite3VdbeMemSetDouble(Mem*, double);
+-#endif
+-SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
+-SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
+-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
+-SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
+-SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
+-SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
+-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
+-SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
+-SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
+-#define VdbeMemRelease(X)  \
+-  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
+-    sqlite3VdbeMemReleaseExternal(X);
+-SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
+-SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
+-SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
+-SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
+-SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
+-SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
+-SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
+-SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
 +  /* setup default flags */
 +  ctx->flags = default_flags;
-+
+ 
+-SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
+-SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
+-SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
+-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
+-SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
+-SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
+-SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
 +  return SQLITE_OK;
 +}
-+
+ 
+-#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
+-SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
+-SQLITE_PRIVATE   void sqlite3VdbeLeave(Vdbe*);
+-#else
+-# define sqlite3VdbeEnter(X)
+-# define sqlite3VdbeLeave(X)
+-#endif
 +/**
 +  * Free and wipe memory associated with a cipher_ctx
 +  */
-+void sqlcipher_cipher_ctx_free(cipher_ctx **iCtx) {
++static void sqlcipher_cipher_ctx_free(cipher_ctx **iCtx) {
 +  cipher_ctx *ctx = *iCtx;
 +  CODEC_TRACE(("cipher_ctx_free: entered iCtx=%p\n", iCtx));
++  ctx->provider->ctx_free(&ctx->provider_ctx);
++  sqlcipher_free(ctx->provider, sizeof(sqlcipher_provider)); 
 +  sqlcipher_free(ctx->key, ctx->key_sz);
 +  sqlcipher_free(ctx->hmac_key, ctx->key_sz);
 +  sqlcipher_free(ctx->pass, ctx->pass_sz);
@@ -1757,18 +2841,18 @@
 +  * returns 0 if all the parameters (except the derived key data) are the same
 +  * returns 1 otherwise
 +  */
-+int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
++static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
 +  CODEC_TRACE(("sqlcipher_cipher_ctx_cmp: entered c1=%p c2=%p\n", c1, c2));
 +
 +  if(
-+    c1->evp_cipher == c2->evp_cipher
-+    && c1->iv_sz == c2->iv_sz
++    c1->iv_sz == c2->iv_sz
 +    && c1->kdf_iter == c2->kdf_iter
 +    && c1->fast_kdf_iter == c2->fast_kdf_iter
 +    && c1->key_sz == c2->key_sz
 +    && c1->pass_sz == c2->pass_sz
 +    && c1->flags == c2->flags
 +    && c1->hmac_sz == c2->hmac_sz
++    && c1->provider->ctx_cmp(c1->provider_ctx, c2->provider_ctx) 
 +    && (
 +      c1->pass == c2->pass
 +      || !sqlcipher_memcmp((const unsigned char*)c1->pass,
@@ -1778,7 +2862,10 @@
 +  ) return 0;
 +  return 1;
 +}
-+
+ 
+-#ifdef SQLITE_DEBUG
+-SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
+-#endif
 +/**
 +  * Copy one cipher_ctx to another. For instance, assuming that read_ctx is a 
 +  * fully initialized context, you could copy it to write_ctx and all yet data
@@ -1787,28 +2874,65 @@
 +  * returns SQLITE_OK if initialization was successful
 +  * returns SQLITE_NOMEM if an error occured allocating memory
 +  */
-+int sqlcipher_cipher_ctx_copy(cipher_ctx *target, cipher_ctx *source) {
++static int sqlcipher_cipher_ctx_copy(cipher_ctx *target, cipher_ctx *source) {
 +  void *key = target->key; 
 +  void *hmac_key = target->hmac_key; 
++  void *provider = target->provider;
++  void *provider_ctx = target->provider_ctx;
 +
 +  CODEC_TRACE(("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source));
 +  sqlcipher_free(target->pass, target->pass_sz); 
 +  memcpy(target, source, sizeof(cipher_ctx));
 +  
 +  target->key = key; //restore pointer to previously allocated key data
-+  memcpy(target->key, source->key, EVP_MAX_KEY_LENGTH);
-+
++  memcpy(target->key, source->key, CIPHER_MAX_KEY_SZ);
+ 
+-#ifndef SQLITE_OMIT_FOREIGN_KEY
+-SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
+-#else
+-# define sqlite3VdbeCheckFk(p,i) 0
+-#endif
 +  target->hmac_key = hmac_key; //restore pointer to previously allocated hmac key data
-+  memcpy(target->hmac_key, source->hmac_key, EVP_MAX_KEY_LENGTH);
-+
++  memcpy(target->hmac_key, source->hmac_key, CIPHER_MAX_KEY_SZ);
+ 
+-SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
+-#ifdef SQLITE_DEBUG
+-SQLITE_PRIVATE   void sqlite3VdbePrintSql(Vdbe*);
+-SQLITE_PRIVATE   void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
+-#endif
+-SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
++  target->provider = provider; // restore pointer to previouly allocated provider;
++  memcpy(target->provider, source->provider, sizeof(sqlcipher_provider));
+ 
+-#ifndef SQLITE_OMIT_INCRBLOB
+-SQLITE_PRIVATE   int sqlite3VdbeMemExpandBlob(Mem *);
+-  #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
+-#else
+-  #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
+-  #define ExpandBlob(P) SQLITE_OK
+-#endif
++  target->provider_ctx = provider_ctx; // restore pointer to previouly allocated provider context;
++  target->provider->ctx_copy(target->provider_ctx, source->provider_ctx);
+ 
+-#endif /* !defined(_VDBEINT_H_) */
 +  target->pass = sqlcipher_malloc(source->pass_sz);
 +  if(target->pass == NULL) return SQLITE_NOMEM;
 +  memcpy(target->pass, source->pass, source->pass_sz);
-+
+ 
+-/************** End of vdbeInt.h *********************************************/
+-/************** Continuing where we left off in status.c *********************/
 +  return SQLITE_OK;
 +}
-+
-+
+ 
+-/*
+-** Variables in which to record status information.
+-*/
+-typedef struct sqlite3StatType sqlite3StatType;
+-static SQLITE_WSD struct sqlite3StatType {
+-  int nowValue[10];         /* Current value */
+-  int mxValue[10];          /* Maximum value */
+-} sqlite3Stat = { {0,}, {0,} };
+ 
 +/**
 +  * Set the raw password / key data for a cipher context
 +  * 
@@ -1816,7 +2940,7 @@
 +  * returns SQLITE_NOMEM if an error occured allocating memory
 +  * returns SQLITE_ERROR if the key couldn't be set because the pass was null or size was zero
 +  */
-+int sqlcipher_cipher_ctx_set_pass(cipher_ctx *ctx, const void *zKey, int nKey) {
++static int sqlcipher_cipher_ctx_set_pass(cipher_ctx *ctx, const void *zKey, int nKey) {
 +  sqlcipher_free(ctx->pass, ctx->pass_sz);
 +  ctx->pass_sz = nKey;
 +  if(zKey && nKey) {
@@ -1831,10 +2955,30 @@
 +int sqlcipher_codec_ctx_set_pass(codec_ctx *ctx, const void *zKey, int nKey, int for_ctx) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  int rc;
-+
+ 
+-/* The "wsdStat" macro will resolve to the status information
+-** state vector.  If writable static data is unsupported on the target,
+-** we have to locate the state vector at run-time.  In the more common
+-** case where writable static data is supported, wsdStat can refer directly
+-** to the "sqlite3Stat" state vector declared above.
+-*/
+-#ifdef SQLITE_OMIT_WSD
+-# define wsdStatInit  sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
+-# define wsdStat x[0]
+-#else
+-# define wsdStatInit
+-# define wsdStat sqlite3Stat
+-#endif
 +  if((rc = sqlcipher_cipher_ctx_set_pass(c_ctx, zKey, nKey)) != SQLITE_OK) return rc; 
 +  c_ctx->derive_key = 1;
-+
+ 
+-/*
+-** Return the current value of a status parameter.
+-*/
+-SQLITE_PRIVATE int sqlite3StatusValue(int op){
+-  wsdStatInit;
+-  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+-  return wsdStat.nowValue[op];
 +  if(for_ctx == 2)
 +    if((rc = sqlcipher_cipher_ctx_copy( for_ctx ? ctx->read_ctx : ctx->write_ctx, c_ctx)) != SQLITE_OK) 
 +      return rc; 
@@ -1846,11 +2990,12 @@
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  int rc;
 +
-+  c_ctx->evp_cipher = (EVP_CIPHER *) EVP_get_cipherbyname(cipher_name);
-+  c_ctx->key_sz = EVP_CIPHER_key_length(c_ctx->evp_cipher);
-+  c_ctx->iv_sz = EVP_CIPHER_iv_length(c_ctx->evp_cipher);
-+  c_ctx->block_sz = EVP_CIPHER_block_size(c_ctx->evp_cipher);
-+  c_ctx->hmac_sz = EVP_MD_size(EVP_sha1());
++  c_ctx->provider->set_cipher(c_ctx->provider_ctx, cipher_name);
++
++  c_ctx->key_sz = c_ctx->provider->get_key_sz(c_ctx->provider_ctx);
++  c_ctx->iv_sz = c_ctx->provider->get_iv_sz(c_ctx->provider_ctx);
++  c_ctx->block_sz = c_ctx->provider->get_block_sz(c_ctx->provider_ctx);
++  c_ctx->hmac_sz = c_ctx->provider->get_hmac_sz(c_ctx->provider_ctx);
 +  c_ctx->derive_key = 1;
 +
 +  if(for_ctx == 2)
@@ -1858,14 +3003,34 @@
 +      return rc; 
 +
 +  return SQLITE_OK;
-+}
-+
+ }
+ 
+-/*
+-** Add N to the value of a status record.  It is assumed that the
+-** caller holds appropriate locks.
+-*/
+-SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
+-  wsdStatInit;
+-  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+-  wsdStat.nowValue[op] += N;
+-  if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+-    wsdStat.mxValue[op] = wsdStat.nowValue[op];
+-  }
 +const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx, int for_ctx) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
-+  EVP_CIPHER *evp_cipher = c_ctx->evp_cipher;
-+  return EVP_CIPHER_name(evp_cipher);
-+}
-+
++  return c_ctx->provider->get_cipher(c_ctx->provider_ctx);
+ }
+ 
+-/*
+-** Set the value of a status to X.
+-*/
+-SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
+-  wsdStatInit;
+-  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+-  wsdStat.nowValue[op] = X;
+-  if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+-    wsdStat.mxValue[op] = wsdStat.nowValue[op];
+-  }
 +int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter, int for_ctx) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  int rc;
@@ -1878,8 +3043,25 @@
 +      return rc; 
 +
 +  return SQLITE_OK;
-+}
-+
+ }
+ 
+-/*
+-** Query status information.
+-**
+-** This implementation assumes that reading or writing an aligned
+-** 32-bit integer is an atomic operation.  If that assumption is not true,
+-** then this routine is not threadsafe.
+-*/
+-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
+-  wsdStatInit;
+-  if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
+-    return SQLITE_MISUSE_BKPT;
+-  }
+-  *pCurrent = wsdStat.nowValue[op];
+-  *pHighwater = wsdStat.mxValue[op];
+-  if( resetFlag ){
+-    wsdStat.mxValue[op] = wsdStat.nowValue[op];
+-  }
 +int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx, int for_ctx) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  return c_ctx->kdf_iter;
@@ -1896,46 +3078,157 @@
 +    if((rc = sqlcipher_cipher_ctx_copy( for_ctx ? ctx->read_ctx : ctx->write_ctx, c_ctx)) != SQLITE_OK)
 +      return rc; 
 +
-+  return SQLITE_OK;
-+}
-+
+   return SQLITE_OK;
+ }
+ 
+-/*
+-** Query status information for a single database connection
+-*/
+-SQLITE_API int sqlite3_db_status(
+-  sqlite3 *db,          /* The database connection whose status is desired */
+-  int op,               /* Status verb */
+-  int *pCurrent,        /* Write current value here */
+-  int *pHighwater,      /* Write high-water mark here */
+-  int resetFlag         /* Reset high-water mark if true */
+-){
+-  int rc = SQLITE_OK;   /* Return code */
+-  sqlite3_mutex_enter(db->mutex);
+-  switch( op ){
+-    case SQLITE_DBSTATUS_LOOKASIDE_USED: {
+-      *pCurrent = db->lookaside.nOut;
+-      *pHighwater = db->lookaside.mxOut;
+-      if( resetFlag ){
+-        db->lookaside.mxOut = db->lookaside.nOut;
+-      }
+-      break;
+-    }
 +int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *ctx, int for_ctx) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  return c_ctx->fast_kdf_iter;
 +}
-+
+ 
+-    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;
+-    }
 +/* set the global default flag for HMAC */
 +void sqlcipher_set_default_use_hmac(int use) {
 +  if(use) default_flags |= CIPHER_FLAG_HMAC; 
 +  else default_flags &= ~CIPHER_FLAG_HMAC; 
 +}
-+
+ 
+-    /* 
+-    ** Return an approximation for the amount of memory currently used
+-    ** by all pagers associated with the given database connection.  The
+-    ** highwater mark is meaningless and is returned as zero.
+-    */
+-    case SQLITE_DBSTATUS_CACHE_USED: {
+-      int totalUsed = 0;
+-      int i;
+-      sqlite3BtreeEnterAll(db);
+-      for(i=0; i<db->nDb; i++){
+-        Btree *pBt = db->aDb[i].pBt;
+-        if( pBt ){
+-          Pager *pPager = sqlite3BtreePager(pBt);
+-          totalUsed += sqlite3PagerMemUsed(pPager);
+-        }
+-      }
+-      sqlite3BtreeLeaveAll(db);
+-      *pCurrent = totalUsed;
+-      *pHighwater = 0;
+-      break;
+-    }
 +int sqlcipher_get_default_use_hmac() {
 +  return (default_flags & CIPHER_FLAG_HMAC) != 0;
 +}
-+
+ 
+-    /*
+-    ** *pCurrent gets an accurate estimate of the amount of memory used
+-    ** to store the schema for all databases (main, temp, and any ATTACHed
+-    ** databases.  *pHighwater is set to zero.
+-    */
+-    case SQLITE_DBSTATUS_SCHEMA_USED: {
+-      int i;                      /* Used to iterate through schemas */
+-      int nByte = 0;              /* Used to accumulate return value */
 +void sqlcipher_set_hmac_salt_mask(unsigned char mask) {
 +  hmac_salt_mask = mask;
 +}
-+
+ 
+-      sqlite3BtreeEnterAll(db);
+-      db->pnBytesFreed = &nByte;
+-      for(i=0; i<db->nDb; i++){
+-        Schema *pSchema = db->aDb[i].pSchema;
+-        if( ALWAYS(pSchema!=0) ){
+-          HashElem *p;
 +unsigned char sqlcipher_get_hmac_salt_mask() {
 +  return hmac_salt_mask;
 +}
-+
+ 
+-          nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
+-              pSchema->tblHash.count 
+-            + pSchema->trigHash.count
+-            + pSchema->idxHash.count
+-            + pSchema->fkeyHash.count
+-          );
+-          nByte += sqlite3MallocSize(pSchema->tblHash.ht);
+-          nByte += sqlite3MallocSize(pSchema->trigHash.ht);
+-          nByte += sqlite3MallocSize(pSchema->idxHash.ht);
+-          nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
 +/* set the codec flag for whether this individual database should be using hmac */
 +int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) {
-+  int reserve = EVP_MAX_IV_LENGTH; /* base reserve size will be IV only */ 
-+
++  int reserve = CIPHER_MAX_IV_SZ; /* base reserve size will be IV only */ 
+ 
+-          for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
+-            sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
+-          }
+-          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
+-            sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
+-          }
+-        }
+-      }
+-      db->pnBytesFreed = 0;
+-      sqlite3BtreeLeaveAll(db);
 +  if(use) reserve += ctx->read_ctx->hmac_sz; /* if reserve will include hmac, update that size */
-+
+ 
+-      *pHighwater = 0;
+-      *pCurrent = nByte;
+-      break;
+-    }
 +  /* calculate the amount of reserve needed in even increments of the cipher block size */
-+
+ 
+-    /*
+-    ** *pCurrent gets an accurate estimate of the amount of memory used
+-    ** to store all prepared statements.
+-    ** *pHighwater is set to zero.
+-    */
+-    case SQLITE_DBSTATUS_STMT_USED: {
+-      struct Vdbe *pVdbe;         /* Used to iterate through VMs */
+-      int nByte = 0;              /* Used to accumulate return value */
 +  reserve = ((reserve % ctx->read_ctx->block_sz) == 0) ? reserve :
 +               ((reserve / ctx->read_ctx->block_sz) + 1) * ctx->read_ctx->block_sz;  
-+
+ 
+-      db->pnBytesFreed = &nByte;
+-      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
+-        sqlite3VdbeClearObject(db, pVdbe);
+-        sqlite3DbFree(db, pVdbe);
+-      }
+-      db->pnBytesFreed = 0;
 +  CODEC_TRACE(("sqlcipher_codec_ctx_set_use_hmac: use=%d block_sz=%d md_size=%d reserve=%d\n", 
 +                use, ctx->read_ctx->block_sz, ctx->read_ctx->hmac_sz, reserve)); 
-+
+ 
+-      *pHighwater = 0;
+-      *pCurrent = nByte;
 +  
 +  if(use) {
 +    sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_HMAC);
@@ -1944,55 +3237,234 @@
 +  } 
 +  
 +  ctx->write_ctx->reserve_sz = ctx->read_ctx->reserve_sz = reserve;
-+
+ 
+-      break;
+-    }
 +  return SQLITE_OK;
 +}
-+
+ 
+-    /*
+-    ** Set *pCurrent to the total cache hits or misses encountered by all
+-    ** pagers the database handle is connected to. *pHighwater is always set 
+-    ** to zero.
+-    */
+-    case SQLITE_DBSTATUS_CACHE_HIT:
+-    case SQLITE_DBSTATUS_CACHE_MISS:
+-    case SQLITE_DBSTATUS_CACHE_WRITE:{
+-      int i;
+-      int nRet = 0;
+-      assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
+-      assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
 +int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx, int for_ctx) {
 +  cipher_ctx * c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  return (c_ctx->flags & CIPHER_FLAG_HMAC) != 0;
 +}
-+
+ 
+-      for(i=0; i<db->nDb; i++){
+-        if( db->aDb[i].pBt ){
+-          Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
+-          sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
+-        }
+-      }
+-      *pHighwater = 0;
+-      *pCurrent = nRet;
+-      break;
+-    }
 +int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag) {
 +  ctx->write_ctx->flags |= flag;
 +  ctx->read_ctx->flags |= flag;
 +  return SQLITE_OK;
 +}
-+
+ 
+-    default: {
+-      rc = SQLITE_ERROR;
+-    }
+-  }
+-  sqlite3_mutex_leave(db->mutex);
+-  return rc;
 +int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag) {
 +  ctx->write_ctx->flags &= ~flag;
 +  ctx->read_ctx->flags &= ~flag;
 +  return SQLITE_OK;
-+}
-+
+ }
+ 
+-/************** End of status.c **********************************************/
+-/************** Begin file date.c ********************************************/
+-/*
+-** 2003 October 31
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-** This file contains the C functions that implement date and time
+-** functions for SQLite.  
+-**
+-** There is only one exported symbol in this file - the function
+-** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
+-** All other code has file scope.
+-**
+-** SQLite processes all times and dates as Julian Day numbers.  The
+-** dates and times are stored as the number of days since noon
+-** in Greenwich on November 24, 4714 B.C. according to the Gregorian
+-** calendar system. 
+-**
+-** 1970-01-01 00:00:00 is JD 2440587.5
+-** 2000-01-01 00:00:00 is JD 2451544.5
+-**
+-** This implemention requires years to be expressed as a 4-digit number
+-** which means that only dates between 0000-01-01 and 9999-12-31 can
+-** be represented, even though julian day numbers allow a much wider
+-** range of dates.
+-**
+-** The Gregorian calendar system is used for all dates and times,
+-** even those that predate the Gregorian calendar.  Historians usually
+-** use the Julian calendar for dates prior to 1582-10-15 and for some
+-** dates afterwards, depending on locale.  Beware of this difference.
+-**
+-** The conversion algorithms are implemented based on descriptions
+-** in the following text:
+-**
+-**      Jean Meeus
+-**      Astronomical Algorithms, 2nd Edition, 1998
+-**      ISBM 0-943396-61-1
+-**      Willmann-Bell, Inc
+-**      Richmond, Virginia (USA)
+-*/
+-/* #include <stdlib.h> */
+-/* #include <assert.h> */
+-#include <time.h>
 +int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx) {
 +  cipher_ctx * c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  return (c_ctx->flags & flag) != 0;
 +}
-+
+ 
+-#ifndef SQLITE_OMIT_DATETIME_FUNCS
 +void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) {
 +  CODEC_TRACE(("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error));
 +  sqlite3pager_sqlite3PagerSetError(ctx->pBt->pBt->pPager, error);
 +  ctx->pBt->pBt->db->errCode = error;
 +}
-+
+ 
 +int sqlcipher_codec_ctx_get_reservesize(codec_ctx *ctx) {
 +  return ctx->read_ctx->reserve_sz;
 +}
-+
+ 
+-/*
+-** A structure for holding a single date and time.
+-*/
+-typedef struct DateTime DateTime;
+-struct DateTime {
+-  sqlite3_int64 iJD; /* The julian day number times 86400000 */
+-  int Y, M, D;       /* Year, month, and day */
+-  int h, m;          /* Hour and minutes */
+-  int tz;            /* Timezone offset in minutes */
+-  double s;          /* Seconds */
+-  char validYMD;     /* True (1) if Y,M,D are valid */
+-  char validHMS;     /* True (1) if h,m,s are valid */
+-  char validJD;      /* True (1) if iJD is valid */
+-  char validTZ;      /* True (1) if tz is valid */
+-};
 +void* sqlcipher_codec_ctx_get_data(codec_ctx *ctx) {
 +  return ctx->buffer;
 +}
-+
+ 
 +void* sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx) {
 +  return ctx->kdf_salt;
 +}
-+
+ 
+-/*
+-** Convert zDate into one or more integers.  Additional arguments
+-** come in groups of 5 as follows:
+-**
+-**       N       number of digits in the integer
+-**       min     minimum allowed value of the integer
+-**       max     maximum allowed value of the integer
+-**       nextC   first character after the integer
+-**       pVal    where to write the integers value.
+-**
+-** Conversions continue until one with nextC==0 is encountered.
+-** The function returns the number of successful conversions.
+-*/
+-static int getDigits(const char *zDate, ...){
+-  va_list ap;
+-  int val;
+-  int N;
+-  int min;
+-  int max;
+-  int nextC;
+-  int *pVal;
+-  int cnt = 0;
+-  va_start(ap, zDate);
+-  do{
+-    N = va_arg(ap, int);
+-    min = va_arg(ap, int);
+-    max = va_arg(ap, int);
+-    nextC = va_arg(ap, int);
+-    pVal = va_arg(ap, int*);
+-    val = 0;
+-    while( N-- ){
+-      if( !sqlite3Isdigit(*zDate) ){
+-        goto end_getDigits;
+-      }
+-      val = val*10 + *zDate - '0';
+-      zDate++;
+-    }
+-    if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
+-      goto end_getDigits;
+-    }
+-    *pVal = val;
+-    zDate++;
+-    cnt++;
+-  }while( nextC );
+-end_getDigits:
+-  va_end(ap);
+-  return cnt;
 +void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey) {
 +  *zKey = ctx->read_ctx->pass;
 +  *nKey = ctx->read_ctx->pass_sz;
-+}
-+
+ }
+ 
+-/*
+-** Parse a timezone extension on the end of a date-time.
+-** The extension is of the form:
+-**
+-**        (+/-)HH:MM
+-**
+-** Or the "zulu" notation:
+-**
+-**        Z
+-**
+-** If the parse is successful, write the number of minutes
+-** of change in p->tz and return 0.  If a parser error occurs,
+-** return non-zero.
+-**
+-** A missing specifier is not considered an error.
+-*/
+-static int parseTimezone(const char *zDate, DateTime *p){
+-  int sgn = 0;
+-  int nHr, nMn;
+-  int c;
+-  while( sqlite3Isspace(*zDate) ){ zDate++; }
+-  p->tz = 0;
+-  c = *zDate;
+-  if( c=='-' ){
+-    sgn = -1;
+-  }else if( c=='+' ){
+-    sgn = +1;
+-  }else if( c=='Z' || c=='z' ){
+-    zDate++;
+-    goto zulu_time;
+-  }else{
+-    return c!=0;
+-  }
+-  zDate++;
+-  if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
+-    return 1;
 +int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) {
 +  /* attempt to free the existing page buffer */
 +  sqlcipher_free(ctx->buffer,ctx->page_sz);
@@ -2048,8 +3520,13 @@
 +
 +  if(fd == NULL || sqlite3OsRead(fd, ctx->kdf_salt, FILE_HEADER_SZ, 0) != SQLITE_OK) {
 +    /* if unable to read the bytes, generate random salt */
-+    if(sqlcipher_random(ctx->kdf_salt, FILE_HEADER_SZ) != 1) return SQLITE_ERROR;
-+  }
++    if(ctx->read_ctx->provider->random(ctx->read_ctx->provider_ctx, ctx->kdf_salt, FILE_HEADER_SZ) != 
SQLITE_OK) return SQLITE_ERROR;
+   }
+-  zDate += 5;
+-  p->tz = sgn*(nMn + nHr*60);
+-zulu_time:
+-  while( sqlite3Isspace(*zDate) ){ zDate++; }
+-  return *zDate!=0;
 +
 +  if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc;
 +  if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
@@ -2088,7 +3565,7 @@
 +  p[3] = (u8)(v>>24);
 +}
 +
-+int sqlcipher_page_hmac(cipher_ctx *ctx, Pgno pgno, unsigned char *in, int in_sz, unsigned char *out) {
++static int sqlcipher_page_hmac(cipher_ctx *ctx, Pgno pgno, unsigned char *in, int in_sz, unsigned char 
*out) {
 +  unsigned char pgno_raw[sizeof(pgno)];
 +  /* we may convert page number to consistent representation before calculating MAC for
 +     compatibility across big-endian and little-endian platforms. 
@@ -2106,20 +3583,35 @@
 +    memcpy(pgno_raw, &pgno, sizeof(pgno));
 +  }
 +
-+  HMAC_CTX_init(&ctx->hctx);
-+  HMAC_Init_ex(&ctx->hctx, ctx->hmac_key, ctx->key_sz, EVP_sha1(), NULL);
-+
 +  /* include the encrypted page data,  initialization vector, and page number in HMAC. This will 
 +     prevent both tampering with the ciphertext, manipulation of the IV, or resequencing otherwise
 +     valid pages out of order in a database */ 
-+  HMAC_Update(&ctx->hctx, in, in_sz);
-+  HMAC_Update(&ctx->hctx, (const unsigned char*) pgno_raw, sizeof(pgno)); 
-+  HMAC_Final(&ctx->hctx, out, NULL);
-+  HMAC_CTX_cleanup(&ctx->hctx);
++  ctx->provider->hmac(
++    ctx->provider_ctx, ctx->hmac_key,
++    ctx->key_sz, in,
++    in_sz, (unsigned char*) &pgno_raw,
++    sizeof(pgno), out);
 +  return SQLITE_OK; 
-+}
-+
-+/*
+ }
+ 
+ /*
+-** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
+-** The HH, MM, and SS must each be exactly 2 digits.  The
+-** fractional seconds FFFF can be one or more digits.
+-**
+-** Return 1 if there is a parsing error and 0 on success.
+-*/
+-static int parseHhMmSs(const char *zDate, DateTime *p){
+-  int h, m, s;
+-  double ms = 0.0;
+-  if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
+-    return 1;
+-  }
+-  zDate += 5;
+-  if( *zDate==':' ){
+-    zDate++;
+-    if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
+-      return 1;
 + * ctx - codec context
 + * pgno - page number in database
 + * size - size in bytes of input and output buffers
@@ -2130,7 +3622,7 @@
 +int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int page_sz, unsigned char *in, 
unsigned char *out) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  unsigned char *iv_in, *iv_out, *hmac_in, *hmac_out, *out_start;
-+  int tmp_csz, csz, size;
++  int size;
 +
 +  /* calculate some required positions into various buffers */
 +  size = page_sz - c_ctx->reserve_sz; /* adjust size to useable size and memset reserve at end of page */
@@ -2155,7 +3647,7 @@
 +
 +  if(mode == CIPHER_ENCRYPT) {
 +    /* start at front of the reserve block, write random data to the end */
-+    if(sqlcipher_random(iv_out, c_ctx->reserve_sz) != 1) return SQLITE_ERROR; 
++    if(c_ctx->provider->random(c_ctx->provider_ctx, iv_out, c_ctx->reserve_sz) != SQLITE_OK) return 
SQLITE_ERROR; 
 +  } else { /* CIPHER_DECRYPT */
 +    memcpy(iv_out, iv_in, c_ctx->iv_sz); /* copy the iv from the input to output buffer */
 +  } 
@@ -2165,7 +3657,15 @@
 +      sqlcipher_memset(out, 0, page_sz); 
 +      CODEC_TRACE(("codec_cipher: hmac operations failed for pgno=%d\n", pgno));
 +      return SQLITE_ERROR;
-+    }
+     }
+-    zDate += 2;
+-    if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
+-      double rScale = 1.0;
+-      zDate++;
+-      while( sqlite3Isdigit(*zDate) ){
+-        ms = ms*10.0 + *zDate - '0';
+-        rScale *= 10.0;
+-        zDate++;
 +
 +    CODEC_TRACE(("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out, 
c_ctx->hmac_sz));
 +    if(sqlcipher_memcmp(hmac_in, hmac_out, c_ctx->hmac_sz) != 0) { /* the hmac check failed */ 
@@ -2184,30 +3684,40 @@
 +              CODEC_TRACE(("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno));
 +        sqlcipher_memset(out, 0, page_sz); 
 +              return SQLITE_ERROR;
-+      }
-+    }
+       }
+-      ms /= rScale;
+     }
+-  }else{
+-    s = 0;
 +  } 
-+
-+  EVP_CipherInit(&c_ctx->ectx, c_ctx->evp_cipher, NULL, NULL, mode);
-+  EVP_CIPHER_CTX_set_padding(&c_ctx->ectx, 0);
-+  EVP_CipherInit(&c_ctx->ectx, NULL, c_ctx->key, iv_out, mode);
-+  EVP_CipherUpdate(&c_ctx->ectx, out, &tmp_csz, in, size);
-+  csz = tmp_csz;  
-+  out += tmp_csz;
-+  EVP_CipherFinal(&c_ctx->ectx, out, &tmp_csz);
-+  csz += tmp_csz;
-+  EVP_CIPHER_CTX_cleanup(&c_ctx->ectx);
-+  assert(size == csz);
++  
++  c_ctx->provider->cipher(c_ctx->provider_ctx, mode, c_ctx->key, c_ctx->key_sz, iv_out, in, size, out);
 +
 +  if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_ENCRYPT)) {
 +    sqlcipher_page_hmac(c_ctx, pgno, out_start, size + c_ctx->iv_sz, hmac_out); 
-+  }
+   }
+-  p->validJD = 0;
+-  p->validHMS = 1;
+-  p->h = h;
+-  p->m = m;
+-  p->s = s + ms;
+-  if( parseTimezone(zDate, p) ) return 1;
+-  p->validTZ = (p->tz!=0)?1:0;
+-  return 0;
 +
 +  CODEC_HEXDUMP("codec_cipher: output page data", out_start, page_sz);
 +
 +  return SQLITE_OK;
-+}
-+
+ }
+ 
+-/*
+-** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
+-** that the YYYY-MM-DD is according to the Gregorian calendar.
+-**
+-** Reference:  Meeus page 61
+-*/
+-static void computeJD(DateTime *p){
+-  int Y, M, D, A, B, X1, X2;
 +/**
 +  * Derive an encryption key for a cipher contex key based on the raw password.
 +  *
@@ -2219,7 +3729,7 @@
 +  * returns SQLITE_OK if initialization was successful
 +  * returns SQLITE_ERROR if the key could't be derived (for instance if pass is NULL or pass_sz is 0)
 +  */
-+int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
++static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
 +  CODEC_TRACE(("codec_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
 +                ctx->kdf_salt=%p ctx->kdf_salt_sz=%d c_ctx->kdf_iter=%d \
 +                ctx->hmac_kdf_salt=%p, c_ctx->fast_kdf_iter=%d c_ctx->key_sz=%d\n", 
@@ -2235,9 +3745,9 @@
 +      cipher_hex2bin(z, n, c_ctx->key);
 +    } else { 
 +      CODEC_TRACE(("codec_key_derive: deriving key using full PBKDF2 with %d iterations\n", 
c_ctx->kdf_iter)); 
-+      PKCS5_PBKDF2_HMAC_SHA1( c_ctx->pass, c_ctx->pass_sz, 
-+                              ctx->kdf_salt, ctx->kdf_salt_sz, 
-+                              c_ctx->kdf_iter, c_ctx->key_sz, c_ctx->key);
++      c_ctx->provider->kdf(c_ctx->provider_ctx, (const char*) c_ctx->pass, c_ctx->pass_sz, 
++                    ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
++                    c_ctx->key_sz, c_ctx->key);
 +                              
 +    }
 +
@@ -2246,7 +3756,20 @@
 +       this KDF run. This ensures a distinct but predictable HMAC key. */
 +    if(c_ctx->flags & CIPHER_FLAG_HMAC) {
 +      int i;
-+
+ 
+-  if( p->validJD ) return;
+-  if( p->validYMD ){
+-    Y = p->Y;
+-    M = p->M;
+-    D = p->D;
+-  }else{
+-    Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
+-    M = 1;
+-    D = 1;
+-  }
+-  if( M<=2 ){
+-    Y--;
+-    M += 12;
 +      /* start by copying the kdf key into the hmac salt slot
 +         then XOR it with the fixed hmac salt defined at compile time
 +         this ensures that the salt passed in to derive the hmac key, while 
@@ -2259,9 +3782,11 @@
 +
 +      CODEC_TRACE(("codec_key_derive: deriving hmac key from encryption key using PBKDF2 with %d 
iterations\n", 
 +        c_ctx->fast_kdf_iter)); 
-+      PKCS5_PBKDF2_HMAC_SHA1( (const char*)c_ctx->key, c_ctx->key_sz, 
-+                              ctx->hmac_kdf_salt, ctx->kdf_salt_sz, 
-+                              c_ctx->fast_kdf_iter, c_ctx->key_sz, c_ctx->hmac_key); 
++
++      
++      c_ctx->provider->kdf(c_ctx->provider_ctx, (const char*)c_ctx->key, c_ctx->key_sz, 
++                    ctx->hmac_kdf_salt, ctx->kdf_salt_sz, c_ctx->fast_kdf_iter,
++                    c_ctx->key_sz, c_ctx->hmac_key); 
 +    }
 +
 +    c_ctx->derive_key = 0;
@@ -2274,7 +3799,20 @@
 +  /* derive key on first use if necessary */
 +  if(ctx->read_ctx->derive_key) {
 +    if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->read_ctx) != SQLITE_OK) return SQLITE_ERROR;
-+  }
+   }
+-  A = Y/100;
+-  B = 2 - A + (A/4);
+-  X1 = 36525*(Y+4716)/100;
+-  X2 = 306001*(M+1)/10000;
+-  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
+-  p->validJD = 1;
+-  if( p->validHMS ){
+-    p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
+-    if( p->validTZ ){
+-      p->iJD -= p->tz*60000;
+-      p->validYMD = 0;
+-      p->validHMS = 0;
+-      p->validTZ = 0;
 +
 +  if(ctx->write_ctx->derive_key) {
 +    if(sqlcipher_cipher_ctx_cmp(ctx->write_ctx, ctx->read_ctx) == 0) {
@@ -2282,8 +3820,8 @@
 +      if(sqlcipher_cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx) != SQLITE_OK) return SQLITE_ERROR;
 +    } else {
 +      if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->write_ctx) != SQLITE_OK) return SQLITE_ERROR;
-+    }
-+  }
+     }
+   }
 +  return SQLITE_OK; 
 +}
 +
@@ -2295,209 +3833,1540 @@
 +  }
 +}
 +
++const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) {
++  return ctx->read_ctx->provider->get_provider_name(ctx->read_ctx);
+ }
+ 
++#endif
++/* END SQLCIPHER */
 +
-+#ifndef OMIT_EXPORT
++/************** End of crypto_impl.c *****************************************/
++/************** Begin file crypto_libtomcrypt.c ******************************/
+ /*
+-** Parse dates of the form
++** SQLCipher
++** http://sqlcipher.net
+ **
+-**     YYYY-MM-DD HH:MM:SS.FFF
+-**     YYYY-MM-DD HH:MM:SS
+-**     YYYY-MM-DD HH:MM
+-**     YYYY-MM-DD
++** Copyright (c) 2008 - 2013, ZETETIC LLC
++** All rights reserved.
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++**     * Redistributions of source code must retain the above copyright
++**       notice, this list of conditions and the following disclaimer.
++**     * Redistributions in binary form must reproduce the above copyright
++**       notice, this list of conditions and the following disclaimer in the
++**       documentation and/or other materials provided with the distribution.
++**     * Neither the name of the ZETETIC LLC nor the
++**       names of its contributors may be used to endorse or promote products
++**       derived from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
++** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
++** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+-** Write the result into the DateTime structure and return 0
+-** on success and 1 if the input string is not a well-formed
+-** date.
+ */
+-static int parseYyyyMmDd(const char *zDate, DateTime *p){
+-  int Y, M, D, neg;
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
++#ifdef SQLCIPHER_CRYPTO_LIBTOMCRYPT
++#include <tomcrypt.h>
+ 
+-  if( zDate[0]=='-' ){
+-    zDate++;
+-    neg = 1;
+-  }else{
+-    neg = 0;
++typedef struct {
++  prng_state prng;
++} ltc_ctx;
 +
-+/*
-+ * Implementation of an "export" function that allows a caller
-+ * to duplicate the main database to an attached database. This is intended
-+ * as a conveneince for users who need to:
-+ * 
-+ *   1. migrate from an non-encrypted database to an encrypted database
-+ *   2. move from an encrypted database to a non-encrypted database
-+ *   3. convert beween the various flavors of encrypted databases.  
-+ *
-+ * This implementation is based heavily on the procedure and code used
-+ * in vacuum.c, but is exposed as a function that allows export to any
-+ * named attached database.
-+ */
++static unsigned int ltc_init = 0;
 +
-+/*
-+** Finalize a prepared statement.  If there was an error, store the
-+** text of the error message in *pzErrMsg.  Return the result code.
-+** 
-+** Based on vacuumFinalize from vacuum.c
-+*/
-+static int sqlcipher_finalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
-+  int rc;
-+  rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
-+  if( rc ){
-+    sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
-+  }
-+  return rc;
++static int sqlcipher_ltc_add_random(void *ctx, void *buffer, int length) {
++  ltc_ctx *ltc = (ltc_ctx*)ctx;
++  int rc = fortuna_add_entropy(buffer, length, &(ltc->prng));
++  return rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK;
 +}
 +
-+/*
-+** Execute zSql on database db. Return an error code.
-+** 
-+** Based on execSql from vacuum.c
-+*/
-+static int sqlcipher_execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
-+  sqlite3_stmt *pStmt;
-+  VVA_ONLY( int rc; )
-+  if( !zSql ){
-+    return SQLITE_NOMEM;
-+  }
-+  if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
-+    sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
-+    return sqlite3_errcode(db);
++static int sqlcipher_ltc_activate(void *ctx) {
++  ltc_ctx *ltc = (ltc_ctx*)ctx;
++  int random_buffer_sz = 32;
++  unsigned char random_buffer[random_buffer_sz];
++  
++  if(ltc_init == 0) {
++    if(register_prng(&fortuna_desc) != CRYPT_OK) return SQLITE_ERROR;
++    if(register_cipher(&rijndael_desc) != CRYPT_OK) return SQLITE_ERROR;
++    if(register_hash(&sha1_desc) != CRYPT_OK) return SQLITE_ERROR;
++    ltc_init = 1;
+   }
+-  if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
+-    return 1;
++  if(fortuna_start(&(ltc->prng)) != CRYPT_OK) {
++    return SQLITE_ERROR;
+   }
+-  zDate += 10;
+-  while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
+-  if( parseHhMmSs(zDate, p)==0 ){
+-    /* We got the time */
+-  }else if( *zDate==0 ){
+-    p->validHMS = 0;
+-  }else{
+-    return 1;
++  sqlite3_randomness(random_buffer_sz, &random_buffer);
++  if(sqlcipher_ltc_add_random(ctx, random_buffer, random_buffer_sz) != SQLITE_OK) {
++    return SQLITE_ERROR;
+   }
+-  p->validJD = 0;
+-  p->validYMD = 1;
+-  p->Y = neg ? -Y : Y;
+-  p->M = M;
+-  p->D = D;
+-  if( p->validTZ ){
+-    computeJD(p);
++  if(sqlcipher_ltc_add_random(ctx, &ltc, sizeof(ltc_ctx*)) != SQLITE_OK) {
++    return SQLITE_ERROR;
+   }
+-  return 0;
++  if(fortuna_ready(&(ltc->prng)) != CRYPT_OK) {
++    return SQLITE_ERROR;
 +  }
-+  VVA_ONLY( rc = ) sqlite3_step(pStmt);
-+  assert( rc!=SQLITE_ROW );
-+  return sqlcipher_finalize(db, pStmt, pzErrMsg);
++  return SQLITE_OK;
+ }
+ 
+-/*
+-** Set the time to the current time reported by the VFS.
+-**
+-** Return the number of errors.
+-*/
+-static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
+-  sqlite3 *db = sqlite3_context_db_handle(context);
+-  if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
+-    p->validJD = 1;
+-    return 0;
+-  }else{
+-    return 1;
++static int sqlcipher_ltc_deactivate(void *ctx) {
++  ltc_ctx *ltc = (ltc_ctx*)ctx;
++  fortuna_done(&(ltc->prng));
 +}
 +
-+/*
-+** Execute zSql on database db. The statement returns exactly
-+** one column. Execute this as SQL on the same database.
-+** 
-+** Based on execExecSql from vacuum.c
-+*/
-+static int sqlcipher_execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
-+  sqlite3_stmt *pStmt;
++static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
++  return "libtomcrypt";
++}
++
++static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) {
++  ltc_ctx *ltc = (ltc_ctx*)ctx;
 +  int rc;
++  
++  if((rc = fortuna_ready(&(ltc->prng))) != CRYPT_OK) {
++    return SQLITE_ERROR;
+   }
++  fortuna_read(buffer, length, &(ltc->prng));
++  return SQLITE_OK;
+ }
+ 
+-/*
+-** Attempt to parse the given string into a Julian Day Number.  Return
+-** the number of errors.
+-**
+-** The following are acceptable forms for the input string:
+-**
+-**      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
+-**      DDDD.DD 
+-**      now
+-**
+-** In the first form, the +/-HH:MM is always optional.  The fractional
+-** seconds extension (the ".FFF") is optional.  The seconds portion
+-** (":SS.FFF") is option.  The year and date can be omitted as long
+-** as there is a time string.  The time string can be omitted as long
+-** as there is a year and date.
+-*/
+-static int parseDateOrTime(
+-  sqlite3_context *context, 
+-  const char *zDate, 
+-  DateTime *p
+-){
+-  double r;
+-  if( parseYyyyMmDd(zDate,p)==0 ){
+-    return 0;
+-  }else if( parseHhMmSs(zDate, p)==0 ){
+-    return 0;
+-  }else if( sqlite3StrICmp(zDate,"now")==0){
+-    return setDateTimeToCurrent(context, p);
+-  }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
+-    p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
+-    p->validJD = 1;
+-    return 0;
++static int sqlcipher_ltc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, 
unsigned char *in2, int in2_sz, unsigned char *out) {
++  int rc, hash_idx;
++  hmac_state hmac;
++  unsigned long outlen = key_sz;
 +
-+  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
-+  if( rc!=SQLITE_OK ) return rc;
++  hash_idx = find_hash("sha1");
++  if((rc = hmac_init(&hmac, hash_idx, hmac_key, key_sz)) != CRYPT_OK) return SQLITE_ERROR;
++  if((rc = hmac_process(&hmac, in, in_sz)) != CRYPT_OK) return SQLITE_ERROR;
++  if((rc = hmac_process(&hmac, in2, in2_sz)) != CRYPT_OK) return SQLITE_ERROR;
++  if((rc = hmac_done(&hmac, out, &outlen)) != CRYPT_OK) return SQLITE_ERROR;
++  return SQLITE_OK;
++}
 +
-+  while( SQLITE_ROW==sqlite3_step(pStmt) ){
-+    rc = sqlcipher_execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
-+    if( rc!=SQLITE_OK ){
-+      sqlcipher_finalize(db, pStmt, pzErrMsg);
-+      return rc;
-+    }
++static int sqlcipher_ltc_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz, 
int workfactor, int key_sz, unsigned char *key) {
++  int rc, hash_idx;
++  unsigned long outlen = key_sz;
++  unsigned long random_buffer_sz = 256;
++  char random_buffer[random_buffer_sz];
++  ltc_ctx *ltc = (ltc_ctx*)ctx;
++
++  hash_idx = find_hash("sha1");
++  if((rc = pkcs_5_alg2(pass, pass_sz, salt, salt_sz,
++                       workfactor, hash_idx, key, &outlen)) != CRYPT_OK) {
++    return SQLITE_ERROR;
+   }
+-  return 1;
++  if((rc = pkcs_5_alg2(key, key_sz, salt, salt_sz,
++                       1, hash_idx, random_buffer, &random_buffer_sz)) != CRYPT_OK) {
++    return SQLITE_ERROR;
 +  }
++  sqlcipher_ltc_add_random(ctx, random_buffer, random_buffer_sz);
++  return SQLITE_OK;
+ }
+ 
+-/*
+-** Compute the Year, Month, and Day from the julian day number.
+-*/
+-static void computeYMD(DateTime *p){
+-  int Z, A, B, C, D, E, X1;
+-  if( p->validYMD ) return;
+-  if( !p->validJD ){
+-    p->Y = 2000;
+-    p->M = 1;
+-    p->D = 1;
+-  }else{
+-    Z = (int)((p->iJD + 43200000)/86400000);
+-    A = (int)((Z - 1867216.25)/36524.25);
+-    A = Z + 1 + A - (A/4);
+-    B = A + 1524;
+-    C = (int)((B - 122.1)/365.25);
+-    D = (36525*C)/100;
+-    E = (int)((B-D)/30.6001);
+-    X1 = (int)(30.6001*E);
+-    p->D = B - D - X1;
+-    p->M = E<14 ? E-1 : E-13;
+-    p->Y = p->M>2 ? C - 4716 : C - 4715;
+-  }
+-  p->validYMD = 1;
++static const char* sqlcipher_ltc_get_cipher(void *ctx) {
++  return "rijndael";
+ }
+ 
+-/*
+-** Compute the Hour, Minute, and Seconds from the julian day number.
+-*/
+-static void computeHMS(DateTime *p){
+-  int s;
+-  if( p->validHMS ) return;
+-  computeJD(p);
+-  s = (int)((p->iJD + 43200000) % 86400000);
+-  p->s = s/1000.0;
+-  s = (int)p->s;
+-  p->s -= s;
+-  p->h = s/3600;
+-  s -= p->h*3600;
+-  p->m = s/60;
+-  p->s += s - p->m*60;
+-  p->validHMS = 1;
++static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, 
unsigned char *in, int in_sz, unsigned char *out) {
++  int rc, cipher_idx, hash_idx;
++  symmetric_CBC cbc;
 +
-+  return sqlcipher_finalize(db, pStmt, pzErrMsg);
++  if((cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx))) == -1) return SQLITE_ERROR;
++  if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR;
++  rc = mode == 1 ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc);
++  if(rc != CRYPT_OK) return SQLITE_ERROR;
++  cbc_done(&cbc);
++  return SQLITE_OK;
+ }
+ 
+-/*
+-** Compute both YMD and HMS
+-*/
+-static void computeYMD_HMS(DateTime *p){
+-  computeYMD(p);
+-  computeHMS(p);
++static int sqlcipher_ltc_set_cipher(void *ctx, const char *cipher_name) {
++  return SQLITE_OK;
+ }
+ 
+-/*
+-** Clear the YMD and HMS and the TZ
+-*/
+-static void clearYMD_HMS_TZ(DateTime *p){
+-  p->validYMD = 0;
+-  p->validHMS = 0;
+-  p->validTZ = 0;
++static int sqlcipher_ltc_get_key_sz(void *ctx) {
++  int cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx));
++  return cipher_descriptor[cipher_idx].max_key_length;
+ }
+ 
+-/*
+-** On recent Windows platforms, the localtime_s() function is available
+-** as part of the "Secure CRT". It is essentially equivalent to 
+-** localtime_r() available under most POSIX platforms, except that the 
+-** order of the parameters is reversed.
+-**
+-** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
+-**
+-** If the user has not indicated to use localtime_r() or localtime_s()
+-** already, check for an MSVC build environment that provides 
+-** localtime_s().
+-*/
+-#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
+-     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
+-#define HAVE_LOCALTIME_S 1
+-#endif
++static int sqlcipher_ltc_get_iv_sz(void *ctx) {
++  int cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx));
++  return cipher_descriptor[cipher_idx].block_length;
++}
+ 
+-#ifndef SQLITE_OMIT_LOCALTIME
+-/*
+-** The following routine implements the rough equivalent of localtime_r()
+-** using whatever operating-system specific localtime facility that
+-** is available.  This routine returns 0 on success and
+-** non-zero on any kind of error.
+-**
+-** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
+-** routine will always fail.
+-*/
+-static int osLocaltime(time_t *t, struct tm *pTm){
+-  int rc;
+-#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
+-      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
+-  struct tm *pX;
+-#if SQLITE_THREADSAFE>0
+-  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+-#endif
+-  sqlite3_mutex_enter(mutex);
+-  pX = localtime(t);
+-#ifndef SQLITE_OMIT_BUILTIN_TEST
+-  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
+-#endif
+-  if( pX ) *pTm = *pX;
+-  sqlite3_mutex_leave(mutex);
+-  rc = pX==0;
+-#else
+-#ifndef SQLITE_OMIT_BUILTIN_TEST
+-  if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
+-#endif
+-#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
+-  rc = localtime_r(t, pTm)==0;
+-#else
+-  rc = localtime_s(pTm, t);
+-#endif /* HAVE_LOCALTIME_R */
+-#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
+-  return rc;
++static int sqlcipher_ltc_get_block_sz(void *ctx) {
++  int cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx));
++  return cipher_descriptor[cipher_idx].block_length;
+ }
+-#endif /* SQLITE_OMIT_LOCALTIME */
+ 
++static int sqlcipher_ltc_get_hmac_sz(void *ctx) {
++  int hash_idx = find_hash("sha1");
++  return hash_descriptor[hash_idx].hashsize;
++}
+ 
+-#ifndef SQLITE_OMIT_LOCALTIME
+-/*
+-** Compute the difference (in milliseconds) between localtime and UTC
+-** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
+-** return this value and set *pRc to SQLITE_OK. 
+-**
+-** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
+-** is undefined in this case.
+-*/
+-static sqlite3_int64 localtimeOffset(
+-  DateTime *p,                    /* Date at which to calculate offset */
+-  sqlite3_context *pCtx,          /* Write error here if one occurs */
+-  int *pRc                        /* OUT: Error code. SQLITE_OK or ERROR */
+-){
+-  DateTime x, y;
+-  time_t t;
+-  struct tm sLocal;
++static int sqlcipher_ltc_ctx_copy(void *target_ctx, void *source_ctx) {
++  memcpy(target_ctx, source_ctx, sizeof(ltc_ctx));
++  return SQLITE_OK;
++}
+ 
+-  /* Initialize the contents of sLocal to avoid a compiler warning. */
+-  memset(&sLocal, 0, sizeof(sLocal));
++static int sqlcipher_ltc_ctx_cmp(void *c1, void *c2) {
++  return 1;
++}
+ 
+-  x = *p;
+-  computeYMD_HMS(&x);
+-  if( x.Y<1971 || x.Y>=2038 ){
+-    x.Y = 2000;
+-    x.M = 1;
+-    x.D = 1;
+-    x.h = 0;
+-    x.m = 0;
+-    x.s = 0.0;
+-  } else {
+-    int s = (int)(x.s + 0.5);
+-    x.s = s;
+-  }
+-  x.tz = 0;
+-  x.validJD = 0;
+-  computeJD(&x);
+-  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
+-  if( osLocaltime(&t, &sLocal) ){
+-    sqlite3_result_error(pCtx, "local time unavailable", -1);
+-    *pRc = SQLITE_ERROR;
+-    return 0;
+-  }
+-  y.Y = sLocal.tm_year + 1900;
+-  y.M = sLocal.tm_mon + 1;
+-  y.D = sLocal.tm_mday;
+-  y.h = sLocal.tm_hour;
+-  y.m = sLocal.tm_min;
+-  y.s = sLocal.tm_sec;
+-  y.validYMD = 1;
+-  y.validHMS = 1;
+-  y.validJD = 0;
+-  y.validTZ = 0;
+-  computeJD(&y);
+-  *pRc = SQLITE_OK;
+-  return y.iJD - x.iJD;
++static int sqlcipher_ltc_ctx_init(void **ctx) {
++  *ctx = sqlcipher_malloc(sizeof(ltc_ctx));
++  if(*ctx == NULL) return SQLITE_NOMEM;
++  sqlcipher_ltc_activate(*ctx);
++  return SQLITE_OK;
 +}
 +
-+/*
-+ * copy database and schema from the main database to an attached database
-+ * 
-+ * Based on sqlite3RunVacuum from vacuum.c
-+*/
-+void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
-+  sqlite3 *db = sqlite3_context_db_handle(context);
-+  const char* attachedDb = (const char*) sqlite3_value_text(argv[0]);
-+  int saved_flags;        /* Saved value of the db->flags */
-+  int saved_nChange;      /* Saved value of db->nChange */
-+  int saved_nTotalChange; /* Saved value of db->nTotalChange */
-+  void (*saved_xTrace)(void*,const char*);  /* Saved db->xTrace */
-+  int rc = SQLITE_OK;     /* Return code from service routines */
-+  char *zSql = NULL;         /* SQL statements */
-+  char *pzErrMsg = NULL;
-+  
-+  saved_flags = db->flags;
-+  saved_nChange = db->nChange;
-+  saved_nTotalChange = db->nTotalChange;
-+  saved_xTrace = db->xTrace;
-+  db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
-+  db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
-+  db->xTrace = 0;
-+
-+  /* Query the schema of the main database. Create a mirror schema
-+  ** in the temporary database.
-+  */
-+  zSql = sqlite3_mprintf(
-+    "SELECT 'CREATE TABLE %s.' || substr(sql,14) "
-+    "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
-+    "   AND rootpage>0"
-+  , attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
-+
-+  zSql = sqlite3_mprintf(
-+    "SELECT 'CREATE INDEX %s.' || substr(sql,14)"
-+    "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %%' "
-+  , attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
++static int sqlcipher_ltc_ctx_free(void **ctx) {
++  sqlcipher_ltc_deactivate(&ctx);
++  sqlcipher_free(*ctx, sizeof(ltc_ctx));
++  return SQLITE_OK;
++}
 +
-+  zSql = sqlite3_mprintf(
-+    "SELECT 'CREATE UNIQUE INDEX %s.' || substr(sql,21) "
-+    "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %%'"
-+  , attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
++int sqlcipher_ltc_setup(sqlcipher_provider *p) {
++  p->activate = sqlcipher_ltc_activate;
++  p->deactivate = sqlcipher_ltc_deactivate;
++  p->get_provider_name = sqlcipher_ltc_get_provider_name;
++  p->random = sqlcipher_ltc_random;
++  p->hmac = sqlcipher_ltc_hmac;
++  p->kdf = sqlcipher_ltc_kdf;
++  p->cipher = sqlcipher_ltc_cipher;
++  p->set_cipher = sqlcipher_ltc_set_cipher;
++  p->get_cipher = sqlcipher_ltc_get_cipher;
++  p->get_key_sz = sqlcipher_ltc_get_key_sz;
++  p->get_iv_sz = sqlcipher_ltc_get_iv_sz;
++  p->get_block_sz = sqlcipher_ltc_get_block_sz;
++  p->get_hmac_sz = sqlcipher_ltc_get_hmac_sz;
++  p->ctx_copy = sqlcipher_ltc_ctx_copy;
++  p->ctx_cmp = sqlcipher_ltc_ctx_cmp;
++  p->ctx_init = sqlcipher_ltc_ctx_init;
++  p->ctx_free = sqlcipher_ltc_ctx_free;
++  p->add_random = sqlcipher_ltc_add_random;
+ }
+-#endif /* SQLITE_OMIT_LOCALTIME */
+ 
+-/*
+-** Process a modifier to a date-time stamp.  The modifiers are
+-** as follows:
+-**
+-**     NNN days
+-**     NNN hours
+-**     NNN minutes
+-**     NNN.NNNN seconds
+-**     NNN months
+-**     NNN years
+-**     start of month
+-**     start of year
+-**     start of week
+-**     start of day
+-**     weekday N
+-**     unixepoch
+-**     localtime
+-**     utc
+-**
+-** Return 0 on success and 1 if there is any kind of error. If the error
+-** is in a system call (i.e. localtime()), then an error message is written
+-** to context pCtx. If the error is an unrecognized modifier, no error is
+-** written to pCtx.
+-*/
+-static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
+-  int rc = 1;
+-  int n;
+-  double r;
+-  char *z, zBuf[30];
+-  z = zBuf;
+-  for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
+-    z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
+-  }
+-  z[n] = 0;
+-  switch( z[0] ){
+-#ifndef SQLITE_OMIT_LOCALTIME
+-    case 'l': {
+-      /*    localtime
+-      **
+-      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
+-      ** show local time.
+-      */
+-      if( strcmp(z, "localtime")==0 ){
+-        computeJD(p);
+-        p->iJD += localtimeOffset(p, pCtx, &rc);
+-        clearYMD_HMS_TZ(p);
+-      }
+-      break;
+-    }
+ #endif
+-    case 'u': {
+-      /*
+-      **    unixepoch
+-      **
+-      ** Treat the current value of p->iJD as the number of
+-      ** seconds since 1970.  Convert to a real julian day number.
+-      */
+-      if( strcmp(z, "unixepoch")==0 && p->validJD ){
+-        p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
+-        clearYMD_HMS_TZ(p);
+-        rc = 0;
+-      }
+-#ifndef SQLITE_OMIT_LOCALTIME
+-      else if( strcmp(z, "utc")==0 ){
+-        sqlite3_int64 c1;
+-        computeJD(p);
+-        c1 = localtimeOffset(p, pCtx, &rc);
+-        if( rc==SQLITE_OK ){
+-          p->iJD -= c1;
+-          clearYMD_HMS_TZ(p);
+-          p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
+-        }
+-      }
+ #endif
+-      break;
+-    }
+-    case 'w': {
+-      /*
+-      **    weekday N
+-      **
+-      ** Move the date to the same time on the next occurrence of
+-      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
+-      ** date is already on the appropriate weekday, this is a no-op.
+-      */
+-      if( strncmp(z, "weekday ", 8)==0
+-               && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
+-               && (n=(int)r)==r && n>=0 && r<7 ){
+-        sqlite3_int64 Z;
+-        computeYMD_HMS(p);
+-        p->validTZ = 0;
+-        p->validJD = 0;
+-        computeJD(p);
+-        Z = ((p->iJD + 129600000)/86400000) % 7;
+-        if( Z>n ) Z -= 7;
+-        p->iJD += (n - Z)*86400000;
+-        clearYMD_HMS_TZ(p);
+-        rc = 0;
+-      }
+-      break;
+-    }
+-    case 's': {
+-      /*
+-      **    start of TTTTT
+-      **
+-      ** Move the date backwards to the beginning of the current day,
+-      ** or month or year.
+-      */
+-      if( strncmp(z, "start of ", 9)!=0 ) break;
+-      z += 9;
+-      computeYMD(p);
+-      p->validHMS = 1;
+-      p->h = p->m = 0;
+-      p->s = 0.0;
+-      p->validTZ = 0;
+-      p->validJD = 0;
+-      if( strcmp(z,"month")==0 ){
+-        p->D = 1;
+-        rc = 0;
+-      }else if( strcmp(z,"year")==0 ){
+-        computeYMD(p);
+-        p->M = 1;
+-        p->D = 1;
+-        rc = 0;
+-      }else if( strcmp(z,"day")==0 ){
+-        rc = 0;
+-      }
+-      break;
+-    }
+-    case '+':
+-    case '-':
+-    case '0':
+-    case '1':
+-    case '2':
+-    case '3':
+-    case '4':
+-    case '5':
+-    case '6':
+-    case '7':
+-    case '8':
+-    case '9': {
+-      double rRounder;
+-      for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
+-      if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
+-        rc = 1;
+-        break;
+-      }
+-      if( z[n]==':' ){
+-        /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
+-        ** specified number of hours, minutes, seconds, and fractional seconds
+-        ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
+-        ** omitted.
+-        */
+-        const char *z2 = z;
+-        DateTime tx;
+-        sqlite3_int64 day;
+-        if( !sqlite3Isdigit(*z2) ) z2++;
+-        memset(&tx, 0, sizeof(tx));
+-        if( parseHhMmSs(z2, &tx) ) break;
+-        computeJD(&tx);
+-        tx.iJD -= 43200000;
+-        day = tx.iJD/86400000;
+-        tx.iJD -= day*86400000;
+-        if( z[0]=='-' ) tx.iJD = -tx.iJD;
+-        computeJD(p);
+-        clearYMD_HMS_TZ(p);
+-        p->iJD += tx.iJD;
+-        rc = 0;
+-        break;
+-      }
+-      z += n;
+-      while( sqlite3Isspace(*z) ) z++;
+-      n = sqlite3Strlen30(z);
+-      if( n>10 || n<3 ) break;
+-      if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
+-      computeJD(p);
+-      rc = 0;
+-      rRounder = r<0 ? -0.5 : +0.5;
+-      if( n==3 && strcmp(z,"day")==0 ){
+-        p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
+-      }else if( n==4 && strcmp(z,"hour")==0 ){
+-        p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
+-      }else if( n==6 && strcmp(z,"minute")==0 ){
+-        p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
+-      }else if( n==6 && strcmp(z,"second")==0 ){
+-        p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
+-      }else if( n==5 && strcmp(z,"month")==0 ){
+-        int x, y;
+-        computeYMD_HMS(p);
+-        p->M += (int)r;
+-        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
+-        p->Y += x;
+-        p->M -= x*12;
+-        p->validJD = 0;
+-        computeJD(p);
+-        y = (int)r;
+-        if( y!=r ){
+-          p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
+-        }
+-      }else if( n==4 && strcmp(z,"year")==0 ){
+-        int y = (int)r;
+-        computeYMD_HMS(p);
+-        p->Y += y;
+-        p->validJD = 0;
+-        computeJD(p);
+-        if( y!=r ){
+-          p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
+-        }
+-      }else{
+-        rc = 1;
+-      }
+-      clearYMD_HMS_TZ(p);
+-      break;
+-    }
+-    default: {
+-      break;
++/* END SQLCIPHER */
 +
-+  /* Loop through the tables in the main database. For each, do
-+  ** an "INSERT INTO rekey_db.xxx SELECT * FROM main.xxx;" to copy
-+  ** the contents to the temporary database.
-+  */
-+  zSql = sqlite3_mprintf(
-+    "SELECT 'INSERT INTO %s.' || quote(name) "
-+    "|| ' SELECT * FROM main.' || quote(name) || ';'"
-+    "FROM main.sqlite_master "
-+    "WHERE type = 'table' AND name!='sqlite_sequence' "
-+    "  AND rootpage>0"
-+  , attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
++/************** End of crypto_libtomcrypt.c **********************************/
++/************** Begin file crypto_openssl.c **********************************/
++/*
++** SQLCipher
++** http://sqlcipher.net
++**
++** Copyright (c) 2008 - 2013, ZETETIC LLC
++** All rights reserved.
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++**     * Redistributions of source code must retain the above copyright
++**       notice, this list of conditions and the following disclaimer.
++**     * Redistributions in binary form must reproduce the above copyright
++**       notice, this list of conditions and the following disclaimer in the
++**       documentation and/or other materials provided with the distribution.
++**     * Neither the name of the ZETETIC LLC nor the
++**       names of its contributors may be used to endorse or promote products
++**       derived from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
++** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
++** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++**
++*/
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
++#ifdef SQLCIPHER_CRYPTO_OPENSSL
++#include <openssl/rand.h>
++#include <openssl/evp.h>
++#include <openssl/hmac.h>
 +
-+  /* Copy over the sequence table
-+  */
-+  zSql = sqlite3_mprintf(
-+    "SELECT 'DELETE FROM %s.' || quote(name) || ';' "
-+    "FROM %s.sqlite_master WHERE name='sqlite_sequence' "
-+  , attachedDb, attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
++typedef struct {
++  EVP_CIPHER *evp_cipher;
++} openssl_ctx;
 +
-+  zSql = sqlite3_mprintf(
-+    "SELECT 'INSERT INTO %s.' || quote(name) "
-+    "|| ' SELECT * FROM main.' || quote(name) || ';' "
-+    "FROM %s.sqlite_master WHERE name=='sqlite_sequence';"
-+  , attachedDb, attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
 +
-+  /* Copy the triggers, views, and virtual tables from the main database
-+  ** over to the temporary database.  None of these objects has any
-+  ** associated storage, so all we have to do is copy their entries
-+  ** from the SQLITE_MASTER table.
-+  */
-+  zSql = sqlite3_mprintf(
-+    "INSERT INTO %s.sqlite_master "
-+    "  SELECT type, name, tbl_name, rootpage, sql"
-+    "    FROM main.sqlite_master"
-+    "   WHERE type='view' OR type='trigger'"
-+    "      OR (type='table' AND rootpage=0)"
-+  , attachedDb);
-+  rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execSql(db, &pzErrMsg, zSql); 
-+  if( rc!=SQLITE_OK ) goto end_of_export;
-+  sqlite3_free(zSql);
++static unsigned int openssl_external_init = 0;
++static unsigned int openssl_init_count = 0;
 +
-+  zSql = NULL;
-+end_of_export:
-+  db->flags = saved_flags;
-+  db->nChange = saved_nChange;
-+  db->nTotalChange = saved_nTotalChange;
-+  db->xTrace = saved_xTrace;
 +
-+  sqlite3_free(zSql);
++static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
++  RAND_add(buffer, length, 0);
++  return SQLITE_OK;
++}
 +
-+  if(rc) {
-+    if(pzErrMsg != NULL) {
-+      sqlite3_result_error(context, pzErrMsg, -1);
-+      sqlite3DbFree(db, pzErrMsg);
-+    } else {
-+      sqlite3_result_error(context, sqlite3ErrStr(rc), -1);
-+    }
++/* activate and initialize sqlcipher. Most importantly, this will automatically
++   intialize OpenSSL's EVP system if it hasn't already be externally. Note that 
++   this function may be called multiple times as new codecs are intiialized. 
++   Thus it performs some basic counting to ensure that only the last and final
++   sqlcipher_openssl_deactivate() will free the EVP structures. 
++*/
++static int sqlcipher_openssl_activate(void *ctx) {
++  /* we'll initialize openssl and increment the internal init counter
++     but only if it hasn't been initalized outside of SQLCipher by this program 
++     e.g. on startup */
++  if(openssl_init_count == 0 && EVP_get_cipherbyname(CIPHER) != NULL) {
++    openssl_external_init = 1;
 +  }
++
++  if(openssl_external_init == 0) {
++    if(openssl_init_count == 0)  {
++      OpenSSL_add_all_algorithms();
+     }
+-  }
+-  return rc;
++    openssl_init_count++; 
++  } 
++  return SQLITE_OK;
+ }
+ 
+-/*
+-** Process time function arguments.  argv[0] is a date-time stamp.
+-** argv[1] and following are modifiers.  Parse them all and write
+-** the resulting time into the DateTime structure p.  Return 0
+-** on success and 1 if there are any errors.
+-**
+-** If there are zero parameters (if even argv[0] is undefined)
+-** then assume a default value of "now" for argv[0].
+-*/
+-static int isDate(
+-  sqlite3_context *context, 
+-  int argc, 
+-  sqlite3_value **argv, 
+-  DateTime *p
+-){
+-  int i;
+-  const unsigned char *z;
+-  int eType;
+-  memset(p, 0, sizeof(*p));
+-  if( argc==0 ){
+-    return setDateTimeToCurrent(context, p);
+-  }
+-  if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
+-                   || eType==SQLITE_INTEGER ){
+-    p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
+-    p->validJD = 1;
+-  }else{
+-    z = sqlite3_value_text(argv[0]);
+-    if( !z || parseDateOrTime(context, (char*)z, p) ){
+-      return 1;
++/* deactivate SQLCipher, most imporantly decremeting the activation count and
++   freeing the EVP structures on the final deactivation to ensure that 
++   OpenSSL memory is cleaned up */
++static int sqlcipher_openssl_deactivate(void *ctx) {
++  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++  /* If it is initialized externally, then the init counter should never be greater than zero.
++     This should prevent SQLCipher from "cleaning up" openssl 
++     when something else in the program might be using it. */
++  if(openssl_external_init == 0) {
++    openssl_init_count--;
++    /* if the counter reaches zero after it's decremented release EVP memory
++       Note: this code will only be reached if OpensSSL_add_all_algorithms()
++       is called by SQLCipher internally. */
++    if(openssl_init_count == 0) {
++      EVP_cleanup();
+     }
+   }
+-  for(i=1; i<argc; i++){
+-    z = sqlite3_value_text(argv[i]);
+-    if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
+-  }
+-  return 0;
++  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++  return SQLITE_OK;
+ }
+ 
++static const char* sqlcipher_openssl_get_provider_name(void *ctx) {
++  return "openssl";
++}
+ 
+-/*
+-** The following routines implement the various date and time functions
+-** of SQLite.
+-*/
++/* generate a defined number of random bytes */
++static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) {
++  return (RAND_bytes((unsigned char *)buffer, length) == 1) ? SQLITE_OK : SQLITE_ERROR;
 +}
 +
++static int sqlcipher_openssl_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int 
in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
++  HMAC_CTX hctx;
++  unsigned int outlen;
++  HMAC_CTX_init(&hctx);
++  HMAC_Init_ex(&hctx, hmac_key, key_sz, EVP_sha1(), NULL);
++  HMAC_Update(&hctx, in, in_sz);
++  HMAC_Update(&hctx, in2, in2_sz);
++  HMAC_Final(&hctx, out, &outlen);
++  HMAC_CTX_cleanup(&hctx);
++  return SQLITE_OK; 
++}
+ 
+-/*
+-**    julianday( TIMESTRING, MOD, MOD, ...)
+-**
+-** Return the julian day number of the date specified in the arguments
+-*/
+-static void juliandayFunc(
+-  sqlite3_context *context,
+-  int argc,
+-  sqlite3_value **argv
+-){
+-  DateTime x;
+-  if( isDate(context, argc, argv, &x)==0 ){
+-    computeJD(&x);
+-    sqlite3_result_double(context, x.iJD/86400000.0);
+-  }
++static int sqlcipher_openssl_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int 
salt_sz, int workfactor, int key_sz, unsigned char *key) {
++  PKCS5_PBKDF2_HMAC_SHA1(pass, pass_sz, salt, salt_sz, workfactor, key_sz, key);
++  return SQLITE_OK; 
+ }
+ 
+-/*
+-**    datetime( TIMESTRING, MOD, MOD, ...)
+-**
+-** Return YYYY-MM-DD HH:MM:SS
+-*/
+-static void datetimeFunc(
+-  sqlite3_context *context,
+-  int argc,
+-  sqlite3_value **argv
+-){
+-  DateTime x;
+-  if( isDate(context, argc, argv, &x)==0 ){
+-    char zBuf[100];
+-    computeYMD_HMS(&x);
+-    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
+-                     x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
+-    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+-  }
++static int sqlcipher_openssl_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, 
unsigned char *in, int in_sz, unsigned char *out) {
++  EVP_CIPHER_CTX ectx;
++  int tmp_csz, csz;
++ 
++  EVP_CipherInit(&ectx, ((openssl_ctx *)ctx)->evp_cipher, NULL, NULL, mode);
++  EVP_CIPHER_CTX_set_padding(&ectx, 0); // no padding
++  EVP_CipherInit(&ectx, NULL, key, iv, mode);
++  EVP_CipherUpdate(&ectx, out, &tmp_csz, in, in_sz);
++  csz = tmp_csz;  
++  out += tmp_csz;
++  EVP_CipherFinal(&ectx, out, &tmp_csz);
++  csz += tmp_csz;
++  EVP_CIPHER_CTX_cleanup(&ectx);
++  assert(in_sz == csz);
++  return SQLITE_OK; 
+ }
+ 
+-/*
+-**    time( TIMESTRING, MOD, MOD, ...)
+-**
+-** Return HH:MM:SS
+-*/
+-static void timeFunc(
+-  sqlite3_context *context,
+-  int argc,
+-  sqlite3_value **argv
+-){
+-  DateTime x;
+-  if( isDate(context, argc, argv, &x)==0 ){
+-    char zBuf[100];
+-    computeHMS(&x);
+-    sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
+-    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+-  }
++static int sqlcipher_openssl_set_cipher(void *ctx, const char *cipher_name) {
++  openssl_ctx *o_ctx = (openssl_ctx *)ctx;
++  o_ctx->evp_cipher = (EVP_CIPHER *) EVP_get_cipherbyname(cipher_name);
++  return SQLITE_OK;
+ }
+ 
+-/*
+-**    date( TIMESTRING, MOD, MOD, ...)
+-**
+-** Return YYYY-MM-DD
+-*/
+-static void dateFunc(
+-  sqlite3_context *context,
+-  int argc,
+-  sqlite3_value **argv
+-){
+-  DateTime x;
+-  if( isDate(context, argc, argv, &x)==0 ){
+-    char zBuf[100];
+-    computeYMD(&x);
+-    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
+-    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+-  }
++static const char* sqlcipher_openssl_get_cipher(void *ctx) {
++  return EVP_CIPHER_name(((openssl_ctx *)ctx)->evp_cipher);
+ }
+ 
+-/*
+-**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
+-**
+-** Return a string described by FORMAT.  Conversions as follows:
+-**
+-**   %d  day of month
+-**   %f  ** fractional seconds  SS.SSS
+-**   %H  hour 00-24
+-**   %j  day of year 000-366
+-**   %J  ** Julian day number
+-**   %m  month 01-12
+-**   %M  minute 00-59
+-**   %s  seconds since 1970-01-01
+-**   %S  seconds 00-59
+-**   %w  day of week 0-6  sunday==0
+-**   %W  week of year 00-53
+-**   %Y  year 0000-9999
+-**   %%  %
+-*/
+-static void strftimeFunc(
+-  sqlite3_context *context,
+-  int argc,
+-  sqlite3_value **argv
+-){
+-  DateTime x;
+-  u64 n;
+-  size_t i,j;
+-  char *z;
+-  sqlite3 *db;
+-  const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
+-  char zBuf[100];
+-  if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
+-  db = sqlite3_context_db_handle(context);
+-  for(i=0, n=1; zFmt[i]; i++, n++){
+-    if( zFmt[i]=='%' ){
+-      switch( zFmt[i+1] ){
+-        case 'd':
+-        case 'H':
+-        case 'm':
+-        case 'M':
+-        case 'S':
+-        case 'W':
+-          n++;
+-          /* fall thru */
+-        case 'w':
+-        case '%':
+-          break;
+-        case 'f':
+-          n += 8;
+-          break;
+-        case 'j':
+-          n += 3;
+-          break;
+-        case 'Y':
+-          n += 8;
+-          break;
+-        case 's':
+-        case 'J':
+-          n += 50;
+-          break;
+-        default:
+-          return;  /* ERROR.  return a NULL */
+-      }
+-      i++;
+-    }
+-  }
+-  testcase( n==sizeof(zBuf)-1 );
+-  testcase( n==sizeof(zBuf) );
+-  testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
+-  testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
+-  if( n<sizeof(zBuf) ){
+-    z = zBuf;
+-  }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+-    sqlite3_result_error_toobig(context);
+-    return;
+-  }else{
+-    z = sqlite3DbMallocRaw(db, (int)n);
+-    if( z==0 ){
+-      sqlite3_result_error_nomem(context);
+-      return;
+-    }
+-  }
+-  computeJD(&x);
+-  computeYMD_HMS(&x);
+-  for(i=j=0; zFmt[i]; i++){
+-    if( zFmt[i]!='%' ){
+-      z[j++] = zFmt[i];
+-    }else{
+-      i++;
+-      switch( zFmt[i] ){
+-        case 'd':  sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
+-        case 'f': {
+-          double s = x.s;
+-          if( s>59.999 ) s = 59.999;
+-          sqlite3_snprintf(7, &z[j],"%06.3f", s);
+-          j += sqlite3Strlen30(&z[j]);
+-          break;
+-        }
+-        case 'H':  sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
+-        case 'W': /* Fall thru */
+-        case 'j': {
+-          int nDay;             /* Number of days since 1st day of year */
+-          DateTime y = x;
+-          y.validJD = 0;
+-          y.M = 1;
+-          y.D = 1;
+-          computeJD(&y);
+-          nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
+-          if( zFmt[i]=='W' ){
+-            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
+-            wd = (int)(((x.iJD+43200000)/86400000)%7);
+-            sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
+-            j += 2;
+-          }else{
+-            sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
+-            j += 3;
+-          }
+-          break;
+-        }
+-        case 'J': {
+-          sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
+-          j+=sqlite3Strlen30(&z[j]);
+-          break;
+-        }
+-        case 'm':  sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
+-        case 'M':  sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
+-        case 's': {
+-          sqlite3_snprintf(30,&z[j],"%lld",
+-                           (i64)(x.iJD/1000 - 21086676*(i64)10000));
+-          j += sqlite3Strlen30(&z[j]);
+-          break;
+-        }
+-        case 'S':  sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
+-        case 'w': {
+-          z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
+-          break;
+-        }
+-        case 'Y': {
+-          sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
+-          break;
+-        }
+-        default:   z[j++] = '%'; break;
+-      }
+-    }
+-  }
+-  z[j] = 0;
+-  sqlite3_result_text(context, z, -1,
+-                      z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
++static int sqlcipher_openssl_get_key_sz(void *ctx) {
++  return EVP_CIPHER_key_length(((openssl_ctx *)ctx)->evp_cipher);
+ }
+ 
+-/*
+-** current_time()
+-**
+-** This function returns the same value as time('now').
+-*/
+-static void ctimeFunc(
+-  sqlite3_context *context,
+-  int NotUsed,
+-  sqlite3_value **NotUsed2
+-){
+-  UNUSED_PARAMETER2(NotUsed, NotUsed2);
+-  timeFunc(context, 0, 0);
++static int sqlcipher_openssl_get_iv_sz(void *ctx) {
++  return EVP_CIPHER_iv_length(((openssl_ctx *)ctx)->evp_cipher);
+ }
+ 
+-/*
+-** current_date()
+-**
+-** This function returns the same value as date('now').
+-*/
+-static void cdateFunc(
+-  sqlite3_context *context,
+-  int NotUsed,
+-  sqlite3_value **NotUsed2
+-){
+-  UNUSED_PARAMETER2(NotUsed, NotUsed2);
+-  dateFunc(context, 0, 0);
++static int sqlcipher_openssl_get_block_sz(void *ctx) {
++  return EVP_CIPHER_block_size(((openssl_ctx *)ctx)->evp_cipher);
+ }
+ 
+-/*
+-** current_timestamp()
+-**
+-** This function returns the same value as datetime('now').
+-*/
+-static void ctimestampFunc(
+-  sqlite3_context *context,
+-  int NotUsed,
+-  sqlite3_value **NotUsed2
+-){
+-  UNUSED_PARAMETER2(NotUsed, NotUsed2);
+-  datetimeFunc(context, 0, 0);
++static int sqlcipher_openssl_get_hmac_sz(void *ctx) {
++  return EVP_MD_size(EVP_sha1());
+ }
+-#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
+ 
+-#ifdef SQLITE_OMIT_DATETIME_FUNCS
+-/*
+-** If the library is compiled to omit the full-scale date and time
+-** handling (to get a smaller binary), the following minimal version
+-** of the functions current_time(), current_date() and current_timestamp()
+-** are included instead. This is to support column declarations that
+-** include "DEFAULT CURRENT_TIME" etc.
+-**
+-** This function uses the C-library functions time(), gmtime()
+-** and strftime(). The format string to pass to strftime() is supplied
+-** as the user-data for the function.
+-*/
+-static void currentTimeFunc(
+-  sqlite3_context *context,
+-  int argc,
+-  sqlite3_value **argv
+-){
+-  time_t t;
+-  char *zFormat = (char *)sqlite3_user_data(context);
+-  sqlite3 *db;
+-  sqlite3_int64 iT;
+-  struct tm *pTm;
+-  struct tm sNow;
+-  char zBuf[20];
++static int sqlcipher_openssl_ctx_copy(void *target_ctx, void *source_ctx) {
++  memcpy(target_ctx, source_ctx, sizeof(openssl_ctx));
++  return SQLITE_OK;
++}
+ 
+-  UNUSED_PARAMETER(argc);
+-  UNUSED_PARAMETER(argv);
++static int sqlcipher_openssl_ctx_cmp(void *c1, void *c2) {
++  return ((openssl_ctx *)c1)->evp_cipher == ((openssl_ctx *)c2)->evp_cipher;
++}
+ 
+-  db = sqlite3_context_db_handle(context);
+-  if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
+-  t = iT/1000 - 10000*(sqlite3_int64)21086676;
+-#ifdef HAVE_GMTIME_R
+-  pTm = gmtime_r(&t, &sNow);
+-#else
+-  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-  pTm = gmtime(&t);
+-  if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
+-  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-#endif
+-  if( pTm ){
+-    strftime(zBuf, 20, zFormat, &sNow);
+-    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+-  }
++static int sqlcipher_openssl_ctx_init(void **ctx) {
++  *ctx = sqlcipher_malloc(sizeof(openssl_ctx));
++  if(*ctx == NULL) return SQLITE_NOMEM;
++  sqlcipher_openssl_activate(*ctx);
++  return SQLITE_OK;
+ }
+-#endif
+ 
+-/*
+-** This function registered all of the above C functions as SQL
+-** functions.  This should be the only routine in this file with
+-** external linkage.
+-*/
+-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
+-  static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
+-#ifndef SQLITE_OMIT_DATETIME_FUNCS
+-    FUNCTION(julianday,        -1, 0, 0, juliandayFunc ),
+-    FUNCTION(date,             -1, 0, 0, dateFunc      ),
+-    FUNCTION(time,             -1, 0, 0, timeFunc      ),
+-    FUNCTION(datetime,         -1, 0, 0, datetimeFunc  ),
+-    FUNCTION(strftime,         -1, 0, 0, strftimeFunc  ),
+-    FUNCTION(current_time,      0, 0, 0, ctimeFunc     ),
+-    FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
+-    FUNCTION(current_date,      0, 0, 0, cdateFunc     ),
+-#else
+-    STR_FUNCTION(current_time,      0, "%H:%M:%S",          0, currentTimeFunc),
+-    STR_FUNCTION(current_date,      0, "%Y-%m-%d",          0, currentTimeFunc),
+-    STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
+-#endif
+-  };
+-  int i;
+-  FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+-  FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
++static int sqlcipher_openssl_ctx_free(void **ctx) {
++  sqlcipher_openssl_deactivate(*ctx);
++  sqlcipher_free(*ctx, sizeof(openssl_ctx));
++  return SQLITE_OK;
++}
+ 
+-  for(i=0; i<ArraySize(aDateTimeFuncs); i++){
+-    sqlite3FuncDefInsert(pHash, &aFunc[i]);
+-  }
++int sqlcipher_openssl_setup(sqlcipher_provider *p) {
++  p->activate = sqlcipher_openssl_activate;  
++  p->deactivate = sqlcipher_openssl_deactivate;
++  p->get_provider_name = sqlcipher_openssl_get_provider_name;
++  p->random = sqlcipher_openssl_random;
++  p->hmac = sqlcipher_openssl_hmac;
++  p->kdf = sqlcipher_openssl_kdf;
++  p->cipher = sqlcipher_openssl_cipher;
++  p->set_cipher = sqlcipher_openssl_set_cipher;
++  p->get_cipher = sqlcipher_openssl_get_cipher;
++  p->get_key_sz = sqlcipher_openssl_get_key_sz;
++  p->get_iv_sz = sqlcipher_openssl_get_iv_sz;
++  p->get_block_sz = sqlcipher_openssl_get_block_sz;
++  p->get_hmac_sz = sqlcipher_openssl_get_hmac_sz;
++  p->ctx_copy = sqlcipher_openssl_ctx_copy;
++  p->ctx_cmp = sqlcipher_openssl_ctx_cmp;
++  p->ctx_init = sqlcipher_openssl_ctx_init;
++  p->ctx_free = sqlcipher_openssl_ctx_free;
++  p->add_random = sqlcipher_openssl_add_random;
++  return SQLITE_OK;
+ }
+ 
+-/************** End of date.c ************************************************/
+-/************** Begin file os.c **********************************************/
+-/*
+-** 2005 November 29
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-******************************************************************************
+-**
+-** This file contains OS interface code that is common to all
+-** architectures.
+-*/
+-#define _SQLITE_OS_C_ 1
+-#undef _SQLITE_OS_C_
 +#endif
 +#endif
++/* END SQLCIPHER */
+ 
++/************** End of crypto_openssl.c **************************************/
++/************** Begin file crypto_cc.c ***************************************/
+ /*
+-** The default SQLite sqlite3_vfs implementations do not allocate
+-** memory (actually, os_unix.c allocates a small amount of memory
+-** from within OsOpen()), but some third-party implementations may.
+-** So we test the effects of a malloc() failing and the sqlite3OsXXX()
+-** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
++** SQLCipher
++** http://sqlcipher.net
+ **
+-** The following functions are instrumented for malloc() failure 
+-** testing:
+-**
+-**     sqlite3OsRead()
+-**     sqlite3OsWrite()
+-**     sqlite3OsSync()
+-**     sqlite3OsFileSize()
+-**     sqlite3OsLock()
+-**     sqlite3OsCheckReservedLock()
+-**     sqlite3OsFileControl()
+-**     sqlite3OsShmMap()
+-**     sqlite3OsOpen()
+-**     sqlite3OsDelete()
+-**     sqlite3OsAccess()
+-**     sqlite3OsFullPathname()
++** Copyright (c) 2008 - 2013, ZETETIC LLC
++** All rights reserved.
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++**     * Redistributions of source code must retain the above copyright
++**       notice, this list of conditions and the following disclaimer.
++**     * Redistributions in binary form must reproduce the above copyright
++**       notice, this list of conditions and the following disclaimer in the
++**       documentation and/or other materials provided with the distribution.
++**     * Neither the name of the ZETETIC LLC nor the
++**       names of its contributors may be used to endorse or promote products
++**       derived from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
++** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
++** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ */
+-#if defined(SQLITE_TEST)
+-SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
+-  #define DO_OS_MALLOC_TEST(x)                                       \
+-  if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) {  \
+-    void *pTstAlloc = sqlite3Malloc(10);                             \
+-    if (!pTstAlloc) return SQLITE_IOERR_NOMEM;                       \
+-    sqlite3_free(pTstAlloc);                                         \
+-  }
+-#else
+-  #define DO_OS_MALLOC_TEST(x)
+-#endif
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
++#ifdef SQLCIPHER_CRYPTO_CC
++#include <CommonCrypto/CommonCrypto.h>
++#include <Security/SecRandom.h>
+ 
+-/*
+-** The following routines are convenience wrappers around methods
+-** of the sqlite3_file object.  This is mostly just syntactic sugar. All
+-** of this would be completely automatic if SQLite were coded using
+-** C++ instead of plain old C.
+-*/
+-SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file *pId){
+-  int rc = SQLITE_OK;
+-  if( pId->pMethods ){
+-    rc = pId->pMethods->xClose(pId);
+-    pId->pMethods = 0;
+-  }
+-  return rc;
+-}
+-SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xRead(id, pBuf, amt, offset);
+-}
+-SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xWrite(id, pBuf, amt, offset);
++/* generate a defined number of random bytes */
++static int sqlcipher_cc_random (void *ctx, void *buffer, int length) {
++  return (SecRandomCopyBytes(kSecRandomDefault, length, (uint8_t *)buffer) == 0) ? SQLITE_OK : SQLITE_ERROR;
+ }
+-SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
+-  return id->pMethods->xTruncate(id, size);
+-}
+-SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xSync(id, flags);
+-}
+-SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xFileSize(id, pSize);
+-}
+-SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xLock(id, lockType);
 +
-+/************** End of crypto_impl.c *****************************************/
++static const char* sqlcipher_cc_get_provider_name(void *ctx) {
++  return "commoncrypto";
+ }
+-SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
+-  return id->pMethods->xUnlock(id, lockType);
++
++static int sqlcipher_cc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, 
unsigned char *in2, int in2_sz, unsigned char *out) {
++  CCHmacContext hmac_context;
++  CCHmacInit(&hmac_context, kCCHmacAlgSHA1, hmac_key, key_sz);
++  CCHmacUpdate(&hmac_context, in, in_sz);
++  CCHmacUpdate(&hmac_context, in2, in2_sz);
++  CCHmacFinal(&hmac_context, out);
++  return SQLITE_OK; 
+ }
+-SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xCheckReservedLock(id, pResOut);
++
++static int sqlcipher_cc_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz, int 
workfactor, int key_sz, unsigned char *key) {
++  CCKeyDerivationPBKDF(kCCPBKDF2, pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA1, workfactor, key, key_sz);
++  return SQLITE_OK; 
+ }
+ 
+-/*
+-** Use sqlite3OsFileControl() when we are doing something that might fail
+-** and we need to know about the failures.  Use sqlite3OsFileControlHint()
+-** when simply tossing information over the wall to the VFS and we do not
+-** really care if the VFS receives and understands the information since it
+-** is only a hint and can be safely ignored.  The sqlite3OsFileControlHint()
+-** routine has no return value since the return value would be meaningless.
+-*/
+-SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xFileControl(id, op, pArg);
++static int sqlcipher_cc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, 
unsigned char *in, int in_sz, unsigned char *out) {
++  CCCryptorRef cryptor;
++  size_t tmp_csz, csz;
++  CCOperation op = mode == CIPHER_ENCRYPT ? kCCEncrypt : kCCDecrypt;
++
++  CCCryptorCreate(op, kCCAlgorithmAES128, 0, key, kCCKeySizeAES256, iv, &cryptor);
++  CCCryptorUpdate(cryptor, in, in_sz, out, in_sz, &tmp_csz);
++  csz = tmp_csz;
++  out += tmp_csz;
++  CCCryptorFinal(cryptor, out, in_sz - csz, &tmp_csz);
++  csz += tmp_csz;
++  CCCryptorRelease(cryptor);
++  assert(size == csz);
++
++  return SQLITE_OK; 
+ }
+-SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
+-  (void)id->pMethods->xFileControl(id, op, pArg);
++
++static int sqlcipher_cc_set_cipher(void *ctx, const char *cipher_name) {
++  return SQLITE_OK;
+ }
+ 
+-SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
+-  int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
+-  return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
++static const char* sqlcipher_cc_get_cipher(void *ctx) {
++  return "aes-256-cbc";
+ }
+-SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
+-  return id->pMethods->xDeviceCharacteristics(id);
++
++static int sqlcipher_cc_get_key_sz(void *ctx) {
++  return kCCKeySizeAES256;
+ }
+-SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
+-  return id->pMethods->xShmLock(id, offset, n, flags);
++
++static int sqlcipher_cc_get_iv_sz(void *ctx) {
++  return kCCBlockSizeAES128;
+ }
+-SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
+-  id->pMethods->xShmBarrier(id);
++
++static int sqlcipher_cc_get_block_sz(void *ctx) {
++  return kCCBlockSizeAES128;
+ }
+-SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
+-  return id->pMethods->xShmUnmap(id, deleteFlag);
++
++static int sqlcipher_cc_get_hmac_sz(void *ctx) {
++  return CC_SHA1_DIGEST_LENGTH;
+ }
+-SQLITE_PRIVATE int sqlite3OsShmMap(
+-  sqlite3_file *id,               /* Database file handle */
+-  int iPage,
+-  int pgsz,
+-  int bExtend,                    /* True to extend file if necessary */
+-  void volatile **pp              /* OUT: Pointer to mapping */
+-){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
++
++static int sqlcipher_cc_ctx_copy(void *target_ctx, void *source_ctx) {
++  return SQLITE_OK;
+ }
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-/* The real implementation of xFetch and xUnfetch */
+-SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
+-  DO_OS_MALLOC_TEST(id);
+-  return id->pMethods->xFetch(id, iOff, iAmt, pp);
++static int sqlcipher_cc_ctx_cmp(void *c1, void *c2) {
++  return SQLITE_OK;
+ }
+-SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
+-  return id->pMethods->xUnfetch(id, iOff, p);
++
++static int sqlcipher_cc_ctx_init(void **ctx) {
++  return SQLITE_OK;
+ }
+-#else
+-/* No-op stubs to use when memory-mapped I/O is disabled */
+-SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
+-  *pp = 0;
++
++static int sqlcipher_cc_ctx_free(void **ctx) {
+   return SQLITE_OK;
+ }
+-SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
++
++int sqlcipher_cc_setup(sqlcipher_provider *p) {
++  p->random = sqlcipher_cc_random;
++  p->get_provider_name = sqlcipher_cc_get_provider_name;
++  p->hmac = sqlcipher_cc_hmac;
++  p->kdf = sqlcipher_cc_kdf;
++  p->cipher = sqlcipher_cc_cipher;
++  p->set_cipher = sqlcipher_cc_set_cipher;
++  p->get_cipher = sqlcipher_cc_get_cipher;
++  p->get_key_sz = sqlcipher_cc_get_key_sz;
++  p->get_iv_sz = sqlcipher_cc_get_iv_sz;
++  p->get_block_sz = sqlcipher_cc_get_block_sz;
++  p->get_hmac_sz = sqlcipher_cc_get_hmac_sz;
++  p->ctx_copy = sqlcipher_cc_ctx_copy;
++  p->ctx_cmp = sqlcipher_cc_ctx_cmp;
++  p->ctx_init = sqlcipher_cc_ctx_init;
++  p->ctx_free = sqlcipher_cc_ctx_free;
+   return SQLITE_OK;
+ }
++
++#endif
+ #endif
++/* END SQLCIPHER */
+ 
++/************** End of crypto_cc.c *******************************************/
 +/************** Begin file global.c ******************************************/
-+/*
+ /*
+-** The next group of routines are convenience wrappers around the
+-** VFS methods.
 +** 2008 June 13
 +**
 +** The author disclaims copyright to this source code.  In place of
@@ -2510,15 +5379,194 @@
 +*************************************************************************
 +**
 +** This file contains definitions of global variables and contants.
-+*/
-+
+ */
+-SQLITE_PRIVATE int sqlite3OsOpen(
+-  sqlite3_vfs *pVfs, 
+-  const char *zPath, 
+-  sqlite3_file *pFile, 
+-  int flags, 
+-  int *pFlagsOut
+-){
+-  int rc;
+-  DO_OS_MALLOC_TEST(0);
+-  /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
+-  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
+-  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
+-  ** reaching the VFS. */
+-  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
+-  assert( rc==SQLITE_OK || pFile->pMethods==0 );
+-  return rc;
+-}
+-SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+-  DO_OS_MALLOC_TEST(0);
+-  assert( dirSync==0 || dirSync==1 );
+-  return pVfs->xDelete(pVfs, zPath, dirSync);
+-}
+-SQLITE_PRIVATE int sqlite3OsAccess(
+-  sqlite3_vfs *pVfs, 
+-  const char *zPath, 
+-  int flags, 
+-  int *pResOut
+-){
+-  DO_OS_MALLOC_TEST(0);
+-  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
+-}
+-SQLITE_PRIVATE int sqlite3OsFullPathname(
+-  sqlite3_vfs *pVfs, 
+-  const char *zPath, 
+-  int nPathOut, 
+-  char *zPathOut
+-){
+-  DO_OS_MALLOC_TEST(0);
+-  zPathOut[0] = 0;
+-  return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
+-}
+-#ifndef SQLITE_OMIT_LOAD_EXTENSION
+-SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+-  return pVfs->xDlOpen(pVfs, zPath);
+-}
+-SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+-  pVfs->xDlError(pVfs, nByte, zBufOut);
+-}
+-SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
+-  return pVfs->xDlSym(pVfs, pHdle, zSym);
+-}
+-SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
+-  pVfs->xDlClose(pVfs, pHandle);
+-}
+-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+-SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+-  return pVfs->xRandomness(pVfs, nByte, zBufOut);
+-}
+-SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
+-  return pVfs->xSleep(pVfs, nMicro);
+-}
+-SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
+-  int rc;
+-  /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
+-  ** method to get the current date and time if that method is available
+-  ** (if iVersion is 2 or greater and the function pointer is not NULL) and
+-  ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
+-  ** unavailable.
+-  */
+-  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
+-    rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
+-  }else{
+-    double r;
+-    rc = pVfs->xCurrentTime(pVfs, &r);
+-    *pTimeOut = (sqlite3_int64)(r*86400000.0);
+-  }
+-  return rc;
+-}
+-
+-SQLITE_PRIVATE int sqlite3OsOpenMalloc(
+-  sqlite3_vfs *pVfs, 
+-  const char *zFile, 
+-  sqlite3_file **ppFile, 
+-  int flags,
+-  int *pOutFlags
+-){
+-  int rc = SQLITE_NOMEM;
+-  sqlite3_file *pFile;
+-  pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
+-  if( pFile ){
+-    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
+-    if( rc!=SQLITE_OK ){
+-      sqlite3_free(pFile);
+-    }else{
+-      *ppFile = pFile;
+-    }
+-  }
+-  return rc;
+-}
+-SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
+-  int rc = SQLITE_OK;
+-  assert( pFile );
+-  rc = sqlite3OsClose(pFile);
+-  sqlite3_free(pFile);
+-  return rc;
+-}
+-
+-/*
+-** This function is a wrapper around the OS specific implementation of
+-** sqlite3_os_init(). The purpose of the wrapper is to provide the
+-** ability to simulate a malloc failure, so that the handling of an
+-** error in sqlite3_os_init() by the upper layers can be tested.
+-*/
+-SQLITE_PRIVATE int sqlite3OsInit(void){
+-  void *p = sqlite3_malloc(10);
+-  if( p==0 ) return SQLITE_NOMEM;
+-  sqlite3_free(p);
+-  return sqlite3_os_init();
+-}
+-
+-/*
+-** The list of all registered VFS implementations.
+-*/
+-static sqlite3_vfs * SQLITE_WSD vfsList = 0;
+-#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
+-
+-/*
+-** Locate a VFS by name.  If no name is given, simply return the
+-** first VFS on the list.
+-*/
+-SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
+-  sqlite3_vfs *pVfs = 0;
+-#if SQLITE_THREADSAFE
+-  sqlite3_mutex *mutex;
+-#endif
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  int rc = sqlite3_initialize();
+-  if( rc ) return 0;
+-#endif
+-#if SQLITE_THREADSAFE
+-  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+-#endif
+-  sqlite3_mutex_enter(mutex);
+-  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
+-    if( zVfs==0 ) break;
+-    if( strcmp(zVfs, pVfs->zName)==0 ) break;
+-  }
+-  sqlite3_mutex_leave(mutex);
+-  return pVfs;
+-}
+-
+-/*
+-** Unlink a VFS from the linked list
+-*/
+-static void vfsUnlink(sqlite3_vfs *pVfs){
+-  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
+-  if( pVfs==0 ){
+-    /* No-op */
+-  }else if( vfsList==pVfs ){
+-    vfsList = pVfs->pNext;
+-  }else if( vfsList ){
+-    sqlite3_vfs *p = vfsList;
+-    while( p->pNext && p->pNext!=pVfs ){
+-      p = p->pNext;
+-    }
+-    if( p->pNext==pVfs ){
+-      p->pNext = pVfs->pNext;
+-    }
+-  }
+-}
+ 
+-/*
+-** Register a VFS with the system.  It is harmless to register the same
+-** VFS multiple times.  The new VFS becomes the default if makeDflt is
+-** true.
 +/* An array to map all upper-case characters into their corresponding
 +** lower-case character. 
 +**
 +** SQLite only considers US-ASCII (or EBCDIC) characters.  We do not
 +** handle case conversions for the UTF character set since the tables
 +** involved are nearly as big or bigger than SQLite itself.
-+*/
+ */
+-SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
+-  MUTEX_LOGIC(sqlite3_mutex *mutex;)
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  int rc = sqlite3_initialize();
+-  if( rc ) return rc;
 +SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
 +#ifdef SQLITE_ASCII
 +      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
@@ -2536,7 +5584,28 @@
 +    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
 +    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
 +    252,253,254,255
-+#endif
+ #endif
+-  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+-  sqlite3_mutex_enter(mutex);
+-  vfsUnlink(pVfs);
+-  if( makeDflt || vfsList==0 ){
+-    pVfs->pNext = vfsList;
+-    vfsList = pVfs;
+-  }else{
+-    pVfs->pNext = vfsList->pNext;
+-    vfsList->pNext = pVfs;
+-  }
+-  assert(vfsList);
+-  sqlite3_mutex_leave(mutex);
+-  return SQLITE_OK;
+-}
+-
+-/*
+-** Unregister a VFS so that it is no longer accessible.
+-*/
+-SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
+-#if SQLITE_THREADSAFE
+-  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
 +#ifdef SQLITE_EBCDIC
 +      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* 0x */
 +     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
@@ -2554,13 +5623,23 @@
 +    208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
 +    224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
 +    239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
-+#endif
+ #endif
+-  sqlite3_mutex_enter(mutex);
+-  vfsUnlink(pVfs);
+-  sqlite3_mutex_leave(mutex);
+-  return SQLITE_OK;
+-}
 +};
-+
-+/*
+ 
+-/************** End of os.c **************************************************/
+-/************** Begin file fault.c *******************************************/
+ /*
+-** 2008 Jan 22
 +** The following 256 byte lookup table is used to support SQLites built-in
 +** equivalents to the following standard library functions:
-+**
+ **
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
 +**   isspace()                        0x01
 +**   isalpha()                        0x02
 +**   isdigit()                        0x04
@@ -2568,17 +5647,32 @@
 +**   isxdigit()                       0x08
 +**   toupper()                        0x20
 +**   SQLite identifier character      0x40
-+**
+ **
+-**    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.
 +** Bit 0x20 is set if the mapped character requires translation to upper
 +** case. i.e. if the character is a lower-case ASCII character.
 +** If x is a lower-case ASCII character, then its upper-case equivalent
 +** is (x - 0x20). Therefore toupper() can be implemented as:
-+**
+ **
+-*************************************************************************
 +**   (x & ~(map[x]&0x20))
-+**
+ **
+-** This file contains code to support the concept of "benign" 
+-** malloc failures (when the xMalloc() or xRealloc() method of the
+-** sqlite3_mem_methods structure fails to allocate a block of memory
+-** and returns 0). 
 +** Standard function tolower() is implemented using the sqlite3UpperToLower[]
 +** array. tolower() is used more often than toupper() by SQLite.
-+**
+ **
+-** Most malloc failures are non-benign. After they occur, SQLite
+-** abandons the current operation and returns an error code (usually
+-** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
+-** fatal. For example, if a malloc fails while resizing a hash table, this 
+-** is completely recoverable simply by not carrying out the resize. The 
+-** hash table will continue to function normally.  So a malloc failure 
+-** during a hash table resize is a benign fault.
 +** Bit 0x40 is set if the character non-alphanumeric and can be used in an 
 +** SQLite identifier.  Identifiers are alphanumerics, "_", "$", and any
 +** non-ASCII UTF character. Hence the test for whether or not a character is
@@ -2586,7 +5680,7 @@
 +**
 +** SQLite's versions are identical to the standard versions assuming a
 +** locale of "C". They are implemented as macros in sqliteInt.h.
-+*/
+ */
 +#ifdef SQLITE_ASCII
 +SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
 +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 00..07    ........ */
@@ -2597,7 +5691,7 @@
 +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 28..2f    ()*+,-./ */
 +  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,  /* 30..37    01234567 */
 +  0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 38..3f    89:;<=>? */
-+
+ 
 +  0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02,  /* 40..47    @ABCDEFG */
 +  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  /* 48..4f    HIJKLMNO */
 +  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  /* 50..57    PQRSTUVW */
@@ -2606,7 +5700,17 @@
 +  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,  /* 68..6f    hijklmno */
 +  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,  /* 70..77    pqrstuvw */
 +  0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 78..7f    xyz{|}~. */
-+
+ 
+-#ifndef SQLITE_OMIT_BUILTIN_TEST
+-
+-/*
+-** Global variables.
+-*/
+-typedef struct BenignMallocHooks BenignMallocHooks;
+-static SQLITE_WSD struct BenignMallocHooks {
+-  void (*xBenignBegin)(void);
+-  void (*xBenignEnd)(void);
+-} sqlite3Hooks = { 0, 0 };
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 80..87    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 88..8f    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 90..97    ........ */
@@ -2615,7 +5719,20 @@
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* a8..af    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* b0..b7    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* b8..bf    ........ */
-+
+ 
+-/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
+-** structure.  If writable static data is unsupported on the target,
+-** we have to locate the state vector at run-time.  In the more common
+-** case where writable static data is supported, wsdHooks can refer directly
+-** to the "sqlite3Hooks" state vector declared above.
+-*/
+-#ifdef SQLITE_OMIT_WSD
+-# define wsdHooksInit \
+-  BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
+-# define wsdHooks x[0]
+-#else
+-# define wsdHooksInit
+-# define wsdHooks sqlite3Hooks
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* c0..c7    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* c8..cf    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* d0..d7    ........ */
@@ -2625,21 +5742,53 @@
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* f0..f7    ........ */
 +  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
 +};
-+#endif
-+
+ #endif
+ 
 +#ifndef SQLITE_USE_URI
 +# define  SQLITE_USE_URI 0
 +#endif
-+
-+/*
+ 
+-/*
+-** Register hooks to call when sqlite3BeginBenignMalloc() and
+-** sqlite3EndBenignMalloc() are called, respectively.
+-*/
+-SQLITE_PRIVATE void sqlite3BenignMallocHooks(
+-  void (*xBenignBegin)(void),
+-  void (*xBenignEnd)(void)
+-){
+-  wsdHooksInit;
+-  wsdHooks.xBenignBegin = xBenignBegin;
+-  wsdHooks.xBenignEnd = xBenignEnd;
+-}
++#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
++# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
++#endif
+ 
+ /*
+-** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
+-** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
+-** indicates that subsequent malloc failures are non-benign.
 +** The following singleton contains the global configuration for
 +** the SQLite library.
-+*/
+ */
+-SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
+-  wsdHooksInit;
+-  if( wsdHooks.xBenignBegin ){
+-    wsdHooks.xBenignBegin();
+-  }
+-}
+-SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
+-  wsdHooksInit;
+-  if( wsdHooks.xBenignEnd ){
+-    wsdHooks.xBenignEnd();
+-  }
+-}
 +SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
 +   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
 +   1,                         /* bCoreMutex */
 +   SQLITE_THREADSAFE==1,      /* bFullMutex */
 +   SQLITE_USE_URI,            /* bOpenUri */
++   SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
 +   0x7ffffffe,                /* mxStrlen */
 +   128,                       /* szLookaside */
 +   500,                       /* nLookaside */
@@ -2649,6 +5798,8 @@
 +   (void*)0,                  /* pHeap */
 +   0,                         /* nHeap */
 +   0, 0,                      /* mnHeap, mxHeap */
++   SQLITE_DEFAULT_MMAP_SIZE,  /* szMmap */
++   SQLITE_MAX_MMAP_SIZE,      /* mxMmap */
 +   (void*)0,                  /* pScratch */
 +   0,                         /* szScratch */
 +   0,                         /* nScratch */
@@ -2668,32 +5819,72 @@
 +   0,                         /* xLog */
 +   0,                         /* pLogArg */
 +   0,                         /* bLocaltimeFault */
++#ifdef SQLITE_ENABLE_SQLLOG
++   0,                         /* xSqllog */
++   0                          /* pSqllogArg */
++#endif
 +};
-+
-+
-+/*
+ 
+-#endif   /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
+ 
+-/************** End of fault.c ***********************************************/
+-/************** Begin file mem0.c ********************************************/
+ /*
+-** 2008 October 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.
+-**
+-*************************************************************************
+-**
+-** This file contains a no-op memory allocation drivers for use when
+-** SQLITE_ZERO_MALLOC is defined.  The allocation drivers implemented
+-** here always fail.  SQLite will not operate with these drivers.  These
+-** are merely placeholders.  Real drivers must be substituted using
+-** sqlite3_config() before SQLite will operate.
 +** Hash table for global functions - functions common to all
 +** database connections.  After initialization, this table is
 +** read-only.
-+*/
+ */
 +SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
-+
-+/*
+ 
+ /*
+-** This version of the memory allocator is the default.  It is
+-** used when no other memory allocator is specified using compile-time
+-** macros.
 +** Constant tokens for values 0 and 1.
-+*/
+ */
+-#ifdef SQLITE_ZERO_MALLOC
 +SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
 +   { "0", 1 },
 +   { "1", 1 }
 +};
-+
-+
-+/*
+ 
+-/*
+-** No-op versions of all memory allocation routines
+-*/
+-static void *sqlite3MemMalloc(int nByte){ return 0; }
+-static void sqlite3MemFree(void *pPrior){ return; }
+-static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
+-static int sqlite3MemSize(void *pPrior){ return 0; }
+-static int sqlite3MemRoundup(int n){ return n; }
+-static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
+-static void sqlite3MemShutdown(void *NotUsed){ return; }
+ 
+ /*
+-** This routine is the only routine in this file with external linkage.
 +** The value of the "pending" byte must be 0x40000000 (1 byte past the
 +** 1-gibabyte boundary) in a compatible database.  SQLite never uses
 +** the database page that contains the pending byte.  It never attempts
 +** to read or write that page.  The pending byte page is set assign
 +** for use by the VFS layers as space for managing file locks.
-+**
+ **
+-** Populate the low-level memory allocation function pointers in
+-** sqlite3GlobalConfig.m with pointers to the routines in this file.
 +** During testing, it is often desirable to move the pending byte to
 +** a different position in the file.  This allows code that has to
 +** deal with the pending byte to run on files that are much smaller
@@ -2704,11 +5895,25 @@
 +** 0x40000000 results in an incompatible database file format!
 +** Changing the pending byte during operating results in undefined
 +** and dileterious behavior.
-+*/
+ */
+-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+-  static const sqlite3_mem_methods defaultMethods = {
+-     sqlite3MemMalloc,
+-     sqlite3MemFree,
+-     sqlite3MemRealloc,
+-     sqlite3MemSize,
+-     sqlite3MemRoundup,
+-     sqlite3MemInit,
+-     sqlite3MemShutdown,
+-     0
+-  };
+-  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+-}
 +#ifndef SQLITE_OMIT_WSD
 +SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
 +#endif
-+
+ 
+-#endif /* SQLITE_ZERO_MALLOC */
 +/*
 +** Properties of opcodes.  The OPFLG_INITIALIZER macro is
 +** created by mkopcodeh.awk during compilation.  Data is obtained
@@ -2716,70 +5921,57720 @@
 +** the vdbe.c file.  
 +*/
 +SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
-+
+ 
+-/************** End of mem0.c ************************************************/
+-/************** Begin file mem1.c ********************************************/
 +/************** End of global.c **********************************************/
 +/************** Begin file ctime.c *******************************************/
-+/*
+ /*
+-** 2007 August 14
 +** 2010 February 23
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -15633,807 +15800,1140 @@
+ **
+ *************************************************************************
+ **
+-** This file contains low-level memory allocation drivers for when
+-** SQLite will use the standard C-library malloc/realloc/free interface
+-** to obtain the memory it needs.
+-**
+-** This file contains implementations of the low-level memory allocation
+-** routines specified in the sqlite3_mem_methods object.  The content of
+-** this file is only used if SQLITE_SYSTEM_MALLOC is defined.  The
+-** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
+-** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined.  The
+-** default configuration is to use memory allocation routines in this
+-** file.
+-**
+-** C-preprocessor macro summary:
+-**
+-**    HAVE_MALLOC_USABLE_SIZE     The configure script sets this symbol if
+-**                                the malloc_usable_size() interface exists
+-**                                on the target platform.  Or, this symbol
+-**                                can be set manually, if desired.
+-**                                If an equivalent interface exists by
+-**                                a different name, using a separate -D
+-**                                option to rename it.
+-**
+-**    SQLITE_WITHOUT_ZONEMALLOC   Some older macs lack support for the zone
+-**                                memory allocator.  Set this symbol to enable
+-**                                building on older macs.
+-**
+-**    SQLITE_WITHOUT_MSIZE        Set this symbol to disable the use of
+-**                                _msize() on windows systems.  This might
+-**                                be necessary when compiling for Delphi,
+-**                                for example.
+-*/
+-
+-/*
+-** This version of the memory allocator is the default.  It is
+-** used when no other memory allocator is specified using compile-time
+-** macros.
++** This file implements routines used to report what compile-time options
++** SQLite was built with.
+ */
+-#ifdef SQLITE_SYSTEM_MALLOC
+ 
+-/*
+-** The MSVCRT has malloc_usable_size() but it is called _msize().
+-** The use of _msize() is automatic, but can be disabled by compiling
+-** with -DSQLITE_WITHOUT_MSIZE
+-*/
+-#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
+-# define SQLITE_MALLOCSIZE _msize
+-#endif
++#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+ 
+-#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
+ 
+ /*
+-** Use the zone allocator available on apple products unless the
+-** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
++** An array of names of all compile-time options.  This array should 
++** be sorted A-Z.
 +**
++** This array looks large, but in a typical installation actually uses
++** only a handful of compile-time options, so most times this array is usually
++** rather short and uses little memory space.
+ */
+-#include <sys/sysctl.h>
+-#include <malloc/malloc.h>
+-#include <libkern/OSAtomic.h>
+-static malloc_zone_t* _sqliteZone_;
+-#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
+-#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
+-#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
+-#define SQLITE_MALLOCSIZE(x) \
+-        (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
++static const char * const azCompileOpt[] = {
+ 
+-#else /* if not __APPLE__ */
++/* These macros are provided to "stringify" the value of the define
++** for those options in which the value is meaningful. */
++#define CTIMEOPT_VAL_(opt) #opt
++#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
+ 
+-/*
+-** Use standard C library malloc and free on non-Apple systems.  
+-** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
+-*/
+-#define SQLITE_MALLOC(x)    malloc(x)
+-#define SQLITE_FREE(x)      free(x)
+-#define SQLITE_REALLOC(x,y) realloc((x),(y))
+-
+-#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
+-      || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
+-# include <malloc.h>    /* Needed for malloc_usable_size on linux */
++#ifdef SQLITE_32BIT_ROWID
++  "32BIT_ROWID",
+ #endif
+-#ifdef HAVE_MALLOC_USABLE_SIZE
+-# ifndef SQLITE_MALLOCSIZE
+-#  define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
+-# endif
+-#else
+-# undef SQLITE_MALLOCSIZE
++#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
++  "4_BYTE_ALIGNED_MALLOC",
+ #endif
+-
+-#endif /* __APPLE__ or not __APPLE__ */
++#ifdef SQLITE_CASE_SENSITIVE_LIKE
++  "CASE_SENSITIVE_LIKE",
++#endif
++#ifdef SQLITE_CHECK_PAGES
++  "CHECK_PAGES",
++#endif
++#ifdef SQLITE_COVERAGE_TEST
++  "COVERAGE_TEST",
++#endif
++#ifdef SQLITE_DEBUG
++  "DEBUG",
++#endif
++#ifdef SQLITE_DEFAULT_LOCKING_MODE
++  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
++#endif
++#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
++  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
++#endif
++#ifdef SQLITE_DISABLE_DIRSYNC
++  "DISABLE_DIRSYNC",
++#endif
++#ifdef SQLITE_DISABLE_LFS
++  "DISABLE_LFS",
++#endif
++#ifdef SQLITE_ENABLE_ATOMIC_WRITE
++  "ENABLE_ATOMIC_WRITE",
++#endif
++#ifdef SQLITE_ENABLE_CEROD
++  "ENABLE_CEROD",
++#endif
++#ifdef SQLITE_ENABLE_COLUMN_METADATA
++  "ENABLE_COLUMN_METADATA",
++#endif
++#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
++  "ENABLE_EXPENSIVE_ASSERT",
++#endif
++#ifdef SQLITE_ENABLE_FTS1
++  "ENABLE_FTS1",
++#endif
++#ifdef SQLITE_ENABLE_FTS2
++  "ENABLE_FTS2",
++#endif
++#ifdef SQLITE_ENABLE_FTS3
++  "ENABLE_FTS3",
++#endif
++#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
++  "ENABLE_FTS3_PARENTHESIS",
++#endif
++#ifdef SQLITE_ENABLE_FTS4
++  "ENABLE_FTS4",
++#endif
++#ifdef SQLITE_ENABLE_ICU
++  "ENABLE_ICU",
++#endif
++#ifdef SQLITE_ENABLE_IOTRACE
++  "ENABLE_IOTRACE",
++#endif
++#ifdef SQLITE_ENABLE_LOAD_EXTENSION
++  "ENABLE_LOAD_EXTENSION",
++#endif
++#ifdef SQLITE_ENABLE_LOCKING_STYLE
++  "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
++#endif
++#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
++  "ENABLE_MEMORY_MANAGEMENT",
++#endif
++#ifdef SQLITE_ENABLE_MEMSYS3
++  "ENABLE_MEMSYS3",
++#endif
++#ifdef SQLITE_ENABLE_MEMSYS5
++  "ENABLE_MEMSYS5",
++#endif
++#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
++  "ENABLE_OVERSIZE_CELL_CHECK",
++#endif
++#ifdef SQLITE_ENABLE_RTREE
++  "ENABLE_RTREE",
++#endif
++#ifdef SQLITE_ENABLE_STAT3
++  "ENABLE_STAT3",
++#endif
++#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
++  "ENABLE_UNLOCK_NOTIFY",
++#endif
++#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
++  "ENABLE_UPDATE_DELETE_LIMIT",
++#endif
++#ifdef SQLITE_HAS_CODEC
++  "HAS_CODEC",
++#endif
++#ifdef SQLITE_HAVE_ISNAN
++  "HAVE_ISNAN",
++#endif
++#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
++  "HOMEGROWN_RECURSIVE_MUTEX",
++#endif
++#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
++  "IGNORE_AFP_LOCK_ERRORS",
++#endif
++#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
++  "IGNORE_FLOCK_LOCK_ERRORS",
++#endif
++#ifdef SQLITE_INT64_TYPE
++  "INT64_TYPE",
++#endif
++#ifdef SQLITE_LOCK_TRACE
++  "LOCK_TRACE",
++#endif
++#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
++  "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
++#endif
++#ifdef SQLITE_MAX_SCHEMA_RETRY
++  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
++#endif
++#ifdef SQLITE_MEMDEBUG
++  "MEMDEBUG",
++#endif
++#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
++  "MIXED_ENDIAN_64BIT_FLOAT",
++#endif
++#ifdef SQLITE_NO_SYNC
++  "NO_SYNC",
++#endif
++#ifdef SQLITE_OMIT_ALTERTABLE
++  "OMIT_ALTERTABLE",
++#endif
++#ifdef SQLITE_OMIT_ANALYZE
++  "OMIT_ANALYZE",
++#endif
++#ifdef SQLITE_OMIT_ATTACH
++  "OMIT_ATTACH",
++#endif
++#ifdef SQLITE_OMIT_AUTHORIZATION
++  "OMIT_AUTHORIZATION",
++#endif
++#ifdef SQLITE_OMIT_AUTOINCREMENT
++  "OMIT_AUTOINCREMENT",
++#endif
++#ifdef SQLITE_OMIT_AUTOINIT
++  "OMIT_AUTOINIT",
++#endif
++#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
++  "OMIT_AUTOMATIC_INDEX",
++#endif
++#ifdef SQLITE_OMIT_AUTORESET
++  "OMIT_AUTORESET",
++#endif
++#ifdef SQLITE_OMIT_AUTOVACUUM
++  "OMIT_AUTOVACUUM",
++#endif
++#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
++  "OMIT_BETWEEN_OPTIMIZATION",
++#endif
++#ifdef SQLITE_OMIT_BLOB_LITERAL
++  "OMIT_BLOB_LITERAL",
++#endif
++#ifdef SQLITE_OMIT_BTREECOUNT
++  "OMIT_BTREECOUNT",
++#endif
++#ifdef SQLITE_OMIT_BUILTIN_TEST
++  "OMIT_BUILTIN_TEST",
++#endif
++#ifdef SQLITE_OMIT_CAST
++  "OMIT_CAST",
++#endif
++#ifdef SQLITE_OMIT_CHECK
++  "OMIT_CHECK",
++#endif
++#ifdef SQLITE_OMIT_COMPLETE
++  "OMIT_COMPLETE",
++#endif
++#ifdef SQLITE_OMIT_COMPOUND_SELECT
++  "OMIT_COMPOUND_SELECT",
++#endif
++#ifdef SQLITE_OMIT_DATETIME_FUNCS
++  "OMIT_DATETIME_FUNCS",
++#endif
++#ifdef SQLITE_OMIT_DECLTYPE
++  "OMIT_DECLTYPE",
++#endif
++#ifdef SQLITE_OMIT_DEPRECATED
++  "OMIT_DEPRECATED",
++#endif
++#ifdef SQLITE_OMIT_DISKIO
++  "OMIT_DISKIO",
++#endif
++#ifdef SQLITE_OMIT_EXPLAIN
++  "OMIT_EXPLAIN",
++#endif
++#ifdef SQLITE_OMIT_FLAG_PRAGMAS
++  "OMIT_FLAG_PRAGMAS",
++#endif
++#ifdef SQLITE_OMIT_FLOATING_POINT
++  "OMIT_FLOATING_POINT",
++#endif
++#ifdef SQLITE_OMIT_FOREIGN_KEY
++  "OMIT_FOREIGN_KEY",
++#endif
++#ifdef SQLITE_OMIT_GET_TABLE
++  "OMIT_GET_TABLE",
++#endif
++#ifdef SQLITE_OMIT_INCRBLOB
++  "OMIT_INCRBLOB",
++#endif
++#ifdef SQLITE_OMIT_INTEGRITY_CHECK
++  "OMIT_INTEGRITY_CHECK",
++#endif
++#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
++  "OMIT_LIKE_OPTIMIZATION",
++#endif
++#ifdef SQLITE_OMIT_LOAD_EXTENSION
++  "OMIT_LOAD_EXTENSION",
++#endif
++#ifdef SQLITE_OMIT_LOCALTIME
++  "OMIT_LOCALTIME",
++#endif
++#ifdef SQLITE_OMIT_LOOKASIDE
++  "OMIT_LOOKASIDE",
++#endif
++#ifdef SQLITE_OMIT_MEMORYDB
++  "OMIT_MEMORYDB",
++#endif
++#ifdef SQLITE_OMIT_OR_OPTIMIZATION
++  "OMIT_OR_OPTIMIZATION",
++#endif
++#ifdef SQLITE_OMIT_PAGER_PRAGMAS
++  "OMIT_PAGER_PRAGMAS",
++#endif
++#ifdef SQLITE_OMIT_PRAGMA
++  "OMIT_PRAGMA",
++#endif
++#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
++  "OMIT_PROGRESS_CALLBACK",
++#endif
++#ifdef SQLITE_OMIT_QUICKBALANCE
++  "OMIT_QUICKBALANCE",
++#endif
++#ifdef SQLITE_OMIT_REINDEX
++  "OMIT_REINDEX",
++#endif
++#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
++  "OMIT_SCHEMA_PRAGMAS",
++#endif
++#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
++  "OMIT_SCHEMA_VERSION_PRAGMAS",
++#endif
++#ifdef SQLITE_OMIT_SHARED_CACHE
++  "OMIT_SHARED_CACHE",
++#endif
++#ifdef SQLITE_OMIT_SUBQUERY
++  "OMIT_SUBQUERY",
++#endif
++#ifdef SQLITE_OMIT_TCL_VARIABLE
++  "OMIT_TCL_VARIABLE",
++#endif
++#ifdef SQLITE_OMIT_TEMPDB
++  "OMIT_TEMPDB",
++#endif
++#ifdef SQLITE_OMIT_TRACE
++  "OMIT_TRACE",
++#endif
++#ifdef SQLITE_OMIT_TRIGGER
++  "OMIT_TRIGGER",
++#endif
++#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
++  "OMIT_TRUNCATE_OPTIMIZATION",
++#endif
++#ifdef SQLITE_OMIT_UTF16
++  "OMIT_UTF16",
++#endif
++#ifdef SQLITE_OMIT_VACUUM
++  "OMIT_VACUUM",
++#endif
++#ifdef SQLITE_OMIT_VIEW
++  "OMIT_VIEW",
++#endif
++#ifdef SQLITE_OMIT_VIRTUALTABLE
++  "OMIT_VIRTUALTABLE",
++#endif
++#ifdef SQLITE_OMIT_WAL
++  "OMIT_WAL",
++#endif
++#ifdef SQLITE_OMIT_WSD
++  "OMIT_WSD",
++#endif
++#ifdef SQLITE_OMIT_XFER_OPT
++  "OMIT_XFER_OPT",
++#endif
++#ifdef SQLITE_PERFORMANCE_TRACE
++  "PERFORMANCE_TRACE",
++#endif
++#ifdef SQLITE_PROXY_DEBUG
++  "PROXY_DEBUG",
++#endif
++#ifdef SQLITE_RTREE_INT_ONLY
++  "RTREE_INT_ONLY",
++#endif
++#ifdef SQLITE_SECURE_DELETE
++  "SECURE_DELETE",
++#endif
++#ifdef SQLITE_SMALL_STACK
++  "SMALL_STACK",
++#endif
++#ifdef SQLITE_SOUNDEX
++  "SOUNDEX",
++#endif
++#ifdef SQLITE_TCL
++  "TCL",
++#endif
++#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
++  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
++#endif
++#ifdef SQLITE_TEST
++  "TEST",
++#endif
++#if defined(SQLITE_THREADSAFE)
++  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
++#endif
++#ifdef SQLITE_USE_ALLOCA
++  "USE_ALLOCA",
++#endif
++#ifdef SQLITE_ZERO_MALLOC
++  "ZERO_MALLOC"
++#endif
++};
+ 
+ /*
+-** Like malloc(), but remember the size of the allocation
+-** so that we can find it later using sqlite3MemSize().
++** Given the name of a compile-time option, return true if that option
++** was used and false if not.
+ **
+-** For this low-level routine, we are guaranteed that nByte>0 because
+-** cases of nByte<=0 will be intercepted and dealt with by higher level
+-** routines.
++** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
++** is not required for a match.
+ */
+-static void *sqlite3MemMalloc(int nByte){
+-#ifdef SQLITE_MALLOCSIZE
+-  void *p = SQLITE_MALLOC( nByte );
+-  if( p==0 ){
+-    testcase( sqlite3GlobalConfig.xLog!=0 );
+-    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
+-  }
+-  return p;
+-#else
+-  sqlite3_int64 *p;
+-  assert( nByte>0 );
+-  nByte = ROUND8(nByte);
+-  p = SQLITE_MALLOC( nByte+8 );
+-  if( p ){
+-    p[0] = nByte;
+-    p++;
+-  }else{
+-    testcase( sqlite3GlobalConfig.xLog!=0 );
+-    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
++SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
++  int i, n;
++  if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
++  n = sqlite3Strlen30(zOptName);
++
++  /* Since ArraySize(azCompileOpt) is normally in single digits, a
++  ** linear search is adequate.  No need for a binary search. */
++  for(i=0; i<ArraySize(azCompileOpt); i++){
++    if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
++     && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
++    ){
++      return 1;
++    }
+   }
+-  return (void *)p;
+-#endif
++  return 0;
+ }
+ 
+ /*
+-** Like free() but works for allocations obtained from sqlite3MemMalloc()
+-** or sqlite3MemRealloc().
+-**
+-** For this low-level routine, we already know that pPrior!=0 since
+-** cases where pPrior==0 will have been intecepted and dealt with
+-** by higher-level routines.
++** Return the N-th compile-time option string.  If N is out of range,
++** return a NULL pointer.
+ */
+-static void sqlite3MemFree(void *pPrior){
+-#ifdef SQLITE_MALLOCSIZE
+-  SQLITE_FREE(pPrior);
+-#else
+-  sqlite3_int64 *p = (sqlite3_int64*)pPrior;
+-  assert( pPrior!=0 );
+-  p--;
+-  SQLITE_FREE(p);
+-#endif
++SQLITE_API const char *sqlite3_compileoption_get(int N){
++  if( N>=0 && N<ArraySize(azCompileOpt) ){
++    return azCompileOpt[N];
++  }
++  return 0;
+ }
+ 
++#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
++
++/************** End of ctime.c ***********************************************/
++/************** Begin file status.c ******************************************/
+ /*
+-** Report the allocated size of a prior return from xMalloc()
+-** or xRealloc().
++** 2008 June 18
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++**
++** This module implements the sqlite3_status() interface and related
++** functionality.
+ */
+-static int sqlite3MemSize(void *pPrior){
+-#ifdef SQLITE_MALLOCSIZE
+-  return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
+-#else
+-  sqlite3_int64 *p;
+-  if( pPrior==0 ) return 0;
+-  p = (sqlite3_int64*)pPrior;
+-  p--;
+-  return (int)p[0];
+-#endif
+-}
+-
++/************** Include vdbeInt.h in the middle of status.c ******************/
++/************** Begin file vdbeInt.h *****************************************/
+ /*
+-** Like realloc().  Resize an allocation previously obtained from
+-** sqlite3MemMalloc().
++** 2003 September 6
+ **
+-** For this low-level interface, we know that pPrior!=0.  Cases where
+-** pPrior==0 while have been intercepted by higher-level routine and
+-** redirected to xMalloc.  Similarly, we know that nByte>0 becauses
+-** cases where nByte<=0 will have been intercepted by higher-level
+-** routines and redirected to xFree.
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This is the header file for information that is private to the
++** VDBE.  This information used to all be at the top of the single
++** source code file "vdbe.c".  When that file became too big (over
++** 6000 lines long) it was split up into several smaller files and
++** this header information was factored out.
+ */
+-static void *sqlite3MemRealloc(void *pPrior, int nByte){
+-#ifdef SQLITE_MALLOCSIZE
+-  void *p = SQLITE_REALLOC(pPrior, nByte);
+-  if( p==0 ){
+-    testcase( sqlite3GlobalConfig.xLog!=0 );
+-    sqlite3_log(SQLITE_NOMEM,
+-      "failed memory resize %u to %u bytes",
+-      SQLITE_MALLOCSIZE(pPrior), nByte);
+-  }
+-  return p;
+-#else
+-  sqlite3_int64 *p = (sqlite3_int64*)pPrior;
+-  assert( pPrior!=0 && nByte>0 );
+-  assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
+-  p--;
+-  p = SQLITE_REALLOC(p, nByte+8 );
+-  if( p ){
+-    p[0] = nByte;
+-    p++;
+-  }else{
+-    testcase( sqlite3GlobalConfig.xLog!=0 );
+-    sqlite3_log(SQLITE_NOMEM,
+-      "failed memory resize %u to %u bytes",
+-      sqlite3MemSize(pPrior), nByte);
+-  }
+-  return (void*)p;
++#ifndef _VDBEINT_H_
++#define _VDBEINT_H_
++
++/*
++** The maximum number of times that a statement will try to reparse
++** itself before giving up and returning SQLITE_SCHEMA.
++*/
++#ifndef SQLITE_MAX_SCHEMA_RETRY
++# define SQLITE_MAX_SCHEMA_RETRY 50
+ #endif
+-}
+ 
+ /*
+-** Round up a request size to the next valid allocation size.
++** SQL is translated into a sequence of instructions to be
++** executed by a virtual machine.  Each instruction is an instance
++** of the following structure.
+ */
+-static int sqlite3MemRoundup(int n){
+-  return ROUND8(n);
+-}
++typedef struct VdbeOp Op;
+ 
+ /*
+-** Initialize this module.
++** Boolean values
+ */
+-static int sqlite3MemInit(void *NotUsed){
+-#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
+-  int cpuCount;
+-  size_t len;
+-  if( _sqliteZone_ ){
+-    return SQLITE_OK;
+-  }
+-  len = sizeof(cpuCount);
+-  /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
+-  sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
+-  if( cpuCount>1 ){
+-    /* defer MT decisions to system malloc */
+-    _sqliteZone_ = malloc_default_zone();
+-  }else{
+-    /* only 1 core, use our own zone to contention over global locks, 
+-    ** e.g. we have our own dedicated locks */
+-    bool success;
+-    malloc_zone_t* newzone = malloc_create_zone(4096, 0);
+-    malloc_set_zone_name(newzone, "Sqlite_Heap");
+-    do{
+-      success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, 
+-                                 (void * volatile *)&_sqliteZone_);
+-    }while(!_sqliteZone_);
+-    if( !success ){
+-      /* somebody registered a zone first */
+-      malloc_destroy_zone(newzone);
+-    }
+-  }
+-#endif
+-  UNUSED_PARAMETER(NotUsed);
+-  return SQLITE_OK;
+-}
++typedef unsigned char Bool;
+ 
+-/*
+-** Deinitialize this module.
+-*/
+-static void sqlite3MemShutdown(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  return;
+-}
++/* Opaque type used by code in vdbesort.c */
++typedef struct VdbeSorter VdbeSorter;
++
++/* Opaque type used by the explainer */
++typedef struct Explain Explain;
+ 
+ /*
+-** This routine is the only routine in this file with external linkage.
+-**
+-** Populate the low-level memory allocation function pointers in
+-** sqlite3GlobalConfig.m with pointers to the routines in this file.
++** A cursor is a pointer into a single BTree within a database file.
++** The cursor can seek to a BTree entry with a particular key, or
++** loop over all entries of the Btree.  You can also insert new BTree
++** entries or retrieve the key or data from the entry that the cursor
++** is currently pointing to.
++** 
++** Every cursor that the virtual machine has open is represented by an
++** instance of the following structure.
+ */
+-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+-  static const sqlite3_mem_methods defaultMethods = {
+-     sqlite3MemMalloc,
+-     sqlite3MemFree,
+-     sqlite3MemRealloc,
+-     sqlite3MemSize,
+-     sqlite3MemRoundup,
+-     sqlite3MemInit,
+-     sqlite3MemShutdown,
+-     0
+-  };
+-  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+-}
++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) */
++  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 */
++  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
++  Bool nullRow;         /* True if pointing to a row with no data */
++  Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
++  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 */
++  Bool isSorter;        /* True if a new-style sorter */
++  Bool multiPseudo;     /* Multi-register pseudo-cursor */
++  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 */
++  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
+ 
+-#endif /* SQLITE_SYSTEM_MALLOC */
++  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
++  ** OP_IsUnique opcode on this cursor. */
++  int seekResult;
++
++  /* Cached information about the header for the data record that the
++  ** cursor is currently pointing to.  Only valid if cacheStatus matches
++  ** Vdbe.cacheCtr.  Vdbe.cacheCtr will never take on the value of
++  ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
++  ** the cache is out of date.
++  **
++  ** aRow might point to (ephemeral) data for the current row, or it might
++  ** be NULL.
++  */
++  u32 cacheStatus;      /* Cache is valid if this matches Vdbe.cacheCtr */
++  int payloadSize;      /* Total number of bytes in the record */
++  u32 *aType;           /* Type values for all entries in the record */
++  u32 *aOffset;         /* Cached offsets to the start of each columns data */
++  u8 *aRow;             /* Data for the current row, if all on one page */
++};
++typedef struct VdbeCursor VdbeCursor;
+ 
+-/************** End of mem1.c ************************************************/
+-/************** Begin file mem2.c ********************************************/
+ /*
+-** 2007 August 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.
+-**
+-*************************************************************************
++** When a sub-program is executed (OP_Program), a structure of this type
++** is allocated to store the current value of the program counter, as
++** well as the current memory cell array and various other frame specific
++** values stored in the Vdbe struct. When the sub-program is finished, 
++** these values are copied back to the Vdbe from the VdbeFrame structure,
++** restoring the state of the VM to as it was before the sub-program
++** began executing.
+ **
+-** This file contains low-level memory allocation drivers for when
+-** SQLite will use the standard C-library malloc/realloc/free interface
+-** to obtain the memory it needs while adding lots of additional debugging
+-** information to each allocation in order to help detect and fix memory
+-** leaks and memory usage errors.
++** The memory for a VdbeFrame object is allocated and managed by a memory
++** cell in the parent (calling) frame. When the memory cell is deleted or
++** overwritten, the VdbeFrame object is not freed immediately. Instead, it
++** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
++** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
++** this instead of deleting the VdbeFrame immediately is to avoid recursive
++** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
++** child frame are released.
+ **
+-** This file contains implementations of the low-level memory allocation
+-** routines specified in the sqlite3_mem_methods object.
++** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
++** set to NULL if the currently executing frame is the main program.
+ */
++typedef struct VdbeFrame VdbeFrame;
++struct VdbeFrame {
++  Vdbe *v;                /* VM this frame belongs to */
++  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
++  Op *aOp;                /* Program instructions for parent frame */
++  Mem *aMem;              /* Array of memory cells for parent frame */
++  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
++  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
++  void *token;            /* Copy of SubProgram.token */
++  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
++  int nCursor;            /* Number of entries in apCsr */
++  int pc;                 /* Program Counter in parent (calling) frame */
++  int nOp;                /* Size of aOp array */
++  int nMem;               /* Number of entries in aMem */
++  int nOnceFlag;          /* Number of entries in aOnceFlag */
++  int nChildMem;          /* Number of memory cells for child frame */
++  int nChildCsr;          /* Number of cursors for child frame */
++  int nChange;            /* Statement changes (Vdbe.nChanges)     */
++};
++
++#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
+ 
+ /*
+-** This version of the memory allocator is used only if the
+-** SQLITE_MEMDEBUG macro is defined
++** A value for VdbeCursor.cacheValid that means the cache is always invalid.
+ */
+-#ifdef SQLITE_MEMDEBUG
++#define CACHE_STALE 0
+ 
+ /*
+-** The backtrace functionality is only available with GLIBC
++** 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.
+ */
+-#ifdef __GLIBC__
+-  extern int backtrace(void**,int);
+-  extern void backtrace_symbols_fd(void*const*,int,int);
+-#else
+-# define backtrace(A,B) 1
+-# define backtrace_symbols_fd(A,B,C)
++struct Mem {
++  sqlite3 *db;        /* The associated database connection */
++  char *z;            /* String or BLOB value */
++  double r;           /* Real value */
++  union {
++    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;
++  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 */
++  u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
++#ifdef SQLITE_DEBUG
++  Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
++  void *pFiller;      /* So that sizeof(Mem) is a multiple of 8 */
+ #endif
+-/* #include <stdio.h> */
++  void (*xDel)(void *);  /* If not null, call this function to delete Mem.z */
++  char *zMalloc;      /* Dynamic buffer allocated by sqlite3_malloc() */
++};
+ 
+-/*
+-** Each memory allocation looks like this:
++/* One or more of the following flags are set to indicate the validOK
++** representations of the value stored in the Mem struct.
+ **
+-**  ------------------------------------------------------------------------
+-**  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
+-**  ------------------------------------------------------------------------
++** If the MEM_Null flag is set, then the value is an SQL NULL value.
++** No other flags may be set in this case.
+ **
+-** The application code sees only a pointer to the allocation.  We have
+-** to back up from the allocation pointer to find the MemBlockHdr.  The
+-** MemBlockHdr tells us the size of the allocation and the number of
+-** backtrace pointers.  There is also a guard word at the end of the
+-** MemBlockHdr.
++** If the MEM_Str flag is set then Mem.z points at a string representation.
++** Usually this is encoded in the same unicode encoding as the main
++** 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.
+ */
+-struct MemBlockHdr {
+-  i64 iSize;                          /* Size of this allocation */
+-  struct MemBlockHdr *pNext, *pPrev;  /* Linked list of all unfreed memory */
+-  char nBacktrace;                    /* Number of backtraces on this alloc */
+-  char nBacktraceSlots;               /* Available backtrace slots */
+-  u8 nTitle;                          /* Bytes of title; includes '\0' */
+-  u8 eType;                           /* Allocation type code */
+-  int iForeGuard;                     /* Guard word for sanity */
+-};
++#define MEM_Null      0x0001   /* Value is NULL */
++#define MEM_Str       0x0002   /* Value is a string */
++#define MEM_Int       0x0004   /* Value is an integer */
++#define MEM_Real      0x0008   /* Value is a real number */
++#define MEM_Blob      0x0010   /* Value is a BLOB */
++#define MEM_RowSet    0x0020   /* Value is a RowSet object */
++#define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
++#define MEM_Invalid   0x0080   /* Value is undefined */
++#define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
++#define MEM_TypeMask  0x01ff   /* Mask of type bits */
+ 
+-/*
+-** Guard words
++
++/* Whenever Mem contains a valid string or blob representation, one of
++** the following flags must be set to determine the memory management
++** policy for Mem.z.  The MEM_Term flag tells us whether or not the
++** string is \000 or \u0000 terminated
+ */
+-#define FOREGUARD 0x80F5E153
+-#define REARGUARD 0xE4676B53
++#define MEM_Term      0x0200   /* String rep is nul terminated */
++#define MEM_Dyn       0x0400   /* Need to call sqliteFree() on Mem.z */
++#define MEM_Static    0x0800   /* Mem.z points to a static string */
++#define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
++#define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
++#define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
++#ifdef SQLITE_OMIT_INCRBLOB
++  #undef MEM_Zero
++  #define MEM_Zero 0x0000
++#endif
+ 
+ /*
+-** Number of malloc size increments to track.
++** Clear any existing type flags from a Mem and replace them with f
+ */
+-#define NCSIZE  1000
++#define MemSetTypeFlag(p, f) \
++   ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
+ 
+ /*
+-** All of the static variables used by this module are collected
+-** into a single structure named "mem".  This is to keep the
+-** static variables organized and to reduce namespace pollution
+-** when this module is combined with other in the amalgamation.
++** Return true if a memory cell is not marked as invalid.  This macro
++** is for use inside assert() statements only.
+ */
+-static struct {
+-  
+-  /*
+-  ** Mutex to control access to the memory allocation subsystem.
+-  */
+-  sqlite3_mutex *mutex;
+-
+-  /*
+-  ** Head and tail of a linked list of all outstanding allocations
+-  */
+-  struct MemBlockHdr *pFirst;
+-  struct MemBlockHdr *pLast;
+-  
+-  /*
+-  ** The number of levels of backtrace to save in new allocations.
+-  */
+-  int nBacktrace;
+-  void (*xBacktrace)(int, int, void **);
+-
+-  /*
+-  ** Title text to insert in front of each block
+-  */
+-  int nTitle;        /* Bytes of zTitle to save.  Includes '\0' and padding */
+-  char zTitle[100];  /* The title text */
+-
+-  /* 
+-  ** sqlite3MallocDisallow() increments the following counter.
+-  ** sqlite3MallocAllow() decrements it.
+-  */
+-  int disallow; /* Do not allow memory allocation */
+-
+-  /*
+-  ** Gather statistics on the sizes of memory allocations.
+-  ** nAlloc[i] is the number of allocation attempts of i*8
+-  ** bytes.  i==NCSIZE is the number of allocation attempts for
+-  ** sizes more than NCSIZE*8 bytes.
+-  */
+-  int nAlloc[NCSIZE];      /* Total number of allocations */
+-  int nCurrent[NCSIZE];    /* Current number of allocations */
+-  int mxCurrent[NCSIZE];   /* Highwater mark for nCurrent */
+-
+-} mem;
++#ifdef SQLITE_DEBUG
++#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
++#endif
+ 
+ 
+-/*
+-** Adjust memory usage statistics
++/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
++** additional information about auxiliary information bound to arguments
++** of the function.  This is used to implement the sqlite3_get_auxdata()
++** and sqlite3_set_auxdata() APIs.  The "auxdata" is some auxiliary data
++** that can be associated with a constant argument to a function.  This
++** allows functions such as "regexp" to compile their constant regular
++** expression argument once and reused the compiled code for multiple
++** invocations.
+ */
+-static void adjustStats(int iSize, int increment){
+-  int i = ROUND8(iSize)/8;
+-  if( i>NCSIZE-1 ){
+-    i = NCSIZE - 1;
+-  }
+-  if( increment>0 ){
+-    mem.nAlloc[i]++;
+-    mem.nCurrent[i]++;
+-    if( mem.nCurrent[i]>mem.mxCurrent[i] ){
+-      mem.mxCurrent[i] = mem.nCurrent[i];
+-    }
+-  }else{
+-    mem.nCurrent[i]--;
+-    assert( mem.nCurrent[i]>=0 );
+-  }
+-}
++struct VdbeFunc {
++  FuncDef *pFunc;               /* The definition of the function */
++  int nAux;                     /* Number of entries allocated for apAux[] */
++  struct AuxData {
++    void *pAux;                   /* Aux data for the i-th argument */
++    void (*xDelete)(void *);      /* Destructor for the aux data */
++  } apAux[1];                   /* One slot for each function argument */
++};
+ 
+ /*
+-** Given an allocation, find the MemBlockHdr for that allocation.
++** The "context" argument for a installable function.  A pointer to an
++** instance of this structure is the first argument to the routines used
++** implement the SQL functions.
+ **
+-** This routine checks the guards at either end of the allocation and
+-** if they are incorrect it asserts.
++** There is a typedef for this structure in sqlite.h.  So all routines,
++** even the public interface to SQLite, can use a pointer to this structure.
++** But this file is the only place where the internal details of this
++** structure are known.
++**
++** This structure is defined inside of vdbeInt.h because it uses substructures
++** (Mem) which are only defined there.
+ */
+-static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
+-  struct MemBlockHdr *p;
+-  int *pInt;
+-  u8 *pU8;
+-  int nReserve;
+-
+-  p = (struct MemBlockHdr*)pAllocation;
+-  p--;
+-  assert( p->iForeGuard==(int)FOREGUARD );
+-  nReserve = ROUND8(p->iSize);
+-  pInt = (int*)pAllocation;
+-  pU8 = (u8*)pAllocation;
+-  assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
+-  /* This checks any of the "extra" bytes allocated due
+-  ** to rounding up to an 8 byte boundary to ensure 
+-  ** they haven't been overwritten.
+-  */
+-  while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
+-  return p;
+-}
++struct sqlite3_context {
++  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
++  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
++  Mem s;                /* The return value is stored here */
++  Mem *pMem;            /* Memory cell used to store aggregate context */
++  CollSeq *pColl;       /* Collating sequence */
++  int isError;          /* Error code returned by the function. */
++  int skipFlag;         /* Skip skip accumulator loading if true */
++};
+ 
+ /*
+-** Return the number of bytes currently allocated at address p.
++** An Explain object accumulates indented output which is helpful
++** in describing recursive data structures.
+ */
+-static int sqlite3MemSize(void *p){
+-  struct MemBlockHdr *pHdr;
+-  if( !p ){
+-    return 0;
+-  }
+-  pHdr = sqlite3MemsysGetHeader(p);
+-  return pHdr->iSize;
+-}
++struct Explain {
++  Vdbe *pVdbe;       /* Attach the explanation to this Vdbe */
++  StrAccum str;      /* The string being accumulated */
++  int nIndent;       /* Number of elements in aIndent */
++  u16 aIndent[100];  /* Levels of indentation */
++  char zBase[100];   /* Initial space */
++};
+ 
+-/*
+-** Initialize the memory allocation subsystem.
++/* A bitfield type for use inside of structures.  Always follow with :N where
++** N is the number of bits.
+ */
+-static int sqlite3MemInit(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  assert( (sizeof(struct MemBlockHdr)&7) == 0 );
+-  if( !sqlite3GlobalConfig.bMemstat ){
+-    /* If memory status is enabled, then the malloc.c wrapper will already
+-    ** hold the STATIC_MEM mutex when the routines here are invoked. */
+-    mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+-  }
+-  return SQLITE_OK;
+-}
++typedef unsigned bft;  /* Bit Field Type */
+ 
+ /*
+-** Deinitialize the memory allocation subsystem.
++** 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_prepare()
++** is really a pointer to an instance of this structure.
++**
++** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
++** any virtual table method invocations made by the vdbe program. It is
++** set to 2 for xDestroy method calls and 1 for all other methods. This
++** variable is used for two purposes: to allow xDestroy methods to execute
++** "DROP TABLE" statements and to prevent some nasty side effects of
++** malloc failure when SQLite is invoked recursively by a virtual table 
++** method function.
+ */
+-static void sqlite3MemShutdown(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  mem.mutex = 0;
+-}
++struct Vdbe {
++  sqlite3 *db;            /* The database connection that owns this statement */
++  Op *aOp;                /* Space to hold the virtual machine's program */
++  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 *aLabel;            /* Space to hold the labels */
++  u16 nResColumn;         /* Number of columns in one row of the result set */
++  int 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 */
++  Mem *aVar;              /* Values for the OP_Variable opcode. */
++  char **azVar;           /* Name of variables */
++  ynVar nVar;             /* Number of entries in aVar[] */
++  ynVar nzVar;            /* Number of entries in azVar[] */
++  u32 cacheCtr;           /* VdbeCursor row cache generation counter */
++  int pc;                 /* The program counter */
++  int rc;                 /* Value to return */
++  u8 errorAction;         /* Recovery action to do in case of an error */
++  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
++  bft explain:2;          /* True if EXPLAIN present on SQL command */
++  bft inVtabMethod:2;     /* See comments above */
++  bft changeCntOn:1;      /* True to update the change-counter */
++  bft expired:1;          /* True if the VM needs to be recompiled */
++  bft runOnlyOnce:1;      /* Automatically expire on reset */
++  bft usesStmtJournal:1;  /* True if uses a statement journal */
++  bft readOnly:1;         /* True for read-only statements */
++  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
++  bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
++  int nChange;            /* Number of db changes made since last reset */
++  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
++  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
++  int iStatement;         /* Statement number (or 0 if has not opened stmt) */
++  int aCounter[3];        /* Counters used by sqlite3_stmt_status() */
++#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 */
++  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
++#ifdef SQLITE_ENABLE_TREE_EXPLAIN
++  Explain *pExplain;      /* The explainer */
++  char *zExplain;         /* Explanation of data structures */
++#endif
++  VdbeFrame *pFrame;      /* Parent frame */
++  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
++  int nFrame;             /* Number of frames in pFrame list */
++  u32 expmask;            /* Binding to these vars invalidates VM */
++  SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */
++  int nOnceFlag;          /* Size of array aOnceFlag[] */
++  u8 *aOnceFlag;          /* Flags for OP_Once */
++};
+ 
+ /*
+-** Round up a request size to the next valid allocation size.
++** The following are allowed values for Vdbe.magic
+ */
+-static int sqlite3MemRoundup(int n){
+-  return ROUND8(n);
+-}
++#define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
++#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */
++#define VDBE_MAGIC_HALT     0x519c2973    /* VDBE has completed execution */
++#define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */
+ 
+ /*
+-** Fill a buffer with pseudo-random bytes.  This is used to preset
+-** the content of a new memory allocation to unpredictable values and
+-** to clear the content of a freed allocation to unpredictable values.
++** Function prototypes
+ */
+-static void randomFill(char *pBuf, int nByte){
+-  unsigned int x, y, r;
+-  x = SQLITE_PTR_TO_INT(pBuf);
+-  y = nByte | 1;
+-  while( nByte >= 4 ){
+-    x = (x>>1) ^ (-(x&1) & 0xd0000001);
+-    y = y*1103515245 + 12345;
+-    r = x ^ y;
+-    *(int*)pBuf = r;
+-    pBuf += 4;
+-    nByte -= 4;
+-  }
+-  while( nByte-- > 0 ){
+-    x = (x>>1) ^ (-(x&1) & 0xd0000001);
+-    y = y*1103515245 + 12345;
+-    r = x ^ y;
+-    *(pBuf++) = r & 0xff;
+-  }
+-}
++SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
++void sqliteVdbePopStack(Vdbe*,int);
++SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*);
++#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
++SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
++#endif
++SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
++SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
++SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
++SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
++SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
+ 
+-/*
+-** Allocate nByte bytes of memory.
+-*/
+-static void *sqlite3MemMalloc(int nByte){
+-  struct MemBlockHdr *pHdr;
+-  void **pBt;
+-  char *z;
+-  int *pInt;
+-  void *p = 0;
+-  int totalSize;
+-  int nReserve;
+-  sqlite3_mutex_enter(mem.mutex);
+-  assert( mem.disallow==0 );
+-  nReserve = ROUND8(nByte);
+-  totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
+-               mem.nBacktrace*sizeof(void*) + mem.nTitle;
+-  p = malloc(totalSize);
+-  if( p ){
+-    z = p;
+-    pBt = (void**)&z[mem.nTitle];
+-    pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
+-    pHdr->pNext = 0;
+-    pHdr->pPrev = mem.pLast;
+-    if( mem.pLast ){
+-      mem.pLast->pNext = pHdr;
+-    }else{
+-      mem.pFirst = pHdr;
+-    }
+-    mem.pLast = pHdr;
+-    pHdr->iForeGuard = FOREGUARD;
+-    pHdr->eType = MEMTYPE_HEAP;
+-    pHdr->nBacktraceSlots = mem.nBacktrace;
+-    pHdr->nTitle = mem.nTitle;
+-    if( mem.nBacktrace ){
+-      void *aAddr[40];
+-      pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
+-      memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
+-      assert(pBt[0]);
+-      if( mem.xBacktrace ){
+-        mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
+-      }
+-    }else{
+-      pHdr->nBacktrace = 0;
+-    }
+-    if( mem.nTitle ){
+-      memcpy(z, mem.zTitle, mem.nTitle);
+-    }
+-    pHdr->iSize = nByte;
+-    adjustStats(nByte, +1);
+-    pInt = (int*)&pHdr[1];
+-    pInt[nReserve/sizeof(int)] = REARGUARD;
+-    randomFill((char*)pInt, nByte);
+-    memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
+-    p = (void*)pInt;
+-  }
+-  sqlite3_mutex_leave(mem.mutex);
+-  return p; 
+-}
++int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
++SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
++SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
++SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
++SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
++SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
++SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
++SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
++SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
++SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
++SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
++SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
++#ifdef SQLITE_OMIT_FLOATING_POINT
++# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
++#else
++SQLITE_PRIVATE   void sqlite3VdbeMemSetDouble(Mem*, double);
++#endif
++SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
++SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
++SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
++SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
++SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
++SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
++SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
++SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
++SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
++#define VdbeMemRelease(X)  \
++  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
++    sqlite3VdbeMemReleaseExternal(X);
++SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
++SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
++SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
++SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
++SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
++SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
++SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
++SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
++
++SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
++SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
++SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
++SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
++SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
++SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
++SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
++
++#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
++SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
++SQLITE_PRIVATE   void sqlite3VdbeLeave(Vdbe*);
++#else
++# define sqlite3VdbeEnter(X)
++# define sqlite3VdbeLeave(X)
++#endif
++
++#ifdef SQLITE_DEBUG
++SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
++#endif
++
++#ifndef SQLITE_OMIT_FOREIGN_KEY
++SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
++#else
++# define sqlite3VdbeCheckFk(p,i) 0
++#endif
++
++SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
++#ifdef SQLITE_DEBUG
++SQLITE_PRIVATE   void sqlite3VdbePrintSql(Vdbe*);
++SQLITE_PRIVATE   void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
++#endif
++SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
++
++#ifndef SQLITE_OMIT_INCRBLOB
++SQLITE_PRIVATE   int sqlite3VdbeMemExpandBlob(Mem *);
++  #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
++#else
++  #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
++  #define ExpandBlob(P) SQLITE_OK
++#endif
++
++#endif /* !defined(_VDBEINT_H_) */
++
++/************** End of vdbeInt.h *********************************************/
++/************** Continuing where we left off in status.c *********************/
+ 
+ /*
+-** Free memory.
++** Variables in which to record status information.
+ */
+-static void sqlite3MemFree(void *pPrior){
+-  struct MemBlockHdr *pHdr;
+-  void **pBt;
+-  char *z;
+-  assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0 
+-       || mem.mutex!=0 );
+-  pHdr = sqlite3MemsysGetHeader(pPrior);
+-  pBt = (void**)pHdr;
+-  pBt -= pHdr->nBacktraceSlots;
+-  sqlite3_mutex_enter(mem.mutex);
+-  if( pHdr->pPrev ){
+-    assert( pHdr->pPrev->pNext==pHdr );
+-    pHdr->pPrev->pNext = pHdr->pNext;
+-  }else{
+-    assert( mem.pFirst==pHdr );
+-    mem.pFirst = pHdr->pNext;
+-  }
+-  if( pHdr->pNext ){
+-    assert( pHdr->pNext->pPrev==pHdr );
+-    pHdr->pNext->pPrev = pHdr->pPrev;
+-  }else{
+-    assert( mem.pLast==pHdr );
+-    mem.pLast = pHdr->pPrev;
+-  }
+-  z = (char*)pBt;
+-  z -= pHdr->nTitle;
+-  adjustStats(pHdr->iSize, -1);
+-  randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
+-                pHdr->iSize + sizeof(int) + pHdr->nTitle);
+-  free(z);
+-  sqlite3_mutex_leave(mem.mutex);  
+-}
++typedef struct sqlite3StatType sqlite3StatType;
++static SQLITE_WSD struct sqlite3StatType {
++  int nowValue[10];         /* Current value */
++  int mxValue[10];          /* Maximum value */
++} sqlite3Stat = { {0,}, {0,} };
+ 
+-/*
+-** Change the size of an existing memory allocation.
+-**
+-** For this debugging implementation, we *always* make a copy of the
+-** allocation into a new place in memory.  In this way, if the 
+-** higher level code is using pointer to the old allocation, it is 
+-** much more likely to break and we are much more liking to find
+-** the error.
++
++/* The "wsdStat" macro will resolve to the status information
++** state vector.  If writable static data is unsupported on the target,
++** we have to locate the state vector at run-time.  In the more common
++** case where writable static data is supported, wsdStat can refer directly
++** to the "sqlite3Stat" state vector declared above.
+ */
+-static void *sqlite3MemRealloc(void *pPrior, int nByte){
+-  struct MemBlockHdr *pOldHdr;
+-  void *pNew;
+-  assert( mem.disallow==0 );
+-  assert( (nByte & 7)==0 );     /* EV: R-46199-30249 */
+-  pOldHdr = sqlite3MemsysGetHeader(pPrior);
+-  pNew = sqlite3MemMalloc(nByte);
+-  if( pNew ){
+-    memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
+-    if( nByte>pOldHdr->iSize ){
+-      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
+-    }
+-    sqlite3MemFree(pPrior);
+-  }
+-  return pNew;
+-}
++#ifdef SQLITE_OMIT_WSD
++# define wsdStatInit  sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
++# define wsdStat x[0]
++#else
++# define wsdStatInit
++# define wsdStat sqlite3Stat
++#endif
+ 
+ /*
+-** Populate the low-level memory allocation function pointers in
+-** sqlite3GlobalConfig.m with pointers to the routines in this file.
++** Return the current value of a status parameter.
+ */
+-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+-  static const sqlite3_mem_methods defaultMethods = {
+-     sqlite3MemMalloc,
+-     sqlite3MemFree,
+-     sqlite3MemRealloc,
+-     sqlite3MemSize,
+-     sqlite3MemRoundup,
+-     sqlite3MemInit,
+-     sqlite3MemShutdown,
+-     0
+-  };
+-  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
++SQLITE_PRIVATE int sqlite3StatusValue(int op){
++  wsdStatInit;
++  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
++  return wsdStat.nowValue[op];
+ }
+ 
+ /*
+-** Set the "type" of an allocation.
++** Add N to the value of a status record.  It is assumed that the
++** caller holds appropriate locks.
+ */
+-SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
+-  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+-    struct MemBlockHdr *pHdr;
+-    pHdr = sqlite3MemsysGetHeader(p);
+-    assert( pHdr->iForeGuard==FOREGUARD );
+-    pHdr->eType = eType;
++SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
++  wsdStatInit;
++  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
++  wsdStat.nowValue[op] += N;
++  if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
++    wsdStat.mxValue[op] = wsdStat.nowValue[op];
+   }
+ }
+ 
+ /*
+-** Return TRUE if the mask of type in eType matches the type of the
+-** allocation p.  Also return true if p==NULL.
+-**
+-** This routine is designed for use within an assert() statement, to
+-** verify the type of an allocation.  For example:
+-**
+-**     assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
++** Set the value of a status to X.
+ */
+-SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
+-  int rc = 1;
+-  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+-    struct MemBlockHdr *pHdr;
+-    pHdr = sqlite3MemsysGetHeader(p);
+-    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
+-    if( (pHdr->eType&eType)==0 ){
+-      rc = 0;
+-    }
++SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
++  wsdStatInit;
++  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
++  wsdStat.nowValue[op] = X;
++  if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
++    wsdStat.mxValue[op] = wsdStat.nowValue[op];
+   }
+-  return rc;
+ }
+ 
+ /*
+-** Return TRUE if the mask of type in eType matches no bits of the type of the
+-** allocation p.  Also return true if p==NULL.
+-**
+-** This routine is designed for use within an assert() statement, to
+-** verify the type of an allocation.  For example:
++** Query status information.
+ **
+-**     assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
++** This implementation assumes that reading or writing an aligned
++** 32-bit integer is an atomic operation.  If that assumption is not true,
++** then this routine is not threadsafe.
+ */
+-SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
+-  int rc = 1;
+-  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+-    struct MemBlockHdr *pHdr;
+-    pHdr = sqlite3MemsysGetHeader(p);
+-    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
+-    if( (pHdr->eType&eType)!=0 ){
+-      rc = 0;
+-    }
++SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
++  wsdStatInit;
++  if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
++    return SQLITE_MISUSE_BKPT;
+   }
+-  return rc;
+-}
+-
+-/*
+-** Set the number of backtrace levels kept for each allocation.
+-** A value of zero turns off backtracing.  The number is always rounded
+-** up to a multiple of 2.
+-*/
+-SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
+-  if( depth<0 ){ depth = 0; }
+-  if( depth>20 ){ depth = 20; }
+-  depth = (depth+1)&0xfe;
+-  mem.nBacktrace = depth;
+-}
+-
+-SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
+-  mem.xBacktrace = xBacktrace;
+-}
+-
+-/*
+-** Set the title string for subsequent allocations.
+-*/
+-SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
+-  unsigned int n = sqlite3Strlen30(zTitle) + 1;
+-  sqlite3_mutex_enter(mem.mutex);
+-  if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
+-  memcpy(mem.zTitle, zTitle, n);
+-  mem.zTitle[n] = 0;
+-  mem.nTitle = ROUND8(n);
+-  sqlite3_mutex_leave(mem.mutex);
+-}
+-
+-SQLITE_PRIVATE void sqlite3MemdebugSync(){
+-  struct MemBlockHdr *pHdr;
+-  for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
+-    void **pBt = (void**)pHdr;
+-    pBt -= pHdr->nBacktraceSlots;
+-    mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
++  *pCurrent = wsdStat.nowValue[op];
++  *pHighwater = wsdStat.mxValue[op];
++  if( resetFlag ){
++    wsdStat.mxValue[op] = wsdStat.nowValue[op];
+   }
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Open the file indicated and write a log of all unfreed memory 
+-** allocations into that log.
++** Query status information for a single database connection
+ */
+-SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
+-  FILE *out;
+-  struct MemBlockHdr *pHdr;
+-  void **pBt;
+-  int i;
+-  out = fopen(zFilename, "w");
+-  if( out==0 ){
+-    fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+-                    zFilename);
+-    return;
+-  }
+-  for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
+-    char *z = (char*)pHdr;
+-    z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
+-    fprintf(out, "**** %lld bytes at %p from %s ****\n", 
+-            pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
+-    if( pHdr->nBacktrace ){
+-      fflush(out);
+-      pBt = (void**)pHdr;
+-      pBt -= pHdr->nBacktraceSlots;
+-      backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
+-      fprintf(out, "\n");
++SQLITE_API int sqlite3_db_status(
++  sqlite3 *db,          /* The database connection whose status is desired */
++  int op,               /* Status verb */
++  int *pCurrent,        /* Write current value here */
++  int *pHighwater,      /* Write high-water mark here */
++  int resetFlag         /* Reset high-water mark if true */
++){
++  int rc = SQLITE_OK;   /* Return code */
++  sqlite3_mutex_enter(db->mutex);
++  switch( op ){
++    case SQLITE_DBSTATUS_LOOKASIDE_USED: {
++      *pCurrent = db->lookaside.nOut;
++      *pHighwater = db->lookaside.mxOut;
++      if( resetFlag ){
++        db->lookaside.mxOut = db->lookaside.nOut;
++      }
++      break;
+     }
+-  }
+-  fprintf(out, "COUNTS:\n");
+-  for(i=0; i<NCSIZE-1; i++){
+-    if( mem.nAlloc[i] ){
+-      fprintf(out, "   %5d: %10d %10d %10d\n", 
+-            i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
++
++    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;
+     }
+-  }
+-  if( mem.nAlloc[NCSIZE-1] ){
+-    fprintf(out, "   %5d: %10d %10d %10d\n",
+-             NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
+-             mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
+-  }
+-  fclose(out);
+-}
+ 
+-/*
+-** Return the number of times sqlite3MemMalloc() has been called.
+-*/
+-SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
+-  int i;
+-  int nTotal = 0;
+-  for(i=0; i<NCSIZE; i++){
+-    nTotal += mem.nAlloc[i];
+-  }
+-  return nTotal;
+-}
++    /* 
++    ** Return an approximation for the amount of memory currently used
++    ** by all pagers associated with the given database connection.  The
++    ** highwater mark is meaningless and is returned as zero.
++    */
++    case SQLITE_DBSTATUS_CACHE_USED: {
++      int totalUsed = 0;
++      int i;
++      sqlite3BtreeEnterAll(db);
++      for(i=0; i<db->nDb; i++){
++        Btree *pBt = db->aDb[i].pBt;
++        if( pBt ){
++          Pager *pPager = sqlite3BtreePager(pBt);
++          totalUsed += sqlite3PagerMemUsed(pPager);
++        }
++      }
++      sqlite3BtreeLeaveAll(db);
++      *pCurrent = totalUsed;
++      *pHighwater = 0;
++      break;
++    }
+ 
++    /*
++    ** *pCurrent gets an accurate estimate of the amount of memory used
++    ** to store the schema for all databases (main, temp, and any ATTACHed
++    ** databases.  *pHighwater is set to zero.
++    */
++    case SQLITE_DBSTATUS_SCHEMA_USED: {
++      int i;                      /* Used to iterate through schemas */
++      int nByte = 0;              /* Used to accumulate return value */
+ 
+-#endif /* SQLITE_MEMDEBUG */
++      sqlite3BtreeEnterAll(db);
++      db->pnBytesFreed = &nByte;
++      for(i=0; i<db->nDb; i++){
++        Schema *pSchema = db->aDb[i].pSchema;
++        if( ALWAYS(pSchema!=0) ){
++          HashElem *p;
+ 
+-/************** End of mem2.c ************************************************/
+-/************** Begin file mem3.c ********************************************/
++          nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
++              pSchema->tblHash.count 
++            + pSchema->trigHash.count
++            + pSchema->idxHash.count
++            + pSchema->fkeyHash.count
++          );
++          nByte += sqlite3MallocSize(pSchema->tblHash.ht);
++          nByte += sqlite3MallocSize(pSchema->trigHash.ht);
++          nByte += sqlite3MallocSize(pSchema->idxHash.ht);
++          nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
++
++          for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
++            sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
++          }
++          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
++            sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
++          }
++        }
++      }
++      db->pnBytesFreed = 0;
++      sqlite3BtreeLeaveAll(db);
++
++      *pHighwater = 0;
++      *pCurrent = nByte;
++      break;
++    }
++
++    /*
++    ** *pCurrent gets an accurate estimate of the amount of memory used
++    ** to store all prepared statements.
++    ** *pHighwater is set to zero.
++    */
++    case SQLITE_DBSTATUS_STMT_USED: {
++      struct Vdbe *pVdbe;         /* Used to iterate through VMs */
++      int nByte = 0;              /* Used to accumulate return value */
++
++      db->pnBytesFreed = &nByte;
++      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
++        sqlite3VdbeClearObject(db, pVdbe);
++        sqlite3DbFree(db, pVdbe);
++      }
++      db->pnBytesFreed = 0;
++
++      *pHighwater = 0;
++      *pCurrent = nByte;
++
++      break;
++    }
++
++    /*
++    ** Set *pCurrent to the total cache hits or misses encountered by all
++    ** pagers the database handle is connected to. *pHighwater is always set 
++    ** to zero.
++    */
++    case SQLITE_DBSTATUS_CACHE_HIT:
++    case SQLITE_DBSTATUS_CACHE_MISS:
++    case SQLITE_DBSTATUS_CACHE_WRITE:{
++      int i;
++      int nRet = 0;
++      assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
++      assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
++
++      for(i=0; i<db->nDb; i++){
++        if( db->aDb[i].pBt ){
++          Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
++          sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
++        }
++      }
++      *pHighwater = 0;
++      *pCurrent = nRet;
++      break;
++    }
++
++    default: {
++      rc = SQLITE_ERROR;
++    }
++  }
++  sqlite3_mutex_leave(db->mutex);
++  return rc;
++}
++
++/************** End of status.c **********************************************/
++/************** Begin file date.c ********************************************/
+ /*
+-** 2007 October 14
++** 2003 October 31
+ **
  ** The author disclaims copyright to this source code.  In place of
  ** a legal notice, here is a blessing:
+@@ -16443,1269 +16943,1505 @@
+ **    May you share freely, never taking more than you give.
  **
-@@ -22677,7 +24991,7 @@
- #include <sys/time.h>
- #include <errno.h>
- #ifndef SQLITE_OMIT_WAL
+ *************************************************************************
+-** This file contains the C functions that implement a memory
+-** allocation subsystem for use by SQLite. 
++** This file contains the C functions that implement date and time
++** functions for SQLite.  
+ **
+-** This version of the memory allocation subsystem omits all
+-** use of malloc(). The SQLite user supplies a block of memory
+-** before calling sqlite3_initialize() from which allocations
+-** are made and returned by the xMalloc() and xRealloc() 
+-** implementations. Once sqlite3_initialize() has been called,
+-** the amount of memory available to SQLite is fixed and cannot
+-** be changed.
++** There is only one exported symbol in this file - the function
++** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
++** All other code has file scope.
+ **
+-** This version of the memory allocation subsystem is included
+-** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
++** SQLite processes all times and dates as Julian Day numbers.  The
++** dates and times are stored as the number of days since noon
++** in Greenwich on November 24, 4714 B.C. according to the Gregorian
++** calendar system. 
++**
++** 1970-01-01 00:00:00 is JD 2440587.5
++** 2000-01-01 00:00:00 is JD 2451544.5
++**
++** This implemention requires years to be expressed as a 4-digit number
++** which means that only dates between 0000-01-01 and 9999-12-31 can
++** be represented, even though julian day numbers allow a much wider
++** range of dates.
++**
++** The Gregorian calendar system is used for all dates and times,
++** even those that predate the Gregorian calendar.  Historians usually
++** use the Julian calendar for dates prior to 1582-10-15 and for some
++** dates afterwards, depending on locale.  Beware of this difference.
++**
++** The conversion algorithms are implemented based on descriptions
++** in the following text:
++**
++**      Jean Meeus
++**      Astronomical Algorithms, 2nd Edition, 1998
++**      ISBM 0-943396-61-1
++**      Willmann-Bell, Inc
++**      Richmond, Virginia (USA)
+ */
++/* #include <stdlib.h> */
++/* #include <assert.h> */
++#include <time.h>
++
++#ifndef SQLITE_OMIT_DATETIME_FUNCS
+ 
+-/*
+-** This version of the memory allocator is only built into the library
+-** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
+-** mean that the library will use a memory-pool by default, just that
+-** it is available. The mempool allocator is activated by calling
+-** sqlite3_config().
+-*/
+-#ifdef SQLITE_ENABLE_MEMSYS3
+ 
+ /*
+-** Maximum size (in Mem3Blocks) of a "small" chunk.
++** A structure for holding a single date and time.
+ */
+-#define MX_SMALL 10
++typedef struct DateTime DateTime;
++struct DateTime {
++  sqlite3_int64 iJD; /* The julian day number times 86400000 */
++  int Y, M, D;       /* Year, month, and day */
++  int h, m;          /* Hour and minutes */
++  int tz;            /* Timezone offset in minutes */
++  double s;          /* Seconds */
++  char validYMD;     /* True (1) if Y,M,D are valid */
++  char validHMS;     /* True (1) if h,m,s are valid */
++  char validJD;      /* True (1) if iJD is valid */
++  char validTZ;      /* True (1) if tz is valid */
++};
+ 
+ 
+ /*
+-** Number of freelist hash slots
++** Convert zDate into one or more integers.  Additional arguments
++** come in groups of 5 as follows:
++**
++**       N       number of digits in the integer
++**       min     minimum allowed value of the integer
++**       max     maximum allowed value of the integer
++**       nextC   first character after the integer
++**       pVal    where to write the integers value.
++**
++** Conversions continue until one with nextC==0 is encountered.
++** The function returns the number of successful conversions.
+ */
+-#define N_HASH  61
++static int getDigits(const char *zDate, ...){
++  va_list ap;
++  int val;
++  int N;
++  int min;
++  int max;
++  int nextC;
++  int *pVal;
++  int cnt = 0;
++  va_start(ap, zDate);
++  do{
++    N = va_arg(ap, int);
++    min = va_arg(ap, int);
++    max = va_arg(ap, int);
++    nextC = va_arg(ap, int);
++    pVal = va_arg(ap, int*);
++    val = 0;
++    while( N-- ){
++      if( !sqlite3Isdigit(*zDate) ){
++        goto end_getDigits;
++      }
++      val = val*10 + *zDate - '0';
++      zDate++;
++    }
++    if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
++      goto end_getDigits;
++    }
++    *pVal = val;
++    zDate++;
++    cnt++;
++  }while( nextC );
++end_getDigits:
++  va_end(ap);
++  return cnt;
++}
+ 
+ /*
+-** A memory allocation (also called a "chunk") consists of two or 
+-** more blocks where each block is 8 bytes.  The first 8 bytes are 
+-** a header that is not returned to the user.
++** Parse a timezone extension on the end of a date-time.
++** The extension is of the form:
+ **
+-** A chunk is two or more blocks that is either checked out or
+-** free.  The first block has format u.hdr.  u.hdr.size4x is 4 times the
+-** size of the allocation in blocks if the allocation is free.
+-** The u.hdr.size4x&1 bit is true if the chunk is checked out and
+-** false if the chunk is on the freelist.  The u.hdr.size4x&2 bit
+-** is true if the previous chunk is checked out and false if the
+-** previous chunk is free.  The u.hdr.prevSize field is the size of
+-** the previous chunk in blocks if the previous chunk is on the
+-** freelist. If the previous chunk is checked out, then
+-** u.hdr.prevSize can be part of the data for that chunk and should
+-** not be read or written.
++**        (+/-)HH:MM
+ **
+-** We often identify a chunk by its index in mem3.aPool[].  When
+-** this is done, the chunk index refers to the second block of
+-** the chunk.  In this way, the first chunk has an index of 1.
+-** A chunk index of 0 means "no such chunk" and is the equivalent
+-** of a NULL pointer.
++** Or the "zulu" notation:
+ **
+-** The second block of free chunks is of the form u.list.  The
+-** two fields form a double-linked list of chunks of related sizes.
+-** Pointers to the head of the list are stored in mem3.aiSmall[] 
+-** for smaller chunks and mem3.aiHash[] for larger chunks.
++**        Z
+ **
+-** The second block of a chunk is user data if the chunk is checked 
+-** out.  If a chunk is checked out, the user data may extend into
+-** the u.hdr.prevSize value of the following chunk.
+-*/
+-typedef struct Mem3Block Mem3Block;
+-struct Mem3Block {
+-  union {
+-    struct {
+-      u32 prevSize;   /* Size of previous chunk in Mem3Block elements */
+-      u32 size4x;     /* 4x the size of current chunk in Mem3Block elements */
+-    } hdr;
+-    struct {
+-      u32 next;       /* Index in mem3.aPool[] of next free chunk */
+-      u32 prev;       /* Index in mem3.aPool[] of previous free chunk */
+-    } list;
+-  } u;
+-};
+-
+-/*
+-** All of the static variables used by this module are collected
+-** into a single structure named "mem3".  This is to keep the
+-** static variables organized and to reduce namespace pollution
+-** when this module is combined with other in the amalgamation.
+-*/
+-static SQLITE_WSD struct Mem3Global {
+-  /*
+-  ** Memory available for allocation. nPool is the size of the array
+-  ** (in Mem3Blocks) pointed to by aPool less 2.
+-  */
+-  u32 nPool;
+-  Mem3Block *aPool;
+-
+-  /*
+-  ** True if we are evaluating an out-of-memory callback.
+-  */
+-  int alarmBusy;
+-  
+-  /*
+-  ** Mutex to control access to the memory allocation subsystem.
+-  */
+-  sqlite3_mutex *mutex;
+-  
+-  /*
+-  ** The minimum amount of free space that we have seen.
+-  */
+-  u32 mnMaster;
+-
+-  /*
+-  ** iMaster is the index of the master chunk.  Most new allocations
+-  ** occur off of this chunk.  szMaster is the size (in Mem3Blocks)
+-  ** of the current master.  iMaster is 0 if there is not master chunk.
+-  ** The master chunk is not in either the aiHash[] or aiSmall[].
+-  */
+-  u32 iMaster;
+-  u32 szMaster;
+-
+-  /*
+-  ** Array of lists of free blocks according to the block size 
+-  ** for smaller chunks, or a hash on the block size for larger
+-  ** chunks.
+-  */
+-  u32 aiSmall[MX_SMALL-1];   /* For sizes 2 through MX_SMALL, inclusive */
+-  u32 aiHash[N_HASH];        /* For sizes MX_SMALL+1 and larger */
+-} mem3 = { 97535575 };
+-
+-#define mem3 GLOBAL(struct Mem3Global, mem3)
+-
+-/*
+-** Unlink the chunk at mem3.aPool[i] from list it is currently
+-** on.  *pRoot is the list that i is a member of.
++** If the parse is successful, write the number of minutes
++** of change in p->tz and return 0.  If a parser error occurs,
++** return non-zero.
++**
++** A missing specifier is not considered an error.
+ */
+-static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
+-  u32 next = mem3.aPool[i].u.list.next;
+-  u32 prev = mem3.aPool[i].u.list.prev;
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  if( prev==0 ){
+-    *pRoot = next;
++static int parseTimezone(const char *zDate, DateTime *p){
++  int sgn = 0;
++  int nHr, nMn;
++  int c;
++  while( sqlite3Isspace(*zDate) ){ zDate++; }
++  p->tz = 0;
++  c = *zDate;
++  if( c=='-' ){
++    sgn = -1;
++  }else if( c=='+' ){
++    sgn = +1;
++  }else if( c=='Z' || c=='z' ){
++    zDate++;
++    goto zulu_time;
+   }else{
+-    mem3.aPool[prev].u.list.next = next;
++    return c!=0;
+   }
+-  if( next ){
+-    mem3.aPool[next].u.list.prev = prev;
++  zDate++;
++  if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
++    return 1;
+   }
+-  mem3.aPool[i].u.list.next = 0;
+-  mem3.aPool[i].u.list.prev = 0;
++  zDate += 5;
++  p->tz = sgn*(nMn + nHr*60);
++zulu_time:
++  while( sqlite3Isspace(*zDate) ){ zDate++; }
++  return *zDate!=0;
+ }
+ 
+ /*
+-** Unlink the chunk at index i from 
+-** whatever list is currently a member of.
++** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
++** The HH, MM, and SS must each be exactly 2 digits.  The
++** fractional seconds FFFF can be one or more digits.
++**
++** Return 1 if there is a parsing error and 0 on success.
+ */
+-static void memsys3Unlink(u32 i){
+-  u32 size, hash;
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
+-  assert( i>=1 );
+-  size = mem3.aPool[i-1].u.hdr.size4x/4;
+-  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
+-  assert( size>=2 );
+-  if( size <= MX_SMALL ){
+-    memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
++static int parseHhMmSs(const char *zDate, DateTime *p){
++  int h, m, s;
++  double ms = 0.0;
++  if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
++    return 1;
++  }
++  zDate += 5;
++  if( *zDate==':' ){
++    zDate++;
++    if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
++      return 1;
++    }
++    zDate += 2;
++    if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
++      double rScale = 1.0;
++      zDate++;
++      while( sqlite3Isdigit(*zDate) ){
++        ms = ms*10.0 + *zDate - '0';
++        rScale *= 10.0;
++        zDate++;
++      }
++      ms /= rScale;
++    }
+   }else{
+-    hash = size % N_HASH;
+-    memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
++    s = 0;
+   }
++  p->validJD = 0;
++  p->validHMS = 1;
++  p->h = h;
++  p->m = m;
++  p->s = s + ms;
++  if( parseTimezone(zDate, p) ) return 1;
++  p->validTZ = (p->tz!=0)?1:0;
++  return 0;
+ }
+ 
+ /*
+-** Link the chunk at mem3.aPool[i] so that is on the list rooted
+-** at *pRoot.
++** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
++** that the YYYY-MM-DD is according to the Gregorian calendar.
++**
++** Reference:  Meeus page 61
+ */
+-static void memsys3LinkIntoList(u32 i, u32 *pRoot){
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  mem3.aPool[i].u.list.next = *pRoot;
+-  mem3.aPool[i].u.list.prev = 0;
+-  if( *pRoot ){
+-    mem3.aPool[*pRoot].u.list.prev = i;
++static void computeJD(DateTime *p){
++  int Y, M, D, A, B, X1, X2;
++
++  if( p->validJD ) return;
++  if( p->validYMD ){
++    Y = p->Y;
++    M = p->M;
++    D = p->D;
++  }else{
++    Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
++    M = 1;
++    D = 1;
++  }
++  if( M<=2 ){
++    Y--;
++    M += 12;
++  }
++  A = Y/100;
++  B = 2 - A + (A/4);
++  X1 = 36525*(Y+4716)/100;
++  X2 = 306001*(M+1)/10000;
++  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
++  p->validJD = 1;
++  if( p->validHMS ){
++    p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
++    if( p->validTZ ){
++      p->iJD -= p->tz*60000;
++      p->validYMD = 0;
++      p->validHMS = 0;
++      p->validTZ = 0;
++    }
+   }
+-  *pRoot = i;
+ }
+ 
+ /*
+-** Link the chunk at index i into either the appropriate
+-** small chunk list, or into the large chunk hash table.
++** Parse dates of the form
++**
++**     YYYY-MM-DD HH:MM:SS.FFF
++**     YYYY-MM-DD HH:MM:SS
++**     YYYY-MM-DD HH:MM
++**     YYYY-MM-DD
++**
++** Write the result into the DateTime structure and return 0
++** on success and 1 if the input string is not a well-formed
++** date.
+ */
+-static void memsys3Link(u32 i){
+-  u32 size, hash;
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  assert( i>=1 );
+-  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
+-  size = mem3.aPool[i-1].u.hdr.size4x/4;
+-  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
+-  assert( size>=2 );
+-  if( size <= MX_SMALL ){
+-    memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
++static int parseYyyyMmDd(const char *zDate, DateTime *p){
++  int Y, M, D, neg;
++
++  if( zDate[0]=='-' ){
++    zDate++;
++    neg = 1;
+   }else{
+-    hash = size % N_HASH;
+-    memsys3LinkIntoList(i, &mem3.aiHash[hash]);
++    neg = 0;
++  }
++  if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
++    return 1;
++  }
++  zDate += 10;
++  while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
++  if( parseHhMmSs(zDate, p)==0 ){
++    /* We got the time */
++  }else if( *zDate==0 ){
++    p->validHMS = 0;
++  }else{
++    return 1;
++  }
++  p->validJD = 0;
++  p->validYMD = 1;
++  p->Y = neg ? -Y : Y;
++  p->M = M;
++  p->D = D;
++  if( p->validTZ ){
++    computeJD(p);
+   }
++  return 0;
+ }
+ 
+ /*
+-** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
+-** will already be held (obtained by code in malloc.c) if
+-** sqlite3GlobalConfig.bMemStat is true.
++** Set the time to the current time reported by the VFS.
++**
++** Return the number of errors.
+ */
+-static void memsys3Enter(void){
+-  if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
+-    mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
++static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
++  sqlite3 *db = sqlite3_context_db_handle(context);
++  if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
++    p->validJD = 1;
++    return 0;
++  }else{
++    return 1;
+   }
+-  sqlite3_mutex_enter(mem3.mutex);
+-}
+-static void memsys3Leave(void){
+-  sqlite3_mutex_leave(mem3.mutex);
+ }
+ 
+ /*
+-** Called when we are unable to satisfy an allocation of nBytes.
+-*/
+-static void memsys3OutOfMemory(int nByte){
+-  if( !mem3.alarmBusy ){
+-    mem3.alarmBusy = 1;
+-    assert( sqlite3_mutex_held(mem3.mutex) );
+-    sqlite3_mutex_leave(mem3.mutex);
+-    sqlite3_release_memory(nByte);
+-    sqlite3_mutex_enter(mem3.mutex);
+-    mem3.alarmBusy = 0;
+-  }
+-}
+-
+-
+-/*
+-** Chunk i is a free chunk that has been unlinked.  Adjust its 
+-** size parameters for check-out and return a pointer to the 
+-** user portion of the chunk.
+-*/
+-static void *memsys3Checkout(u32 i, u32 nBlock){
+-  u32 x;
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  assert( i>=1 );
+-  assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
+-  assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
+-  x = mem3.aPool[i-1].u.hdr.size4x;
+-  mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
+-  mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
+-  mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
+-  return &mem3.aPool[i];
+-}
+-
+-/*
+-** Carve a piece off of the end of the mem3.iMaster free chunk.
+-** Return a pointer to the new allocation.  Or, if the master chunk
+-** is not large enough, return 0.
+-*/
+-static void *memsys3FromMaster(u32 nBlock){
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  assert( mem3.szMaster>=nBlock );
+-  if( nBlock>=mem3.szMaster-1 ){
+-    /* Use the entire master */
+-    void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
+-    mem3.iMaster = 0;
+-    mem3.szMaster = 0;
+-    mem3.mnMaster = 0;
+-    return p;
+-  }else{
+-    /* Split the master block.  Return the tail. */
+-    u32 newi, x;
+-    newi = mem3.iMaster + mem3.szMaster - nBlock;
+-    assert( newi > mem3.iMaster+1 );
+-    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
+-    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
+-    mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
+-    mem3.szMaster -= nBlock;
+-    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
+-    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
+-    mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
+-    if( mem3.szMaster < mem3.mnMaster ){
+-      mem3.mnMaster = mem3.szMaster;
+-    }
+-    return (void*)&mem3.aPool[newi];
+-  }
+-}
+-
+-/*
+-** *pRoot is the head of a list of free chunks of the same size
+-** or same size hash.  In other words, *pRoot is an entry in either
+-** mem3.aiSmall[] or mem3.aiHash[].  
++** Attempt to parse the given string into a Julian Day Number.  Return
++** the number of errors.
+ **
+-** This routine examines all entries on the given list and tries
+-** to coalesce each entries with adjacent free chunks.  
++** The following are acceptable forms for the input string:
+ **
+-** If it sees a chunk that is larger than mem3.iMaster, it replaces 
+-** the current mem3.iMaster with the new larger chunk.  In order for
+-** this mem3.iMaster replacement to work, the master chunk must be
+-** linked into the hash tables.  That is not the normal state of
+-** affairs, of course.  The calling routine must link the master
+-** chunk before invoking this routine, then must unlink the (possibly
+-** changed) master chunk once this routine has finished.
++**      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
++**      DDDD.DD 
++**      now
++**
++** In the first form, the +/-HH:MM is always optional.  The fractional
++** seconds extension (the ".FFF") is optional.  The seconds portion
++** (":SS.FFF") is option.  The year and date can be omitted as long
++** as there is a time string.  The time string can be omitted as long
++** as there is a year and date.
+ */
+-static void memsys3Merge(u32 *pRoot){
+-  u32 iNext, prev, size, i, x;
+-
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  for(i=*pRoot; i>0; i=iNext){
+-    iNext = mem3.aPool[i].u.list.next;
+-    size = mem3.aPool[i-1].u.hdr.size4x;
+-    assert( (size&1)==0 );
+-    if( (size&2)==0 ){
+-      memsys3UnlinkFromList(i, pRoot);
+-      assert( i > mem3.aPool[i-1].u.hdr.prevSize );
+-      prev = i - mem3.aPool[i-1].u.hdr.prevSize;
+-      if( prev==iNext ){
+-        iNext = mem3.aPool[prev].u.list.next;
+-      }
+-      memsys3Unlink(prev);
+-      size = i + size/4 - prev;
+-      x = mem3.aPool[prev-1].u.hdr.size4x & 2;
+-      mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
+-      mem3.aPool[prev+size-1].u.hdr.prevSize = size;
+-      memsys3Link(prev);
+-      i = prev;
+-    }else{
+-      size /= 4;
+-    }
+-    if( size>mem3.szMaster ){
+-      mem3.iMaster = i;
+-      mem3.szMaster = size;
+-    }
++static int parseDateOrTime(
++  sqlite3_context *context, 
++  const char *zDate, 
++  DateTime *p
++){
++  double r;
++  if( parseYyyyMmDd(zDate,p)==0 ){
++    return 0;
++  }else if( parseHhMmSs(zDate, p)==0 ){
++    return 0;
++  }else if( sqlite3StrICmp(zDate,"now")==0){
++    return setDateTimeToCurrent(context, p);
++  }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
++    p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
++    p->validJD = 1;
++    return 0;
+   }
++  return 1;
+ }
+ 
+ /*
+-** Return a block of memory of at least nBytes in size.
+-** Return NULL if unable.
+-**
+-** This function assumes that the necessary mutexes, if any, are
+-** already held by the caller. Hence "Unsafe".
++** Compute the Year, Month, and Day from the julian day number.
+ */
+-static void *memsys3MallocUnsafe(int nByte){
+-  u32 i;
+-  u32 nBlock;
+-  u32 toFree;
+-
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  assert( sizeof(Mem3Block)==8 );
+-  if( nByte<=12 ){
+-    nBlock = 2;
+-  }else{
+-    nBlock = (nByte + 11)/8;
+-  }
+-  assert( nBlock>=2 );
+-
+-  /* STEP 1:
+-  ** Look for an entry of the correct size in either the small
+-  ** chunk table or in the large chunk hash table.  This is
+-  ** successful most of the time (about 9 times out of 10).
+-  */
+-  if( nBlock <= MX_SMALL ){
+-    i = mem3.aiSmall[nBlock-2];
+-    if( i>0 ){
+-      memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
+-      return memsys3Checkout(i, nBlock);
+-    }
++static void computeYMD(DateTime *p){
++  int Z, A, B, C, D, E, X1;
++  if( p->validYMD ) return;
++  if( !p->validJD ){
++    p->Y = 2000;
++    p->M = 1;
++    p->D = 1;
+   }else{
+-    int hash = nBlock % N_HASH;
+-    for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
+-      if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
+-        memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
+-        return memsys3Checkout(i, nBlock);
+-      }
+-    }
+-  }
+-
+-  /* STEP 2:
+-  ** Try to satisfy the allocation by carving a piece off of the end
+-  ** of the master chunk.  This step usually works if step 1 fails.
+-  */
+-  if( mem3.szMaster>=nBlock ){
+-    return memsys3FromMaster(nBlock);
+-  }
+-
+-
+-  /* STEP 3:  
+-  ** Loop through the entire memory pool.  Coalesce adjacent free
+-  ** chunks.  Recompute the master chunk as the largest free chunk.
+-  ** Then try again to satisfy the allocation by carving a piece off
+-  ** of the end of the master chunk.  This step happens very
+-  ** rarely (we hope!)
+-  */
+-  for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
+-    memsys3OutOfMemory(toFree);
+-    if( mem3.iMaster ){
+-      memsys3Link(mem3.iMaster);
+-      mem3.iMaster = 0;
+-      mem3.szMaster = 0;
+-    }
+-    for(i=0; i<N_HASH; i++){
+-      memsys3Merge(&mem3.aiHash[i]);
+-    }
+-    for(i=0; i<MX_SMALL-1; i++){
+-      memsys3Merge(&mem3.aiSmall[i]);
+-    }
+-    if( mem3.szMaster ){
+-      memsys3Unlink(mem3.iMaster);
+-      if( mem3.szMaster>=nBlock ){
+-        return memsys3FromMaster(nBlock);
+-      }
+-    }
++    Z = (int)((p->iJD + 43200000)/86400000);
++    A = (int)((Z - 1867216.25)/36524.25);
++    A = Z + 1 + A - (A/4);
++    B = A + 1524;
++    C = (int)((B - 122.1)/365.25);
++    D = (36525*C)/100;
++    E = (int)((B-D)/30.6001);
++    X1 = (int)(30.6001*E);
++    p->D = B - D - X1;
++    p->M = E<14 ? E-1 : E-13;
++    p->Y = p->M>2 ? C - 4716 : C - 4715;
+   }
+-
+-  /* If none of the above worked, then we fail. */
+-  return 0;
++  p->validYMD = 1;
+ }
+ 
+ /*
+-** Free an outstanding memory allocation.
+-**
+-** This function assumes that the necessary mutexes, if any, are
+-** already held by the caller. Hence "Unsafe".
++** Compute the Hour, Minute, and Seconds from the julian day number.
+ */
+-static void memsys3FreeUnsafe(void *pOld){
+-  Mem3Block *p = (Mem3Block*)pOld;
+-  int i;
+-  u32 size, x;
+-  assert( sqlite3_mutex_held(mem3.mutex) );
+-  assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
+-  i = p - mem3.aPool;
+-  assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
+-  size = mem3.aPool[i-1].u.hdr.size4x/4;
+-  assert( i+size<=mem3.nPool+1 );
+-  mem3.aPool[i-1].u.hdr.size4x &= ~1;
+-  mem3.aPool[i+size-1].u.hdr.prevSize = size;
+-  mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
+-  memsys3Link(i);
+-
+-  /* Try to expand the master using the newly freed chunk */
+-  if( mem3.iMaster ){
+-    while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
+-      size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
+-      mem3.iMaster -= size;
+-      mem3.szMaster += size;
+-      memsys3Unlink(mem3.iMaster);
+-      x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
+-      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
+-      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+-    }
+-    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
+-    while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
+-      memsys3Unlink(mem3.iMaster+mem3.szMaster);
+-      mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
+-      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
+-      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+-    }
+-  }
++static void computeHMS(DateTime *p){
++  int s;
++  if( p->validHMS ) return;
++  computeJD(p);
++  s = (int)((p->iJD + 43200000) % 86400000);
++  p->s = s/1000.0;
++  s = (int)p->s;
++  p->s -= s;
++  p->h = s/3600;
++  s -= p->h*3600;
++  p->m = s/60;
++  p->s += s - p->m*60;
++  p->validHMS = 1;
+ }
+ 
+ /*
+-** Return the size of an outstanding allocation, in bytes.  The
+-** size returned omits the 8-byte header overhead.  This only
+-** works for chunks that are currently checked out.
++** Compute both YMD and HMS
+ */
+-static int memsys3Size(void *p){
+-  Mem3Block *pBlock;
+-  if( p==0 ) return 0;
+-  pBlock = (Mem3Block*)p;
+-  assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
+-  return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
++static void computeYMD_HMS(DateTime *p){
++  computeYMD(p);
++  computeHMS(p);
+ }
+ 
+ /*
+-** Round up a request size to the next valid allocation size.
++** Clear the YMD and HMS and the TZ
+ */
+-static int memsys3Roundup(int n){
+-  if( n<=12 ){
+-    return 12;
+-  }else{
+-    return ((n+11)&~7) - 4;
+-  }
++static void clearYMD_HMS_TZ(DateTime *p){
++  p->validYMD = 0;
++  p->validHMS = 0;
++  p->validTZ = 0;
+ }
+ 
+ /*
+-** Allocate nBytes of memory.
++** On recent Windows platforms, the localtime_s() function is available
++** as part of the "Secure CRT". It is essentially equivalent to 
++** localtime_r() available under most POSIX platforms, except that the 
++** order of the parameters is reversed.
++**
++** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
++**
++** If the user has not indicated to use localtime_r() or localtime_s()
++** already, check for an MSVC build environment that provides 
++** localtime_s().
+ */
+-static void *memsys3Malloc(int nBytes){
+-  sqlite3_int64 *p;
+-  assert( nBytes>0 );          /* malloc.c filters out 0 byte requests */
+-  memsys3Enter();
+-  p = memsys3MallocUnsafe(nBytes);
+-  memsys3Leave();
+-  return (void*)p; 
+-}
++#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
++     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
++#define HAVE_LOCALTIME_S 1
++#endif
+ 
++#ifndef SQLITE_OMIT_LOCALTIME
+ /*
+-** Free memory.
++** The following routine implements the rough equivalent of localtime_r()
++** using whatever operating-system specific localtime facility that
++** is available.  This routine returns 0 on success and
++** non-zero on any kind of error.
++**
++** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
++** routine will always fail.
+ */
+-static void memsys3Free(void *pPrior){
+-  assert( pPrior );
+-  memsys3Enter();
+-  memsys3FreeUnsafe(pPrior);
+-  memsys3Leave();
++static int osLocaltime(time_t *t, struct tm *pTm){
++  int rc;
++#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
++      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
++  struct tm *pX;
++#if SQLITE_THREADSAFE>0
++  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
++#endif
++  sqlite3_mutex_enter(mutex);
++  pX = localtime(t);
++#ifndef SQLITE_OMIT_BUILTIN_TEST
++  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
++#endif
++  if( pX ) *pTm = *pX;
++  sqlite3_mutex_leave(mutex);
++  rc = pX==0;
++#else
++#ifndef SQLITE_OMIT_BUILTIN_TEST
++  if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
++#endif
++#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
++  rc = localtime_r(t, pTm)==0;
++#else
++  rc = localtime_s(pTm, t);
++#endif /* HAVE_LOCALTIME_R */
++#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
++  return rc;
+ }
++#endif /* SQLITE_OMIT_LOCALTIME */
++
+ 
++#ifndef SQLITE_OMIT_LOCALTIME
+ /*
+-** Change the size of an existing memory allocation
++** Compute the difference (in milliseconds) between localtime and UTC
++** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
++** return this value and set *pRc to SQLITE_OK. 
++**
++** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
++** is undefined in this case.
+ */
+-static void *memsys3Realloc(void *pPrior, int nBytes){
+-  int nOld;
+-  void *p;
+-  if( pPrior==0 ){
+-    return sqlite3_malloc(nBytes);
++static sqlite3_int64 localtimeOffset(
++  DateTime *p,                    /* Date at which to calculate offset */
++  sqlite3_context *pCtx,          /* Write error here if one occurs */
++  int *pRc                        /* OUT: Error code. SQLITE_OK or ERROR */
++){
++  DateTime x, y;
++  time_t t;
++  struct tm sLocal;
++
++  /* Initialize the contents of sLocal to avoid a compiler warning. */
++  memset(&sLocal, 0, sizeof(sLocal));
++
++  x = *p;
++  computeYMD_HMS(&x);
++  if( x.Y<1971 || x.Y>=2038 ){
++    x.Y = 2000;
++    x.M = 1;
++    x.D = 1;
++    x.h = 0;
++    x.m = 0;
++    x.s = 0.0;
++  } else {
++    int s = (int)(x.s + 0.5);
++    x.s = s;
+   }
+-  if( nBytes<=0 ){
+-    sqlite3_free(pPrior);
++  x.tz = 0;
++  x.validJD = 0;
++  computeJD(&x);
++  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
++  if( osLocaltime(&t, &sLocal) ){
++    sqlite3_result_error(pCtx, "local time unavailable", -1);
++    *pRc = SQLITE_ERROR;
+     return 0;
+   }
+-  nOld = memsys3Size(pPrior);
+-  if( nBytes<=nOld && nBytes>=nOld-128 ){
+-    return pPrior;
+-  }
+-  memsys3Enter();
+-  p = memsys3MallocUnsafe(nBytes);
+-  if( p ){
+-    if( nOld<nBytes ){
+-      memcpy(p, pPrior, nOld);
+-    }else{
+-      memcpy(p, pPrior, nBytes);
+-    }
+-    memsys3FreeUnsafe(pPrior);
+-  }
+-  memsys3Leave();
+-  return p;
++  y.Y = sLocal.tm_year + 1900;
++  y.M = sLocal.tm_mon + 1;
++  y.D = sLocal.tm_mday;
++  y.h = sLocal.tm_hour;
++  y.m = sLocal.tm_min;
++  y.s = sLocal.tm_sec;
++  y.validYMD = 1;
++  y.validHMS = 1;
++  y.validJD = 0;
++  y.validTZ = 0;
++  computeJD(&y);
++  *pRc = SQLITE_OK;
++  return y.iJD - x.iJD;
+ }
++#endif /* SQLITE_OMIT_LOCALTIME */
+ 
+ /*
+-** Initialize this module.
++** Process a modifier to a date-time stamp.  The modifiers are
++** as follows:
++**
++**     NNN days
++**     NNN hours
++**     NNN minutes
++**     NNN.NNNN seconds
++**     NNN months
++**     NNN years
++**     start of month
++**     start of year
++**     start of week
++**     start of day
++**     weekday N
++**     unixepoch
++**     localtime
++**     utc
++**
++** Return 0 on success and 1 if there is any kind of error. If the error
++** is in a system call (i.e. localtime()), then an error message is written
++** to context pCtx. If the error is an unrecognized modifier, no error is
++** written to pCtx.
+ */
+-static int memsys3Init(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  if( !sqlite3GlobalConfig.pHeap ){
+-    return SQLITE_ERROR;
++static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
++  int rc = 1;
++  int n;
++  double r;
++  char *z, zBuf[30];
++  z = zBuf;
++  for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
++    z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
+   }
+-
+-  /* Store a pointer to the memory block in global structure mem3. */
+-  assert( sizeof(Mem3Block)==8 );
+-  mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
+-  mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
+-
+-  /* Initialize the master block. */
+-  mem3.szMaster = mem3.nPool;
+-  mem3.mnMaster = mem3.szMaster;
+-  mem3.iMaster = 1;
+-  mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
+-  mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
+-  mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
+-
+-  return SQLITE_OK;
+-}
+-
+-/*
+-** Deinitialize this module.
+-*/
+-static void memsys3Shutdown(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  mem3.mutex = 0;
+-  return;
+-}
+-
+-
+-
+-/*
+-** Open the file indicated and write a log of all unfreed memory 
+-** allocations into that log.
+-*/
+-SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
+-#ifdef SQLITE_DEBUG
+-  FILE *out;
+-  u32 i, j;
+-  u32 size;
+-  if( zFilename==0 || zFilename[0]==0 ){
+-    out = stdout;
+-  }else{
+-    out = fopen(zFilename, "w");
+-    if( out==0 ){
+-      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+-                      zFilename);
+-      return;
+-    }
+-  }
+-  memsys3Enter();
+-  fprintf(out, "CHUNKS:\n");
+-  for(i=1; i<=mem3.nPool; i+=size/4){
+-    size = mem3.aPool[i-1].u.hdr.size4x;
+-    if( size/4<=1 ){
+-      fprintf(out, "%p size error\n", &mem3.aPool[i]);
+-      assert( 0 );
++  z[n] = 0;
++  switch( z[0] ){
++#ifndef SQLITE_OMIT_LOCALTIME
++    case 'l': {
++      /*    localtime
++      **
++      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
++      ** show local time.
++      */
++      if( strcmp(z, "localtime")==0 ){
++        computeJD(p);
++        p->iJD += localtimeOffset(p, pCtx, &rc);
++        clearYMD_HMS_TZ(p);
++      }
+       break;
+     }
+-    if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
+-      fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
+-      assert( 0 );
++#endif
++    case 'u': {
++      /*
++      **    unixepoch
++      **
++      ** Treat the current value of p->iJD as the number of
++      ** seconds since 1970.  Convert to a real julian day number.
++      */
++      if( strcmp(z, "unixepoch")==0 && p->validJD ){
++        p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
++        clearYMD_HMS_TZ(p);
++        rc = 0;
++      }
++#ifndef SQLITE_OMIT_LOCALTIME
++      else if( strcmp(z, "utc")==0 ){
++        sqlite3_int64 c1;
++        computeJD(p);
++        c1 = localtimeOffset(p, pCtx, &rc);
++        if( rc==SQLITE_OK ){
++          p->iJD -= c1;
++          clearYMD_HMS_TZ(p);
++          p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
++        }
++      }
++#endif
+       break;
+     }
+-    if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
+-      fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
+-      assert( 0 );
++    case 'w': {
++      /*
++      **    weekday N
++      **
++      ** Move the date to the same time on the next occurrence of
++      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
++      ** date is already on the appropriate weekday, this is a no-op.
++      */
++      if( strncmp(z, "weekday ", 8)==0
++               && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
++               && (n=(int)r)==r && n>=0 && r<7 ){
++        sqlite3_int64 Z;
++        computeYMD_HMS(p);
++        p->validTZ = 0;
++        p->validJD = 0;
++        computeJD(p);
++        Z = ((p->iJD + 129600000)/86400000) % 7;
++        if( Z>n ) Z -= 7;
++        p->iJD += (n - Z)*86400000;
++        clearYMD_HMS_TZ(p);
++        rc = 0;
++      }
+       break;
+     }
+-    if( size&1 ){
+-      fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
+-    }else{
+-      fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
+-                  i==mem3.iMaster ? " **master**" : "");
++    case 's': {
++      /*
++      **    start of TTTTT
++      **
++      ** Move the date backwards to the beginning of the current day,
++      ** or month or year.
++      */
++      if( strncmp(z, "start of ", 9)!=0 ) break;
++      z += 9;
++      computeYMD(p);
++      p->validHMS = 1;
++      p->h = p->m = 0;
++      p->s = 0.0;
++      p->validTZ = 0;
++      p->validJD = 0;
++      if( strcmp(z,"month")==0 ){
++        p->D = 1;
++        rc = 0;
++      }else if( strcmp(z,"year")==0 ){
++        computeYMD(p);
++        p->M = 1;
++        p->D = 1;
++        rc = 0;
++      }else if( strcmp(z,"day")==0 ){
++        rc = 0;
++      }
++      break;
+     }
+-  }
+-  for(i=0; i<MX_SMALL-1; i++){
+-    if( mem3.aiSmall[i]==0 ) continue;
+-    fprintf(out, "small(%2d):", i);
+-    for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
+-      fprintf(out, " %p(%d)", &mem3.aPool[j],
+-              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
++    case '+':
++    case '-':
++    case '0':
++    case '1':
++    case '2':
++    case '3':
++    case '4':
++    case '5':
++    case '6':
++    case '7':
++    case '8':
++    case '9': {
++      double rRounder;
++      for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
++      if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
++        rc = 1;
++        break;
++      }
++      if( z[n]==':' ){
++        /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
++        ** specified number of hours, minutes, seconds, and fractional seconds
++        ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
++        ** omitted.
++        */
++        const char *z2 = z;
++        DateTime tx;
++        sqlite3_int64 day;
++        if( !sqlite3Isdigit(*z2) ) z2++;
++        memset(&tx, 0, sizeof(tx));
++        if( parseHhMmSs(z2, &tx) ) break;
++        computeJD(&tx);
++        tx.iJD -= 43200000;
++        day = tx.iJD/86400000;
++        tx.iJD -= day*86400000;
++        if( z[0]=='-' ) tx.iJD = -tx.iJD;
++        computeJD(p);
++        clearYMD_HMS_TZ(p);
++        p->iJD += tx.iJD;
++        rc = 0;
++        break;
++      }
++      z += n;
++      while( sqlite3Isspace(*z) ) z++;
++      n = sqlite3Strlen30(z);
++      if( n>10 || n<3 ) break;
++      if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
++      computeJD(p);
++      rc = 0;
++      rRounder = r<0 ? -0.5 : +0.5;
++      if( n==3 && strcmp(z,"day")==0 ){
++        p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
++      }else if( n==4 && strcmp(z,"hour")==0 ){
++        p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
++      }else if( n==6 && strcmp(z,"minute")==0 ){
++        p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
++      }else if( n==6 && strcmp(z,"second")==0 ){
++        p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
++      }else if( n==5 && strcmp(z,"month")==0 ){
++        int x, y;
++        computeYMD_HMS(p);
++        p->M += (int)r;
++        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
++        p->Y += x;
++        p->M -= x*12;
++        p->validJD = 0;
++        computeJD(p);
++        y = (int)r;
++        if( y!=r ){
++          p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
++        }
++      }else if( n==4 && strcmp(z,"year")==0 ){
++        int y = (int)r;
++        computeYMD_HMS(p);
++        p->Y += y;
++        p->validJD = 0;
++        computeJD(p);
++        if( y!=r ){
++          p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
++        }
++      }else{
++        rc = 1;
++      }
++      clearYMD_HMS_TZ(p);
++      break;
+     }
+-    fprintf(out, "\n"); 
+-  }
+-  for(i=0; i<N_HASH; i++){
+-    if( mem3.aiHash[i]==0 ) continue;
+-    fprintf(out, "hash(%2d):", i);
+-    for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
+-      fprintf(out, " %p(%d)", &mem3.aPool[j],
+-              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
++    default: {
++      break;
+     }
+-    fprintf(out, "\n"); 
+-  }
+-  fprintf(out, "master=%d\n", mem3.iMaster);
+-  fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
+-  fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
+-  sqlite3_mutex_leave(mem3.mutex);
+-  if( out==stdout ){
+-    fflush(stdout);
+-  }else{
+-    fclose(out);
+   }
+-#else
+-  UNUSED_PARAMETER(zFilename);
+-#endif
++  return rc;
+ }
+ 
+ /*
+-** This routine is the only routine in this file with external 
+-** linkage.
+-**
+-** Populate the low-level memory allocation function pointers in
+-** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+-** arguments specify the block of memory to manage.
++** Process time function arguments.  argv[0] is a date-time stamp.
++** argv[1] and following are modifiers.  Parse them all and write
++** the resulting time into the DateTime structure p.  Return 0
++** on success and 1 if there are any errors.
+ **
+-** This routine is only called by sqlite3_config(), and therefore
+-** is not required to be threadsafe (it is not).
++** If there are zero parameters (if even argv[0] is undefined)
++** then assume a default value of "now" for argv[0].
+ */
+-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
+-  static const sqlite3_mem_methods mempoolMethods = {
+-     memsys3Malloc,
+-     memsys3Free,
+-     memsys3Realloc,
+-     memsys3Size,
+-     memsys3Roundup,
+-     memsys3Init,
+-     memsys3Shutdown,
+-     0
+-  };
+-  return &mempoolMethods;
++static int isDate(
++  sqlite3_context *context, 
++  int argc, 
++  sqlite3_value **argv, 
++  DateTime *p
++){
++  int i;
++  const unsigned char *z;
++  int eType;
++  memset(p, 0, sizeof(*p));
++  if( argc==0 ){
++    return setDateTimeToCurrent(context, p);
++  }
++  if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
++                   || eType==SQLITE_INTEGER ){
++    p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
++    p->validJD = 1;
++  }else{
++    z = sqlite3_value_text(argv[0]);
++    if( !z || parseDateOrTime(context, (char*)z, p) ){
++      return 1;
++    }
++  }
++  for(i=1; i<argc; i++){
++    z = sqlite3_value_text(argv[i]);
++    if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
++  }
++  return 0;
+ }
+ 
+-#endif /* SQLITE_ENABLE_MEMSYS3 */
+-
+-/************** End of mem3.c ************************************************/
+-/************** Begin file mem5.c ********************************************/
+-/*
+-** 2007 October 14
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-** This file contains the C functions that implement a memory
+-** allocation subsystem for use by SQLite. 
+-**
+-** This version of the memory allocation subsystem omits all
+-** use of malloc(). The application gives SQLite a block of memory
+-** before calling sqlite3_initialize() from which allocations
+-** are made and returned by the xMalloc() and xRealloc() 
+-** implementations. Once sqlite3_initialize() has been called,
+-** the amount of memory available to SQLite is fixed and cannot
+-** be changed.
+-**
+-** This version of the memory allocation subsystem is included
+-** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
+-**
+-** This memory allocator uses the following algorithm:
+-**
+-**   1.  All memory allocations sizes are rounded up to a power of 2.
+-**
+-**   2.  If two adjacent free blocks are the halves of a larger block,
+-**       then the two blocks are coalesed into the single larger block.
+-**
+-**   3.  New memory is allocated from the first available free block.
+-**
+-** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
+-** Concerning Dynamic Storage Allocation". Journal of the Association for
+-** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
+-** 
+-** Let n be the size of the largest allocation divided by the minimum
+-** allocation size (after rounding all sizes up to a power of 2.)  Let M
+-** be the maximum amount of memory ever outstanding at one time.  Let
+-** N be the total amount of memory available for allocation.  Robson
+-** proved that this memory allocator will never breakdown due to 
+-** fragmentation as long as the following constraint holds:
+-**
+-**      N >=  M*(1 + log2(n)/2) - n + 1
+-**
+-** The sqlite3_status() logic tracks the maximum values of n and M so
+-** that an application can, at any time, verify this constraint.
+-*/
+ 
+ /*
+-** This version of the memory allocator is used only when 
+-** SQLITE_ENABLE_MEMSYS5 is defined.
++** The following routines implement the various date and time functions
++** of SQLite.
+ */
+-#ifdef SQLITE_ENABLE_MEMSYS5
+ 
+ /*
+-** A minimum allocation is an instance of the following structure.
+-** Larger allocations are an array of these structures where the
+-** size of the array is a power of 2.
++**    julianday( TIMESTRING, MOD, MOD, ...)
+ **
+-** The size of this object must be a power of two.  That fact is
+-** verified in memsys5Init().
+-*/
+-typedef struct Mem5Link Mem5Link;
+-struct Mem5Link {
+-  int next;       /* Index of next free chunk */
+-  int prev;       /* Index of previous free chunk */
+-};
+-
+-/*
+-** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
+-** mem5.szAtom is always at least 8 and 32-bit integers are used,
+-** it is not actually possible to reach this limit.
+-*/
+-#define LOGMAX 30
+-
+-/*
+-** Masks used for mem5.aCtrl[] elements.
+-*/
+-#define CTRL_LOGSIZE  0x1f    /* Log2 Size of this block */
+-#define CTRL_FREE     0x20    /* True if not checked out */
+-
+-/*
+-** All of the static variables used by this module are collected
+-** into a single structure named "mem5".  This is to keep the
+-** static variables organized and to reduce namespace pollution
+-** when this module is combined with other in the amalgamation.
+-*/
+-static SQLITE_WSD struct Mem5Global {
+-  /*
+-  ** Memory available for allocation
+-  */
+-  int szAtom;      /* Smallest possible allocation in bytes */
+-  int nBlock;      /* Number of szAtom sized blocks in zPool */
+-  u8 *zPool;       /* Memory available to be allocated */
+-  
+-  /*
+-  ** Mutex to control access to the memory allocation subsystem.
+-  */
+-  sqlite3_mutex *mutex;
+-
+-  /*
+-  ** Performance statistics
+-  */
+-  u64 nAlloc;         /* Total number of calls to malloc */
+-  u64 totalAlloc;     /* Total of all malloc calls - includes internal frag */
+-  u64 totalExcess;    /* Total internal fragmentation */
+-  u32 currentOut;     /* Current checkout, including internal fragmentation */
+-  u32 currentCount;   /* Current number of distinct checkouts */
+-  u32 maxOut;         /* Maximum instantaneous currentOut */
+-  u32 maxCount;       /* Maximum instantaneous currentCount */
+-  u32 maxRequest;     /* Largest allocation (exclusive of internal frag) */
+-  
+-  /*
+-  ** Lists of free blocks.  aiFreelist[0] is a list of free blocks of
+-  ** size mem5.szAtom.  aiFreelist[1] holds blocks of size szAtom*2.
+-  ** and so forth.
+-  */
+-  int aiFreelist[LOGMAX+1];
+-
+-  /*
+-  ** Space for tracking which blocks are checked out and the size
+-  ** of each block.  One byte per block.
+-  */
+-  u8 *aCtrl;
+-
+-} mem5;
+-
+-/*
+-** Access the static variable through a macro for SQLITE_OMIT_WSD
+-*/
+-#define mem5 GLOBAL(struct Mem5Global, mem5)
+-
+-/*
+-** Assuming mem5.zPool is divided up into an array of Mem5Link
+-** structures, return a pointer to the idx-th such lik.
++** Return the julian day number of the date specified in the arguments
+ */
+-#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
++static void juliandayFunc(
++  sqlite3_context *context,
++  int argc,
++  sqlite3_value **argv
++){
++  DateTime x;
++  if( isDate(context, argc, argv, &x)==0 ){
++    computeJD(&x);
++    sqlite3_result_double(context, x.iJD/86400000.0);
++  }
++}
+ 
+ /*
+-** Unlink the chunk at mem5.aPool[i] from list it is currently
+-** on.  It should be found on mem5.aiFreelist[iLogsize].
++**    datetime( TIMESTRING, MOD, MOD, ...)
++**
++** Return YYYY-MM-DD HH:MM:SS
+ */
+-static void memsys5Unlink(int i, int iLogsize){
+-  int next, prev;
+-  assert( i>=0 && i<mem5.nBlock );
+-  assert( iLogsize>=0 && iLogsize<=LOGMAX );
+-  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+-
+-  next = MEM5LINK(i)->next;
+-  prev = MEM5LINK(i)->prev;
+-  if( prev<0 ){
+-    mem5.aiFreelist[iLogsize] = next;
+-  }else{
+-    MEM5LINK(prev)->next = next;
+-  }
+-  if( next>=0 ){
+-    MEM5LINK(next)->prev = prev;
++static void datetimeFunc(
++  sqlite3_context *context,
++  int argc,
++  sqlite3_value **argv
++){
++  DateTime x;
++  if( isDate(context, argc, argv, &x)==0 ){
++    char zBuf[100];
++    computeYMD_HMS(&x);
++    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
++                     x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
++    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+   }
+ }
+ 
+ /*
+-** Link the chunk at mem5.aPool[i] so that is on the iLogsize
+-** free list.
++**    time( TIMESTRING, MOD, MOD, ...)
++**
++** Return HH:MM:SS
+ */
+-static void memsys5Link(int i, int iLogsize){
+-  int x;
+-  assert( sqlite3_mutex_held(mem5.mutex) );
+-  assert( i>=0 && i<mem5.nBlock );
+-  assert( iLogsize>=0 && iLogsize<=LOGMAX );
+-  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+-
+-  x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
+-  MEM5LINK(i)->prev = -1;
+-  if( x>=0 ){
+-    assert( x<mem5.nBlock );
+-    MEM5LINK(x)->prev = i;
++static void timeFunc(
++  sqlite3_context *context,
++  int argc,
++  sqlite3_value **argv
++){
++  DateTime x;
++  if( isDate(context, argc, argv, &x)==0 ){
++    char zBuf[100];
++    computeHMS(&x);
++    sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
++    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+   }
+-  mem5.aiFreelist[iLogsize] = i;
+ }
+ 
+ /*
+-** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
+-** will already be held (obtained by code in malloc.c) if
+-** sqlite3GlobalConfig.bMemStat is true.
++**    date( TIMESTRING, MOD, MOD, ...)
++**
++** Return YYYY-MM-DD
+ */
+-static void memsys5Enter(void){
+-  sqlite3_mutex_enter(mem5.mutex);
+-}
+-static void memsys5Leave(void){
+-  sqlite3_mutex_leave(mem5.mutex);
+-}
+-
+-/*
+-** Return the size of an outstanding allocation, in bytes.  The
+-** size returned omits the 8-byte header overhead.  This only
+-** works for chunks that are currently checked out.
+-*/
+-static int memsys5Size(void *p){
+-  int iSize = 0;
+-  if( p ){
+-    int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
+-    assert( i>=0 && i<mem5.nBlock );
+-    iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
+-  }
+-  return iSize;
+-}
+-
+-/*
+-** Find the first entry on the freelist iLogsize.  Unlink that
+-** entry and return its index. 
+-*/
+-static int memsys5UnlinkFirst(int iLogsize){
+-  int i;
+-  int iFirst;
+-
+-  assert( iLogsize>=0 && iLogsize<=LOGMAX );
+-  i = iFirst = mem5.aiFreelist[iLogsize];
+-  assert( iFirst>=0 );
+-  while( i>0 ){
+-    if( i<iFirst ) iFirst = i;
+-    i = MEM5LINK(i)->next;
++static void dateFunc(
++  sqlite3_context *context,
++  int argc,
++  sqlite3_value **argv
++){
++  DateTime x;
++  if( isDate(context, argc, argv, &x)==0 ){
++    char zBuf[100];
++    computeYMD(&x);
++    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
++    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+   }
+-  memsys5Unlink(iFirst, iLogsize);
+-  return iFirst;
+ }
+ 
+ /*
+-** Return a block of memory of at least nBytes in size.
+-** Return NULL if unable.  Return NULL if nBytes==0.
++**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
+ **
+-** The caller guarantees that nByte positive.
++** Return a string described by FORMAT.  Conversions as follows:
+ **
+-** The caller has obtained a mutex prior to invoking this
+-** routine so there is never any chance that two or more
+-** threads can be in this routine at the same time.
++**   %d  day of month
++**   %f  ** fractional seconds  SS.SSS
++**   %H  hour 00-24
++**   %j  day of year 000-366
++**   %J  ** Julian day number
++**   %m  month 01-12
++**   %M  minute 00-59
++**   %s  seconds since 1970-01-01
++**   %S  seconds 00-59
++**   %w  day of week 0-6  sunday==0
++**   %W  week of year 00-53
++**   %Y  year 0000-9999
++**   %%  %
+ */
+-static void *memsys5MallocUnsafe(int nByte){
+-  int i;           /* Index of a mem5.aPool[] slot */
+-  int iBin;        /* Index into mem5.aiFreelist[] */
+-  int iFullSz;     /* Size of allocation rounded up to power of 2 */
+-  int iLogsize;    /* Log2 of iFullSz/POW2_MIN */
+-
+-  /* nByte must be a positive */
+-  assert( nByte>0 );
+-
+-  /* Keep track of the maximum allocation request.  Even unfulfilled
+-  ** requests are counted */
+-  if( (u32)nByte>mem5.maxRequest ){
+-    mem5.maxRequest = nByte;
+-  }
+-
+-  /* Abort if the requested allocation size is larger than the largest
+-  ** power of two that we can represent using 32-bit signed integers.
+-  */
+-  if( nByte > 0x40000000 ){
+-    return 0;
++static void strftimeFunc(
++  sqlite3_context *context,
++  int argc,
++  sqlite3_value **argv
++){
++  DateTime x;
++  u64 n;
++  size_t i,j;
++  char *z;
++  sqlite3 *db;
++  const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
++  char zBuf[100];
++  if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
++  db = sqlite3_context_db_handle(context);
++  for(i=0, n=1; zFmt[i]; i++, n++){
++    if( zFmt[i]=='%' ){
++      switch( zFmt[i+1] ){
++        case 'd':
++        case 'H':
++        case 'm':
++        case 'M':
++        case 'S':
++        case 'W':
++          n++;
++          /* fall thru */
++        case 'w':
++        case '%':
++          break;
++        case 'f':
++          n += 8;
++          break;
++        case 'j':
++          n += 3;
++          break;
++        case 'Y':
++          n += 8;
++          break;
++        case 's':
++        case 'J':
++          n += 50;
++          break;
++        default:
++          return;  /* ERROR.  return a NULL */
++      }
++      i++;
++    }
+   }
+-
+-  /* Round nByte up to the next valid power of two */
+-  for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
+-
+-  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
+-  ** block.  If not, then split a block of the next larger power of
+-  ** two in order to create a new free block of size iLogsize.
+-  */
+-  for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
+-  if( iBin>LOGMAX ){
+-    testcase( sqlite3GlobalConfig.xLog!=0 );
+-    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
+-    return 0;
++  testcase( n==sizeof(zBuf)-1 );
++  testcase( n==sizeof(zBuf) );
++  testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
++  testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
++  if( n<sizeof(zBuf) ){
++    z = zBuf;
++  }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
++    sqlite3_result_error_toobig(context);
++    return;
++  }else{
++    z = sqlite3DbMallocRaw(db, (int)n);
++    if( z==0 ){
++      sqlite3_result_error_nomem(context);
++      return;
++    }
+   }
+-  i = memsys5UnlinkFirst(iBin);
+-  while( iBin>iLogsize ){
+-    int newSize;
+-
+-    iBin--;
+-    newSize = 1 << iBin;
+-    mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
+-    memsys5Link(i+newSize, iBin);
++  computeJD(&x);
++  computeYMD_HMS(&x);
++  for(i=j=0; zFmt[i]; i++){
++    if( zFmt[i]!='%' ){
++      z[j++] = zFmt[i];
++    }else{
++      i++;
++      switch( zFmt[i] ){
++        case 'd':  sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
++        case 'f': {
++          double s = x.s;
++          if( s>59.999 ) s = 59.999;
++          sqlite3_snprintf(7, &z[j],"%06.3f", s);
++          j += sqlite3Strlen30(&z[j]);
++          break;
++        }
++        case 'H':  sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
++        case 'W': /* Fall thru */
++        case 'j': {
++          int nDay;             /* Number of days since 1st day of year */
++          DateTime y = x;
++          y.validJD = 0;
++          y.M = 1;
++          y.D = 1;
++          computeJD(&y);
++          nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
++          if( zFmt[i]=='W' ){
++            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
++            wd = (int)(((x.iJD+43200000)/86400000)%7);
++            sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
++            j += 2;
++          }else{
++            sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
++            j += 3;
++          }
++          break;
++        }
++        case 'J': {
++          sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
++          j+=sqlite3Strlen30(&z[j]);
++          break;
++        }
++        case 'm':  sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
++        case 'M':  sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
++        case 's': {
++          sqlite3_snprintf(30,&z[j],"%lld",
++                           (i64)(x.iJD/1000 - 21086676*(i64)10000));
++          j += sqlite3Strlen30(&z[j]);
++          break;
++        }
++        case 'S':  sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
++        case 'w': {
++          z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
++          break;
++        }
++        case 'Y': {
++          sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
++          break;
++        }
++        default:   z[j++] = '%'; break;
++      }
++    }
+   }
+-  mem5.aCtrl[i] = iLogsize;
+-
+-  /* Update allocator performance statistics. */
+-  mem5.nAlloc++;
+-  mem5.totalAlloc += iFullSz;
+-  mem5.totalExcess += iFullSz - nByte;
+-  mem5.currentCount++;
+-  mem5.currentOut += iFullSz;
+-  if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
+-  if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
+-
+-  /* Return a pointer to the allocated memory. */
+-  return (void*)&mem5.zPool[i*mem5.szAtom];
++  z[j] = 0;
++  sqlite3_result_text(context, z, -1,
++                      z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
+ }
+ 
+ /*
+-** Free an outstanding memory allocation.
++** current_time()
++**
++** This function returns the same value as time('now').
+ */
+-static void memsys5FreeUnsafe(void *pOld){
+-  u32 size, iLogsize;
+-  int iBlock;
+-
+-  /* Set iBlock to the index of the block pointed to by pOld in 
+-  ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
+-  */
+-  iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
+-
+-  /* Check that the pointer pOld points to a valid, non-free block. */
+-  assert( iBlock>=0 && iBlock<mem5.nBlock );
+-  assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
+-  assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
+-
+-  iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
+-  size = 1<<iLogsize;
+-  assert( iBlock+size-1<(u32)mem5.nBlock );
+-
+-  mem5.aCtrl[iBlock] |= CTRL_FREE;
+-  mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
+-  assert( mem5.currentCount>0 );
+-  assert( mem5.currentOut>=(size*mem5.szAtom) );
+-  mem5.currentCount--;
+-  mem5.currentOut -= size*mem5.szAtom;
+-  assert( mem5.currentOut>0 || mem5.currentCount==0 );
+-  assert( mem5.currentCount>0 || mem5.currentOut==0 );
+-
+-  mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
+-  while( ALWAYS(iLogsize<LOGMAX) ){
+-    int iBuddy;
+-    if( (iBlock>>iLogsize) & 1 ){
+-      iBuddy = iBlock - size;
+-    }else{
+-      iBuddy = iBlock + size;
+-    }
+-    assert( iBuddy>=0 );
+-    if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
+-    if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
+-    memsys5Unlink(iBuddy, iLogsize);
+-    iLogsize++;
+-    if( iBuddy<iBlock ){
+-      mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
+-      mem5.aCtrl[iBlock] = 0;
+-      iBlock = iBuddy;
+-    }else{
+-      mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
+-      mem5.aCtrl[iBuddy] = 0;
+-    }
+-    size *= 2;
+-  }
+-  memsys5Link(iBlock, iLogsize);
++static void ctimeFunc(
++  sqlite3_context *context,
++  int NotUsed,
++  sqlite3_value **NotUsed2
++){
++  UNUSED_PARAMETER2(NotUsed, NotUsed2);
++  timeFunc(context, 0, 0);
+ }
+ 
+ /*
+-** Allocate nBytes of memory
++** current_date()
++**
++** This function returns the same value as date('now').
+ */
+-static void *memsys5Malloc(int nBytes){
+-  sqlite3_int64 *p = 0;
+-  if( nBytes>0 ){
+-    memsys5Enter();
+-    p = memsys5MallocUnsafe(nBytes);
+-    memsys5Leave();
+-  }
+-  return (void*)p; 
++static void cdateFunc(
++  sqlite3_context *context,
++  int NotUsed,
++  sqlite3_value **NotUsed2
++){
++  UNUSED_PARAMETER2(NotUsed, NotUsed2);
++  dateFunc(context, 0, 0);
+ }
+ 
+ /*
+-** Free memory.
++** current_timestamp()
+ **
+-** The outer layer memory allocator prevents this routine from
+-** being called with pPrior==0.
++** This function returns the same value as datetime('now').
+ */
+-static void memsys5Free(void *pPrior){
+-  assert( pPrior!=0 );
+-  memsys5Enter();
+-  memsys5FreeUnsafe(pPrior);
+-  memsys5Leave();  
++static void ctimestampFunc(
++  sqlite3_context *context,
++  int NotUsed,
++  sqlite3_value **NotUsed2
++){
++  UNUSED_PARAMETER2(NotUsed, NotUsed2);
++  datetimeFunc(context, 0, 0);
+ }
++#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
+ 
++#ifdef SQLITE_OMIT_DATETIME_FUNCS
+ /*
+-** Change the size of an existing memory allocation.
+-**
+-** The outer layer memory allocator prevents this routine from
+-** being called with pPrior==0.  
++** If the library is compiled to omit the full-scale date and time
++** handling (to get a smaller binary), the following minimal version
++** of the functions current_time(), current_date() and current_timestamp()
++** are included instead. This is to support column declarations that
++** include "DEFAULT CURRENT_TIME" etc.
+ **
+-** nBytes is always a value obtained from a prior call to
+-** memsys5Round().  Hence nBytes is always a non-negative power
+-** of two.  If nBytes==0 that means that an oversize allocation
+-** (an allocation larger than 0x40000000) was requested and this
+-** routine should return 0 without freeing pPrior.
++** This function uses the C-library functions time(), gmtime()
++** and strftime(). The format string to pass to strftime() is supplied
++** as the user-data for the function.
+ */
+-static void *memsys5Realloc(void *pPrior, int nBytes){
+-  int nOld;
+-  void *p;
+-  assert( pPrior!=0 );
+-  assert( (nBytes&(nBytes-1))==0 );  /* EV: R-46199-30249 */
+-  assert( nBytes>=0 );
+-  if( nBytes==0 ){
+-    return 0;
+-  }
+-  nOld = memsys5Size(pPrior);
+-  if( nBytes<=nOld ){
+-    return pPrior;
+-  }
+-  memsys5Enter();
+-  p = memsys5MallocUnsafe(nBytes);
+-  if( p ){
+-    memcpy(p, pPrior, nOld);
+-    memsys5FreeUnsafe(pPrior);
++static void currentTimeFunc(
++  sqlite3_context *context,
++  int argc,
++  sqlite3_value **argv
++){
++  time_t t;
++  char *zFormat = (char *)sqlite3_user_data(context);
++  sqlite3 *db;
++  sqlite3_int64 iT;
++  struct tm *pTm;
++  struct tm sNow;
++  char zBuf[20];
++
++  UNUSED_PARAMETER(argc);
++  UNUSED_PARAMETER(argv);
++
++  db = sqlite3_context_db_handle(context);
++  if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
++  t = iT/1000 - 10000*(sqlite3_int64)21086676;
++#ifdef HAVE_GMTIME_R
++  pTm = gmtime_r(&t, &sNow);
++#else
++  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++  pTm = gmtime(&t);
++  if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
++  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++#endif
++  if( pTm ){
++    strftime(zBuf, 20, zFormat, &sNow);
++    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+   }
+-  memsys5Leave();
+-  return p;
+ }
++#endif
+ 
+ /*
+-** Round up a request size to the next valid allocation size.  If
+-** the allocation is too large to be handled by this allocation system,
+-** return 0.
+-**
+-** All allocations must be a power of two and must be expressed by a
+-** 32-bit signed integer.  Hence the largest allocation is 0x40000000
+-** or 1073741824 bytes.
++** This function registered all of the above C functions as SQL
++** functions.  This should be the only routine in this file with
++** external linkage.
+ */
+-static int memsys5Roundup(int n){
+-  int iFullSz;
+-  if( n > 0x40000000 ) return 0;
+-  for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
+-  return iFullSz;
++SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
++  static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
++#ifndef SQLITE_OMIT_DATETIME_FUNCS
++    FUNCTION(julianday,        -1, 0, 0, juliandayFunc ),
++    FUNCTION(date,             -1, 0, 0, dateFunc      ),
++    FUNCTION(time,             -1, 0, 0, timeFunc      ),
++    FUNCTION(datetime,         -1, 0, 0, datetimeFunc  ),
++    FUNCTION(strftime,         -1, 0, 0, strftimeFunc  ),
++    FUNCTION(current_time,      0, 0, 0, ctimeFunc     ),
++    FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
++    FUNCTION(current_date,      0, 0, 0, cdateFunc     ),
++#else
++    STR_FUNCTION(current_time,      0, "%H:%M:%S",          0, currentTimeFunc),
++    STR_FUNCTION(current_date,      0, "%Y-%m-%d",          0, currentTimeFunc),
++    STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
++#endif
++  };
++  int i;
++  FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
++  FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
++
++  for(i=0; i<ArraySize(aDateTimeFuncs); i++){
++    sqlite3FuncDefInsert(pHash, &aFunc[i]);
++  }
+ }
+ 
++/************** End of date.c ************************************************/
++/************** Begin file os.c **********************************************/
+ /*
+-** Return the ceiling of the logarithm base 2 of iValue.
++** 2005 November 29
+ **
+-** Examples:   memsys5Log(1) -> 0
+-**             memsys5Log(2) -> 1
+-**             memsys5Log(4) -> 2
+-**             memsys5Log(5) -> 3
+-**             memsys5Log(8) -> 3
+-**             memsys5Log(9) -> 4
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++******************************************************************************
++**
++** This file contains OS interface code that is common to all
++** architectures.
+ */
+-static int memsys5Log(int iValue){
+-  int iLog;
+-  for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
+-  return iLog;
+-}
++#define _SQLITE_OS_C_ 1
++#undef _SQLITE_OS_C_
+ 
+ /*
+-** Initialize the memory allocator.
++** The default SQLite sqlite3_vfs implementations do not allocate
++** memory (actually, os_unix.c allocates a small amount of memory
++** from within OsOpen()), but some third-party implementations may.
++** So we test the effects of a malloc() failing and the sqlite3OsXXX()
++** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
++**
++** The following functions are instrumented for malloc() failure 
++** testing:
++**
++**     sqlite3OsRead()
++**     sqlite3OsWrite()
++**     sqlite3OsSync()
++**     sqlite3OsFileSize()
++**     sqlite3OsLock()
++**     sqlite3OsCheckReservedLock()
++**     sqlite3OsFileControl()
++**     sqlite3OsShmMap()
++**     sqlite3OsOpen()
++**     sqlite3OsDelete()
++**     sqlite3OsAccess()
++**     sqlite3OsFullPathname()
+ **
+-** This routine is not threadsafe.  The caller must be holding a mutex
+-** to prevent multiple threads from entering at the same time.
+ */
+-static int memsys5Init(void *NotUsed){
+-  int ii;            /* Loop counter */
+-  int nByte;         /* Number of bytes of memory available to this allocator */
+-  u8 *zByte;         /* Memory usable by this allocator */
+-  int nMinLog;       /* Log base 2 of minimum allocation size in bytes */
+-  int iOffset;       /* An offset into mem5.aCtrl[] */
+-
+-  UNUSED_PARAMETER(NotUsed);
+-
+-  /* For the purposes of this routine, disable the mutex */
+-  mem5.mutex = 0;
++#if defined(SQLITE_TEST)
++SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
++  #define DO_OS_MALLOC_TEST(x)                                       \
++  if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) {  \
++    void *pTstAlloc = sqlite3Malloc(10);                             \
++    if (!pTstAlloc) return SQLITE_IOERR_NOMEM;                       \
++    sqlite3_free(pTstAlloc);                                         \
++  }
++#else
++  #define DO_OS_MALLOC_TEST(x)
++#endif
+ 
+-  /* The size of a Mem5Link object must be a power of two.  Verify that
+-  ** this is case.
+-  */
+-  assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
++/*
++** The following routines are convenience wrappers around methods
++** of the sqlite3_file object.  This is mostly just syntactic sugar. All
++** of this would be completely automatic if SQLite were coded using
++** C++ instead of plain old C.
++*/
++SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file *pId){
++  int rc = SQLITE_OK;
++  if( pId->pMethods ){
++    rc = pId->pMethods->xClose(pId);
++    pId->pMethods = 0;
++  }
++  return rc;
++}
++SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xRead(id, pBuf, amt, offset);
++}
++SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xWrite(id, pBuf, amt, offset);
++}
++SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
++  return id->pMethods->xTruncate(id, size);
++}
++SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xSync(id, flags);
++}
++SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xFileSize(id, pSize);
++}
++SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xLock(id, lockType);
++}
++SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
++  return id->pMethods->xUnlock(id, lockType);
++}
++SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xCheckReservedLock(id, pResOut);
++}
+ 
+-  nByte = sqlite3GlobalConfig.nHeap;
+-  zByte = (u8*)sqlite3GlobalConfig.pHeap;
+-  assert( zByte!=0 );  /* sqlite3_config() does not allow otherwise */
++/*
++** Use sqlite3OsFileControl() when we are doing something that might fail
++** and we need to know about the failures.  Use sqlite3OsFileControlHint()
++** when simply tossing information over the wall to the VFS and we do not
++** really care if the VFS receives and understands the information since it
++** is only a hint and can be safely ignored.  The sqlite3OsFileControlHint()
++** routine has no return value since the return value would be meaningless.
++*/
++SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xFileControl(id, op, pArg);
++}
++SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
++  (void)id->pMethods->xFileControl(id, op, pArg);
++}
+ 
+-  /* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
+-  nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
+-  mem5.szAtom = (1<<nMinLog);
+-  while( (int)sizeof(Mem5Link)>mem5.szAtom ){
+-    mem5.szAtom = mem5.szAtom << 1;
+-  }
++SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
++  int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
++  return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
++}
++SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
++  return id->pMethods->xDeviceCharacteristics(id);
++}
++SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
++  return id->pMethods->xShmLock(id, offset, n, flags);
++}
++SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
++  id->pMethods->xShmBarrier(id);
++}
++SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
++  return id->pMethods->xShmUnmap(id, deleteFlag);
++}
++SQLITE_PRIVATE int sqlite3OsShmMap(
++  sqlite3_file *id,               /* Database file handle */
++  int iPage,
++  int pgsz,
++  int bExtend,                    /* True to extend file if necessary */
++  void volatile **pp              /* OUT: Pointer to mapping */
++){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
++}
+ 
+-  mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
+-  mem5.zPool = zByte;
+-  mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
++#if SQLITE_MAX_MMAP_SIZE>0
++/* The real implementation of xFetch and xUnfetch */
++SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
++  DO_OS_MALLOC_TEST(id);
++  return id->pMethods->xFetch(id, iOff, iAmt, pp);
++}
++SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
++  return id->pMethods->xUnfetch(id, iOff, p);
++}
++#else
++/* No-op stubs to use when memory-mapped I/O is disabled */
++SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
++  *pp = 0;
++  return SQLITE_OK;
++}
++SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
++  return SQLITE_OK;
++}
++#endif
+ 
+-  for(ii=0; ii<=LOGMAX; ii++){
+-    mem5.aiFreelist[ii] = -1;
++/*
++** The next group of routines are convenience wrappers around the
++** VFS methods.
++*/
++SQLITE_PRIVATE int sqlite3OsOpen(
++  sqlite3_vfs *pVfs, 
++  const char *zPath, 
++  sqlite3_file *pFile, 
++  int flags, 
++  int *pFlagsOut
++){
++  int rc;
++  DO_OS_MALLOC_TEST(0);
++  /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
++  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
++  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
++  ** reaching the VFS. */
++  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
++  assert( rc==SQLITE_OK || pFile->pMethods==0 );
++  return rc;
++}
++SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
++  DO_OS_MALLOC_TEST(0);
++  assert( dirSync==0 || dirSync==1 );
++  return pVfs->xDelete(pVfs, zPath, dirSync);
++}
++SQLITE_PRIVATE int sqlite3OsAccess(
++  sqlite3_vfs *pVfs, 
++  const char *zPath, 
++  int flags, 
++  int *pResOut
++){
++  DO_OS_MALLOC_TEST(0);
++  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
++}
++SQLITE_PRIVATE int sqlite3OsFullPathname(
++  sqlite3_vfs *pVfs, 
++  const char *zPath, 
++  int nPathOut, 
++  char *zPathOut
++){
++  DO_OS_MALLOC_TEST(0);
++  zPathOut[0] = 0;
++  return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
++}
++#ifndef SQLITE_OMIT_LOAD_EXTENSION
++SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
++  return pVfs->xDlOpen(pVfs, zPath);
++}
++SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
++  pVfs->xDlError(pVfs, nByte, zBufOut);
++}
++SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
++  return pVfs->xDlSym(pVfs, pHdle, zSym);
++}
++SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
++  pVfs->xDlClose(pVfs, pHandle);
++}
++#endif /* SQLITE_OMIT_LOAD_EXTENSION */
++SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
++  return pVfs->xRandomness(pVfs, nByte, zBufOut);
++}
++SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
++  return pVfs->xSleep(pVfs, nMicro);
++}
++SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
++  int rc;
++  /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
++  ** method to get the current date and time if that method is available
++  ** (if iVersion is 2 or greater and the function pointer is not NULL) and
++  ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
++  ** unavailable.
++  */
++  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
++    rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
++  }else{
++    double r;
++    rc = pVfs->xCurrentTime(pVfs, &r);
++    *pTimeOut = (sqlite3_int64)(r*86400000.0);
+   }
++  return rc;
++}
+ 
+-  iOffset = 0;
+-  for(ii=LOGMAX; ii>=0; ii--){
+-    int nAlloc = (1<<ii);
+-    if( (iOffset+nAlloc)<=mem5.nBlock ){
+-      mem5.aCtrl[iOffset] = ii | CTRL_FREE;
+-      memsys5Link(iOffset, ii);
+-      iOffset += nAlloc;
++SQLITE_PRIVATE int sqlite3OsOpenMalloc(
++  sqlite3_vfs *pVfs, 
++  const char *zFile, 
++  sqlite3_file **ppFile, 
++  int flags,
++  int *pOutFlags
++){
++  int rc = SQLITE_NOMEM;
++  sqlite3_file *pFile;
++  pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
++  if( pFile ){
++    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
++    if( rc!=SQLITE_OK ){
++      sqlite3_free(pFile);
++    }else{
++      *ppFile = pFile;
+     }
+-    assert((iOffset+nAlloc)>mem5.nBlock);
+-  }
+-
+-  /* If a mutex is required for normal operation, allocate one */
+-  if( sqlite3GlobalConfig.bMemstat==0 ){
+-    mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+   }
+-
+-  return SQLITE_OK;
++  return rc;
++}
++SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
++  int rc = SQLITE_OK;
++  assert( pFile );
++  rc = sqlite3OsClose(pFile);
++  sqlite3_free(pFile);
++  return rc;
+ }
+ 
+ /*
+-** Deinitialize this module.
++** This function is a wrapper around the OS specific implementation of
++** sqlite3_os_init(). The purpose of the wrapper is to provide the
++** ability to simulate a malloc failure, so that the handling of an
++** error in sqlite3_os_init() by the upper layers can be tested.
+ */
+-static void memsys5Shutdown(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  mem5.mutex = 0;
+-  return;
++SQLITE_PRIVATE int sqlite3OsInit(void){
++  void *p = sqlite3_malloc(10);
++  if( p==0 ) return SQLITE_NOMEM;
++  sqlite3_free(p);
++  return sqlite3_os_init();
+ }
+ 
+-#ifdef SQLITE_TEST
+ /*
+-** Open the file indicated and write a log of all unfreed memory 
+-** allocations into that log.
++** The list of all registered VFS implementations.
+ */
+-SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
+-  FILE *out;
+-  int i, j, n;
+-  int nMinLog;
++static sqlite3_vfs * SQLITE_WSD vfsList = 0;
++#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
+ 
+-  if( zFilename==0 || zFilename[0]==0 ){
+-    out = stdout;
+-  }else{
+-    out = fopen(zFilename, "w");
+-    if( out==0 ){
+-      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+-                      zFilename);
+-      return;
+-    }
++/*
++** Locate a VFS by name.  If no name is given, simply return the
++** first VFS on the list.
++*/
++SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
++  sqlite3_vfs *pVfs = 0;
++#if SQLITE_THREADSAFE
++  sqlite3_mutex *mutex;
++#endif
++#ifndef SQLITE_OMIT_AUTOINIT
++  int rc = sqlite3_initialize();
++  if( rc ) return 0;
++#endif
++#if SQLITE_THREADSAFE
++  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
++#endif
++  sqlite3_mutex_enter(mutex);
++  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
++    if( zVfs==0 ) break;
++    if( strcmp(zVfs, pVfs->zName)==0 ) break;
+   }
+-  memsys5Enter();
+-  nMinLog = memsys5Log(mem5.szAtom);
+-  for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
+-    for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
+-    fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
++  sqlite3_mutex_leave(mutex);
++  return pVfs;
++}
++
++/*
++** Unlink a VFS from the linked list
++*/
++static void vfsUnlink(sqlite3_vfs *pVfs){
++  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
++  if( pVfs==0 ){
++    /* No-op */
++  }else if( vfsList==pVfs ){
++    vfsList = pVfs->pNext;
++  }else if( vfsList ){
++    sqlite3_vfs *p = vfsList;
++    while( p->pNext && p->pNext!=pVfs ){
++      p = p->pNext;
++    }
++    if( p->pNext==pVfs ){
++      p->pNext = pVfs->pNext;
++    }
+   }
+-  fprintf(out, "mem5.nAlloc       = %llu\n", mem5.nAlloc);
+-  fprintf(out, "mem5.totalAlloc   = %llu\n", mem5.totalAlloc);
+-  fprintf(out, "mem5.totalExcess  = %llu\n", mem5.totalExcess);
+-  fprintf(out, "mem5.currentOut   = %u\n", mem5.currentOut);
+-  fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
+-  fprintf(out, "mem5.maxOut       = %u\n", mem5.maxOut);
+-  fprintf(out, "mem5.maxCount     = %u\n", mem5.maxCount);
+-  fprintf(out, "mem5.maxRequest   = %u\n", mem5.maxRequest);
+-  memsys5Leave();
+-  if( out==stdout ){
+-    fflush(stdout);
++}
++
++/*
++** Register a VFS with the system.  It is harmless to register the same
++** VFS multiple times.  The new VFS becomes the default if makeDflt is
++** true.
++*/
++SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
++  MUTEX_LOGIC(sqlite3_mutex *mutex;)
++#ifndef SQLITE_OMIT_AUTOINIT
++  int rc = sqlite3_initialize();
++  if( rc ) return rc;
++#endif
++  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
++  sqlite3_mutex_enter(mutex);
++  vfsUnlink(pVfs);
++  if( makeDflt || vfsList==0 ){
++    pVfs->pNext = vfsList;
++    vfsList = pVfs;
+   }else{
+-    fclose(out);
++    pVfs->pNext = vfsList->pNext;
++    vfsList->pNext = pVfs;
+   }
++  assert(vfsList);
++  sqlite3_mutex_leave(mutex);
++  return SQLITE_OK;
+ }
+-#endif
+ 
+ /*
+-** This routine is the only routine in this file with external 
+-** linkage. It returns a pointer to a static sqlite3_mem_methods
+-** struct populated with the memsys5 methods.
++** Unregister a VFS so that it is no longer accessible.
+ */
+-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
+-  static const sqlite3_mem_methods memsys5Methods = {
+-     memsys5Malloc,
+-     memsys5Free,
+-     memsys5Realloc,
+-     memsys5Size,
+-     memsys5Roundup,
+-     memsys5Init,
+-     memsys5Shutdown,
+-     0
+-  };
+-  return &memsys5Methods;
++SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
++#if SQLITE_THREADSAFE
++  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
++#endif
++  sqlite3_mutex_enter(mutex);
++  vfsUnlink(pVfs);
++  sqlite3_mutex_leave(mutex);
++  return SQLITE_OK;
+ }
+ 
+-#endif /* SQLITE_ENABLE_MEMSYS5 */
+-
+-/************** End of mem5.c ************************************************/
+-/************** Begin file mutex.c *******************************************/
++/************** End of os.c **************************************************/
++/************** Begin file fault.c *******************************************/
+ /*
+-** 2007 August 14
++** 2008 Jan 22
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -17715,152 +18451,147 @@
+ **    May you share freely, never taking more than you give.
+ **
+ *************************************************************************
+-** This file contains the C functions that implement mutexes.
+ **
+-** This file contains code that is common across all mutex implementations.
++** This file contains code to support the concept of "benign" 
++** malloc failures (when the xMalloc() or xRealloc() method of the
++** sqlite3_mem_methods structure fails to allocate a block of memory
++** and returns 0). 
++**
++** Most malloc failures are non-benign. After they occur, SQLite
++** abandons the current operation and returns an error code (usually
++** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
++** fatal. For example, if a malloc fails while resizing a hash table, this 
++** is completely recoverable simply by not carrying out the resize. The 
++** hash table will continue to function normally.  So a malloc failure 
++** during a hash table resize is a benign fault.
+ */
+ 
+-#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
+-/*
+-** For debugging purposes, record when the mutex subsystem is initialized
+-** and uninitialized so that we can assert() if there is an attempt to
+-** allocate a mutex while the system is uninitialized.
+-*/
+-static SQLITE_WSD int mutexIsInit = 0;
+-#endif /* SQLITE_DEBUG */
+ 
++#ifndef SQLITE_OMIT_BUILTIN_TEST
+ 
+-#ifndef SQLITE_MUTEX_OMIT
+ /*
+-** Initialize the mutex system.
++** Global variables.
+ */
+-SQLITE_PRIVATE int sqlite3MutexInit(void){ 
+-  int rc = SQLITE_OK;
+-  if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
+-    /* If the xMutexAlloc method has not been set, then the user did not
+-    ** install a mutex implementation via sqlite3_config() prior to 
+-    ** sqlite3_initialize() being called. This block copies pointers to
+-    ** the default implementation into the sqlite3GlobalConfig structure.
+-    */
+-    sqlite3_mutex_methods const *pFrom;
+-    sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
+-
+-    if( sqlite3GlobalConfig.bCoreMutex ){
+-      pFrom = sqlite3DefaultMutex();
+-    }else{
+-      pFrom = sqlite3NoopMutex();
+-    }
+-    memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
+-    memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
+-           sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
+-    pTo->xMutexAlloc = pFrom->xMutexAlloc;
+-  }
+-  rc = sqlite3GlobalConfig.mutex.xMutexInit();
++typedef struct BenignMallocHooks BenignMallocHooks;
++static SQLITE_WSD struct BenignMallocHooks {
++  void (*xBenignBegin)(void);
++  void (*xBenignEnd)(void);
++} sqlite3Hooks = { 0, 0 };
+ 
+-#ifdef SQLITE_DEBUG
+-  GLOBAL(int, mutexIsInit) = 1;
++/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
++** structure.  If writable static data is unsupported on the target,
++** we have to locate the state vector at run-time.  In the more common
++** case where writable static data is supported, wsdHooks can refer directly
++** to the "sqlite3Hooks" state vector declared above.
++*/
++#ifdef SQLITE_OMIT_WSD
++# define wsdHooksInit \
++  BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
++# define wsdHooks x[0]
++#else
++# define wsdHooksInit
++# define wsdHooks sqlite3Hooks
+ #endif
+ 
+-  return rc;
+-}
+ 
+ /*
+-** Shutdown the mutex system. This call frees resources allocated by
+-** sqlite3MutexInit().
++** Register hooks to call when sqlite3BeginBenignMalloc() and
++** sqlite3EndBenignMalloc() are called, respectively.
+ */
+-SQLITE_PRIVATE int sqlite3MutexEnd(void){
+-  int rc = SQLITE_OK;
+-  if( sqlite3GlobalConfig.mutex.xMutexEnd ){
+-    rc = sqlite3GlobalConfig.mutex.xMutexEnd();
+-  }
+-
+-#ifdef SQLITE_DEBUG
+-  GLOBAL(int, mutexIsInit) = 0;
+-#endif
+-
+-  return rc;
++SQLITE_PRIVATE void sqlite3BenignMallocHooks(
++  void (*xBenignBegin)(void),
++  void (*xBenignEnd)(void)
++){
++  wsdHooksInit;
++  wsdHooks.xBenignBegin = xBenignBegin;
++  wsdHooks.xBenignEnd = xBenignEnd;
+ }
+ 
+ /*
+-** Retrieve a pointer to a static mutex or allocate a new dynamic one.
++** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
++** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
++** indicates that subsequent malloc failures are non-benign.
+ */
+-SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  if( sqlite3_initialize() ) return 0;
+-#endif
+-  return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+-}
+-
+-SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
+-  if( !sqlite3GlobalConfig.bCoreMutex ){
+-    return 0;
++SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
++  wsdHooksInit;
++  if( wsdHooks.xBenignBegin ){
++    wsdHooks.xBenignBegin();
+   }
+-  assert( GLOBAL(int, mutexIsInit) );
+-  return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+ }
+-
+-/*
+-** Free a dynamic mutex.
+-*/
+-SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
+-  if( p ){
+-    sqlite3GlobalConfig.mutex.xMutexFree(p);
++SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
++  wsdHooksInit;
++  if( wsdHooks.xBenignEnd ){
++    wsdHooks.xBenignEnd();
+   }
+ }
+ 
++#endif   /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
++
++/************** End of fault.c ***********************************************/
++/************** Begin file mem0.c ********************************************/
+ /*
+-** Obtain the mutex p. If some other thread already has the mutex, block
+-** until it can be obtained.
++** 2008 October 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.
++**
++*************************************************************************
++**
++** This file contains a no-op memory allocation drivers for use when
++** SQLITE_ZERO_MALLOC is defined.  The allocation drivers implemented
++** here always fail.  SQLite will not operate with these drivers.  These
++** are merely placeholders.  Real drivers must be substituted using
++** sqlite3_config() before SQLite will operate.
+ */
+-SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
+-  if( p ){
+-    sqlite3GlobalConfig.mutex.xMutexEnter(p);
+-  }
+-}
+ 
+ /*
+-** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
+-** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
++** This version of the memory allocator is the default.  It is
++** used when no other memory allocator is specified using compile-time
++** macros.
+ */
+-SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
+-  int rc = SQLITE_OK;
+-  if( p ){
+-    return sqlite3GlobalConfig.mutex.xMutexTry(p);
+-  }
+-  return rc;
+-}
++#ifdef SQLITE_ZERO_MALLOC
+ 
+ /*
+-** The sqlite3_mutex_leave() routine exits a mutex that was previously
+-** entered by the same thread.  The behavior is undefined if the mutex 
+-** is not currently entered. If a NULL pointer is passed as an argument
+-** this function is a no-op.
++** No-op versions of all memory allocation routines
+ */
+-SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
+-  if( p ){
+-    sqlite3GlobalConfig.mutex.xMutexLeave(p);
+-  }
+-}
++static void *sqlite3MemMalloc(int nByte){ return 0; }
++static void sqlite3MemFree(void *pPrior){ return; }
++static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
++static int sqlite3MemSize(void *pPrior){ return 0; }
++static int sqlite3MemRoundup(int n){ return n; }
++static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
++static void sqlite3MemShutdown(void *NotUsed){ return; }
+ 
+-#ifndef NDEBUG
+ /*
+-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+-** intended for use inside assert() statements.
++** This routine is the only routine in this file with external linkage.
++**
++** Populate the low-level memory allocation function pointers in
++** sqlite3GlobalConfig.m with pointers to the routines in this file.
+ */
+-SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+-  return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
+-}
+-SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+-  return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
++SQLITE_PRIVATE void sqlite3MemSetDefault(void){
++  static const sqlite3_mem_methods defaultMethods = {
++     sqlite3MemMalloc,
++     sqlite3MemFree,
++     sqlite3MemRealloc,
++     sqlite3MemSize,
++     sqlite3MemRoundup,
++     sqlite3MemInit,
++     sqlite3MemShutdown,
++     0
++  };
++  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+ }
+-#endif
+ 
+-#endif /* !defined(SQLITE_MUTEX_OMIT) */
++#endif /* SQLITE_ZERO_MALLOC */
+ 
+-/************** End of mutex.c ***********************************************/
+-/************** Begin file mutex_noop.c **************************************/
++/************** End of mem0.c ************************************************/
++/************** Begin file mem1.c ********************************************/
+ /*
+-** 2008 October 07
++** 2007 August 14
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -17870,205 +18601,278 @@
+ **    May you share freely, never taking more than you give.
+ **
+ *************************************************************************
+-** This file contains the C functions that implement mutexes.
+ **
+-** This implementation in this file does not provide any mutual
+-** exclusion and is thus suitable for use only in applications
+-** that use SQLite in a single thread.  The routines defined
+-** here are place-holders.  Applications can substitute working
+-** mutex routines at start-time using the
++** This file contains low-level memory allocation drivers for when
++** SQLite will use the standard C-library malloc/realloc/free interface
++** to obtain the memory it needs.
+ **
+-**     sqlite3_config(SQLITE_CONFIG_MUTEX,...)
++** This file contains implementations of the low-level memory allocation
++** routines specified in the sqlite3_mem_methods object.  The content of
++** this file is only used if SQLITE_SYSTEM_MALLOC is defined.  The
++** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
++** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined.  The
++** default configuration is to use memory allocation routines in this
++** file.
+ **
+-** interface.
++** C-preprocessor macro summary:
+ **
+-** If compiled with SQLITE_DEBUG, then additional logic is inserted
+-** that does error checking on mutexes to make sure they are being
+-** called correctly.
++**    HAVE_MALLOC_USABLE_SIZE     The configure script sets this symbol if
++**                                the malloc_usable_size() interface exists
++**                                on the target platform.  Or, this symbol
++**                                can be set manually, if desired.
++**                                If an equivalent interface exists by
++**                                a different name, using a separate -D
++**                                option to rename it.
++**
++**    SQLITE_WITHOUT_ZONEMALLOC   Some older macs lack support for the zone
++**                                memory allocator.  Set this symbol to enable
++**                                building on older macs.
++**
++**    SQLITE_WITHOUT_MSIZE        Set this symbol to disable the use of
++**                                _msize() on windows systems.  This might
++**                                be necessary when compiling for Delphi,
++**                                for example.
+ */
+ 
+-#ifndef SQLITE_MUTEX_OMIT
++/*
++** This version of the memory allocator is the default.  It is
++** used when no other memory allocator is specified using compile-time
++** macros.
++*/
++#ifdef SQLITE_SYSTEM_MALLOC
+ 
+-#ifndef SQLITE_DEBUG
+ /*
+-** Stub routines for all mutex methods.
+-**
+-** This routines provide no mutual exclusion or error checking.
++** The MSVCRT has malloc_usable_size() but it is called _msize().
++** The use of _msize() is automatic, but can be disabled by compiling
++** with -DSQLITE_WITHOUT_MSIZE
+ */
+-static int noopMutexInit(void){ return SQLITE_OK; }
+-static int noopMutexEnd(void){ return SQLITE_OK; }
+-static sqlite3_mutex *noopMutexAlloc(int id){ 
+-  UNUSED_PARAMETER(id);
+-  return (sqlite3_mutex*)8; 
+-}
+-static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
+-static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
+-static int noopMutexTry(sqlite3_mutex *p){
+-  UNUSED_PARAMETER(p);
+-  return SQLITE_OK;
+-}
+-static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
++#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
++# define SQLITE_MALLOCSIZE _msize
++#endif
+ 
+-SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
+-  static const sqlite3_mutex_methods sMutex = {
+-    noopMutexInit,
+-    noopMutexEnd,
+-    noopMutexAlloc,
+-    noopMutexFree,
+-    noopMutexEnter,
+-    noopMutexTry,
+-    noopMutexLeave,
++#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
+ 
+-    0,
+-    0,
+-  };
++/*
++** Use the zone allocator available on apple products unless the
++** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
++*/
++#include <sys/sysctl.h>
++#include <malloc/malloc.h>
++#include <libkern/OSAtomic.h>
++static malloc_zone_t* _sqliteZone_;
++#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
++#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
++#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
++#define SQLITE_MALLOCSIZE(x) \
++        (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
+ 
+-  return &sMutex;
+-}
+-#endif /* !SQLITE_DEBUG */
++#else /* if not __APPLE__ */
+ 
+-#ifdef SQLITE_DEBUG
+ /*
+-** In this implementation, error checking is provided for testing
+-** and debugging purposes.  The mutexes still do not provide any
+-** mutual exclusion.
++** Use standard C library malloc and free on non-Apple systems.  
++** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
+ */
++#define SQLITE_MALLOC(x)    malloc(x)
++#define SQLITE_FREE(x)      free(x)
++#define SQLITE_REALLOC(x,y) realloc((x),(y))
++
++#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
++      || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
++# include <malloc.h>    /* Needed for malloc_usable_size on linux */
++#endif
++#ifdef HAVE_MALLOC_USABLE_SIZE
++# ifndef SQLITE_MALLOCSIZE
++#  define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
++# endif
++#else
++# undef SQLITE_MALLOCSIZE
++#endif
++
++#endif /* __APPLE__ or not __APPLE__ */
+ 
+ /*
+-** The mutex object
++** Like malloc(), but remember the size of the allocation
++** so that we can find it later using sqlite3MemSize().
++**
++** For this low-level routine, we are guaranteed that nByte>0 because
++** cases of nByte<=0 will be intercepted and dealt with by higher level
++** routines.
+ */
+-typedef struct sqlite3_debug_mutex {
+-  int id;     /* The mutex type */
+-  int cnt;    /* Number of entries without a matching leave */
+-} sqlite3_debug_mutex;
++static void *sqlite3MemMalloc(int nByte){
++#ifdef SQLITE_MALLOCSIZE
++  void *p = SQLITE_MALLOC( nByte );
++  if( p==0 ){
++    testcase( sqlite3GlobalConfig.xLog!=0 );
++    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
++  }
++  return p;
++#else
++  sqlite3_int64 *p;
++  assert( nByte>0 );
++  nByte = ROUND8(nByte);
++  p = SQLITE_MALLOC( nByte+8 );
++  if( p ){
++    p[0] = nByte;
++    p++;
++  }else{
++    testcase( sqlite3GlobalConfig.xLog!=0 );
++    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
++  }
++  return (void *)p;
++#endif
++}
+ 
+ /*
+-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+-** intended for use inside assert() statements.
++** Like free() but works for allocations obtained from sqlite3MemMalloc()
++** or sqlite3MemRealloc().
++**
++** For this low-level routine, we already know that pPrior!=0 since
++** cases where pPrior==0 will have been intecepted and dealt with
++** by higher-level routines.
+ */
+-static int debugMutexHeld(sqlite3_mutex *pX){
+-  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+-  return p==0 || p->cnt>0;
+-}
+-static int debugMutexNotheld(sqlite3_mutex *pX){
+-  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+-  return p==0 || p->cnt==0;
++static void sqlite3MemFree(void *pPrior){
++#ifdef SQLITE_MALLOCSIZE
++  SQLITE_FREE(pPrior);
++#else
++  sqlite3_int64 *p = (sqlite3_int64*)pPrior;
++  assert( pPrior!=0 );
++  p--;
++  SQLITE_FREE(p);
++#endif
+ }
+ 
+ /*
+-** Initialize and deinitialize the mutex subsystem.
++** Report the allocated size of a prior return from xMalloc()
++** or xRealloc().
+ */
+-static int debugMutexInit(void){ return SQLITE_OK; }
+-static int debugMutexEnd(void){ return SQLITE_OK; }
++static int sqlite3MemSize(void *pPrior){
++#ifdef SQLITE_MALLOCSIZE
++  return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
++#else
++  sqlite3_int64 *p;
++  if( pPrior==0 ) return 0;
++  p = (sqlite3_int64*)pPrior;
++  p--;
++  return (int)p[0];
++#endif
++}
+ 
+ /*
+-** The sqlite3_mutex_alloc() routine allocates a new
+-** mutex and returns a pointer to it.  If it returns NULL
+-** that means that a mutex could not be allocated. 
++** Like realloc().  Resize an allocation previously obtained from
++** sqlite3MemMalloc().
++**
++** For this low-level interface, we know that pPrior!=0.  Cases where
++** pPrior==0 while have been intercepted by higher-level routine and
++** redirected to xMalloc.  Similarly, we know that nByte>0 becauses
++** cases where nByte<=0 will have been intercepted by higher-level
++** routines and redirected to xFree.
+ */
+-static sqlite3_mutex *debugMutexAlloc(int id){
+-  static sqlite3_debug_mutex aStatic[6];
+-  sqlite3_debug_mutex *pNew = 0;
+-  switch( id ){
+-    case SQLITE_MUTEX_FAST:
+-    case SQLITE_MUTEX_RECURSIVE: {
+-      pNew = sqlite3Malloc(sizeof(*pNew));
+-      if( pNew ){
+-        pNew->id = id;
+-        pNew->cnt = 0;
+-      }
+-      break;
+-    }
+-    default: {
+-      assert( id-2 >= 0 );
+-      assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
+-      pNew = &aStatic[id-2];
+-      pNew->id = id;
+-      break;
+-    }
++static void *sqlite3MemRealloc(void *pPrior, int nByte){
++#ifdef SQLITE_MALLOCSIZE
++  void *p = SQLITE_REALLOC(pPrior, nByte);
++  if( p==0 ){
++    testcase( sqlite3GlobalConfig.xLog!=0 );
++    sqlite3_log(SQLITE_NOMEM,
++      "failed memory resize %u to %u bytes",
++      SQLITE_MALLOCSIZE(pPrior), nByte);
+   }
+-  return (sqlite3_mutex*)pNew;
++  return p;
++#else
++  sqlite3_int64 *p = (sqlite3_int64*)pPrior;
++  assert( pPrior!=0 && nByte>0 );
++  assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
++  p--;
++  p = SQLITE_REALLOC(p, nByte+8 );
++  if( p ){
++    p[0] = nByte;
++    p++;
++  }else{
++    testcase( sqlite3GlobalConfig.xLog!=0 );
++    sqlite3_log(SQLITE_NOMEM,
++      "failed memory resize %u to %u bytes",
++      sqlite3MemSize(pPrior), nByte);
++  }
++  return (void*)p;
++#endif
+ }
+ 
+ /*
+-** This routine deallocates a previously allocated mutex.
++** Round up a request size to the next valid allocation size.
+ */
+-static void debugMutexFree(sqlite3_mutex *pX){
+-  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+-  assert( p->cnt==0 );
+-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+-  sqlite3_free(p);
++static int sqlite3MemRoundup(int n){
++  return ROUND8(n);
+ }
+ 
+ /*
+-** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+-** to enter a mutex.  If another thread is already within the mutex,
+-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+-** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
+-** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
+-** be entered multiple times by the same thread.  In such cases the,
+-** mutex must be exited an equal number of times before another thread
+-** can enter.  If the same thread tries to enter any other kind of mutex
+-** more than once, the behavior is undefined.
++** Initialize this module.
+ */
+-static void debugMutexEnter(sqlite3_mutex *pX){
+-  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+-  p->cnt++;
+-}
+-static int debugMutexTry(sqlite3_mutex *pX){
+-  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+-  p->cnt++;
++static int sqlite3MemInit(void *NotUsed){
++#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
++  int cpuCount;
++  size_t len;
++  if( _sqliteZone_ ){
++    return SQLITE_OK;
++  }
++  len = sizeof(cpuCount);
++  /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
++  sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
++  if( cpuCount>1 ){
++    /* defer MT decisions to system malloc */
++    _sqliteZone_ = malloc_default_zone();
++  }else{
++    /* only 1 core, use our own zone to contention over global locks, 
++    ** e.g. we have our own dedicated locks */
++    bool success;
++    malloc_zone_t* newzone = malloc_create_zone(4096, 0);
++    malloc_set_zone_name(newzone, "Sqlite_Heap");
++    do{
++      success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, 
++                                 (void * volatile *)&_sqliteZone_);
++    }while(!_sqliteZone_);
++    if( !success ){
++      /* somebody registered a zone first */
++      malloc_destroy_zone(newzone);
++    }
++  }
++#endif
++  UNUSED_PARAMETER(NotUsed);
+   return SQLITE_OK;
+ }
+ 
+ /*
+-** The sqlite3_mutex_leave() routine exits a mutex that was
+-** previously entered by the same thread.  The behavior
+-** is undefined if the mutex is not currently entered or
+-** is not currently allocated.  SQLite will never do either.
++** Deinitialize this module.
+ */
+-static void debugMutexLeave(sqlite3_mutex *pX){
+-  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+-  assert( debugMutexHeld(pX) );
+-  p->cnt--;
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+-}
+-
+-SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
+-  static const sqlite3_mutex_methods sMutex = {
+-    debugMutexInit,
+-    debugMutexEnd,
+-    debugMutexAlloc,
+-    debugMutexFree,
+-    debugMutexEnter,
+-    debugMutexTry,
+-    debugMutexLeave,
+-
+-    debugMutexHeld,
+-    debugMutexNotheld
+-  };
+-
+-  return &sMutex;
++static void sqlite3MemShutdown(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  return;
+ }
+-#endif /* SQLITE_DEBUG */
+ 
+ /*
+-** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
+-** is used regardless of the run-time threadsafety setting.
++** This routine is the only routine in this file with external linkage.
++**
++** Populate the low-level memory allocation function pointers in
++** sqlite3GlobalConfig.m with pointers to the routines in this file.
+ */
+-#ifdef SQLITE_MUTEX_NOOP
+-SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
+-  return sqlite3NoopMutex();
++SQLITE_PRIVATE void sqlite3MemSetDefault(void){
++  static const sqlite3_mem_methods defaultMethods = {
++     sqlite3MemMalloc,
++     sqlite3MemFree,
++     sqlite3MemRealloc,
++     sqlite3MemSize,
++     sqlite3MemRoundup,
++     sqlite3MemInit,
++     sqlite3MemShutdown,
++     0
++  };
++  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+ }
+-#endif /* defined(SQLITE_MUTEX_NOOP) */
+-#endif /* !defined(SQLITE_MUTEX_OMIT) */
+ 
+-/************** End of mutex_noop.c ******************************************/
+-/************** Begin file mutex_unix.c **************************************/
++#endif /* SQLITE_SYSTEM_MALLOC */
++
++/************** End of mem1.c ************************************************/
++/************** Begin file mem2.c ********************************************/
+ /*
+-** 2007 August 28
++** 2007 August 15
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -18078,694 +18882,527 @@
+ **    May you share freely, never taking more than you give.
+ **
+ *************************************************************************
+-** This file contains the C functions that implement mutexes for pthreads
++**
++** This file contains low-level memory allocation drivers for when
++** SQLite will use the standard C-library malloc/realloc/free interface
++** to obtain the memory it needs while adding lots of additional debugging
++** information to each allocation in order to help detect and fix memory
++** leaks and memory usage errors.
++**
++** This file contains implementations of the low-level memory allocation
++** routines specified in the sqlite3_mem_methods object.
+ */
+ 
+ /*
+-** The code in this file is only used if we are compiling threadsafe
+-** under unix with pthreads.
+-**
+-** Note that this implementation requires a version of pthreads that
+-** supports recursive mutexes.
++** This version of the memory allocator is used only if the
++** SQLITE_MEMDEBUG macro is defined
+ */
+-#ifdef SQLITE_MUTEX_PTHREADS
+-
+-#include <pthread.h>
++#ifdef SQLITE_MEMDEBUG
+ 
+ /*
+-** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
+-** are necessary under two condidtions:  (1) Debug builds and (2) using
+-** home-grown mutexes.  Encapsulate these conditions into a single #define.
++** The backtrace functionality is only available with GLIBC
+ */
+-#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
+-# define SQLITE_MUTEX_NREF 1
+-#else
+-# define SQLITE_MUTEX_NREF 0
+-#endif
+-
+-/*
+-** Each recursive mutex is an instance of the following structure.
+-*/
+-struct sqlite3_mutex {
+-  pthread_mutex_t mutex;     /* Mutex controlling the lock */
+-#if SQLITE_MUTEX_NREF
+-  int id;                    /* Mutex type */
+-  volatile int nRef;         /* Number of entrances */
+-  volatile pthread_t owner;  /* Thread that is within this mutex */
+-  int trace;                 /* True to trace changes */
+-#endif
+-};
+-#if SQLITE_MUTEX_NREF
+-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
++#ifdef __GLIBC__
++  extern int backtrace(void**,int);
++  extern void backtrace_symbols_fd(void*const*,int,int);
+ #else
+-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
++# define backtrace(A,B) 1
++# define backtrace_symbols_fd(A,B,C)
+ #endif
++/* #include <stdio.h> */
+ 
+ /*
+-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+-** intended for use only inside assert() statements.  On some platforms,
+-** there might be race conditions that can cause these routines to
+-** deliver incorrect results.  In particular, if pthread_equal() is
+-** not an atomic operation, then these routines might delivery
+-** incorrect results.  On most platforms, pthread_equal() is a 
+-** comparison of two integers and is therefore atomic.  But we are
+-** told that HPUX is not such a platform.  If so, then these routines
+-** will not always work correctly on HPUX.
++** Each memory allocation looks like this:
+ **
+-** On those platforms where pthread_equal() is not atomic, SQLite
+-** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
+-** make sure no assert() statements are evaluated and hence these
+-** routines are never called.
+-*/
+-#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
+-static int pthreadMutexHeld(sqlite3_mutex *p){
+-  return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
+-}
+-static int pthreadMutexNotheld(sqlite3_mutex *p){
+-  return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
+-}
+-#endif
+-
+-/*
+-** Initialize and deinitialize the mutex subsystem.
++**  ------------------------------------------------------------------------
++**  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
++**  ------------------------------------------------------------------------
++**
++** The application code sees only a pointer to the allocation.  We have
++** to back up from the allocation pointer to find the MemBlockHdr.  The
++** MemBlockHdr tells us the size of the allocation and the number of
++** backtrace pointers.  There is also a guard word at the end of the
++** MemBlockHdr.
+ */
+-static int pthreadMutexInit(void){ return SQLITE_OK; }
+-static int pthreadMutexEnd(void){ return SQLITE_OK; }
++struct MemBlockHdr {
++  i64 iSize;                          /* Size of this allocation */
++  struct MemBlockHdr *pNext, *pPrev;  /* Linked list of all unfreed memory */
++  char nBacktrace;                    /* Number of backtraces on this alloc */
++  char nBacktraceSlots;               /* Available backtrace slots */
++  u8 nTitle;                          /* Bytes of title; includes '\0' */
++  u8 eType;                           /* Allocation type code */
++  int iForeGuard;                     /* Guard word for sanity */
++};
+ 
+ /*
+-** The sqlite3_mutex_alloc() routine allocates a new
+-** mutex and returns a pointer to it.  If it returns NULL
+-** that means that a mutex could not be allocated.  SQLite
+-** will unwind its stack and return an error.  The argument
+-** to sqlite3_mutex_alloc() is one of these integer constants:
+-**
+-** <ul>
+-** <li>  SQLITE_MUTEX_FAST
+-** <li>  SQLITE_MUTEX_RECURSIVE
+-** <li>  SQLITE_MUTEX_STATIC_MASTER
+-** <li>  SQLITE_MUTEX_STATIC_MEM
+-** <li>  SQLITE_MUTEX_STATIC_MEM2
+-** <li>  SQLITE_MUTEX_STATIC_PRNG
+-** <li>  SQLITE_MUTEX_STATIC_LRU
+-** <li>  SQLITE_MUTEX_STATIC_PMEM
+-** </ul>
+-**
+-** The first two constants cause sqlite3_mutex_alloc() to create
+-** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
+-** The mutex implementation does not need to make a distinction
+-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+-** not want to.  But SQLite will only request a recursive mutex in
+-** cases where it really needs one.  If a faster non-recursive mutex
+-** implementation is available on the host platform, the mutex subsystem
+-** might return such a mutex in response to SQLITE_MUTEX_FAST.
+-**
+-** The other allowed parameters to sqlite3_mutex_alloc() each return
+-** a pointer to a static preexisting mutex.  Six static mutexes are
+-** used by the current version of SQLite.  Future versions of SQLite
+-** may add additional static mutexes.  Static mutexes are for internal
+-** use by SQLite only.  Applications that use SQLite mutexes should
+-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+-** SQLITE_MUTEX_RECURSIVE.
+-**
+-** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+-** returns a different mutex on every call.  But for the static 
+-** mutex types, the same mutex is returned on every call that has
+-** the same type number.
++** Guard words
+ */
+-static sqlite3_mutex *pthreadMutexAlloc(int iType){
+-  static sqlite3_mutex staticMutexes[] = {
+-    SQLITE3_MUTEX_INITIALIZER,
+-    SQLITE3_MUTEX_INITIALIZER,
+-    SQLITE3_MUTEX_INITIALIZER,
+-    SQLITE3_MUTEX_INITIALIZER,
+-    SQLITE3_MUTEX_INITIALIZER,
+-    SQLITE3_MUTEX_INITIALIZER
+-  };
+-  sqlite3_mutex *p;
+-  switch( iType ){
+-    case SQLITE_MUTEX_RECURSIVE: {
+-      p = sqlite3MallocZero( sizeof(*p) );
+-      if( p ){
+-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+-        /* If recursive mutexes are not available, we will have to
+-        ** build our own.  See below. */
+-        pthread_mutex_init(&p->mutex, 0);
+-#else
+-        /* Use a recursive mutex if it is available */
+-        pthread_mutexattr_t recursiveAttr;
+-        pthread_mutexattr_init(&recursiveAttr);
+-        pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
+-        pthread_mutex_init(&p->mutex, &recursiveAttr);
+-        pthread_mutexattr_destroy(&recursiveAttr);
+-#endif
+-#if SQLITE_MUTEX_NREF
+-        p->id = iType;
+-#endif
+-      }
+-      break;
+-    }
+-    case SQLITE_MUTEX_FAST: {
+-      p = sqlite3MallocZero( sizeof(*p) );
+-      if( p ){
+-#if SQLITE_MUTEX_NREF
+-        p->id = iType;
+-#endif
+-        pthread_mutex_init(&p->mutex, 0);
+-      }
+-      break;
+-    }
+-    default: {
+-      assert( iType-2 >= 0 );
+-      assert( iType-2 < ArraySize(staticMutexes) );
+-      p = &staticMutexes[iType-2];
+-#if SQLITE_MUTEX_NREF
+-      p->id = iType;
+-#endif
+-      break;
+-    }
+-  }
+-  return p;
+-}
+-
++#define FOREGUARD 0x80F5E153
++#define REARGUARD 0xE4676B53
+ 
+ /*
+-** This routine deallocates a previously
+-** allocated mutex.  SQLite is careful to deallocate every
+-** mutex that it allocates.
++** Number of malloc size increments to track.
+ */
+-static void pthreadMutexFree(sqlite3_mutex *p){
+-  assert( p->nRef==0 );
+-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+-  pthread_mutex_destroy(&p->mutex);
+-  sqlite3_free(p);
+-}
++#define NCSIZE  1000
+ 
+ /*
+-** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+-** to enter a mutex.  If another thread is already within the mutex,
+-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+-** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
+-** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
+-** be entered multiple times by the same thread.  In such cases the,
+-** mutex must be exited an equal number of times before another thread
+-** can enter.  If the same thread tries to enter any other kind of mutex
+-** more than once, the behavior is undefined.
++** All of the static variables used by this module are collected
++** into a single structure named "mem".  This is to keep the
++** static variables organized and to reduce namespace pollution
++** when this module is combined with other in the amalgamation.
+ */
+-static void pthreadMutexEnter(sqlite3_mutex *p){
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
++static struct {
++  
++  /*
++  ** Mutex to control access to the memory allocation subsystem.
++  */
++  sqlite3_mutex *mutex;
+ 
+-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+-  /* If recursive mutexes are not available, then we have to grow
+-  ** our own.  This implementation assumes that pthread_equal()
+-  ** is atomic - that it cannot be deceived into thinking self
+-  ** and p->owner are equal if p->owner changes between two values
+-  ** that are not equal to self while the comparison is taking place.
+-  ** This implementation also assumes a coherent cache - that 
+-  ** separate processes cannot read different values from the same
+-  ** address at the same time.  If either of these two conditions
+-  ** are not met, then the mutexes will fail and problems will result.
++  /*
++  ** Head and tail of a linked list of all outstanding allocations
+   */
+-  {
+-    pthread_t self = pthread_self();
+-    if( p->nRef>0 && pthread_equal(p->owner, self) ){
+-      p->nRef++;
+-    }else{
+-      pthread_mutex_lock(&p->mutex);
+-      assert( p->nRef==0 );
+-      p->owner = self;
+-      p->nRef = 1;
+-    }
+-  }
+-#else
+-  /* Use the built-in recursive mutexes if they are available.
++  struct MemBlockHdr *pFirst;
++  struct MemBlockHdr *pLast;
++  
++  /*
++  ** The number of levels of backtrace to save in new allocations.
+   */
+-  pthread_mutex_lock(&p->mutex);
+-#if SQLITE_MUTEX_NREF
+-  assert( p->nRef>0 || p->owner==0 );
+-  p->owner = pthread_self();
+-  p->nRef++;
+-#endif
+-#endif
++  int nBacktrace;
++  void (*xBacktrace)(int, int, void **);
+ 
+-#ifdef SQLITE_DEBUG
+-  if( p->trace ){
+-    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+-  }
+-#endif
+-}
+-static int pthreadMutexTry(sqlite3_mutex *p){
+-  int rc;
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
++  /*
++  ** Title text to insert in front of each block
++  */
++  int nTitle;        /* Bytes of zTitle to save.  Includes '\0' and padding */
++  char zTitle[100];  /* The title text */
+ 
+-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+-  /* If recursive mutexes are not available, then we have to grow
+-  ** our own.  This implementation assumes that pthread_equal()
+-  ** is atomic - that it cannot be deceived into thinking self
+-  ** and p->owner are equal if p->owner changes between two values
+-  ** that are not equal to self while the comparison is taking place.
+-  ** This implementation also assumes a coherent cache - that 
+-  ** separate processes cannot read different values from the same
+-  ** address at the same time.  If either of these two conditions
+-  ** are not met, then the mutexes will fail and problems will result.
++  /* 
++  ** sqlite3MallocDisallow() increments the following counter.
++  ** sqlite3MallocAllow() decrements it.
+   */
+-  {
+-    pthread_t self = pthread_self();
+-    if( p->nRef>0 && pthread_equal(p->owner, self) ){
+-      p->nRef++;
+-      rc = SQLITE_OK;
+-    }else if( pthread_mutex_trylock(&p->mutex)==0 ){
+-      assert( p->nRef==0 );
+-      p->owner = self;
+-      p->nRef = 1;
+-      rc = SQLITE_OK;
+-    }else{
+-      rc = SQLITE_BUSY;
+-    }
+-  }
+-#else
+-  /* Use the built-in recursive mutexes if they are available.
++  int disallow; /* Do not allow memory allocation */
++
++  /*
++  ** Gather statistics on the sizes of memory allocations.
++  ** nAlloc[i] is the number of allocation attempts of i*8
++  ** bytes.  i==NCSIZE is the number of allocation attempts for
++  ** sizes more than NCSIZE*8 bytes.
+   */
+-  if( pthread_mutex_trylock(&p->mutex)==0 ){
+-#if SQLITE_MUTEX_NREF
+-    p->owner = pthread_self();
+-    p->nRef++;
+-#endif
+-    rc = SQLITE_OK;
+-  }else{
+-    rc = SQLITE_BUSY;
+-  }
+-#endif
++  int nAlloc[NCSIZE];      /* Total number of allocations */
++  int nCurrent[NCSIZE];    /* Current number of allocations */
++  int mxCurrent[NCSIZE];   /* Highwater mark for nCurrent */
++
++} mem;
+ 
+-#ifdef SQLITE_DEBUG
+-  if( rc==SQLITE_OK && p->trace ){
+-    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+-  }
+-#endif
+-  return rc;
+-}
+ 
+ /*
+-** The sqlite3_mutex_leave() routine exits a mutex that was
+-** previously entered by the same thread.  The behavior
+-** is undefined if the mutex is not currently entered or
+-** is not currently allocated.  SQLite will never do either.
++** Adjust memory usage statistics
+ */
+-static void pthreadMutexLeave(sqlite3_mutex *p){
+-  assert( pthreadMutexHeld(p) );
+-#if SQLITE_MUTEX_NREF
+-  p->nRef--;
+-  if( p->nRef==0 ) p->owner = 0;
+-#endif
+-  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
+-
+-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+-  if( p->nRef==0 ){
+-    pthread_mutex_unlock(&p->mutex);
++static void adjustStats(int iSize, int increment){
++  int i = ROUND8(iSize)/8;
++  if( i>NCSIZE-1 ){
++    i = NCSIZE - 1;
+   }
+-#else
+-  pthread_mutex_unlock(&p->mutex);
+-#endif
+-
+-#ifdef SQLITE_DEBUG
+-  if( p->trace ){
+-    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++  if( increment>0 ){
++    mem.nAlloc[i]++;
++    mem.nCurrent[i]++;
++    if( mem.nCurrent[i]>mem.mxCurrent[i] ){
++      mem.mxCurrent[i] = mem.nCurrent[i];
++    }
++  }else{
++    mem.nCurrent[i]--;
++    assert( mem.nCurrent[i]>=0 );
+   }
+-#endif
+-}
+-
+-SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
+-  static const sqlite3_mutex_methods sMutex = {
+-    pthreadMutexInit,
+-    pthreadMutexEnd,
+-    pthreadMutexAlloc,
+-    pthreadMutexFree,
+-    pthreadMutexEnter,
+-    pthreadMutexTry,
+-    pthreadMutexLeave,
+-#ifdef SQLITE_DEBUG
+-    pthreadMutexHeld,
+-    pthreadMutexNotheld
+-#else
+-    0,
+-    0
+-#endif
+-  };
+-
+-  return &sMutex;
+ }
+ 
+-#endif /* SQLITE_MUTEX_PTHREADS */
+-
+-/************** End of mutex_unix.c ******************************************/
+-/************** Begin file mutex_w32.c ***************************************/
+ /*
+-** 2007 August 14
+-**
+-** 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.
++** Given an allocation, find the MemBlockHdr for that allocation.
+ **
+-*************************************************************************
+-** This file contains the C functions that implement mutexes for win32
++** This routine checks the guards at either end of the allocation and
++** if they are incorrect it asserts.
+ */
++static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
++  struct MemBlockHdr *p;
++  int *pInt;
++  u8 *pU8;
++  int nReserve;
+ 
+-/*
+-** The code in this file is only used if we are compiling multithreaded
+-** on a win32 system.
+-*/
+-#ifdef SQLITE_MUTEX_W32
++  p = (struct MemBlockHdr*)pAllocation;
++  p--;
++  assert( p->iForeGuard==(int)FOREGUARD );
++  nReserve = ROUND8(p->iSize);
++  pInt = (int*)pAllocation;
++  pU8 = (u8*)pAllocation;
++  assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
++  /* This checks any of the "extra" bytes allocated due
++  ** to rounding up to an 8 byte boundary to ensure 
++  ** they haven't been overwritten.
++  */
++  while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
++  return p;
++}
+ 
+ /*
+-** Each recursive mutex is an instance of the following structure.
++** Return the number of bytes currently allocated at address p.
+ */
+-struct sqlite3_mutex {
+-  CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
+-  int id;                    /* Mutex type */
+-#ifdef SQLITE_DEBUG
+-  volatile int nRef;         /* Number of enterances */
+-  volatile DWORD owner;      /* Thread holding this mutex */
+-  int trace;                 /* True to trace changes */
+-#endif
+-};
+-#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
+-#ifdef SQLITE_DEBUG
+-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
+-#else
+-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
+-#endif
++static int sqlite3MemSize(void *p){
++  struct MemBlockHdr *pHdr;
++  if( !p ){
++    return 0;
++  }
++  pHdr = sqlite3MemsysGetHeader(p);
++  return pHdr->iSize;
++}
+ 
+ /*
+-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
+-** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
+-**
+-** Here is an interesting observation:  Win95, Win98, and WinME lack
+-** the LockFileEx() API.  But we can still statically link against that
+-** API as long as we don't call it win running Win95/98/ME.  A call to
+-** this routine is used to determine if the host is Win95/98/ME or
+-** WinNT/2K/XP so that we will know whether or not we can safely call
+-** the LockFileEx() API.
+-**
+-** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
+-** which is only available if your application was compiled with 
+-** _WIN32_WINNT defined to a value >= 0x0400.  Currently, the only
+-** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef 
+-** this out as well.
++** Initialize the memory allocation subsystem.
+ */
+-#if 0
+-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+-# define mutexIsNT()  (1)
+-#else
+-  static int mutexIsNT(void){
+-    static int osType = 0;
+-    if( osType==0 ){
+-      OSVERSIONINFO sInfo;
+-      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+-      GetVersionEx(&sInfo);
+-      osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
+-    }
+-    return osType==2;
++static int sqlite3MemInit(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  assert( (sizeof(struct MemBlockHdr)&7) == 0 );
++  if( !sqlite3GlobalConfig.bMemstat ){
++    /* If memory status is enabled, then the malloc.c wrapper will already
++    ** hold the STATIC_MEM mutex when the routines here are invoked. */
++    mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+   }
+-#endif /* SQLITE_OS_WINCE */
+-#endif
++  return SQLITE_OK;
++}
+ 
+-#ifdef SQLITE_DEBUG
+ /*
+-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+-** intended for use only inside assert() statements.
++** Deinitialize the memory allocation subsystem.
+ */
+-static int winMutexHeld(sqlite3_mutex *p){
+-  return p->nRef!=0 && p->owner==GetCurrentThreadId();
+-}
+-static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
+-  return p->nRef==0 || p->owner!=tid;
+-}
+-static int winMutexNotheld(sqlite3_mutex *p){
+-  DWORD tid = GetCurrentThreadId(); 
+-  return winMutexNotheld2(p, tid);
++static void sqlite3MemShutdown(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  mem.mutex = 0;
+ }
+-#endif
+-
+ 
+ /*
+-** Initialize and deinitialize the mutex subsystem.
+-*/
+-static sqlite3_mutex winMutex_staticMutexes[6] = {
+-  SQLITE3_MUTEX_INITIALIZER,
+-  SQLITE3_MUTEX_INITIALIZER,
+-  SQLITE3_MUTEX_INITIALIZER,
+-  SQLITE3_MUTEX_INITIALIZER,
+-  SQLITE3_MUTEX_INITIALIZER,
+-  SQLITE3_MUTEX_INITIALIZER
+-};
+-static int winMutex_isInit = 0;
+-/* As winMutexInit() and winMutexEnd() are called as part
+-** of the sqlite3_initialize and sqlite3_shutdown()
+-** processing, the "interlocked" magic is probably not
+-** strictly necessary.
++** Round up a request size to the next valid allocation size.
+ */
+-static long winMutex_lock = 0;
++static int sqlite3MemRoundup(int n){
++  return ROUND8(n);
++}
+ 
+-SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
++/*
++** Fill a buffer with pseudo-random bytes.  This is used to preset
++** the content of a new memory allocation to unpredictable values and
++** to clear the content of a freed allocation to unpredictable values.
++*/
++static void randomFill(char *pBuf, int nByte){
++  unsigned int x, y, r;
++  x = SQLITE_PTR_TO_INT(pBuf);
++  y = nByte | 1;
++  while( nByte >= 4 ){
++    x = (x>>1) ^ (-(x&1) & 0xd0000001);
++    y = y*1103515245 + 12345;
++    r = x ^ y;
++    *(int*)pBuf = r;
++    pBuf += 4;
++    nByte -= 4;
++  }
++  while( nByte-- > 0 ){
++    x = (x>>1) ^ (-(x&1) & 0xd0000001);
++    y = y*1103515245 + 12345;
++    r = x ^ y;
++    *(pBuf++) = r & 0xff;
++  }
++}
+ 
+-static int winMutexInit(void){ 
+-  /* The first to increment to 1 does actual initialization */
+-  if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
+-    int i;
+-    for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
+-#if SQLITE_OS_WINRT
+-      InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
+-#else
+-      InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
+-#endif
++/*
++** Allocate nByte bytes of memory.
++*/
++static void *sqlite3MemMalloc(int nByte){
++  struct MemBlockHdr *pHdr;
++  void **pBt;
++  char *z;
++  int *pInt;
++  void *p = 0;
++  int totalSize;
++  int nReserve;
++  sqlite3_mutex_enter(mem.mutex);
++  assert( mem.disallow==0 );
++  nReserve = ROUND8(nByte);
++  totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
++               mem.nBacktrace*sizeof(void*) + mem.nTitle;
++  p = malloc(totalSize);
++  if( p ){
++    z = p;
++    pBt = (void**)&z[mem.nTitle];
++    pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
++    pHdr->pNext = 0;
++    pHdr->pPrev = mem.pLast;
++    if( mem.pLast ){
++      mem.pLast->pNext = pHdr;
++    }else{
++      mem.pFirst = pHdr;
+     }
+-    winMutex_isInit = 1;
+-  }else{
+-    /* Someone else is in the process of initing the static mutexes */
+-    while( !winMutex_isInit ){
+-      sqlite3_win32_sleep(1);
++    mem.pLast = pHdr;
++    pHdr->iForeGuard = FOREGUARD;
++    pHdr->eType = MEMTYPE_HEAP;
++    pHdr->nBacktraceSlots = mem.nBacktrace;
++    pHdr->nTitle = mem.nTitle;
++    if( mem.nBacktrace ){
++      void *aAddr[40];
++      pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
++      memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
++      assert(pBt[0]);
++      if( mem.xBacktrace ){
++        mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
++      }
++    }else{
++      pHdr->nBacktrace = 0;
++    }
++    if( mem.nTitle ){
++      memcpy(z, mem.zTitle, mem.nTitle);
+     }
++    pHdr->iSize = nByte;
++    adjustStats(nByte, +1);
++    pInt = (int*)&pHdr[1];
++    pInt[nReserve/sizeof(int)] = REARGUARD;
++    randomFill((char*)pInt, nByte);
++    memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
++    p = (void*)pInt;
+   }
+-  return SQLITE_OK; 
++  sqlite3_mutex_leave(mem.mutex);
++  return p; 
+ }
+ 
+-static int winMutexEnd(void){ 
+-  /* The first to decrement to 0 does actual shutdown 
+-  ** (which should be the last to shutdown.) */
+-  if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
+-    if( winMutex_isInit==1 ){
+-      int i;
+-      for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
+-        DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
+-      }
+-      winMutex_isInit = 0;
++/*
++** Free memory.
++*/
++static void sqlite3MemFree(void *pPrior){
++  struct MemBlockHdr *pHdr;
++  void **pBt;
++  char *z;
++  assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0 
++       || mem.mutex!=0 );
++  pHdr = sqlite3MemsysGetHeader(pPrior);
++  pBt = (void**)pHdr;
++  pBt -= pHdr->nBacktraceSlots;
++  sqlite3_mutex_enter(mem.mutex);
++  if( pHdr->pPrev ){
++    assert( pHdr->pPrev->pNext==pHdr );
++    pHdr->pPrev->pNext = pHdr->pNext;
++  }else{
++    assert( mem.pFirst==pHdr );
++    mem.pFirst = pHdr->pNext;
++  }
++  if( pHdr->pNext ){
++    assert( pHdr->pNext->pPrev==pHdr );
++    pHdr->pNext->pPrev = pHdr->pPrev;
++  }else{
++    assert( mem.pLast==pHdr );
++    mem.pLast = pHdr->pPrev;
++  }
++  z = (char*)pBt;
++  z -= pHdr->nTitle;
++  adjustStats(pHdr->iSize, -1);
++  randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
++                pHdr->iSize + sizeof(int) + pHdr->nTitle);
++  free(z);
++  sqlite3_mutex_leave(mem.mutex);  
++}
++
++/*
++** Change the size of an existing memory allocation.
++**
++** For this debugging implementation, we *always* make a copy of the
++** allocation into a new place in memory.  In this way, if the 
++** higher level code is using pointer to the old allocation, it is 
++** much more likely to break and we are much more liking to find
++** the error.
++*/
++static void *sqlite3MemRealloc(void *pPrior, int nByte){
++  struct MemBlockHdr *pOldHdr;
++  void *pNew;
++  assert( mem.disallow==0 );
++  assert( (nByte & 7)==0 );     /* EV: R-46199-30249 */
++  pOldHdr = sqlite3MemsysGetHeader(pPrior);
++  pNew = sqlite3MemMalloc(nByte);
++  if( pNew ){
++    memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
++    if( nByte>pOldHdr->iSize ){
++      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
+     }
++    sqlite3MemFree(pPrior);
+   }
+-  return SQLITE_OK; 
++  return pNew;
+ }
+ 
+ /*
+-** The sqlite3_mutex_alloc() routine allocates a new
+-** mutex and returns a pointer to it.  If it returns NULL
+-** that means that a mutex could not be allocated.  SQLite
+-** will unwind its stack and return an error.  The argument
+-** to sqlite3_mutex_alloc() is one of these integer constants:
++** Populate the low-level memory allocation function pointers in
++** sqlite3GlobalConfig.m with pointers to the routines in this file.
++*/
++SQLITE_PRIVATE void sqlite3MemSetDefault(void){
++  static const sqlite3_mem_methods defaultMethods = {
++     sqlite3MemMalloc,
++     sqlite3MemFree,
++     sqlite3MemRealloc,
++     sqlite3MemSize,
++     sqlite3MemRoundup,
++     sqlite3MemInit,
++     sqlite3MemShutdown,
++     0
++  };
++  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
++}
++
++/*
++** Set the "type" of an allocation.
++*/
++SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
++  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
++    struct MemBlockHdr *pHdr;
++    pHdr = sqlite3MemsysGetHeader(p);
++    assert( pHdr->iForeGuard==FOREGUARD );
++    pHdr->eType = eType;
++  }
++}
++
++/*
++** Return TRUE if the mask of type in eType matches the type of the
++** allocation p.  Also return true if p==NULL.
+ **
+-** <ul>
+-** <li>  SQLITE_MUTEX_FAST
+-** <li>  SQLITE_MUTEX_RECURSIVE
+-** <li>  SQLITE_MUTEX_STATIC_MASTER
+-** <li>  SQLITE_MUTEX_STATIC_MEM
+-** <li>  SQLITE_MUTEX_STATIC_MEM2
+-** <li>  SQLITE_MUTEX_STATIC_PRNG
+-** <li>  SQLITE_MUTEX_STATIC_LRU
+-** <li>  SQLITE_MUTEX_STATIC_PMEM
+-** </ul>
++** This routine is designed for use within an assert() statement, to
++** verify the type of an allocation.  For example:
+ **
+-** The first two constants cause sqlite3_mutex_alloc() to create
+-** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
+-** The mutex implementation does not need to make a distinction
+-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+-** not want to.  But SQLite will only request a recursive mutex in
+-** cases where it really needs one.  If a faster non-recursive mutex
+-** implementation is available on the host platform, the mutex subsystem
+-** might return such a mutex in response to SQLITE_MUTEX_FAST.
++**     assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
++*/
++SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
++  int rc = 1;
++  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
++    struct MemBlockHdr *pHdr;
++    pHdr = sqlite3MemsysGetHeader(p);
++    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
++    if( (pHdr->eType&eType)==0 ){
++      rc = 0;
++    }
++  }
++  return rc;
++}
++
++/*
++** Return TRUE if the mask of type in eType matches no bits of the type of the
++** allocation p.  Also return true if p==NULL.
+ **
+-** The other allowed parameters to sqlite3_mutex_alloc() each return
+-** a pointer to a static preexisting mutex.  Six static mutexes are
+-** used by the current version of SQLite.  Future versions of SQLite
+-** may add additional static mutexes.  Static mutexes are for internal
+-** use by SQLite only.  Applications that use SQLite mutexes should
+-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+-** SQLITE_MUTEX_RECURSIVE.
++** This routine is designed for use within an assert() statement, to
++** verify the type of an allocation.  For example:
+ **
+-** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+-** returns a different mutex on every call.  But for the static 
+-** mutex types, the same mutex is returned on every call that has
+-** the same type number.
++**     assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
+ */
+-static sqlite3_mutex *winMutexAlloc(int iType){
+-  sqlite3_mutex *p;
+-
+-  switch( iType ){
+-    case SQLITE_MUTEX_FAST:
+-    case SQLITE_MUTEX_RECURSIVE: {
+-      p = sqlite3MallocZero( sizeof(*p) );
+-      if( p ){  
+-#ifdef SQLITE_DEBUG
+-        p->id = iType;
+-#endif
+-#if SQLITE_OS_WINRT
+-        InitializeCriticalSectionEx(&p->mutex, 0, 0);
+-#else
+-        InitializeCriticalSection(&p->mutex);
+-#endif
+-      }
+-      break;
+-    }
+-    default: {
+-      assert( winMutex_isInit==1 );
+-      assert( iType-2 >= 0 );
+-      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
+-      p = &winMutex_staticMutexes[iType-2];
+-#ifdef SQLITE_DEBUG
+-      p->id = iType;
+-#endif
+-      break;
++SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
++  int rc = 1;
++  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
++    struct MemBlockHdr *pHdr;
++    pHdr = sqlite3MemsysGetHeader(p);
++    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
++    if( (pHdr->eType&eType)!=0 ){
++      rc = 0;
+     }
+   }
+-  return p;
++  return rc;
+ }
+ 
+-
+ /*
+-** This routine deallocates a previously
+-** allocated mutex.  SQLite is careful to deallocate every
+-** mutex that it allocates.
++** Set the number of backtrace levels kept for each allocation.
++** A value of zero turns off backtracing.  The number is always rounded
++** up to a multiple of 2.
+ */
+-static void winMutexFree(sqlite3_mutex *p){
+-  assert( p );
+-  assert( p->nRef==0 && p->owner==0 );
+-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+-  DeleteCriticalSection(&p->mutex);
+-  sqlite3_free(p);
++SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
++  if( depth<0 ){ depth = 0; }
++  if( depth>20 ){ depth = 20; }
++  depth = (depth+1)&0xfe;
++  mem.nBacktrace = depth;
++}
++
++SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
++  mem.xBacktrace = xBacktrace;
+ }
+ 
+ /*
+-** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+-** to enter a mutex.  If another thread is already within the mutex,
+-** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+-** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
+-** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
+-** be entered multiple times by the same thread.  In such cases the,
+-** mutex must be exited an equal number of times before another thread
+-** can enter.  If the same thread tries to enter any other kind of mutex
+-** more than once, the behavior is undefined.
++** Set the title string for subsequent allocations.
+ */
+-static void winMutexEnter(sqlite3_mutex *p){
+-#ifdef SQLITE_DEBUG
+-  DWORD tid = GetCurrentThreadId(); 
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+-#endif
+-  EnterCriticalSection(&p->mutex);
+-#ifdef SQLITE_DEBUG
+-  assert( p->nRef>0 || p->owner==0 );
+-  p->owner = tid; 
+-  p->nRef++;
+-  if( p->trace ){
+-    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
++  unsigned int n = sqlite3Strlen30(zTitle) + 1;
++  sqlite3_mutex_enter(mem.mutex);
++  if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
++  memcpy(mem.zTitle, zTitle, n);
++  mem.zTitle[n] = 0;
++  mem.nTitle = ROUND8(n);
++  sqlite3_mutex_leave(mem.mutex);
++}
++
++SQLITE_PRIVATE void sqlite3MemdebugSync(){
++  struct MemBlockHdr *pHdr;
++  for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
++    void **pBt = (void**)pHdr;
++    pBt -= pHdr->nBacktraceSlots;
++    mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
+   }
+-#endif
+ }
+-static int winMutexTry(sqlite3_mutex *p){
+-#ifndef NDEBUG
+-  DWORD tid = GetCurrentThreadId(); 
+-#endif
+-  int rc = SQLITE_BUSY;
+-  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+-  /*
+-  ** The sqlite3_mutex_try() routine is very rarely used, and when it
+-  ** is used it is merely an optimization.  So it is OK for it to always
+-  ** fail.  
+-  **
+-  ** The TryEnterCriticalSection() interface is only available on WinNT.
+-  ** And some windows compilers complain if you try to use it without
+-  ** first doing some #defines that prevent SQLite from building on Win98.
+-  ** For that reason, we will omit this optimization for now.  See
+-  ** ticket #2685.
+-  */
+-#if 0
+-  if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
+-    p->owner = tid;
+-    p->nRef++;
+-    rc = SQLITE_OK;
++
++/*
++** Open the file indicated and write a log of all unfreed memory 
++** allocations into that log.
++*/
++SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
++  FILE *out;
++  struct MemBlockHdr *pHdr;
++  void **pBt;
++  int i;
++  out = fopen(zFilename, "w");
++  if( out==0 ){
++    fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
++                    zFilename);
++    return;
+   }
+-#else
+-  UNUSED_PARAMETER(p);
+-#endif
+-#ifdef SQLITE_DEBUG
+-  if( rc==SQLITE_OK && p->trace ){
+-    printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++  for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
++    char *z = (char*)pHdr;
++    z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
++    fprintf(out, "**** %lld bytes at %p from %s ****\n", 
++            pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
++    if( pHdr->nBacktrace ){
++      fflush(out);
++      pBt = (void**)pHdr;
++      pBt -= pHdr->nBacktraceSlots;
++      backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
++      fprintf(out, "\n");
++    }
+   }
+-#endif
+-  return rc;
++  fprintf(out, "COUNTS:\n");
++  for(i=0; i<NCSIZE-1; i++){
++    if( mem.nAlloc[i] ){
++      fprintf(out, "   %5d: %10d %10d %10d\n", 
++            i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
++    }
++  }
++  if( mem.nAlloc[NCSIZE-1] ){
++    fprintf(out, "   %5d: %10d %10d %10d\n",
++             NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
++             mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
++  }
++  fclose(out);
+ }
+ 
+ /*
+-** The sqlite3_mutex_leave() routine exits a mutex that was
+-** previously entered by the same thread.  The behavior
+-** is undefined if the mutex is not currently entered or
+-** is not currently allocated.  SQLite will never do either.
++** Return the number of times sqlite3MemMalloc() has been called.
+ */
+-static void winMutexLeave(sqlite3_mutex *p){
+-#ifndef NDEBUG
+-  DWORD tid = GetCurrentThreadId();
+-  assert( p->nRef>0 );
+-  assert( p->owner==tid );
+-  p->nRef--;
+-  if( p->nRef==0 ) p->owner = 0;
+-  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
+-#endif
+-  LeaveCriticalSection(&p->mutex);
+-#ifdef SQLITE_DEBUG
+-  if( p->trace ){
+-    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
++  int i;
++  int nTotal = 0;
++  for(i=0; i<NCSIZE; i++){
++    nTotal += mem.nAlloc[i];
+   }
+-#endif
++  return nTotal;
+ }
+ 
+-SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
+-  static const sqlite3_mutex_methods sMutex = {
+-    winMutexInit,
+-    winMutexEnd,
+-    winMutexAlloc,
+-    winMutexFree,
+-    winMutexEnter,
+-    winMutexTry,
+-    winMutexLeave,
+-#ifdef SQLITE_DEBUG
+-    winMutexHeld,
+-    winMutexNotheld
+-#else
+-    0,
+-    0
+-#endif
+-  };
+ 
+-  return &sMutex;
+-}
+-#endif /* SQLITE_MUTEX_W32 */
++#endif /* SQLITE_MEMDEBUG */
+ 
+-/************** End of mutex_w32.c *******************************************/
+-/************** Begin file malloc.c ******************************************/
++/************** End of mem2.c ************************************************/
++/************** Begin file mem3.c ********************************************/
+ /*
+-** 2001 September 15
++** 2007 October 14
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -18775,1904 +19412,1632 @@
+ **    May you share freely, never taking more than you give.
+ **
+ *************************************************************************
++** This file contains the C functions that implement a memory
++** allocation subsystem for use by SQLite. 
+ **
+-** Memory allocation functions used throughout sqlite.
++** This version of the memory allocation subsystem omits all
++** use of malloc(). The SQLite user supplies a block of memory
++** before calling sqlite3_initialize() from which allocations
++** are made and returned by the xMalloc() and xRealloc() 
++** implementations. Once sqlite3_initialize() has been called,
++** the amount of memory available to SQLite is fixed and cannot
++** be changed.
++**
++** This version of the memory allocation subsystem is included
++** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
+ */
+-/* #include <stdarg.h> */
+ 
+ /*
+-** Attempt to release up to n bytes of non-essential memory currently
+-** held by SQLite. An example of non-essential memory is memory used to
+-** cache database pages that are not currently in use.
++** This version of the memory allocator is only built into the library
++** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
++** mean that the library will use a memory-pool by default, just that
++** it is available. The mempool allocator is activated by calling
++** sqlite3_config().
+ */
+-SQLITE_API int sqlite3_release_memory(int n){
+-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+-  return sqlite3PcacheReleaseMemory(n);
+-#else
+-  /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
+-  ** is a no-op returning zero if SQLite is not compiled with
+-  ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
+-  UNUSED_PARAMETER(n);
+-  return 0;
+-#endif
+-}
++#ifdef SQLITE_ENABLE_MEMSYS3
+ 
+ /*
+-** An instance of the following object records the location of
+-** each unused scratch buffer.
++** Maximum size (in Mem3Blocks) of a "small" chunk.
+ */
+-typedef struct ScratchFreeslot {
+-  struct ScratchFreeslot *pNext;   /* Next unused scratch buffer */
+-} ScratchFreeslot;
++#define MX_SMALL 10
++
+ 
+ /*
+-** State information local to the memory allocation subsystem.
++** Number of freelist hash slots
+ */
+-static SQLITE_WSD struct Mem0Global {
+-  sqlite3_mutex *mutex;         /* Mutex to serialize access */
++#define N_HASH  61
++
++/*
++** A memory allocation (also called a "chunk") consists of two or 
++** more blocks where each block is 8 bytes.  The first 8 bytes are 
++** a header that is not returned to the user.
++**
++** A chunk is two or more blocks that is either checked out or
++** free.  The first block has format u.hdr.  u.hdr.size4x is 4 times the
++** size of the allocation in blocks if the allocation is free.
++** The u.hdr.size4x&1 bit is true if the chunk is checked out and
++** false if the chunk is on the freelist.  The u.hdr.size4x&2 bit
++** is true if the previous chunk is checked out and false if the
++** previous chunk is free.  The u.hdr.prevSize field is the size of
++** the previous chunk in blocks if the previous chunk is on the
++** freelist. If the previous chunk is checked out, then
++** u.hdr.prevSize can be part of the data for that chunk and should
++** not be read or written.
++**
++** We often identify a chunk by its index in mem3.aPool[].  When
++** this is done, the chunk index refers to the second block of
++** the chunk.  In this way, the first chunk has an index of 1.
++** A chunk index of 0 means "no such chunk" and is the equivalent
++** of a NULL pointer.
++**
++** The second block of free chunks is of the form u.list.  The
++** two fields form a double-linked list of chunks of related sizes.
++** Pointers to the head of the list are stored in mem3.aiSmall[] 
++** for smaller chunks and mem3.aiHash[] for larger chunks.
++**
++** The second block of a chunk is user data if the chunk is checked 
++** out.  If a chunk is checked out, the user data may extend into
++** the u.hdr.prevSize value of the following chunk.
++*/
++typedef struct Mem3Block Mem3Block;
++struct Mem3Block {
++  union {
++    struct {
++      u32 prevSize;   /* Size of previous chunk in Mem3Block elements */
++      u32 size4x;     /* 4x the size of current chunk in Mem3Block elements */
++    } hdr;
++    struct {
++      u32 next;       /* Index in mem3.aPool[] of next free chunk */
++      u32 prev;       /* Index in mem3.aPool[] of previous free chunk */
++    } list;
++  } u;
++};
+ 
++/*
++** All of the static variables used by this module are collected
++** into a single structure named "mem3".  This is to keep the
++** static variables organized and to reduce namespace pollution
++** when this module is combined with other in the amalgamation.
++*/
++static SQLITE_WSD struct Mem3Global {
+   /*
+-  ** The alarm callback and its arguments.  The mem0.mutex lock will
+-  ** be held while the callback is running.  Recursive calls into
+-  ** the memory subsystem are allowed, but no new callbacks will be
+-  ** issued.
++  ** Memory available for allocation. nPool is the size of the array
++  ** (in Mem3Blocks) pointed to by aPool less 2.
+   */
+-  sqlite3_int64 alarmThreshold;
+-  void (*alarmCallback)(void*, sqlite3_int64,int);
+-  void *alarmArg;
++  u32 nPool;
++  Mem3Block *aPool;
+ 
+   /*
+-  ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
+-  ** (so that a range test can be used to determine if an allocation
+-  ** being freed came from pScratch) and a pointer to the list of
+-  ** unused scratch allocations.
++  ** True if we are evaluating an out-of-memory callback.
+   */
+-  void *pScratchEnd;
+-  ScratchFreeslot *pScratchFree;
+-  u32 nScratchFree;
++  int alarmBusy;
++  
++  /*
++  ** Mutex to control access to the memory allocation subsystem.
++  */
++  sqlite3_mutex *mutex;
++  
++  /*
++  ** The minimum amount of free space that we have seen.
++  */
++  u32 mnMaster;
+ 
+   /*
+-  ** True if heap is nearly "full" where "full" is defined by the
+-  ** sqlite3_soft_heap_limit() setting.
++  ** iMaster is the index of the master chunk.  Most new allocations
++  ** occur off of this chunk.  szMaster is the size (in Mem3Blocks)
++  ** of the current master.  iMaster is 0 if there is not master chunk.
++  ** The master chunk is not in either the aiHash[] or aiSmall[].
+   */
+-  int nearlyFull;
+-} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
++  u32 iMaster;
++  u32 szMaster;
+ 
+-#define mem0 GLOBAL(struct Mem0Global, mem0)
++  /*
++  ** Array of lists of free blocks according to the block size 
++  ** for smaller chunks, or a hash on the block size for larger
++  ** chunks.
++  */
++  u32 aiSmall[MX_SMALL-1];   /* For sizes 2 through MX_SMALL, inclusive */
++  u32 aiHash[N_HASH];        /* For sizes MX_SMALL+1 and larger */
++} mem3 = { 97535575 };
+ 
+-/*
+-** This routine runs when the memory allocator sees that the
+-** total memory allocation is about to exceed the soft heap
+-** limit.
+-*/
+-static void softHeapLimitEnforcer(
+-  void *NotUsed, 
+-  sqlite3_int64 NotUsed2,
+-  int allocSize
+-){
+-  UNUSED_PARAMETER2(NotUsed, NotUsed2);
+-  sqlite3_release_memory(allocSize);
+-}
++#define mem3 GLOBAL(struct Mem3Global, mem3)
+ 
+ /*
+-** Change the alarm callback
++** Unlink the chunk at mem3.aPool[i] from list it is currently
++** on.  *pRoot is the list that i is a member of.
+ */
+-static int sqlite3MemoryAlarm(
+-  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+-  void *pArg,
+-  sqlite3_int64 iThreshold
+-){
+-  int nUsed;
+-  sqlite3_mutex_enter(mem0.mutex);
+-  mem0.alarmCallback = xCallback;
+-  mem0.alarmArg = pArg;
+-  mem0.alarmThreshold = iThreshold;
+-  nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+-  mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed);
+-  sqlite3_mutex_leave(mem0.mutex);
+-  return SQLITE_OK;
++static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
++  u32 next = mem3.aPool[i].u.list.next;
++  u32 prev = mem3.aPool[i].u.list.prev;
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  if( prev==0 ){
++    *pRoot = next;
++  }else{
++    mem3.aPool[prev].u.list.next = next;
++  }
++  if( next ){
++    mem3.aPool[next].u.list.prev = prev;
++  }
++  mem3.aPool[i].u.list.next = 0;
++  mem3.aPool[i].u.list.prev = 0;
+ }
+ 
+-#ifndef SQLITE_OMIT_DEPRECATED
+ /*
+-** Deprecated external interface.  Internal/core SQLite code
+-** should call sqlite3MemoryAlarm.
++** Unlink the chunk at index i from 
++** whatever list is currently a member of.
+ */
+-SQLITE_API int sqlite3_memory_alarm(
+-  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+-  void *pArg,
+-  sqlite3_int64 iThreshold
+-){
+-  return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
++static void memsys3Unlink(u32 i){
++  u32 size, hash;
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
++  assert( i>=1 );
++  size = mem3.aPool[i-1].u.hdr.size4x/4;
++  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
++  assert( size>=2 );
++  if( size <= MX_SMALL ){
++    memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
++  }else{
++    hash = size % N_HASH;
++    memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
++  }
+ }
+-#endif
+ 
+ /*
+-** Set the soft heap-size limit for the library. Passing a zero or 
+-** negative value indicates no limit.
++** Link the chunk at mem3.aPool[i] so that is on the list rooted
++** at *pRoot.
+ */
+-SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
+-  sqlite3_int64 priorLimit;
+-  sqlite3_int64 excess;
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  int rc = sqlite3_initialize();
+-  if( rc ) return -1;
+-#endif
+-  sqlite3_mutex_enter(mem0.mutex);
+-  priorLimit = mem0.alarmThreshold;
+-  sqlite3_mutex_leave(mem0.mutex);
+-  if( n<0 ) return priorLimit;
+-  if( n>0 ){
+-    sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
+-  }else{
+-    sqlite3MemoryAlarm(0, 0, 0);
++static void memsys3LinkIntoList(u32 i, u32 *pRoot){
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  mem3.aPool[i].u.list.next = *pRoot;
++  mem3.aPool[i].u.list.prev = 0;
++  if( *pRoot ){
++    mem3.aPool[*pRoot].u.list.prev = i;
+   }
+-  excess = sqlite3_memory_used() - n;
+-  if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
+-  return priorLimit;
+-}
+-SQLITE_API void sqlite3_soft_heap_limit(int n){
+-  if( n<0 ) n = 0;
+-  sqlite3_soft_heap_limit64(n);
++  *pRoot = i;
+ }
+ 
+ /*
+-** Initialize the memory allocation subsystem.
++** Link the chunk at index i into either the appropriate
++** small chunk list, or into the large chunk hash table.
+ */
+-SQLITE_PRIVATE int sqlite3MallocInit(void){
+-  if( sqlite3GlobalConfig.m.xMalloc==0 ){
+-    sqlite3MemSetDefault();
+-  }
+-  memset(&mem0, 0, sizeof(mem0));
+-  if( sqlite3GlobalConfig.bCoreMutex ){
+-    mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+-  }
+-  if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
+-      && sqlite3GlobalConfig.nScratch>0 ){
+-    int i, n, sz;
+-    ScratchFreeslot *pSlot;
+-    sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
+-    sqlite3GlobalConfig.szScratch = sz;
+-    pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
+-    n = sqlite3GlobalConfig.nScratch;
+-    mem0.pScratchFree = pSlot;
+-    mem0.nScratchFree = n;
+-    for(i=0; i<n-1; i++){
+-      pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
+-      pSlot = pSlot->pNext;
+-    }
+-    pSlot->pNext = 0;
+-    mem0.pScratchEnd = (void*)&pSlot[1];
++static void memsys3Link(u32 i){
++  u32 size, hash;
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  assert( i>=1 );
++  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
++  size = mem3.aPool[i-1].u.hdr.size4x/4;
++  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
++  assert( size>=2 );
++  if( size <= MX_SMALL ){
++    memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
+   }else{
+-    mem0.pScratchEnd = 0;
+-    sqlite3GlobalConfig.pScratch = 0;
+-    sqlite3GlobalConfig.szScratch = 0;
+-    sqlite3GlobalConfig.nScratch = 0;
+-  }
+-  if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
+-      || sqlite3GlobalConfig.nPage<1 ){
+-    sqlite3GlobalConfig.pPage = 0;
+-    sqlite3GlobalConfig.szPage = 0;
+-    sqlite3GlobalConfig.nPage = 0;
++    hash = size % N_HASH;
++    memsys3LinkIntoList(i, &mem3.aiHash[hash]);
+   }
+-  return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
+ }
+ 
+ /*
+-** Return true if the heap is currently under memory pressure - in other
+-** words if the amount of heap used is close to the limit set by
+-** sqlite3_soft_heap_limit().
++** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
++** will already be held (obtained by code in malloc.c) if
++** sqlite3GlobalConfig.bMemStat is true.
+ */
+-SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
+-  return mem0.nearlyFull;
++static void memsys3Enter(void){
++  if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
++    mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
++  }
++  sqlite3_mutex_enter(mem3.mutex);
++}
++static void memsys3Leave(void){
++  sqlite3_mutex_leave(mem3.mutex);
+ }
+ 
+ /*
+-** Deinitialize the memory allocation subsystem.
++** Called when we are unable to satisfy an allocation of nBytes.
+ */
+-SQLITE_PRIVATE void sqlite3MallocEnd(void){
+-  if( sqlite3GlobalConfig.m.xShutdown ){
+-    sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
++static void memsys3OutOfMemory(int nByte){
++  if( !mem3.alarmBusy ){
++    mem3.alarmBusy = 1;
++    assert( sqlite3_mutex_held(mem3.mutex) );
++    sqlite3_mutex_leave(mem3.mutex);
++    sqlite3_release_memory(nByte);
++    sqlite3_mutex_enter(mem3.mutex);
++    mem3.alarmBusy = 0;
+   }
+-  memset(&mem0, 0, sizeof(mem0));
+ }
+ 
+-/*
+-** Return the amount of memory currently checked out.
+-*/
+-SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
+-  int n, mx;
+-  sqlite3_int64 res;
+-  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
+-  res = (sqlite3_int64)n;  /* Work around bug in Borland C. Ticket #3216 */
+-  return res;
+-}
+ 
+ /*
+-** Return the maximum amount of memory that has ever been
+-** checked out since either the beginning of this process
+-** or since the most recent reset.
++** Chunk i is a free chunk that has been unlinked.  Adjust its 
++** size parameters for check-out and return a pointer to the 
++** user portion of the chunk.
+ */
+-SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
+-  int n, mx;
+-  sqlite3_int64 res;
+-  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
+-  res = (sqlite3_int64)mx;  /* Work around bug in Borland C. Ticket #3216 */
+-  return res;
++static void *memsys3Checkout(u32 i, u32 nBlock){
++  u32 x;
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  assert( i>=1 );
++  assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
++  assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
++  x = mem3.aPool[i-1].u.hdr.size4x;
++  mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
++  mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
++  mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
++  return &mem3.aPool[i];
+ }
+ 
+ /*
+-** Trigger the alarm 
++** Carve a piece off of the end of the mem3.iMaster free chunk.
++** Return a pointer to the new allocation.  Or, if the master chunk
++** is not large enough, return 0.
+ */
+-static void sqlite3MallocAlarm(int nByte){
+-  void (*xCallback)(void*,sqlite3_int64,int);
+-  sqlite3_int64 nowUsed;
+-  void *pArg;
+-  if( mem0.alarmCallback==0 ) return;
+-  xCallback = mem0.alarmCallback;
+-  nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+-  pArg = mem0.alarmArg;
+-  mem0.alarmCallback = 0;
+-  sqlite3_mutex_leave(mem0.mutex);
+-  xCallback(pArg, nowUsed, nByte);
+-  sqlite3_mutex_enter(mem0.mutex);
+-  mem0.alarmCallback = xCallback;
+-  mem0.alarmArg = pArg;
++static void *memsys3FromMaster(u32 nBlock){
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  assert( mem3.szMaster>=nBlock );
++  if( nBlock>=mem3.szMaster-1 ){
++    /* Use the entire master */
++    void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
++    mem3.iMaster = 0;
++    mem3.szMaster = 0;
++    mem3.mnMaster = 0;
++    return p;
++  }else{
++    /* Split the master block.  Return the tail. */
++    u32 newi, x;
++    newi = mem3.iMaster + mem3.szMaster - nBlock;
++    assert( newi > mem3.iMaster+1 );
++    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
++    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
++    mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
++    mem3.szMaster -= nBlock;
++    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
++    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
++    mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
++    if( mem3.szMaster < mem3.mnMaster ){
++      mem3.mnMaster = mem3.szMaster;
++    }
++    return (void*)&mem3.aPool[newi];
++  }
+ }
+ 
+ /*
+-** Do a memory allocation with statistics and alarms.  Assume the
+-** lock is already held.
++** *pRoot is the head of a list of free chunks of the same size
++** or same size hash.  In other words, *pRoot is an entry in either
++** mem3.aiSmall[] or mem3.aiHash[].  
++**
++** This routine examines all entries on the given list and tries
++** to coalesce each entries with adjacent free chunks.  
++**
++** If it sees a chunk that is larger than mem3.iMaster, it replaces 
++** the current mem3.iMaster with the new larger chunk.  In order for
++** this mem3.iMaster replacement to work, the master chunk must be
++** linked into the hash tables.  That is not the normal state of
++** affairs, of course.  The calling routine must link the master
++** chunk before invoking this routine, then must unlink the (possibly
++** changed) master chunk once this routine has finished.
+ */
+-static int mallocWithAlarm(int n, void **pp){
+-  int nFull;
+-  void *p;
+-  assert( sqlite3_mutex_held(mem0.mutex) );
+-  nFull = sqlite3GlobalConfig.m.xRoundup(n);
+-  sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
+-  if( mem0.alarmCallback!=0 ){
+-    int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+-    if( nUsed >= mem0.alarmThreshold - nFull ){
+-      mem0.nearlyFull = 1;
+-      sqlite3MallocAlarm(nFull);
++static void memsys3Merge(u32 *pRoot){
++  u32 iNext, prev, size, i, x;
++
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  for(i=*pRoot; i>0; i=iNext){
++    iNext = mem3.aPool[i].u.list.next;
++    size = mem3.aPool[i-1].u.hdr.size4x;
++    assert( (size&1)==0 );
++    if( (size&2)==0 ){
++      memsys3UnlinkFromList(i, pRoot);
++      assert( i > mem3.aPool[i-1].u.hdr.prevSize );
++      prev = i - mem3.aPool[i-1].u.hdr.prevSize;
++      if( prev==iNext ){
++        iNext = mem3.aPool[prev].u.list.next;
++      }
++      memsys3Unlink(prev);
++      size = i + size/4 - prev;
++      x = mem3.aPool[prev-1].u.hdr.size4x & 2;
++      mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
++      mem3.aPool[prev+size-1].u.hdr.prevSize = size;
++      memsys3Link(prev);
++      i = prev;
+     }else{
+-      mem0.nearlyFull = 0;
++      size /= 4;
++    }
++    if( size>mem3.szMaster ){
++      mem3.iMaster = i;
++      mem3.szMaster = size;
+     }
+   }
+-  p = sqlite3GlobalConfig.m.xMalloc(nFull);
+-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+-  if( p==0 && mem0.alarmCallback ){
+-    sqlite3MallocAlarm(nFull);
+-    p = sqlite3GlobalConfig.m.xMalloc(nFull);
+-  }
+-#endif
+-  if( p ){
+-    nFull = sqlite3MallocSize(p);
+-    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
+-    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
+-  }
+-  *pp = p;
+-  return nFull;
+ }
+ 
+ /*
+-** Allocate memory.  This routine is like sqlite3_malloc() except that it
+-** assumes the memory subsystem has already been initialized.
++** Return a block of memory of at least nBytes in size.
++** Return NULL if unable.
++**
++** This function assumes that the necessary mutexes, if any, are
++** already held by the caller. Hence "Unsafe".
+ */
+-SQLITE_PRIVATE void *sqlite3Malloc(int n){
+-  void *p;
+-  if( n<=0               /* IMP: R-65312-04917 */ 
+-   || n>=0x7fffff00
+-  ){
+-    /* A memory allocation of a number of bytes which is near the maximum
+-    ** signed integer value might cause an integer overflow inside of the
+-    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
+-    ** 255 bytes of overhead.  SQLite itself will never use anything near
+-    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
+-    p = 0;
+-  }else if( sqlite3GlobalConfig.bMemstat ){
+-    sqlite3_mutex_enter(mem0.mutex);
+-    mallocWithAlarm(n, &p);
+-    sqlite3_mutex_leave(mem0.mutex);
++static void *memsys3MallocUnsafe(int nByte){
++  u32 i;
++  u32 nBlock;
++  u32 toFree;
++
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  assert( sizeof(Mem3Block)==8 );
++  if( nByte<=12 ){
++    nBlock = 2;
+   }else{
+-    p = sqlite3GlobalConfig.m.xMalloc(n);
++    nBlock = (nByte + 11)/8;
+   }
+-  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
+-  return p;
+-}
++  assert( nBlock>=2 );
+ 
+-/*
+-** This version of the memory allocation is for use by the application.
+-** First make sure the memory subsystem is initialized, then do the
+-** allocation.
+-*/
+-SQLITE_API void *sqlite3_malloc(int n){
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  if( sqlite3_initialize() ) return 0;
+-#endif
+-  return sqlite3Malloc(n);
+-}
+-
+-/*
+-** Each thread may only have a single outstanding allocation from
+-** xScratchMalloc().  We verify this constraint in the single-threaded
+-** case by setting scratchAllocOut to 1 when an allocation
+-** is outstanding clearing it when the allocation is freed.
+-*/
+-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+-static int scratchAllocOut = 0;
+-#endif
++  /* STEP 1:
++  ** Look for an entry of the correct size in either the small
++  ** chunk table or in the large chunk hash table.  This is
++  ** successful most of the time (about 9 times out of 10).
++  */
++  if( nBlock <= MX_SMALL ){
++    i = mem3.aiSmall[nBlock-2];
++    if( i>0 ){
++      memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
++      return memsys3Checkout(i, nBlock);
++    }
++  }else{
++    int hash = nBlock % N_HASH;
++    for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
++      if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
++        memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
++        return memsys3Checkout(i, nBlock);
++      }
++    }
++  }
+ 
++  /* STEP 2:
++  ** Try to satisfy the allocation by carving a piece off of the end
++  ** of the master chunk.  This step usually works if step 1 fails.
++  */
++  if( mem3.szMaster>=nBlock ){
++    return memsys3FromMaster(nBlock);
++  }
+ 
+-/*
+-** Allocate memory that is to be used and released right away.
+-** This routine is similar to alloca() in that it is not intended
+-** for situations where the memory might be held long-term.  This
+-** routine is intended to get memory to old large transient data
+-** structures that would not normally fit on the stack of an
+-** embedded processor.
+-*/
+-SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
+-  void *p;
+-  assert( n>0 );
+ 
+-  sqlite3_mutex_enter(mem0.mutex);
+-  if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
+-    p = mem0.pScratchFree;
+-    mem0.pScratchFree = mem0.pScratchFree->pNext;
+-    mem0.nScratchFree--;
+-    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
+-    sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+-    sqlite3_mutex_leave(mem0.mutex);
+-  }else{
+-    if( sqlite3GlobalConfig.bMemstat ){
+-      sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+-      n = mallocWithAlarm(n, &p);
+-      if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
+-      sqlite3_mutex_leave(mem0.mutex);
+-    }else{
+-      sqlite3_mutex_leave(mem0.mutex);
+-      p = sqlite3GlobalConfig.m.xMalloc(n);
++  /* STEP 3:  
++  ** Loop through the entire memory pool.  Coalesce adjacent free
++  ** chunks.  Recompute the master chunk as the largest free chunk.
++  ** Then try again to satisfy the allocation by carving a piece off
++  ** of the end of the master chunk.  This step happens very
++  ** rarely (we hope!)
++  */
++  for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
++    memsys3OutOfMemory(toFree);
++    if( mem3.iMaster ){
++      memsys3Link(mem3.iMaster);
++      mem3.iMaster = 0;
++      mem3.szMaster = 0;
++    }
++    for(i=0; i<N_HASH; i++){
++      memsys3Merge(&mem3.aiHash[i]);
++    }
++    for(i=0; i<MX_SMALL-1; i++){
++      memsys3Merge(&mem3.aiSmall[i]);
++    }
++    if( mem3.szMaster ){
++      memsys3Unlink(mem3.iMaster);
++      if( mem3.szMaster>=nBlock ){
++        return memsys3FromMaster(nBlock);
++      }
+     }
+-    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
+   }
+-  assert( sqlite3_mutex_notheld(mem0.mutex) );
+-
+-
+-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+-  /* Verify that no more than two scratch allocations per thread
+-  ** are outstanding at one time.  (This is only checked in the
+-  ** single-threaded case since checking in the multi-threaded case
+-  ** would be much more complicated.) */
+-  assert( scratchAllocOut<=1 );
+-  if( p ) scratchAllocOut++;
+-#endif
+ 
+-  return p;
++  /* If none of the above worked, then we fail. */
++  return 0;
+ }
+-SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
+-  if( p ){
+ 
+-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+-    /* Verify that no more than two scratch allocation per thread
+-    ** is outstanding at one time.  (This is only checked in the
+-    ** single-threaded case since checking in the multi-threaded case
+-    ** would be much more complicated.) */
+-    assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
+-    scratchAllocOut--;
+-#endif
++/*
++** Free an outstanding memory allocation.
++**
++** This function assumes that the necessary mutexes, if any, are
++** already held by the caller. Hence "Unsafe".
++*/
++static void memsys3FreeUnsafe(void *pOld){
++  Mem3Block *p = (Mem3Block*)pOld;
++  int i;
++  u32 size, x;
++  assert( sqlite3_mutex_held(mem3.mutex) );
++  assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
++  i = p - mem3.aPool;
++  assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
++  size = mem3.aPool[i-1].u.hdr.size4x/4;
++  assert( i+size<=mem3.nPool+1 );
++  mem3.aPool[i-1].u.hdr.size4x &= ~1;
++  mem3.aPool[i+size-1].u.hdr.prevSize = size;
++  mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
++  memsys3Link(i);
+ 
+-    if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){
+-      /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
+-      ScratchFreeslot *pSlot;
+-      pSlot = (ScratchFreeslot*)p;
+-      sqlite3_mutex_enter(mem0.mutex);
+-      pSlot->pNext = mem0.pScratchFree;
+-      mem0.pScratchFree = pSlot;
+-      mem0.nScratchFree++;
+-      assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
+-      sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
+-      sqlite3_mutex_leave(mem0.mutex);
+-    }else{
+-      /* Release memory back to the heap */
+-      assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
+-      assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
+-      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+-      if( sqlite3GlobalConfig.bMemstat ){
+-        int iSize = sqlite3MallocSize(p);
+-        sqlite3_mutex_enter(mem0.mutex);
+-        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
+-        sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
+-        sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
+-        sqlite3GlobalConfig.m.xFree(p);
+-        sqlite3_mutex_leave(mem0.mutex);
+-      }else{
+-        sqlite3GlobalConfig.m.xFree(p);
+-      }
++  /* Try to expand the master using the newly freed chunk */
++  if( mem3.iMaster ){
++    while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
++      size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
++      mem3.iMaster -= size;
++      mem3.szMaster += size;
++      memsys3Unlink(mem3.iMaster);
++      x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
++      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
++      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
++    }
++    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
++    while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
++      memsys3Unlink(mem3.iMaster+mem3.szMaster);
++      mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
++      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
++      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+     }
+   }
+ }
+ 
+ /*
+-** TRUE if p is a lookaside memory allocation from db
++** Return the size of an outstanding allocation, in bytes.  The
++** size returned omits the 8-byte header overhead.  This only
++** works for chunks that are currently checked out.
+ */
+-#ifndef SQLITE_OMIT_LOOKASIDE
+-static int isLookaside(sqlite3 *db, void *p){
+-  return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
++static int memsys3Size(void *p){
++  Mem3Block *pBlock;
++  if( p==0 ) return 0;
++  pBlock = (Mem3Block*)p;
++  assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
++  return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
+ }
+-#else
+-#define isLookaside(A,B) 0
+-#endif
+ 
+ /*
+-** Return the size of a memory allocation previously obtained from
+-** sqlite3Malloc() or sqlite3_malloc().
++** Round up a request size to the next valid allocation size.
+ */
+-SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+-  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+-  assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
+-  return sqlite3GlobalConfig.m.xSize(p);
+-}
+-SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
+-  assert( db==0 || sqlite3_mutex_held(db->mutex) );
+-  if( db && isLookaside(db, p) ){
+-    return db->lookaside.sz;
++static int memsys3Roundup(int n){
++  if( n<=12 ){
++    return 12;
+   }else{
+-    assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+-    assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
+-    assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
+-    return sqlite3GlobalConfig.m.xSize(p);
++    return ((n+11)&~7) - 4;
+   }
+ }
+ 
+ /*
+-** Free memory previously obtained from sqlite3Malloc().
++** Allocate nBytes of memory.
+ */
+-SQLITE_API void sqlite3_free(void *p){
+-  if( p==0 ) return;  /* IMP: R-49053-54554 */
+-  assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
+-  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+-  if( sqlite3GlobalConfig.bMemstat ){
+-    sqlite3_mutex_enter(mem0.mutex);
+-    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
+-    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
+-    sqlite3GlobalConfig.m.xFree(p);
+-    sqlite3_mutex_leave(mem0.mutex);
+-  }else{
+-    sqlite3GlobalConfig.m.xFree(p);
+-  }
++static void *memsys3Malloc(int nBytes){
++  sqlite3_int64 *p;
++  assert( nBytes>0 );          /* malloc.c filters out 0 byte requests */
++  memsys3Enter();
++  p = memsys3MallocUnsafe(nBytes);
++  memsys3Leave();
++  return (void*)p; 
+ }
+ 
+ /*
+-** Free memory that might be associated with a particular database
+-** connection.
++** Free memory.
+ */
+-SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+-  assert( db==0 || sqlite3_mutex_held(db->mutex) );
+-  if( db ){
+-    if( db->pnBytesFreed ){
+-      *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
+-      return;
+-    }
+-    if( isLookaside(db, p) ){
+-      LookasideSlot *pBuf = (LookasideSlot*)p;
+-#if SQLITE_DEBUG
+-      /* Trash all content in the buffer being freed */
+-      memset(p, 0xaa, db->lookaside.sz);
+-#endif
+-      pBuf->pNext = db->lookaside.pFree;
+-      db->lookaside.pFree = pBuf;
+-      db->lookaside.nOut--;
+-      return;
+-    }
+-  }
+-  assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+-  assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
+-  assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
+-  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+-  sqlite3_free(p);
++static void memsys3Free(void *pPrior){
++  assert( pPrior );
++  memsys3Enter();
++  memsys3FreeUnsafe(pPrior);
++  memsys3Leave();
+ }
+ 
+ /*
+ ** Change the size of an existing memory allocation
+ */
+-SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
+-  int nOld, nNew, nDiff;
+-  void *pNew;
+-  if( pOld==0 ){
+-    return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
++static void *memsys3Realloc(void *pPrior, int nBytes){
++  int nOld;
++  void *p;
++  if( pPrior==0 ){
++    return sqlite3_malloc(nBytes);
+   }
+   if( nBytes<=0 ){
+-    sqlite3_free(pOld); /* IMP: R-31593-10574 */
++    sqlite3_free(pPrior);
+     return 0;
+   }
+-  if( nBytes>=0x7fffff00 ){
+-    /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
+-    return 0;
++  nOld = memsys3Size(pPrior);
++  if( nBytes<=nOld && nBytes>=nOld-128 ){
++    return pPrior;
+   }
+-  nOld = sqlite3MallocSize(pOld);
+-  /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
+-  ** argument to xRealloc is always a value returned by a prior call to
+-  ** xRoundup. */
+-  nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
+-  if( nOld==nNew ){
+-    pNew = pOld;
+-  }else if( sqlite3GlobalConfig.bMemstat ){
+-    sqlite3_mutex_enter(mem0.mutex);
+-    sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
+-    nDiff = nNew - nOld;
+-    if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
+-          mem0.alarmThreshold-nDiff ){
+-      sqlite3MallocAlarm(nDiff);
+-    }
+-    assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
+-    assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
+-    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+-    if( pNew==0 && mem0.alarmCallback ){
+-      sqlite3MallocAlarm(nBytes);
+-      pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+-    }
+-    if( pNew ){
+-      nNew = sqlite3MallocSize(pNew);
+-      sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
++  memsys3Enter();
++  p = memsys3MallocUnsafe(nBytes);
++  if( p ){
++    if( nOld<nBytes ){
++      memcpy(p, pPrior, nOld);
++    }else{
++      memcpy(p, pPrior, nBytes);
+     }
+-    sqlite3_mutex_leave(mem0.mutex);
+-  }else{
+-    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
++    memsys3FreeUnsafe(pPrior);
+   }
+-  assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
+-  return pNew;
++  memsys3Leave();
++  return p;
+ }
+ 
+ /*
+-** The public interface to sqlite3Realloc.  Make sure that the memory
+-** subsystem is initialized prior to invoking sqliteRealloc.
++** Initialize this module.
+ */
+-SQLITE_API void *sqlite3_realloc(void *pOld, int n){
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  if( sqlite3_initialize() ) return 0;
+-#endif
+-  return sqlite3Realloc(pOld, n);
+-}
++static int memsys3Init(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  if( !sqlite3GlobalConfig.pHeap ){
++    return SQLITE_ERROR;
++  }
+ 
++  /* Store a pointer to the memory block in global structure mem3. */
++  assert( sizeof(Mem3Block)==8 );
++  mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
++  mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
+ 
+-/*
+-** Allocate and zero memory.
+-*/ 
+-SQLITE_PRIVATE void *sqlite3MallocZero(int n){
+-  void *p = sqlite3Malloc(n);
+-  if( p ){
+-    memset(p, 0, n);
+-  }
+-  return p;
++  /* Initialize the master block. */
++  mem3.szMaster = mem3.nPool;
++  mem3.mnMaster = mem3.szMaster;
++  mem3.iMaster = 1;
++  mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
++  mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
++  mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
++
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Allocate and zero memory.  If the allocation fails, make
+-** the mallocFailed flag in the connection pointer.
++** Deinitialize this module.
+ */
+-SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){
+-  void *p = sqlite3DbMallocRaw(db, n);
+-  if( p ){
+-    memset(p, 0, n);
+-  }
+-  return p;
++static void memsys3Shutdown(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  mem3.mutex = 0;
++  return;
+ }
+ 
++
++
+ /*
+-** Allocate and zero memory.  If the allocation fails, make
+-** the mallocFailed flag in the connection pointer.
+-**
+-** If db!=0 and db->mallocFailed is true (indicating a prior malloc
+-** failure on the same database connection) then always return 0.
+-** Hence for a particular database connection, once malloc starts
+-** failing, it fails consistently until mallocFailed is reset.
+-** This is an important assumption.  There are many places in the
+-** code that do things like this:
+-**
+-**         int *a = (int*)sqlite3DbMallocRaw(db, 100);
+-**         int *b = (int*)sqlite3DbMallocRaw(db, 200);
+-**         if( b ) a[10] = 9;
+-**
+-** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
+-** that all prior mallocs (ex: "a") worked too.
++** Open the file indicated and write a log of all unfreed memory 
++** allocations into that log.
+ */
+-SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
+-  void *p;
+-  assert( db==0 || sqlite3_mutex_held(db->mutex) );
+-  assert( db==0 || db->pnBytesFreed==0 );
+-#ifndef SQLITE_OMIT_LOOKASIDE
+-  if( db ){
+-    LookasideSlot *pBuf;
+-    if( db->mallocFailed ){
+-      return 0;
+-    }
+-    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;
+-      }
++SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
++#ifdef SQLITE_DEBUG
++  FILE *out;
++  u32 i, j;
++  u32 size;
++  if( zFilename==0 || zFilename[0]==0 ){
++    out = stdout;
++  }else{
++    out = fopen(zFilename, "w");
++    if( out==0 ){
++      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
++                      zFilename);
++      return;
+     }
+   }
+-#else
+-  if( db && db->mallocFailed ){
+-    return 0;
+-  }
+-#endif
+-  p = sqlite3Malloc(n);
+-  if( !p && db ){
+-    db->mallocFailed = 1;
+-  }
+-  sqlite3MemdebugSetType(p, MEMTYPE_DB |
+-         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
+-  return p;
+-}
+-
+-/*
+-** Resize the block of memory pointed to by p to n bytes. If the
+-** resize fails, set the mallocFailed flag in the connection object.
+-*/
+-SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
+-  void *pNew = 0;
+-  assert( db!=0 );
+-  assert( sqlite3_mutex_held(db->mutex) );
+-  if( db->mallocFailed==0 ){
+-    if( p==0 ){
+-      return sqlite3DbMallocRaw(db, n);
++  memsys3Enter();
++  fprintf(out, "CHUNKS:\n");
++  for(i=1; i<=mem3.nPool; i+=size/4){
++    size = mem3.aPool[i-1].u.hdr.size4x;
++    if( size/4<=1 ){
++      fprintf(out, "%p size error\n", &mem3.aPool[i]);
++      assert( 0 );
++      break;
+     }
+-    if( isLookaside(db, p) ){
+-      if( n<=db->lookaside.sz ){
+-        return p;
+-      }
+-      pNew = sqlite3DbMallocRaw(db, n);
+-      if( pNew ){
+-        memcpy(pNew, p, db->lookaside.sz);
+-        sqlite3DbFree(db, p);
+-      }
++    if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
++      fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
++      assert( 0 );
++      break;
++    }
++    if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
++      fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
++      assert( 0 );
++      break;
++    }
++    if( size&1 ){
++      fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
+     }else{
+-      assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+-      assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
+-      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+-      pNew = sqlite3_realloc(p, n);
+-      if( !pNew ){
+-        sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
+-        db->mallocFailed = 1;
+-      }
+-      sqlite3MemdebugSetType(pNew, MEMTYPE_DB | 
+-            (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
++      fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
++                  i==mem3.iMaster ? " **master**" : "");
+     }
+   }
+-  return pNew;
++  for(i=0; i<MX_SMALL-1; i++){
++    if( mem3.aiSmall[i]==0 ) continue;
++    fprintf(out, "small(%2d):", i);
++    for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
++      fprintf(out, " %p(%d)", &mem3.aPool[j],
++              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
++    }
++    fprintf(out, "\n"); 
++  }
++  for(i=0; i<N_HASH; i++){
++    if( mem3.aiHash[i]==0 ) continue;
++    fprintf(out, "hash(%2d):", i);
++    for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
++      fprintf(out, " %p(%d)", &mem3.aPool[j],
++              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
++    }
++    fprintf(out, "\n"); 
++  }
++  fprintf(out, "master=%d\n", mem3.iMaster);
++  fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
++  fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
++  sqlite3_mutex_leave(mem3.mutex);
++  if( out==stdout ){
++    fflush(stdout);
++  }else{
++    fclose(out);
++  }
++#else
++  UNUSED_PARAMETER(zFilename);
++#endif
+ }
+ 
+ /*
+-** Attempt to reallocate p.  If the reallocation fails, then free p
+-** and set the mallocFailed flag in the database connection.
++** This routine is the only routine in this file with external 
++** linkage.
++**
++** Populate the low-level memory allocation function pointers in
++** sqlite3GlobalConfig.m with pointers to the routines in this file. The
++** arguments specify the block of memory to manage.
++**
++** This routine is only called by sqlite3_config(), and therefore
++** is not required to be threadsafe (it is not).
+ */
+-SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
+-  void *pNew;
+-  pNew = sqlite3DbRealloc(db, p, n);
+-  if( !pNew ){
+-    sqlite3DbFree(db, p);
+-  }
+-  return pNew;
++SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
++  static const sqlite3_mem_methods mempoolMethods = {
++     memsys3Malloc,
++     memsys3Free,
++     memsys3Realloc,
++     memsys3Size,
++     memsys3Roundup,
++     memsys3Init,
++     memsys3Shutdown,
++     0
++  };
++  return &mempoolMethods;
+ }
+ 
++#endif /* SQLITE_ENABLE_MEMSYS3 */
++
++/************** End of mem3.c ************************************************/
++/************** Begin file mem5.c ********************************************/
+ /*
+-** Make a copy of a string in memory obtained from sqliteMalloc(). These 
+-** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
+-** is because when memory debugging is turned on, these two functions are 
+-** called via macros that record the current file and line number in the
+-** ThreadData structure.
++** 2007 October 14
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This file contains the C functions that implement a memory
++** allocation subsystem for use by SQLite. 
++**
++** This version of the memory allocation subsystem omits all
++** use of malloc(). The application gives SQLite a block of memory
++** before calling sqlite3_initialize() from which allocations
++** are made and returned by the xMalloc() and xRealloc() 
++** implementations. Once sqlite3_initialize() has been called,
++** the amount of memory available to SQLite is fixed and cannot
++** be changed.
++**
++** This version of the memory allocation subsystem is included
++** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
++**
++** This memory allocator uses the following algorithm:
++**
++**   1.  All memory allocations sizes are rounded up to a power of 2.
++**
++**   2.  If two adjacent free blocks are the halves of a larger block,
++**       then the two blocks are coalesed into the single larger block.
++**
++**   3.  New memory is allocated from the first available free block.
++**
++** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
++** Concerning Dynamic Storage Allocation". Journal of the Association for
++** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
++** 
++** Let n be the size of the largest allocation divided by the minimum
++** allocation size (after rounding all sizes up to a power of 2.)  Let M
++** be the maximum amount of memory ever outstanding at one time.  Let
++** N be the total amount of memory available for allocation.  Robson
++** proved that this memory allocator will never breakdown due to 
++** fragmentation as long as the following constraint holds:
++**
++**      N >=  M*(1 + log2(n)/2) - n + 1
++**
++** The sqlite3_status() logic tracks the maximum values of n and M so
++** that an application can, at any time, verify this constraint.
+ */
+-SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
+-  char *zNew;
+-  size_t n;
+-  if( z==0 ){
+-    return 0;
+-  }
+-  n = sqlite3Strlen30(z) + 1;
+-  assert( (n&0x7fffffff)==n );
+-  zNew = sqlite3DbMallocRaw(db, (int)n);
+-  if( zNew ){
+-    memcpy(zNew, z, n);
+-  }
+-  return zNew;
+-}
+-SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
+-  char *zNew;
+-  if( z==0 ){
+-    return 0;
+-  }
+-  assert( (n&0x7fffffff)==n );
+-  zNew = sqlite3DbMallocRaw(db, n+1);
+-  if( zNew ){
+-    memcpy(zNew, z, n);
+-    zNew[n] = 0;
+-  }
+-  return zNew;
+-}
+ 
+ /*
+-** Create a string from the zFromat argument and the va_list that follows.
+-** Store the string in memory obtained from sqliteMalloc() and make *pz
+-** point to that string.
++** This version of the memory allocator is used only when 
++** SQLITE_ENABLE_MEMSYS5 is defined.
+ */
+-SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
+-  va_list ap;
+-  char *z;
+-
+-  va_start(ap, zFormat);
+-  z = sqlite3VMPrintf(db, zFormat, ap);
+-  va_end(ap);
+-  sqlite3DbFree(db, *pz);
+-  *pz = z;
+-}
+-
++#ifdef SQLITE_ENABLE_MEMSYS5
+ 
+ /*
+-** This function must be called before exiting any API function (i.e. 
+-** returning control to the user) that has called sqlite3_malloc or
+-** sqlite3_realloc.
+-**
+-** The returned value is normally a copy of the second argument to this
+-** function. However, if a malloc() failure has occurred since the previous
+-** invocation SQLITE_NOMEM is returned instead. 
++** A minimum allocation is an instance of the following structure.
++** Larger allocations are an array of these structures where the
++** size of the array is a power of 2.
+ **
+-** If the first argument, db, is not NULL and a malloc() error has occurred,
+-** then the connection error-code (the value returned by sqlite3_errcode())
+-** is set to SQLITE_NOMEM.
++** The size of this object must be a power of two.  That fact is
++** verified in memsys5Init().
+ */
+-SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
+-  /* If the db handle is not NULL, then we must hold the connection handle
+-  ** mutex here. Otherwise the read (and possible write) of db->mallocFailed 
+-  ** is unsafe, as is the call to sqlite3Error().
+-  */
+-  assert( !db || sqlite3_mutex_held(db->mutex) );
+-  if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
+-    sqlite3Error(db, SQLITE_NOMEM, 0);
+-    db->mallocFailed = 0;
+-    rc = SQLITE_NOMEM;
+-  }
+-  return rc & (db ? db->errMask : 0xff);
+-}
++typedef struct Mem5Link Mem5Link;
++struct Mem5Link {
++  int next;       /* Index of next free chunk */
++  int prev;       /* Index of previous free chunk */
++};
+ 
+-/************** End of malloc.c **********************************************/
+-/************** Begin file printf.c ******************************************/
+ /*
+-** The "printf" code that follows dates from the 1980's.  It is in
+-** the public domain.  The original comments are included here for
+-** completeness.  They are very out-of-date but might be useful as
+-** an historical reference.  Most of the "enhancements" have been backed
+-** out so that the functionality is now the same as standard printf().
+-**
+-**************************************************************************
+-**
+-** This file contains code for a set of "printf"-like routines.  These
+-** routines format strings much like the printf() from the standard C
+-** library, though the implementation here has enhancements to support
+-** SQLlite.
++** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
++** mem5.szAtom is always at least 8 and 32-bit integers are used,
++** it is not actually possible to reach this limit.
+ */
++#define LOGMAX 30
+ 
+ /*
+-** Conversion types fall into various categories as defined by the
+-** following enumeration.
++** Masks used for mem5.aCtrl[] elements.
+ */
+-#define etRADIX       1 /* Integer types.  %d, %x, %o, and so forth */
+-#define etFLOAT       2 /* Floating point.  %f */
+-#define etEXP         3 /* Exponentional notation. %e and %E */
+-#define etGENERIC     4 /* Floating or exponential, depending on exponent. %g */
+-#define etSIZE        5 /* Return number of characters processed so far. %n */
+-#define etSTRING      6 /* Strings. %s */
+-#define etDYNSTRING   7 /* Dynamically allocated strings. %z */
+-#define etPERCENT     8 /* Percent symbol. %% */
+-#define etCHARX       9 /* Characters. %c */
+-/* The rest are extensions, not normally found in printf() */
+-#define etSQLESCAPE  10 /* Strings with '\'' doubled.  %q */
+-#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
+-                          NULL pointers replaced by SQL NULL.  %Q */
+-#define etTOKEN      12 /* a pointer to a Token structure */
+-#define etSRCLIST    13 /* a pointer to a SrcList */
+-#define etPOINTER    14 /* The %p conversion */
+-#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
+-#define etORDINAL    16 /* %r -> 1st, 2nd, 3rd, 4th, etc.  English only */
++#define CTRL_LOGSIZE  0x1f    /* Log2 Size of this block */
++#define CTRL_FREE     0x20    /* True if not checked out */
+ 
+-#define etINVALID     0 /* Any unrecognized conversion type */
++/*
++** All of the static variables used by this module are collected
++** into a single structure named "mem5".  This is to keep the
++** static variables organized and to reduce namespace pollution
++** when this module is combined with other in the amalgamation.
++*/
++static SQLITE_WSD struct Mem5Global {
++  /*
++  ** Memory available for allocation
++  */
++  int szAtom;      /* Smallest possible allocation in bytes */
++  int nBlock;      /* Number of szAtom sized blocks in zPool */
++  u8 *zPool;       /* Memory available to be allocated */
++  
++  /*
++  ** Mutex to control access to the memory allocation subsystem.
++  */
++  sqlite3_mutex *mutex;
++
++  /*
++  ** Performance statistics
++  */
++  u64 nAlloc;         /* Total number of calls to malloc */
++  u64 totalAlloc;     /* Total of all malloc calls - includes internal frag */
++  u64 totalExcess;    /* Total internal fragmentation */
++  u32 currentOut;     /* Current checkout, including internal fragmentation */
++  u32 currentCount;   /* Current number of distinct checkouts */
++  u32 maxOut;         /* Maximum instantaneous currentOut */
++  u32 maxCount;       /* Maximum instantaneous currentCount */
++  u32 maxRequest;     /* Largest allocation (exclusive of internal frag) */
++  
++  /*
++  ** Lists of free blocks.  aiFreelist[0] is a list of free blocks of
++  ** size mem5.szAtom.  aiFreelist[1] holds blocks of size szAtom*2.
++  ** and so forth.
++  */
++  int aiFreelist[LOGMAX+1];
++
++  /*
++  ** Space for tracking which blocks are checked out and the size
++  ** of each block.  One byte per block.
++  */
++  u8 *aCtrl;
+ 
++} mem5;
+ 
+ /*
+-** An "etByte" is an 8-bit unsigned value.
++** Access the static variable through a macro for SQLITE_OMIT_WSD
+ */
+-typedef unsigned char etByte;
++#define mem5 GLOBAL(struct Mem5Global, mem5)
+ 
+ /*
+-** Each builtin conversion character (ex: the 'd' in "%d") is described
+-** by an instance of the following structure
++** Assuming mem5.zPool is divided up into an array of Mem5Link
++** structures, return a pointer to the idx-th such lik.
+ */
+-typedef struct et_info {   /* Information about each format field */
+-  char fmttype;            /* The format field code letter */
+-  etByte base;             /* The base for radix conversion */
+-  etByte flags;            /* One or more of FLAG_ constants below */
+-  etByte type;             /* Conversion paradigm */
+-  etByte charset;          /* Offset into aDigits[] of the digits string */
+-  etByte prefix;           /* Offset into aPrefix[] of the prefix string */
+-} et_info;
++#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
+ 
+ /*
+-** Allowed values for et_info.flags
++** Unlink the chunk at mem5.aPool[i] from list it is currently
++** on.  It should be found on mem5.aiFreelist[iLogsize].
+ */
+-#define FLAG_SIGNED  1     /* True if the value to convert is signed */
+-#define FLAG_INTERN  2     /* True if for internal use only */
+-#define FLAG_STRING  4     /* Allow infinity precision */
++static void memsys5Unlink(int i, int iLogsize){
++  int next, prev;
++  assert( i>=0 && i<mem5.nBlock );
++  assert( iLogsize>=0 && iLogsize<=LOGMAX );
++  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+ 
++  next = MEM5LINK(i)->next;
++  prev = MEM5LINK(i)->prev;
++  if( prev<0 ){
++    mem5.aiFreelist[iLogsize] = next;
++  }else{
++    MEM5LINK(prev)->next = next;
++  }
++  if( next>=0 ){
++    MEM5LINK(next)->prev = prev;
++  }
++}
+ 
+ /*
+-** The following table is searched linearly, so it is good to put the
+-** most frequently used conversion types first.
++** Link the chunk at mem5.aPool[i] so that is on the iLogsize
++** free list.
+ */
+-static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
+-static const char aPrefix[] = "-x0\000X0";
+-static const et_info fmtinfo[] = {
+-  {  'd', 10, 1, etRADIX,      0,  0 },
+-  {  's',  0, 4, etSTRING,     0,  0 },
+-  {  'g',  0, 1, etGENERIC,    30, 0 },
+-  {  'z',  0, 4, etDYNSTRING,  0,  0 },
+-  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
+-  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
+-  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
+-  {  'c',  0, 0, etCHARX,      0,  0 },
+-  {  'o',  8, 0, etRADIX,      0,  2 },
+-  {  'u', 10, 0, etRADIX,      0,  0 },
+-  {  'x', 16, 0, etRADIX,      16, 1 },
+-  {  'X', 16, 0, etRADIX,      0,  4 },
+-#ifndef SQLITE_OMIT_FLOATING_POINT
+-  {  'f',  0, 1, etFLOAT,      0,  0 },
+-  {  'e',  0, 1, etEXP,        30, 0 },
+-  {  'E',  0, 1, etEXP,        14, 0 },
+-  {  'G',  0, 1, etGENERIC,    14, 0 },
+-#endif
+-  {  'i', 10, 1, etRADIX,      0,  0 },
+-  {  'n',  0, 0, etSIZE,       0,  0 },
+-  {  '%',  0, 0, etPERCENT,    0,  0 },
+-  {  'p', 16, 0, etPOINTER,    0,  1 },
++static void memsys5Link(int i, int iLogsize){
++  int x;
++  assert( sqlite3_mutex_held(mem5.mutex) );
++  assert( i>=0 && i<mem5.nBlock );
++  assert( iLogsize>=0 && iLogsize<=LOGMAX );
++  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+ 
+-/* All the rest have the FLAG_INTERN bit set and are thus for internal
+-** use only */
+-  {  'T',  0, 2, etTOKEN,      0,  0 },
+-  {  'S',  0, 2, etSRCLIST,    0,  0 },
+-  {  'r', 10, 3, etORDINAL,    0,  0 },
+-};
++  x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
++  MEM5LINK(i)->prev = -1;
++  if( x>=0 ){
++    assert( x<mem5.nBlock );
++    MEM5LINK(x)->prev = i;
++  }
++  mem5.aiFreelist[iLogsize] = i;
++}
+ 
+ /*
+-** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
+-** conversions will work.
++** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
++** will already be held (obtained by code in malloc.c) if
++** sqlite3GlobalConfig.bMemStat is true.
+ */
+-#ifndef SQLITE_OMIT_FLOATING_POINT
++static void memsys5Enter(void){
++  sqlite3_mutex_enter(mem5.mutex);
++}
++static void memsys5Leave(void){
++  sqlite3_mutex_leave(mem5.mutex);
++}
++
+ /*
+-** "*val" is a double such that 0.1 <= *val < 10.0
+-** Return the ascii code for the leading digit of *val, then
+-** multiply "*val" by 10.0 to renormalize.
+-**
+-** Example:
+-**     input:     *val = 3.14159
+-**     output:    *val = 1.4159    function return = '3'
+-**
+-** The counter *cnt is incremented each time.  After counter exceeds
+-** 16 (the number of significant digits in a 64-bit float) '0' is
+-** always returned.
++** Return the size of an outstanding allocation, in bytes.  The
++** size returned omits the 8-byte header overhead.  This only
++** works for chunks that are currently checked out.
+ */
+-static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
+-  int digit;
+-  LONGDOUBLE_TYPE d;
+-  if( (*cnt)<=0 ) return '0';
+-  (*cnt)--;
+-  digit = (int)*val;
+-  d = digit;
+-  digit += '0';
+-  *val = (*val - d)*10.0;
+-  return (char)digit;
++static int memsys5Size(void *p){
++  int iSize = 0;
++  if( p ){
++    int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
++    assert( i>=0 && i<mem5.nBlock );
++    iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
++  }
++  return iSize;
+ }
+-#endif /* SQLITE_OMIT_FLOATING_POINT */
+ 
+ /*
+-** Append N space characters to the given string buffer.
++** Find the first entry on the freelist iLogsize.  Unlink that
++** entry and return its index. 
+ */
+-SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
+-  static const char zSpaces[] = "                             ";
+-  while( N>=(int)sizeof(zSpaces)-1 ){
+-    sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
+-    N -= sizeof(zSpaces)-1;
+-  }
+-  if( N>0 ){
+-    sqlite3StrAccumAppend(pAccum, zSpaces, N);
++static int memsys5UnlinkFirst(int iLogsize){
++  int i;
++  int iFirst;
++
++  assert( iLogsize>=0 && iLogsize<=LOGMAX );
++  i = iFirst = mem5.aiFreelist[iLogsize];
++  assert( iFirst>=0 );
++  while( i>0 ){
++    if( i<iFirst ) iFirst = i;
++    i = MEM5LINK(i)->next;
+   }
++  memsys5Unlink(iFirst, iLogsize);
++  return iFirst;
+ }
+ 
+ /*
+-** On machines with a small stack size, you can redefine the
+-** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
++** Return a block of memory of at least nBytes in size.
++** Return NULL if unable.  Return NULL if nBytes==0.
++**
++** The caller guarantees that nByte positive.
++**
++** The caller has obtained a mutex prior to invoking this
++** routine so there is never any chance that two or more
++** threads can be in this routine at the same time.
+ */
+-#ifndef SQLITE_PRINT_BUF_SIZE
+-# define SQLITE_PRINT_BUF_SIZE 70
+-#endif
+-#define etBUFSIZE SQLITE_PRINT_BUF_SIZE  /* Size of the output buffer */
++static void *memsys5MallocUnsafe(int nByte){
++  int i;           /* Index of a mem5.aPool[] slot */
++  int iBin;        /* Index into mem5.aiFreelist[] */
++  int iFullSz;     /* Size of allocation rounded up to power of 2 */
++  int iLogsize;    /* Log2 of iFullSz/POW2_MIN */
++
++  /* nByte must be a positive */
++  assert( nByte>0 );
++
++  /* Keep track of the maximum allocation request.  Even unfulfilled
++  ** requests are counted */
++  if( (u32)nByte>mem5.maxRequest ){
++    mem5.maxRequest = nByte;
++  }
++
++  /* Abort if the requested allocation size is larger than the largest
++  ** power of two that we can represent using 32-bit signed integers.
++  */
++  if( nByte > 0x40000000 ){
++    return 0;
++  }
++
++  /* Round nByte up to the next valid power of two */
++  for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
++
++  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
++  ** block.  If not, then split a block of the next larger power of
++  ** two in order to create a new free block of size iLogsize.
++  */
++  for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
++  if( iBin>LOGMAX ){
++    testcase( sqlite3GlobalConfig.xLog!=0 );
++    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
++    return 0;
++  }
++  i = memsys5UnlinkFirst(iBin);
++  while( iBin>iLogsize ){
++    int newSize;
++
++    iBin--;
++    newSize = 1 << iBin;
++    mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
++    memsys5Link(i+newSize, iBin);
++  }
++  mem5.aCtrl[i] = iLogsize;
++
++  /* Update allocator performance statistics. */
++  mem5.nAlloc++;
++  mem5.totalAlloc += iFullSz;
++  mem5.totalExcess += iFullSz - nByte;
++  mem5.currentCount++;
++  mem5.currentOut += iFullSz;
++  if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
++  if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
++
++  /* Return a pointer to the allocated memory. */
++  return (void*)&mem5.zPool[i*mem5.szAtom];
++}
+ 
+ /*
+-** Render a string given by "fmt" into the StrAccum object.
++** Free an outstanding memory allocation.
+ */
+-SQLITE_PRIVATE void sqlite3VXPrintf(
+-  StrAccum *pAccum,                  /* Accumulate results here */
+-  int useExtended,                   /* Allow extended %-conversions */
+-  const char *fmt,                   /* Format string */
+-  va_list ap                         /* arguments */
+-){
+-  int c;                     /* Next character in the format string */
+-  char *bufpt;               /* Pointer to the conversion buffer */
+-  int precision;             /* Precision of the current field */
+-  int length;                /* Length of the field */
+-  int idx;                   /* A general purpose loop counter */
+-  int width;                 /* Width of the current field */
+-  etByte flag_leftjustify;   /* True if "-" flag is present */
+-  etByte flag_plussign;      /* True if "+" flag is present */
+-  etByte flag_blanksign;     /* True if " " flag is present */
+-  etByte flag_alternateform; /* True if "#" flag is present */
+-  etByte flag_altform2;      /* True if "!" flag is present */
+-  etByte flag_zeropad;       /* True if field width constant starts with zero */
+-  etByte flag_long;          /* True if "l" flag is present */
+-  etByte flag_longlong;      /* True if the "ll" flag is present */
+-  etByte done;               /* Loop termination flag */
+-  etByte xtype = 0;          /* Conversion paradigm */
+-  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
+-  sqlite_uint64 longvalue;   /* Value for integer types */
+-  LONGDOUBLE_TYPE realvalue; /* Value for real types */
+-  const et_info *infop;      /* Pointer to the appropriate info structure */
+-  char *zOut;                /* Rendering buffer */
+-  int nOut;                  /* Size of the rendering buffer */
+-  char *zExtra;              /* Malloced memory used by some conversion */
+-#ifndef SQLITE_OMIT_FLOATING_POINT
+-  int  exp, e2;              /* exponent of real numbers */
+-  int nsd;                   /* Number of significant digits returned */
+-  double rounder;            /* Used for rounding floating point values */
+-  etByte flag_dp;            /* True if decimal point should be shown */
+-  etByte flag_rtz;           /* True if trailing zeros should be removed */
+-#endif
+-  char buf[etBUFSIZE];       /* Conversion buffer */
++static void memsys5FreeUnsafe(void *pOld){
++  u32 size, iLogsize;
++  int iBlock;
+ 
+-  bufpt = 0;
+-  for(; (c=(*fmt))!=0; ++fmt){
+-    if( c!='%' ){
+-      int amt;
+-      bufpt = (char *)fmt;
+-      amt = 1;
+-      while( (c=(*++fmt))!='%' && c!=0 ) amt++;
+-      sqlite3StrAccumAppend(pAccum, bufpt, amt);
+-      if( c==0 ) break;
+-    }
+-    if( (c=(*++fmt))==0 ){
+-      sqlite3StrAccumAppend(pAccum, "%", 1);
+-      break;
+-    }
+-    /* Find out what flags are present */
+-    flag_leftjustify = flag_plussign = flag_blanksign = 
+-     flag_alternateform = flag_altform2 = flag_zeropad = 0;
+-    done = 0;
+-    do{
+-      switch( c ){
+-        case '-':   flag_leftjustify = 1;     break;
+-        case '+':   flag_plussign = 1;        break;
+-        case ' ':   flag_blanksign = 1;       break;
+-        case '#':   flag_alternateform = 1;   break;
+-        case '!':   flag_altform2 = 1;        break;
+-        case '0':   flag_zeropad = 1;         break;
+-        default:    done = 1;                 break;
+-      }
+-    }while( !done && (c=(*++fmt))!=0 );
+-    /* Get the field width */
+-    width = 0;
+-    if( c=='*' ){
+-      width = va_arg(ap,int);
+-      if( width<0 ){
+-        flag_leftjustify = 1;
+-        width = -width;
+-      }
+-      c = *++fmt;
++  /* Set iBlock to the index of the block pointed to by pOld in 
++  ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
++  */
++  iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
++
++  /* Check that the pointer pOld points to a valid, non-free block. */
++  assert( iBlock>=0 && iBlock<mem5.nBlock );
++  assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
++  assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
++
++  iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
++  size = 1<<iLogsize;
++  assert( iBlock+size-1<(u32)mem5.nBlock );
++
++  mem5.aCtrl[iBlock] |= CTRL_FREE;
++  mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
++  assert( mem5.currentCount>0 );
++  assert( mem5.currentOut>=(size*mem5.szAtom) );
++  mem5.currentCount--;
++  mem5.currentOut -= size*mem5.szAtom;
++  assert( mem5.currentOut>0 || mem5.currentCount==0 );
++  assert( mem5.currentCount>0 || mem5.currentOut==0 );
++
++  mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
++  while( ALWAYS(iLogsize<LOGMAX) ){
++    int iBuddy;
++    if( (iBlock>>iLogsize) & 1 ){
++      iBuddy = iBlock - size;
+     }else{
+-      while( c>='0' && c<='9' ){
+-        width = width*10 + c - '0';
+-        c = *++fmt;
+-      }
++      iBuddy = iBlock + size;
+     }
+-    /* Get the precision */
+-    if( c=='.' ){
+-      precision = 0;
+-      c = *++fmt;
+-      if( c=='*' ){
+-        precision = va_arg(ap,int);
+-        if( precision<0 ) precision = -precision;
+-        c = *++fmt;
+-      }else{
+-        while( c>='0' && c<='9' ){
+-          precision = precision*10 + c - '0';
+-          c = *++fmt;
+-        }
+-      }
++    assert( iBuddy>=0 );
++    if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
++    if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
++    memsys5Unlink(iBuddy, iLogsize);
++    iLogsize++;
++    if( iBuddy<iBlock ){
++      mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
++      mem5.aCtrl[iBlock] = 0;
++      iBlock = iBuddy;
+     }else{
+-      precision = -1;
++      mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
++      mem5.aCtrl[iBuddy] = 0;
+     }
+-    /* Get the conversion type modifier */
+-    if( c=='l' ){
+-      flag_long = 1;
+-      c = *++fmt;
+-      if( c=='l' ){
+-        flag_longlong = 1;
+-        c = *++fmt;
+-      }else{
+-        flag_longlong = 0;
+-      }
+-    }else{
+-      flag_long = flag_longlong = 0;
++    size *= 2;
++  }
++  memsys5Link(iBlock, iLogsize);
++}
++
++/*
++** Allocate nBytes of memory
++*/
++static void *memsys5Malloc(int nBytes){
++  sqlite3_int64 *p = 0;
++  if( nBytes>0 ){
++    memsys5Enter();
++    p = memsys5MallocUnsafe(nBytes);
++    memsys5Leave();
++  }
++  return (void*)p; 
++}
++
++/*
++** Free memory.
++**
++** The outer layer memory allocator prevents this routine from
++** being called with pPrior==0.
++*/
++static void memsys5Free(void *pPrior){
++  assert( pPrior!=0 );
++  memsys5Enter();
++  memsys5FreeUnsafe(pPrior);
++  memsys5Leave();  
++}
++
++/*
++** Change the size of an existing memory allocation.
++**
++** The outer layer memory allocator prevents this routine from
++** being called with pPrior==0.  
++**
++** nBytes is always a value obtained from a prior call to
++** memsys5Round().  Hence nBytes is always a non-negative power
++** of two.  If nBytes==0 that means that an oversize allocation
++** (an allocation larger than 0x40000000) was requested and this
++** routine should return 0 without freeing pPrior.
++*/
++static void *memsys5Realloc(void *pPrior, int nBytes){
++  int nOld;
++  void *p;
++  assert( pPrior!=0 );
++  assert( (nBytes&(nBytes-1))==0 );  /* EV: R-46199-30249 */
++  assert( nBytes>=0 );
++  if( nBytes==0 ){
++    return 0;
++  }
++  nOld = memsys5Size(pPrior);
++  if( nBytes<=nOld ){
++    return pPrior;
++  }
++  memsys5Enter();
++  p = memsys5MallocUnsafe(nBytes);
++  if( p ){
++    memcpy(p, pPrior, nOld);
++    memsys5FreeUnsafe(pPrior);
++  }
++  memsys5Leave();
++  return p;
++}
++
++/*
++** Round up a request size to the next valid allocation size.  If
++** the allocation is too large to be handled by this allocation system,
++** return 0.
++**
++** All allocations must be a power of two and must be expressed by a
++** 32-bit signed integer.  Hence the largest allocation is 0x40000000
++** or 1073741824 bytes.
++*/
++static int memsys5Roundup(int n){
++  int iFullSz;
++  if( n > 0x40000000 ) return 0;
++  for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
++  return iFullSz;
++}
++
++/*
++** Return the ceiling of the logarithm base 2 of iValue.
++**
++** Examples:   memsys5Log(1) -> 0
++**             memsys5Log(2) -> 1
++**             memsys5Log(4) -> 2
++**             memsys5Log(5) -> 3
++**             memsys5Log(8) -> 3
++**             memsys5Log(9) -> 4
++*/
++static int memsys5Log(int iValue){
++  int iLog;
++  for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
++  return iLog;
++}
++
++/*
++** Initialize the memory allocator.
++**
++** This routine is not threadsafe.  The caller must be holding a mutex
++** to prevent multiple threads from entering at the same time.
++*/
++static int memsys5Init(void *NotUsed){
++  int ii;            /* Loop counter */
++  int nByte;         /* Number of bytes of memory available to this allocator */
++  u8 *zByte;         /* Memory usable by this allocator */
++  int nMinLog;       /* Log base 2 of minimum allocation size in bytes */
++  int iOffset;       /* An offset into mem5.aCtrl[] */
++
++  UNUSED_PARAMETER(NotUsed);
++
++  /* For the purposes of this routine, disable the mutex */
++  mem5.mutex = 0;
++
++  /* The size of a Mem5Link object must be a power of two.  Verify that
++  ** this is case.
++  */
++  assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
++
++  nByte = sqlite3GlobalConfig.nHeap;
++  zByte = (u8*)sqlite3GlobalConfig.pHeap;
++  assert( zByte!=0 );  /* sqlite3_config() does not allow otherwise */
++
++  /* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
++  nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
++  mem5.szAtom = (1<<nMinLog);
++  while( (int)sizeof(Mem5Link)>mem5.szAtom ){
++    mem5.szAtom = mem5.szAtom << 1;
++  }
++
++  mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
++  mem5.zPool = zByte;
++  mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
++
++  for(ii=0; ii<=LOGMAX; ii++){
++    mem5.aiFreelist[ii] = -1;
++  }
++
++  iOffset = 0;
++  for(ii=LOGMAX; ii>=0; ii--){
++    int nAlloc = (1<<ii);
++    if( (iOffset+nAlloc)<=mem5.nBlock ){
++      mem5.aCtrl[iOffset] = ii | CTRL_FREE;
++      memsys5Link(iOffset, ii);
++      iOffset += nAlloc;
+     }
+-    /* Fetch the info entry for the field */
+-    infop = &fmtinfo[0];
+-    xtype = etINVALID;
+-    for(idx=0; idx<ArraySize(fmtinfo); idx++){
+-      if( c==fmtinfo[idx].fmttype ){
+-        infop = &fmtinfo[idx];
+-        if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
+-          xtype = infop->type;
+-        }else{
+-          return;
+-        }
+-        break;
+-      }
++    assert((iOffset+nAlloc)>mem5.nBlock);
++  }
++
++  /* If a mutex is required for normal operation, allocate one */
++  if( sqlite3GlobalConfig.bMemstat==0 ){
++    mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
++  }
++
++  return SQLITE_OK;
++}
++
++/*
++** Deinitialize this module.
++*/
++static void memsys5Shutdown(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  mem5.mutex = 0;
++  return;
++}
++
++#ifdef SQLITE_TEST
++/*
++** Open the file indicated and write a log of all unfreed memory 
++** allocations into that log.
++*/
++SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
++  FILE *out;
++  int i, j, n;
++  int nMinLog;
++
++  if( zFilename==0 || zFilename[0]==0 ){
++    out = stdout;
++  }else{
++    out = fopen(zFilename, "w");
++    if( out==0 ){
++      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
++                      zFilename);
++      return;
+     }
+-    zExtra = 0;
++  }
++  memsys5Enter();
++  nMinLog = memsys5Log(mem5.szAtom);
++  for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
++    for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
++    fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
++  }
++  fprintf(out, "mem5.nAlloc       = %llu\n", mem5.nAlloc);
++  fprintf(out, "mem5.totalAlloc   = %llu\n", mem5.totalAlloc);
++  fprintf(out, "mem5.totalExcess  = %llu\n", mem5.totalExcess);
++  fprintf(out, "mem5.currentOut   = %u\n", mem5.currentOut);
++  fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
++  fprintf(out, "mem5.maxOut       = %u\n", mem5.maxOut);
++  fprintf(out, "mem5.maxCount     = %u\n", mem5.maxCount);
++  fprintf(out, "mem5.maxRequest   = %u\n", mem5.maxRequest);
++  memsys5Leave();
++  if( out==stdout ){
++    fflush(stdout);
++  }else{
++    fclose(out);
++  }
++}
++#endif
+ 
+-    /*
+-    ** At this point, variables are initialized as follows:
+-    **
+-    **   flag_alternateform          TRUE if a '#' is present.
+-    **   flag_altform2               TRUE if a '!' is present.
+-    **   flag_plussign               TRUE if a '+' is present.
+-    **   flag_leftjustify            TRUE if a '-' is present or if the
+-    **                               field width was negative.
+-    **   flag_zeropad                TRUE if the width began with 0.
+-    **   flag_long                   TRUE if the letter 'l' (ell) prefixed
+-    **                               the conversion character.
+-    **   flag_longlong               TRUE if the letter 'll' (ell ell) prefixed
+-    **                               the conversion character.
+-    **   flag_blanksign              TRUE if a ' ' is present.
+-    **   width                       The specified field width.  This is
+-    **                               always non-negative.  Zero is the default.
+-    **   precision                   The specified precision.  The default
+-    **                               is -1.
+-    **   xtype                       The class of the conversion.
+-    **   infop                       Pointer to the appropriate info struct.
++/*
++** This routine is the only routine in this file with external 
++** linkage. It returns a pointer to a static sqlite3_mem_methods
++** struct populated with the memsys5 methods.
++*/
++SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
++  static const sqlite3_mem_methods memsys5Methods = {
++     memsys5Malloc,
++     memsys5Free,
++     memsys5Realloc,
++     memsys5Size,
++     memsys5Roundup,
++     memsys5Init,
++     memsys5Shutdown,
++     0
++  };
++  return &memsys5Methods;
++}
++
++#endif /* SQLITE_ENABLE_MEMSYS5 */
++
++/************** End of mem5.c ************************************************/
++/************** Begin file mutex.c *******************************************/
++/*
++** 2007 August 14
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This file contains the C functions that implement mutexes.
++**
++** This file contains code that is common across all mutex implementations.
++*/
++
++#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
++/*
++** For debugging purposes, record when the mutex subsystem is initialized
++** and uninitialized so that we can assert() if there is an attempt to
++** allocate a mutex while the system is uninitialized.
++*/
++static SQLITE_WSD int mutexIsInit = 0;
++#endif /* SQLITE_DEBUG */
++
++
++#ifndef SQLITE_MUTEX_OMIT
++/*
++** Initialize the mutex system.
++*/
++SQLITE_PRIVATE int sqlite3MutexInit(void){ 
++  int rc = SQLITE_OK;
++  if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
++    /* If the xMutexAlloc method has not been set, then the user did not
++    ** install a mutex implementation via sqlite3_config() prior to 
++    ** sqlite3_initialize() being called. This block copies pointers to
++    ** the default implementation into the sqlite3GlobalConfig structure.
+     */
+-    switch( xtype ){
+-      case etPOINTER:
+-        flag_longlong = sizeof(char*)==sizeof(i64);
+-        flag_long = sizeof(char*)==sizeof(long int);
+-        /* Fall through into the next case */
+-      case etORDINAL:
+-      case etRADIX:
+-        if( infop->flags & FLAG_SIGNED ){
+-          i64 v;
+-          if( flag_longlong ){
+-            v = va_arg(ap,i64);
+-          }else if( flag_long ){
+-            v = va_arg(ap,long int);
+-          }else{
+-            v = va_arg(ap,int);
+-          }
+-          if( v<0 ){
+-            if( v==SMALLEST_INT64 ){
+-              longvalue = ((u64)1)<<63;
+-            }else{
+-              longvalue = -v;
+-            }
+-            prefix = '-';
+-          }else{
+-            longvalue = v;
+-            if( flag_plussign )        prefix = '+';
+-            else if( flag_blanksign )  prefix = ' ';
+-            else                       prefix = 0;
+-          }
+-        }else{
+-          if( flag_longlong ){
+-            longvalue = va_arg(ap,u64);
+-          }else if( flag_long ){
+-            longvalue = va_arg(ap,unsigned long int);
+-          }else{
+-            longvalue = va_arg(ap,unsigned int);
+-          }
+-          prefix = 0;
+-        }
+-        if( longvalue==0 ) flag_alternateform = 0;
+-        if( flag_zeropad && precision<width-(prefix!=0) ){
+-          precision = width-(prefix!=0);
+-        }
+-        if( precision<etBUFSIZE-10 ){
+-          nOut = etBUFSIZE;
+-          zOut = buf;
+-        }else{
+-          nOut = precision + 10;
+-          zOut = zExtra = sqlite3Malloc( nOut );
+-          if( zOut==0 ){
+-            pAccum->mallocFailed = 1;
+-            return;
+-          }
+-        }
+-        bufpt = &zOut[nOut-1];
+-        if( xtype==etORDINAL ){
+-          static const char zOrd[] = "thstndrd";
+-          int x = (int)(longvalue % 10);
+-          if( x>=4 || (longvalue/10)%10==1 ){
+-            x = 0;
+-          }
+-          *(--bufpt) = zOrd[x*2+1];
+-          *(--bufpt) = zOrd[x*2];
+-        }
+-        {
+-          register const char *cset;      /* Use registers for speed */
+-          register int base;
+-          cset = &aDigits[infop->charset];
+-          base = infop->base;
+-          do{                                           /* Convert to ascii */
+-            *(--bufpt) = cset[longvalue%base];
+-            longvalue = longvalue/base;
+-          }while( longvalue>0 );
+-        }
+-        length = (int)(&zOut[nOut-1]-bufpt);
+-        for(idx=precision-length; idx>0; idx--){
+-          *(--bufpt) = '0';                             /* Zero pad */
+-        }
+-        if( prefix ) *(--bufpt) = prefix;               /* Add sign */
+-        if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */
+-          const char *pre;
+-          char x;
+-          pre = &aPrefix[infop->prefix];
+-          for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
+-        }
+-        length = (int)(&zOut[nOut-1]-bufpt);
+-        break;
+-      case etFLOAT:
+-      case etEXP:
+-      case etGENERIC:
+-        realvalue = va_arg(ap,double);
+-#ifdef SQLITE_OMIT_FLOATING_POINT
+-        length = 0;
+-#else
+-        if( precision<0 ) precision = 6;         /* Set default precision */
+-        if( realvalue<0.0 ){
+-          realvalue = -realvalue;
+-          prefix = '-';
+-        }else{
+-          if( flag_plussign )          prefix = '+';
+-          else if( flag_blanksign )    prefix = ' ';
+-          else                         prefix = 0;
+-        }
+-        if( xtype==etGENERIC && precision>0 ) precision--;
+-#if 0
+-        /* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
+-        for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
+-#else
+-        /* It makes more sense to use 0.5 */
+-        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
+-#endif
+-        if( xtype==etFLOAT ) realvalue += rounder;
+-        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
+-        exp = 0;
+-        if( sqlite3IsNaN((double)realvalue) ){
+-          bufpt = "NaN";
+-          length = 3;
+-          break;
+-        }
+-        if( realvalue>0.0 ){
+-          LONGDOUBLE_TYPE scale = 1.0;
+-          while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
+-          while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
+-          while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
+-          while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
+-          realvalue /= scale;
+-          while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
+-          while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
+-          if( exp>350 ){
+-            if( prefix=='-' ){
+-              bufpt = "-Inf";
+-            }else if( prefix=='+' ){
+-              bufpt = "+Inf";
+-            }else{
+-              bufpt = "Inf";
+-            }
+-            length = sqlite3Strlen30(bufpt);
+-            break;
+-          }
+-        }
+-        bufpt = buf;
+-        /*
+-        ** If the field type is etGENERIC, then convert to either etEXP
+-        ** or etFLOAT, as appropriate.
+-        */
+-        if( xtype!=etFLOAT ){
+-          realvalue += rounder;
+-          if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
+-        }
+-        if( xtype==etGENERIC ){
+-          flag_rtz = !flag_alternateform;
+-          if( exp<-4 || exp>precision ){
+-            xtype = etEXP;
+-          }else{
+-            precision = precision - exp;
+-            xtype = etFLOAT;
+-          }
+-        }else{
+-          flag_rtz = flag_altform2;
+-        }
+-        if( xtype==etEXP ){
+-          e2 = 0;
+-        }else{
+-          e2 = exp;
+-        }
+-        if( e2+precision+width > etBUFSIZE - 15 ){
+-          bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
+-          if( bufpt==0 ){
+-            pAccum->mallocFailed = 1;
+-            return;
+-          }
+-        }
+-        zOut = bufpt;
+-        nsd = 16 + flag_altform2*10;
+-        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
+-        /* The sign in front of the number */
+-        if( prefix ){
+-          *(bufpt++) = prefix;
+-        }
+-        /* Digits prior to the decimal point */
+-        if( e2<0 ){
+-          *(bufpt++) = '0';
+-        }else{
+-          for(; e2>=0; e2--){
+-            *(bufpt++) = et_getdigit(&realvalue,&nsd);
+-          }
+-        }
+-        /* The decimal point */
+-        if( flag_dp ){
+-          *(bufpt++) = '.';
+-        }
+-        /* "0" digits after the decimal point but before the first
+-        ** significant digit of the number */
+-        for(e2++; e2<0; precision--, e2++){
+-          assert( precision>0 );
+-          *(bufpt++) = '0';
+-        }
+-        /* Significant digits after the decimal point */
+-        while( (precision--)>0 ){
+-          *(bufpt++) = et_getdigit(&realvalue,&nsd);
+-        }
+-        /* Remove trailing zeros and the "." if no digits follow the "." */
+-        if( flag_rtz && flag_dp ){
+-          while( bufpt[-1]=='0' ) *(--bufpt) = 0;
+-          assert( bufpt>zOut );
+-          if( bufpt[-1]=='.' ){
+-            if( flag_altform2 ){
+-              *(bufpt++) = '0';
+-            }else{
+-              *(--bufpt) = 0;
+-            }
+-          }
+-        }
+-        /* Add the "eNNN" suffix */
+-        if( xtype==etEXP ){
+-          *(bufpt++) = aDigits[infop->charset];
+-          if( exp<0 ){
+-            *(bufpt++) = '-'; exp = -exp;
+-          }else{
+-            *(bufpt++) = '+';
+-          }
+-          if( exp>=100 ){
+-            *(bufpt++) = (char)((exp/100)+'0');        /* 100's digit */
+-            exp %= 100;
+-          }
+-          *(bufpt++) = (char)(exp/10+'0');             /* 10's digit */
+-          *(bufpt++) = (char)(exp%10+'0');             /* 1's digit */
+-        }
+-        *bufpt = 0;
+-
+-        /* The converted number is in buf[] and zero terminated. Output it.
+-        ** Note that the number is in the usual order, not reversed as with
+-        ** integer conversions. */
+-        length = (int)(bufpt-zOut);
+-        bufpt = zOut;
+-
+-        /* Special case:  Add leading zeros if the flag_zeropad flag is
+-        ** set and we are not left justified */
+-        if( flag_zeropad && !flag_leftjustify && length < width){
+-          int i;
+-          int nPad = width - length;
+-          for(i=width; i>=nPad; i--){
+-            bufpt[i] = bufpt[i-nPad];
+-          }
+-          i = prefix!=0;
+-          while( nPad-- ) bufpt[i++] = '0';
+-          length = width;
+-        }
+-#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
+-        break;
+-      case etSIZE:
+-        *(va_arg(ap,int*)) = pAccum->nChar;
+-        length = width = 0;
+-        break;
+-      case etPERCENT:
+-        buf[0] = '%';
+-        bufpt = buf;
+-        length = 1;
+-        break;
+-      case etCHARX:
+-        c = va_arg(ap,int);
+-        buf[0] = (char)c;
+-        if( precision>=0 ){
+-          for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
+-          length = precision;
+-        }else{
+-          length =1;
+-        }
+-        bufpt = buf;
+-        break;
+-      case etSTRING:
+-      case etDYNSTRING:
+-        bufpt = va_arg(ap,char*);
+-        if( bufpt==0 ){
+-          bufpt = "";
+-        }else if( xtype==etDYNSTRING ){
+-          zExtra = bufpt;
+-        }
+-        if( precision>=0 ){
+-          for(length=0; length<precision && bufpt[length]; length++){}
+-        }else{
+-          length = sqlite3Strlen30(bufpt);
+-        }
+-        break;
+-      case etSQLESCAPE:
+-      case etSQLESCAPE2:
+-      case etSQLESCAPE3: {
+-        int i, j, k, n, isnull;
+-        int needQuote;
+-        char ch;
+-        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
+-        char *escarg = va_arg(ap,char*);
+-        isnull = escarg==0;
+-        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
+-        k = precision;
+-        for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
+-          if( ch==q )  n++;
+-        }
+-        needQuote = !isnull && xtype==etSQLESCAPE2;
+-        n += i + 1 + needQuote*2;
+-        if( n>etBUFSIZE ){
+-          bufpt = zExtra = sqlite3Malloc( n );
+-          if( bufpt==0 ){
+-            pAccum->mallocFailed = 1;
+-            return;
+-          }
+-        }else{
+-          bufpt = buf;
+-        }
+-        j = 0;
+-        if( needQuote ) bufpt[j++] = q;
+-        k = i;
+-        for(i=0; i<k; i++){
+-          bufpt[j++] = ch = escarg[i];
+-          if( ch==q ) bufpt[j++] = ch;
+-        }
+-        if( needQuote ) bufpt[j++] = q;
+-        bufpt[j] = 0;
+-        length = j;
+-        /* The precision in %q and %Q means how many input characters to
+-        ** consume, not the length of the output...
+-        ** if( precision>=0 && precision<length ) length = precision; */
+-        break;
+-      }
+-      case etTOKEN: {
+-        Token *pToken = va_arg(ap, Token*);
+-        if( pToken ){
+-          sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
+-        }
+-        length = width = 0;
+-        break;
+-      }
+-      case etSRCLIST: {
+-        SrcList *pSrc = va_arg(ap, SrcList*);
+-        int k = va_arg(ap, int);
+-        struct SrcList_item *pItem = &pSrc->a[k];
+-        assert( k>=0 && k<pSrc->nSrc );
+-        if( pItem->zDatabase ){
+-          sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
+-          sqlite3StrAccumAppend(pAccum, ".", 1);
+-        }
+-        sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
+-        length = width = 0;
+-        break;
+-      }
+-      default: {
+-        assert( xtype==etINVALID );
+-        return;
+-      }
+-    }/* End switch over the format type */
+-    /*
+-    ** The text of the conversion is pointed to by "bufpt" and is
+-    ** "length" characters long.  The field width is "width".  Do
+-    ** the output.
+-    */
+-    if( !flag_leftjustify ){
+-      register int nspace;
+-      nspace = width-length;
+-      if( nspace>0 ){
+-        sqlite3AppendSpace(pAccum, nspace);
+-      }
+-    }
+-    if( length>0 ){
+-      sqlite3StrAccumAppend(pAccum, bufpt, length);
+-    }
+-    if( flag_leftjustify ){
+-      register int nspace;
+-      nspace = width-length;
+-      if( nspace>0 ){
+-        sqlite3AppendSpace(pAccum, nspace);
+-      }
+-    }
+-    sqlite3_free(zExtra);
+-  }/* End for loop over the format string */
+-} /* End of function */
++    sqlite3_mutex_methods const *pFrom;
++    sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
+ 
+-/*
+-** Append N bytes of text from z to the StrAccum object.
+-*/
+-SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
+-  assert( z!=0 || N==0 );
+-  if( p->tooBig | p->mallocFailed ){
+-    testcase(p->tooBig);
+-    testcase(p->mallocFailed);
+-    return;
+-  }
+-  assert( p->zText!=0 || p->nChar==0 );
+-  if( N<0 ){
+-    N = sqlite3Strlen30(z);
+-  }
+-  if( N==0 || NEVER(z==0) ){
+-    return;
+-  }
+-  if( p->nChar+N >= p->nAlloc ){
+-    char *zNew;
+-    if( !p->useMalloc ){
+-      p->tooBig = 1;
+-      N = p->nAlloc - p->nChar - 1;
+-      if( N<=0 ){
+-        return;
+-      }
++    if( sqlite3GlobalConfig.bCoreMutex ){
++      pFrom = sqlite3DefaultMutex();
+     }else{
+-      char *zOld = (p->zText==p->zBase ? 0 : p->zText);
+-      i64 szNew = p->nChar;
+-      szNew += N + 1;
+-      if( szNew > p->mxAlloc ){
+-        sqlite3StrAccumReset(p);
+-        p->tooBig = 1;
+-        return;
+-      }else{
+-        p->nAlloc = (int)szNew;
+-      }
+-      if( p->useMalloc==1 ){
+-        zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
+-      }else{
+-        zNew = sqlite3_realloc(zOld, p->nAlloc);
+-      }
+-      if( zNew ){
+-        if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
+-        p->zText = zNew;
+-      }else{
+-        p->mallocFailed = 1;
+-        sqlite3StrAccumReset(p);
+-        return;
+-      }
++      pFrom = sqlite3NoopMutex();
+     }
++    memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
++    memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
++           sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
++    pTo->xMutexAlloc = pFrom->xMutexAlloc;
+   }
+-  assert( p->zText );
+-  memcpy(&p->zText[p->nChar], z, N);
+-  p->nChar += N;
++  rc = sqlite3GlobalConfig.mutex.xMutexInit();
++
++#ifdef SQLITE_DEBUG
++  GLOBAL(int, mutexIsInit) = 1;
++#endif
++
++  return rc;
+ }
+ 
+ /*
+-** Finish off a string by making sure it is zero-terminated.
+-** Return a pointer to the resulting string.  Return a NULL
+-** pointer if any kind of error was encountered.
++** Shutdown the mutex system. This call frees resources allocated by
++** sqlite3MutexInit().
+ */
+-SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
+-  if( p->zText ){
+-    p->zText[p->nChar] = 0;
+-    if( p->useMalloc && p->zText==p->zBase ){
+-      if( p->useMalloc==1 ){
+-        p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+-      }else{
+-        p->zText = sqlite3_malloc(p->nChar+1);
+-      }
+-      if( p->zText ){
+-        memcpy(p->zText, p->zBase, p->nChar+1);
+-      }else{
+-        p->mallocFailed = 1;
+-      }
+-    }
++SQLITE_PRIVATE int sqlite3MutexEnd(void){
++  int rc = SQLITE_OK;
++  if( sqlite3GlobalConfig.mutex.xMutexEnd ){
++    rc = sqlite3GlobalConfig.mutex.xMutexEnd();
+   }
+-  return p->zText;
++
++#ifdef SQLITE_DEBUG
++  GLOBAL(int, mutexIsInit) = 0;
++#endif
++
++  return rc;
+ }
+ 
+ /*
+-** Reset an StrAccum string.  Reclaim all malloced memory.
++** Retrieve a pointer to a static mutex or allocate a new dynamic one.
+ */
+-SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
+-  if( p->zText!=p->zBase ){
+-    if( p->useMalloc==1 ){
+-      sqlite3DbFree(p->db, p->zText);
+-    }else{
+-      sqlite3_free(p->zText);
+-    }
+-  }
+-  p->zText = 0;
++SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
++#ifndef SQLITE_OMIT_AUTOINIT
++  if( sqlite3_initialize() ) return 0;
++#endif
++  return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+ }
+ 
+-/*
+-** Initialize a string accumulator
+-*/
+-SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
+-  p->zText = p->zBase = zBase;
+-  p->db = 0;
+-  p->nChar = 0;
+-  p->nAlloc = n;
+-  p->mxAlloc = mx;
+-  p->useMalloc = 1;
+-  p->tooBig = 0;
+-  p->mallocFailed = 0;
++SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
++  if( !sqlite3GlobalConfig.bCoreMutex ){
++    return 0;
++  }
++  assert( GLOBAL(int, mutexIsInit) );
++  return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+ }
+ 
+ /*
+-** Print into memory obtained from sqliteMalloc().  Use the internal
+-** %-conversion extensions.
++** Free a dynamic mutex.
+ */
+-SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
+-  char *z;
+-  char zBase[SQLITE_PRINT_BUF_SIZE];
+-  StrAccum acc;
+-  assert( db!=0 );
+-  sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
+-                      db->aLimit[SQLITE_LIMIT_LENGTH]);
+-  acc.db = db;
+-  sqlite3VXPrintf(&acc, 1, zFormat, ap);
+-  z = sqlite3StrAccumFinish(&acc);
+-  if( acc.mallocFailed ){
+-    db->mallocFailed = 1;
++SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
++  if( p ){
++    sqlite3GlobalConfig.mutex.xMutexFree(p);
+   }
+-  return z;
+ }
+ 
+ /*
+-** Print into memory obtained from sqliteMalloc().  Use the internal
+-** %-conversion extensions.
++** Obtain the mutex p. If some other thread already has the mutex, block
++** until it can be obtained.
+ */
+-SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
+-  va_list ap;
+-  char *z;
+-  va_start(ap, zFormat);
+-  z = sqlite3VMPrintf(db, zFormat, ap);
+-  va_end(ap);
+-  return z;
++SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
++  if( p ){
++    sqlite3GlobalConfig.mutex.xMutexEnter(p);
++  }
+ }
+ 
+ /*
+-** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
+-** the string and before returnning.  This routine is intended to be used
+-** to modify an existing string.  For example:
+-**
+-**       x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
+-**
++** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
++** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
+ */
+-SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
+-  va_list ap;
+-  char *z;
+-  va_start(ap, zFormat);
+-  z = sqlite3VMPrintf(db, zFormat, ap);
+-  va_end(ap);
+-  sqlite3DbFree(db, zStr);
+-  return z;
++SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
++  int rc = SQLITE_OK;
++  if( p ){
++    return sqlite3GlobalConfig.mutex.xMutexTry(p);
++  }
++  return rc;
+ }
+ 
+ /*
+-** Print into memory obtained from sqlite3_malloc().  Omit the internal
+-** %-conversion extensions.
++** The sqlite3_mutex_leave() routine exits a mutex that was previously
++** entered by the same thread.  The behavior is undefined if the mutex 
++** is not currently entered. If a NULL pointer is passed as an argument
++** this function is a no-op.
+ */
+-SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
+-  char *z;
+-  char zBase[SQLITE_PRINT_BUF_SIZE];
+-  StrAccum acc;
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  if( sqlite3_initialize() ) return 0;
+-#endif
+-  sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
+-  acc.useMalloc = 2;
+-  sqlite3VXPrintf(&acc, 0, zFormat, ap);
+-  z = sqlite3StrAccumFinish(&acc);
+-  return z;
++SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
++  if( p ){
++    sqlite3GlobalConfig.mutex.xMutexLeave(p);
++  }
+ }
+ 
++#ifndef NDEBUG
+ /*
+-** Print into memory obtained from sqlite3_malloc()().  Omit the internal
+-** %-conversion extensions.
++** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
++** intended for use inside assert() statements.
+ */
+-SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
+-  va_list ap;
+-  char *z;
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  if( sqlite3_initialize() ) return 0;
+-#endif
+-  va_start(ap, zFormat);
+-  z = sqlite3_vmprintf(zFormat, ap);
+-  va_end(ap);
+-  return z;
++SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
++  return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
+ }
++SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
++  return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
++}
++#endif
+ 
++#endif /* !defined(SQLITE_MUTEX_OMIT) */
++
++/************** End of mutex.c ***********************************************/
++/************** Begin file mutex_noop.c **************************************/
+ /*
+-** sqlite3_snprintf() works like snprintf() except that it ignores the
+-** 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.
++** 2008 October 07
+ **
+-** 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.
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-** sqlite3_vsnprintf() is the varargs version.
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This file contains the C functions that implement mutexes.
++**
++** This implementation in this file does not provide any mutual
++** exclusion and is thus suitable for use only in applications
++** that use SQLite in a single thread.  The routines defined
++** here are place-holders.  Applications can substitute working
++** mutex routines at start-time using the
++**
++**     sqlite3_config(SQLITE_CONFIG_MUTEX,...)
++**
++** interface.
++**
++** If compiled with SQLITE_DEBUG, then additional logic is inserted
++** that does error checking on mutexes to make sure they are being
++** called correctly.
+ */
+-SQLITE_API 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);
+-}
+-SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
+-  char *z;
+-  va_list ap;
+-  va_start(ap,zFormat);
+-  z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
+-  va_end(ap);
+-  return z;
+-}
+ 
++#ifndef SQLITE_MUTEX_OMIT
++
++#ifndef SQLITE_DEBUG
+ /*
+-** This is the routine that actually formats the sqlite3_log() message.
+-** We house it in a separate routine from sqlite3_log() to avoid using
+-** stack space on small-stack systems when logging is disabled.
++** Stub routines for all mutex methods.
+ **
+-** sqlite3_log() must render into a static buffer.  It cannot dynamically
+-** allocate memory because it might be called while the memory allocator
+-** mutex is held.
++** This routines provide no mutual exclusion or error checking.
+ */
+-static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
+-  StrAccum acc;                          /* String accumulator */
+-  char zMsg[SQLITE_PRINT_BUF_SIZE*3];    /* Complete log message */
++static int noopMutexInit(void){ return SQLITE_OK; }
++static int noopMutexEnd(void){ return SQLITE_OK; }
++static sqlite3_mutex *noopMutexAlloc(int id){ 
++  UNUSED_PARAMETER(id);
++  return (sqlite3_mutex*)8; 
++}
++static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
++static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
++static int noopMutexTry(sqlite3_mutex *p){
++  UNUSED_PARAMETER(p);
++  return SQLITE_OK;
++}
++static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
+ 
+-  sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
+-  acc.useMalloc = 0;
+-  sqlite3VXPrintf(&acc, 0, zFormat, ap);
+-  sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
+-                           sqlite3StrAccumFinish(&acc));
++SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
++  static const sqlite3_mutex_methods sMutex = {
++    noopMutexInit,
++    noopMutexEnd,
++    noopMutexAlloc,
++    noopMutexFree,
++    noopMutexEnter,
++    noopMutexTry,
++    noopMutexLeave,
++
++    0,
++    0,
++  };
++
++  return &sMutex;
+ }
++#endif /* !SQLITE_DEBUG */
+ 
++#ifdef SQLITE_DEBUG
+ /*
+-** Format and write a message to the log if logging is enabled.
++** In this implementation, error checking is provided for testing
++** and debugging purposes.  The mutexes still do not provide any
++** mutual exclusion.
+ */
+-SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
+-  va_list ap;                             /* Vararg list */
+-  if( sqlite3GlobalConfig.xLog ){
+-    va_start(ap, zFormat);
+-    renderLogMsg(iErrCode, zFormat, ap);
+-    va_end(ap);
+-  }
+-}
+ 
+-#if defined(SQLITE_DEBUG)
+ /*
+-** A version of printf() that understands %lld.  Used for debugging.
+-** The printf() built into some versions of windows does not understand %lld
+-** and segfaults if you give it a long long int.
++** The mutex object
+ */
+-SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
+-  va_list ap;
+-  StrAccum acc;
+-  char zBuf[500];
+-  sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
+-  acc.useMalloc = 0;
+-  va_start(ap,zFormat);
+-  sqlite3VXPrintf(&acc, 0, zFormat, ap);
+-  va_end(ap);
+-  sqlite3StrAccumFinish(&acc);
+-  fprintf(stdout,"%s", zBuf);
+-  fflush(stdout);
+-}
+-#endif
++typedef struct sqlite3_debug_mutex {
++  int id;     /* The mutex type */
++  int cnt;    /* Number of entries without a matching leave */
++} sqlite3_debug_mutex;
+ 
+-#ifndef SQLITE_OMIT_TRACE
+ /*
+-** variable-argument wrapper around sqlite3VXPrintf().
++** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
++** intended for use inside assert() statements.
+ */
+-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
+-  va_list ap;
+-  va_start(ap,zFormat);
+-  sqlite3VXPrintf(p, 1, zFormat, ap);
+-  va_end(ap);
++static int debugMutexHeld(sqlite3_mutex *pX){
++  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
++  return p==0 || p->cnt>0;
++}
++static int debugMutexNotheld(sqlite3_mutex *pX){
++  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
++  return p==0 || p->cnt==0;
+ }
+-#endif
+ 
+-/************** End of printf.c **********************************************/
+-/************** Begin file random.c ******************************************/
+ /*
+-** 2001 September 15
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-** This file contains code to implement a pseudo-random number
+-** generator (PRNG) for SQLite.
+-**
+-** Random numbers are used by some of the database backends in order
+-** to generate random integer keys for tables or random filenames.
+-*/
+-
+-
+-/* All threads share a single random number generator.
+-** This structure is the current state of the generator.
++** Initialize and deinitialize the mutex subsystem.
+ */
+-static SQLITE_WSD struct sqlite3PrngType {
+-  unsigned char isInit;          /* True if initialized */
+-  unsigned char i, j;            /* State variables */
+-  unsigned char s[256];          /* State variables */
+-} sqlite3Prng;
++static int debugMutexInit(void){ return SQLITE_OK; }
++static int debugMutexEnd(void){ return SQLITE_OK; }
+ 
+ /*
+-** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
+-** must be held while executing this routine.
+-**
+-** Why not just use a library random generator like lrand48() for this?
+-** Because the OP_NewRowid opcode in the VDBE depends on having a very
+-** good source of random numbers.  The lrand48() library function may
+-** well be good enough.  But maybe not.  Or maybe lrand48() has some
+-** subtle problems on some systems that could cause problems.  It is hard
+-** to know.  To minimize the risk of problems due to bad lrand48()
+-** implementations, SQLite uses this random number generator based
+-** on RC4, which we know works very well.
+-**
+-** (Later):  Actually, OP_NewRowid does not depend on a good source of
+-** randomness any more.  But we will leave this code in all the same.
++** The sqlite3_mutex_alloc() routine allocates a new
++** mutex and returns a pointer to it.  If it returns NULL
++** that means that a mutex could not be allocated. 
+ */
+-static u8 randomByte(void){
+-  unsigned char t;
+-
+-
+-  /* The "wsdPrng" macro will resolve to the pseudo-random number generator
+-  ** state vector.  If writable static data is unsupported on the target,
+-  ** we have to locate the state vector at run-time.  In the more common
+-  ** case where writable static data is supported, wsdPrng can refer directly
+-  ** to the "sqlite3Prng" state vector declared above.
+-  */
+-#ifdef SQLITE_OMIT_WSD
+-  struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
+-# define wsdPrng p[0]
+-#else
+-# define wsdPrng sqlite3Prng
+-#endif
+-
+-
+-  /* Initialize the state of the random number generator once,
+-  ** the first time this routine is called.  The seed value does
+-  ** not need to contain a lot of randomness since we are not
+-  ** trying to do secure encryption or anything like that...
+-  **
+-  ** Nothing in this file or anywhere else in SQLite does any kind of
+-  ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
+-  ** number generator) not as an encryption device.
+-  */
+-  if( !wsdPrng.isInit ){
+-    int i;
+-    char k[256];
+-    wsdPrng.j = 0;
+-    wsdPrng.i = 0;
+-    sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
+-    for(i=0; i<256; i++){
+-      wsdPrng.s[i] = (u8)i;
++static sqlite3_mutex *debugMutexAlloc(int id){
++  static sqlite3_debug_mutex aStatic[6];
++  sqlite3_debug_mutex *pNew = 0;
++  switch( id ){
++    case SQLITE_MUTEX_FAST:
++    case SQLITE_MUTEX_RECURSIVE: {
++      pNew = sqlite3Malloc(sizeof(*pNew));
++      if( pNew ){
++        pNew->id = id;
++        pNew->cnt = 0;
++      }
++      break;
+     }
+-    for(i=0; i<256; i++){
+-      wsdPrng.j += wsdPrng.s[i] + k[i];
+-      t = wsdPrng.s[wsdPrng.j];
+-      wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
+-      wsdPrng.s[i] = t;
++    default: {
++      assert( id-2 >= 0 );
++      assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
++      pNew = &aStatic[id-2];
++      pNew->id = id;
++      break;
+     }
+-    wsdPrng.isInit = 1;
+   }
++  return (sqlite3_mutex*)pNew;
++}
+ 
+-  /* Generate and return single random byte
+-  */
+-  wsdPrng.i++;
+-  t = wsdPrng.s[wsdPrng.i];
+-  wsdPrng.j += t;
+-  wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+-  wsdPrng.s[wsdPrng.j] = t;
+-  t += wsdPrng.s[wsdPrng.i];
+-  return wsdPrng.s[t];
++/*
++** This routine deallocates a previously allocated mutex.
++*/
++static void debugMutexFree(sqlite3_mutex *pX){
++  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
++  assert( p->cnt==0 );
++  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
++  sqlite3_free(p);
+ }
+ 
+ /*
+-** Return N random bytes.
++** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
++** to enter a mutex.  If another thread is already within the mutex,
++** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
++** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
++** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
++** be entered multiple times by the same thread.  In such cases the,
++** mutex must be exited an equal number of times before another thread
++** can enter.  If the same thread tries to enter any other kind of mutex
++** more than once, the behavior is undefined.
+ */
+-SQLITE_API void sqlite3_randomness(int N, void *pBuf){
+-  unsigned char *zBuf = pBuf;
+-#if SQLITE_THREADSAFE
+-  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
+-#endif
+-  sqlite3_mutex_enter(mutex);
+-  while( N-- ){
+-    *(zBuf++) = randomByte();
+-  }
+-  sqlite3_mutex_leave(mutex);
++static void debugMutexEnter(sqlite3_mutex *pX){
++  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
++  p->cnt++;
++}
++static int debugMutexTry(sqlite3_mutex *pX){
++  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
++  p->cnt++;
++  return SQLITE_OK;
+ }
+ 
+-#ifndef SQLITE_OMIT_BUILTIN_TEST
+ /*
+-** For testing purposes, we sometimes want to preserve the state of
+-** PRNG and restore the PRNG to its saved state at a later time, or
+-** to reset the PRNG to its initial state.  These routines accomplish
+-** those tasks.
+-**
+-** The sqlite3_test_control() interface calls these routines to
+-** control the PRNG.
++** The sqlite3_mutex_leave() routine exits a mutex that was
++** previously entered by the same thread.  The behavior
++** is undefined if the mutex is not currently entered or
++** is not currently allocated.  SQLite will never do either.
+ */
+-static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
+-SQLITE_PRIVATE void sqlite3PrngSaveState(void){
+-  memcpy(
+-    &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+-    &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+-    sizeof(sqlite3Prng)
+-  );
++static void debugMutexLeave(sqlite3_mutex *pX){
++  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
++  assert( debugMutexHeld(pX) );
++  p->cnt--;
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+ }
+-SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
+-  memcpy(
+-    &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+-    &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+-    sizeof(sqlite3Prng)
+-  );
++
++SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
++  static const sqlite3_mutex_methods sMutex = {
++    debugMutexInit,
++    debugMutexEnd,
++    debugMutexAlloc,
++    debugMutexFree,
++    debugMutexEnter,
++    debugMutexTry,
++    debugMutexLeave,
++
++    debugMutexHeld,
++    debugMutexNotheld
++  };
++
++  return &sMutex;
+ }
+-SQLITE_PRIVATE void sqlite3PrngResetState(void){
+-  GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
++#endif /* SQLITE_DEBUG */
++
++/*
++** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
++** is used regardless of the run-time threadsafety setting.
++*/
++#ifdef SQLITE_MUTEX_NOOP
++SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
++  return sqlite3NoopMutex();
+ }
+-#endif /* SQLITE_OMIT_BUILTIN_TEST */
++#endif /* defined(SQLITE_MUTEX_NOOP) */
++#endif /* !defined(SQLITE_MUTEX_OMIT) */
+ 
+-/************** End of random.c **********************************************/
+-/************** Begin file utf.c *********************************************/
++/************** End of mutex_noop.c ******************************************/
++/************** Begin file mutex_unix.c **************************************/
+ /*
+-** 2004 April 13
++** 2007 August 28
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -20682,2498 +21047,2601 @@
+ **    May you share freely, never taking more than you give.
+ **
+ *************************************************************************
+-** This file contains routines used to translate between UTF-8, 
+-** UTF-16, UTF-16BE, and UTF-16LE.
+-**
+-** Notes on UTF-8:
+-**
+-**   Byte-0    Byte-1    Byte-2    Byte-3    Value
+-**  0xxxxxxx                                 00000000 00000000 0xxxxxxx
+-**  110yyyyy  10xxxxxx                       00000000 00000yyy yyxxxxxx
+-**  1110zzzz  10yyyyyy  10xxxxxx             00000000 zzzzyyyy yyxxxxxx
+-**  11110uuu  10uuzzzz  10yyyyyy  10xxxxxx   000uuuuu zzzzyyyy yyxxxxxx
+-**
+-**
+-** Notes on UTF-16:  (with wwww+1==uuuuu)
+-**
+-**      Word-0               Word-1          Value
+-**  110110ww wwzzzzyy   110111yy yyxxxxxx    000uuuuu zzzzyyyy yyxxxxxx
+-**  zzzzyyyy yyxxxxxx                        00000000 zzzzyyyy yyxxxxxx
+-**
+-**
+-** BOM or Byte Order Mark:
+-**     0xff 0xfe   little-endian utf-16 follows
+-**     0xfe 0xff   big-endian utf-16 follows
++** This file contains the C functions that implement mutexes for pthreads
++*/
++
++/*
++** The code in this file is only used if we are compiling threadsafe
++** under unix with pthreads.
+ **
++** Note that this implementation requires a version of pthreads that
++** supports recursive mutexes.
+ */
+-/* #include <assert.h> */
++#ifdef SQLITE_MUTEX_PTHREADS
++
++#include <pthread.h>
+ 
+-#ifndef SQLITE_AMALGAMATION
+ /*
+-** The following constant value is used by the SQLITE_BIGENDIAN and
+-** SQLITE_LITTLEENDIAN macros.
++** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
++** are necessary under two condidtions:  (1) Debug builds and (2) using
++** home-grown mutexes.  Encapsulate these conditions into a single #define.
+ */
+-SQLITE_PRIVATE const int sqlite3one = 1;
+-#endif /* SQLITE_AMALGAMATION */
++#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
++# define SQLITE_MUTEX_NREF 1
++#else
++# define SQLITE_MUTEX_NREF 0
++#endif
+ 
+ /*
+-** This lookup table is used to help decode the first byte of
+-** a multi-byte UTF8 character.
++** Each recursive mutex is an instance of the following structure.
+ */
+-static const unsigned char sqlite3Utf8Trans1[] = {
+-  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-  0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
++struct sqlite3_mutex {
++  pthread_mutex_t mutex;     /* Mutex controlling the lock */
++#if SQLITE_MUTEX_NREF
++  int id;                    /* Mutex type */
++  volatile int nRef;         /* Number of entrances */
++  volatile pthread_t owner;  /* Thread that is within this mutex */
++  int trace;                 /* True to trace changes */
++#endif
+ };
++#if SQLITE_MUTEX_NREF
++#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
++#else
++#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
++#endif
+ 
+-
+-#define WRITE_UTF8(zOut, c) {                          \
+-  if( c<0x00080 ){                                     \
+-    *zOut++ = (u8)(c&0xFF);                            \
+-  }                                                    \
+-  else if( c<0x00800 ){                                \
+-    *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);                \
+-    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
+-  }                                                    \
+-  else if( c<0x10000 ){                                \
+-    *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);               \
+-    *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);              \
+-    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
+-  }else{                                               \
+-    *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);             \
+-    *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);             \
+-    *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);              \
+-    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
+-  }                                                    \
+-}
+-
+-#define WRITE_UTF16LE(zOut, c) {                                    \
+-  if( c<=0xFFFF ){                                                  \
+-    *zOut++ = (u8)(c&0x00FF);                                       \
+-    *zOut++ = (u8)((c>>8)&0x00FF);                                  \
+-  }else{                                                            \
+-    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
+-    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
+-    *zOut++ = (u8)(c&0x00FF);                                       \
+-    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
+-  }                                                                 \
++/*
++** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
++** intended for use only inside assert() statements.  On some platforms,
++** there might be race conditions that can cause these routines to
++** deliver incorrect results.  In particular, if pthread_equal() is
++** not an atomic operation, then these routines might delivery
++** incorrect results.  On most platforms, pthread_equal() is a 
++** comparison of two integers and is therefore atomic.  But we are
++** told that HPUX is not such a platform.  If so, then these routines
++** will not always work correctly on HPUX.
++**
++** On those platforms where pthread_equal() is not atomic, SQLite
++** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
++** make sure no assert() statements are evaluated and hence these
++** routines are never called.
++*/
++#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
++static int pthreadMutexHeld(sqlite3_mutex *p){
++  return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
+ }
+-
+-#define WRITE_UTF16BE(zOut, c) {                                    \
+-  if( c<=0xFFFF ){                                                  \
+-    *zOut++ = (u8)((c>>8)&0x00FF);                                  \
+-    *zOut++ = (u8)(c&0x00FF);                                       \
+-  }else{                                                            \
+-    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
+-    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
+-    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
+-    *zOut++ = (u8)(c&0x00FF);                                       \
+-  }                                                                 \
++static int pthreadMutexNotheld(sqlite3_mutex *p){
++  return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
+ }
++#endif
+ 
+-#define READ_UTF16LE(zIn, TERM, c){                                   \
+-  c = (*zIn++);                                                       \
+-  c += ((*zIn++)<<8);                                                 \
+-  if( c>=0xD800 && c<0xE000 && TERM ){                                \
+-    int c2 = (*zIn++);                                                \
+-    c2 += ((*zIn++)<<8);                                              \
+-    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
+-  }                                                                   \
+-}
+-
+-#define READ_UTF16BE(zIn, TERM, c){                                   \
+-  c = ((*zIn++)<<8);                                                  \
+-  c += (*zIn++);                                                      \
+-  if( c>=0xD800 && c<0xE000 && TERM ){                                \
+-    int c2 = ((*zIn++)<<8);                                           \
+-    c2 += (*zIn++);                                                   \
+-    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
+-  }                                                                   \
+-}
++/*
++** Initialize and deinitialize the mutex subsystem.
++*/
++static int pthreadMutexInit(void){ return SQLITE_OK; }
++static int pthreadMutexEnd(void){ return SQLITE_OK; }
+ 
+ /*
+-** Translate a single UTF-8 character.  Return the unicode value.
+-**
+-** During translation, assume that the byte that zTerm points
+-** is a 0x00.
+-**
+-** Write a pointer to the next unread byte back into *pzNext.
+-**
+-** Notes On Invalid UTF-8:
++** The sqlite3_mutex_alloc() routine allocates a new
++** mutex and returns a pointer to it.  If it returns NULL
++** that means that a mutex could not be allocated.  SQLite
++** will unwind its stack and return an error.  The argument
++** to sqlite3_mutex_alloc() is one of these integer constants:
+ **
+-**  *  This routine never allows a 7-bit character (0x00 through 0x7f) to
+-**     be encoded as a multi-byte character.  Any multi-byte character that
+-**     attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
++** <ul>
++** <li>  SQLITE_MUTEX_FAST
++** <li>  SQLITE_MUTEX_RECURSIVE
++** <li>  SQLITE_MUTEX_STATIC_MASTER
++** <li>  SQLITE_MUTEX_STATIC_MEM
++** <li>  SQLITE_MUTEX_STATIC_MEM2
++** <li>  SQLITE_MUTEX_STATIC_PRNG
++** <li>  SQLITE_MUTEX_STATIC_LRU
++** <li>  SQLITE_MUTEX_STATIC_PMEM
++** </ul>
+ **
+-**  *  This routine never allows a UTF16 surrogate value to be encoded.
+-**     If a multi-byte character attempts to encode a value between
+-**     0xd800 and 0xe000 then it is rendered as 0xfffd.
++** The first two constants cause sqlite3_mutex_alloc() to create
++** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
++** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
++** The mutex implementation does not need to make a distinction
++** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
++** not want to.  But SQLite will only request a recursive mutex in
++** cases where it really needs one.  If a faster non-recursive mutex
++** implementation is available on the host platform, the mutex subsystem
++** might return such a mutex in response to SQLITE_MUTEX_FAST.
+ **
+-**  *  Bytes in the range of 0x80 through 0xbf which occur as the first
+-**     byte of a character are interpreted as single-byte characters
+-**     and rendered as themselves even though they are technically
+-**     invalid characters.
++** The other allowed parameters to sqlite3_mutex_alloc() each return
++** a pointer to a static preexisting mutex.  Six static mutexes are
++** used by the current version of SQLite.  Future versions of SQLite
++** may add additional static mutexes.  Static mutexes are for internal
++** use by SQLite only.  Applications that use SQLite mutexes should
++** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
++** SQLITE_MUTEX_RECURSIVE.
+ **
+-**  *  This routine accepts an infinite number of different UTF8 encodings
+-**     for unicode values 0x80 and greater.  It do not change over-length
+-**     encodings to 0xfffd as some systems recommend.
++** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
++** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
++** returns a different mutex on every call.  But for the static 
++** mutex types, the same mutex is returned on every call that has
++** the same type number.
+ */
+-#define READ_UTF8(zIn, zTerm, c)                           \
+-  c = *(zIn++);                                            \
+-  if( c>=0xc0 ){                                           \
+-    c = sqlite3Utf8Trans1[c-0xc0];                         \
+-    while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
+-      c = (c<<6) + (0x3f & *(zIn++));                      \
+-    }                                                      \
+-    if( c<0x80                                             \
+-        || (c&0xFFFFF800)==0xD800                          \
+-        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
+-  }
+-SQLITE_PRIVATE u32 sqlite3Utf8Read(
+-  const unsigned char **pz    /* Pointer to string from which to read char */
+-){
+-  unsigned int c;
+-
+-  /* Same as READ_UTF8() above but without the zTerm parameter.
+-  ** For this routine, we assume the UTF8 string is always zero-terminated.
+-  */
+-  c = *((*pz)++);
+-  if( c>=0xc0 ){
+-    c = sqlite3Utf8Trans1[c-0xc0];
+-    while( (*(*pz) & 0xc0)==0x80 ){
+-      c = (c<<6) + (0x3f & *((*pz)++));
++static sqlite3_mutex *pthreadMutexAlloc(int iType){
++  static sqlite3_mutex staticMutexes[] = {
++    SQLITE3_MUTEX_INITIALIZER,
++    SQLITE3_MUTEX_INITIALIZER,
++    SQLITE3_MUTEX_INITIALIZER,
++    SQLITE3_MUTEX_INITIALIZER,
++    SQLITE3_MUTEX_INITIALIZER,
++    SQLITE3_MUTEX_INITIALIZER
++  };
++  sqlite3_mutex *p;
++  switch( iType ){
++    case SQLITE_MUTEX_RECURSIVE: {
++      p = sqlite3MallocZero( sizeof(*p) );
++      if( p ){
++#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
++        /* If recursive mutexes are not available, we will have to
++        ** build our own.  See below. */
++        pthread_mutex_init(&p->mutex, 0);
++#else
++        /* Use a recursive mutex if it is available */
++        pthread_mutexattr_t recursiveAttr;
++        pthread_mutexattr_init(&recursiveAttr);
++        pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
++        pthread_mutex_init(&p->mutex, &recursiveAttr);
++        pthread_mutexattr_destroy(&recursiveAttr);
++#endif
++#if SQLITE_MUTEX_NREF
++        p->id = iType;
++#endif
++      }
++      break;
++    }
++    case SQLITE_MUTEX_FAST: {
++      p = sqlite3MallocZero( sizeof(*p) );
++      if( p ){
++#if SQLITE_MUTEX_NREF
++        p->id = iType;
++#endif
++        pthread_mutex_init(&p->mutex, 0);
++      }
++      break;
++    }
++    default: {
++      assert( iType-2 >= 0 );
++      assert( iType-2 < ArraySize(staticMutexes) );
++      p = &staticMutexes[iType-2];
++#if SQLITE_MUTEX_NREF
++      p->id = iType;
++#endif
++      break;
+     }
+-    if( c<0x80
+-        || (c&0xFFFFF800)==0xD800
+-        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
+   }
+-  return c;
++  return p;
+ }
+ 
+ 
+-
+-
+ /*
+-** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
+-** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
+-*/ 
+-/* #define TRANSLATE_TRACE 1 */
++** This routine deallocates a previously
++** allocated mutex.  SQLite is careful to deallocate every
++** mutex that it allocates.
++*/
++static void pthreadMutexFree(sqlite3_mutex *p){
++  assert( p->nRef==0 );
++  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
++  pthread_mutex_destroy(&p->mutex);
++  sqlite3_free(p);
++}
+ 
+-#ifndef SQLITE_OMIT_UTF16
+ /*
+-** This routine transforms the internal text encoding used by pMem to
+-** desiredEnc. It is an error if the string is already of the desired
+-** encoding, or if *pMem does not contain a string value.
++** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
++** to enter a mutex.  If another thread is already within the mutex,
++** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
++** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
++** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
++** be entered multiple times by the same thread.  In such cases the,
++** mutex must be exited an equal number of times before another thread
++** can enter.  If the same thread tries to enter any other kind of mutex
++** more than once, the behavior is undefined.
+ */
+-SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
+-  int len;                    /* Maximum length of output string in bytes */
+-  unsigned char *zOut;                  /* Output buffer */
+-  unsigned char *zIn;                   /* Input iterator */
+-  unsigned char *zTerm;                 /* End of input */
+-  unsigned char *z;                     /* Output iterator */
+-  unsigned int c;
+-
+-  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+-  assert( pMem->flags&MEM_Str );
+-  assert( pMem->enc!=desiredEnc );
+-  assert( pMem->enc!=0 );
+-  assert( pMem->n>=0 );
+-
+-#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
+-  {
+-    char zBuf[100];
+-    sqlite3VdbeMemPrettyPrint(pMem, zBuf);
+-    fprintf(stderr, "INPUT:  %s\n", zBuf);
+-  }
+-#endif
++static void pthreadMutexEnter(sqlite3_mutex *p){
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
+ 
+-  /* If the translation is between UTF-16 little and big endian, then 
+-  ** all that is required is to swap the byte order. This case is handled
+-  ** differently from the others.
++#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
++  /* If recursive mutexes are not available, then we have to grow
++  ** our own.  This implementation assumes that pthread_equal()
++  ** is atomic - that it cannot be deceived into thinking self
++  ** and p->owner are equal if p->owner changes between two values
++  ** that are not equal to self while the comparison is taking place.
++  ** This implementation also assumes a coherent cache - that 
++  ** separate processes cannot read different values from the same
++  ** address at the same time.  If either of these two conditions
++  ** are not met, then the mutexes will fail and problems will result.
+   */
+-  if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
+-    u8 temp;
+-    int rc;
+-    rc = sqlite3VdbeMemMakeWriteable(pMem);
+-    if( rc!=SQLITE_OK ){
+-      assert( rc==SQLITE_NOMEM );
+-      return SQLITE_NOMEM;
+-    }
+-    zIn = (u8*)pMem->z;
+-    zTerm = &zIn[pMem->n&~1];
+-    while( zIn<zTerm ){
+-      temp = *zIn;
+-      *zIn = *(zIn+1);
+-      zIn++;
+-      *zIn++ = temp;
++  {
++    pthread_t self = pthread_self();
++    if( p->nRef>0 && pthread_equal(p->owner, self) ){
++      p->nRef++;
++    }else{
++      pthread_mutex_lock(&p->mutex);
++      assert( p->nRef==0 );
++      p->owner = self;
++      p->nRef = 1;
+     }
+-    pMem->enc = desiredEnc;
+-    goto translate_out;
+   }
++#else
++  /* Use the built-in recursive mutexes if they are available.
++  */
++  pthread_mutex_lock(&p->mutex);
++#if SQLITE_MUTEX_NREF
++  assert( p->nRef>0 || p->owner==0 );
++  p->owner = pthread_self();
++  p->nRef++;
++#endif
++#endif
+ 
+-  /* Set len to the maximum number of bytes required in the output buffer. */
+-  if( desiredEnc==SQLITE_UTF8 ){
+-    /* When converting from UTF-16, the maximum growth results from
+-    ** translating a 2-byte character to a 4-byte UTF-8 character.
+-    ** A single byte is required for the output string
+-    ** nul-terminator.
+-    */
+-    pMem->n &= ~1;
+-    len = pMem->n * 2 + 1;
+-  }else{
+-    /* When converting from UTF-8 to UTF-16 the maximum growth is caused
+-    ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
+-    ** character. Two bytes are required in the output buffer for the
+-    ** nul-terminator.
+-    */
+-    len = pMem->n * 2 + 2;
++#ifdef SQLITE_DEBUG
++  if( p->trace ){
++    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+   }
++#endif
++}
++static int pthreadMutexTry(sqlite3_mutex *p){
++  int rc;
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
+ 
+-  /* Set zIn to point at the start of the input buffer and zTerm to point 1
+-  ** byte past the end.
+-  **
+-  ** Variable zOut is set to point at the output buffer, space obtained
+-  ** from sqlite3_malloc().
++#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
++  /* If recursive mutexes are not available, then we have to grow
++  ** our own.  This implementation assumes that pthread_equal()
++  ** is atomic - that it cannot be deceived into thinking self
++  ** and p->owner are equal if p->owner changes between two values
++  ** that are not equal to self while the comparison is taking place.
++  ** This implementation also assumes a coherent cache - that 
++  ** separate processes cannot read different values from the same
++  ** address at the same time.  If either of these two conditions
++  ** are not met, then the mutexes will fail and problems will result.
+   */
+-  zIn = (u8*)pMem->z;
+-  zTerm = &zIn[pMem->n];
+-  zOut = sqlite3DbMallocRaw(pMem->db, len);
+-  if( !zOut ){
+-    return SQLITE_NOMEM;
+-  }
+-  z = zOut;
+-
+-  if( pMem->enc==SQLITE_UTF8 ){
+-    if( desiredEnc==SQLITE_UTF16LE ){
+-      /* UTF-8 -> UTF-16 Little-endian */
+-      while( zIn<zTerm ){
+-        READ_UTF8(zIn, zTerm, c);
+-        WRITE_UTF16LE(z, c);
+-      }
++  {
++    pthread_t self = pthread_self();
++    if( p->nRef>0 && pthread_equal(p->owner, self) ){
++      p->nRef++;
++      rc = SQLITE_OK;
++    }else if( pthread_mutex_trylock(&p->mutex)==0 ){
++      assert( p->nRef==0 );
++      p->owner = self;
++      p->nRef = 1;
++      rc = SQLITE_OK;
+     }else{
+-      assert( desiredEnc==SQLITE_UTF16BE );
+-      /* UTF-8 -> UTF-16 Big-endian */
+-      while( zIn<zTerm ){
+-        READ_UTF8(zIn, zTerm, c);
+-        WRITE_UTF16BE(z, c);
+-      }
++      rc = SQLITE_BUSY;
+     }
+-    pMem->n = (int)(z - zOut);
+-    *z++ = 0;
++  }
++#else
++  /* Use the built-in recursive mutexes if they are available.
++  */
++  if( pthread_mutex_trylock(&p->mutex)==0 ){
++#if SQLITE_MUTEX_NREF
++    p->owner = pthread_self();
++    p->nRef++;
++#endif
++    rc = SQLITE_OK;
+   }else{
+-    assert( desiredEnc==SQLITE_UTF8 );
+-    if( pMem->enc==SQLITE_UTF16LE ){
+-      /* UTF-16 Little-endian -> UTF-8 */
+-      while( zIn<zTerm ){
+-        READ_UTF16LE(zIn, zIn<zTerm, c); 
+-        WRITE_UTF8(z, c);
+-      }
+-    }else{
+-      /* UTF-16 Big-endian -> UTF-8 */
+-      while( zIn<zTerm ){
+-        READ_UTF16BE(zIn, zIn<zTerm, c); 
+-        WRITE_UTF8(z, c);
+-      }
+-    }
+-    pMem->n = (int)(z - zOut);
++    rc = SQLITE_BUSY;
+   }
+-  *z = 0;
+-  assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
+-
+-  sqlite3VdbeMemRelease(pMem);
+-  pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
+-  pMem->enc = desiredEnc;
+-  pMem->flags |= (MEM_Term|MEM_Dyn);
+-  pMem->z = (char*)zOut;
+-  pMem->zMalloc = pMem->z;
++#endif
+ 
+-translate_out:
+-#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
+-  {
+-    char zBuf[100];
+-    sqlite3VdbeMemPrettyPrint(pMem, zBuf);
+-    fprintf(stderr, "OUTPUT: %s\n", zBuf);
++#ifdef SQLITE_DEBUG
++  if( rc==SQLITE_OK && p->trace ){
++    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+   }
+ #endif
+-  return SQLITE_OK;
++  return rc;
+ }
+ 
+ /*
+-** This routine checks for a byte-order mark at the beginning of the 
+-** UTF-16 string stored in *pMem. If one is present, it is removed and
+-** the encoding of the Mem adjusted. This routine does not do any
+-** byte-swapping, it just sets Mem.enc appropriately.
+-**
+-** The allocation (static, dynamic etc.) and encoding of the Mem may be
+-** changed by this function.
++** The sqlite3_mutex_leave() routine exits a mutex that was
++** previously entered by the same thread.  The behavior
++** is undefined if the mutex is not currently entered or
++** is not currently allocated.  SQLite will never do either.
+ */
+-SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
+-  int rc = SQLITE_OK;
+-  u8 bom = 0;
++static void pthreadMutexLeave(sqlite3_mutex *p){
++  assert( pthreadMutexHeld(p) );
++#if SQLITE_MUTEX_NREF
++  p->nRef--;
++  if( p->nRef==0 ) p->owner = 0;
++#endif
++  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
+ 
+-  assert( pMem->n>=0 );
+-  if( pMem->n>1 ){
+-    u8 b1 = *(u8 *)pMem->z;
+-    u8 b2 = *(((u8 *)pMem->z) + 1);
+-    if( b1==0xFE && b2==0xFF ){
+-      bom = SQLITE_UTF16BE;
+-    }
+-    if( b1==0xFF && b2==0xFE ){
+-      bom = SQLITE_UTF16LE;
+-    }
++#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
++  if( p->nRef==0 ){
++    pthread_mutex_unlock(&p->mutex);
+   }
+-  
+-  if( bom ){
+-    rc = sqlite3VdbeMemMakeWriteable(pMem);
+-    if( rc==SQLITE_OK ){
+-      pMem->n -= 2;
+-      memmove(pMem->z, &pMem->z[2], pMem->n);
+-      pMem->z[pMem->n] = '\0';
+-      pMem->z[pMem->n+1] = '\0';
+-      pMem->flags |= MEM_Term;
+-      pMem->enc = bom;
+-    }
++#else
++  pthread_mutex_unlock(&p->mutex);
++#endif
++
++#ifdef SQLITE_DEBUG
++  if( p->trace ){
++    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+   }
+-  return rc;
++#endif
+ }
+-#endif /* SQLITE_OMIT_UTF16 */
+ 
+-/*
+-** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
+-** return the number of unicode characters in pZ up to (but not including)
+-** the first 0x00 byte. If nByte is not less than zero, return the
+-** number of unicode characters in the first nByte of pZ (or up to 
+-** the first 0x00, whichever comes first).
+-*/
+-SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
+-  int r = 0;
+-  const u8 *z = (const u8*)zIn;
+-  const u8 *zTerm;
+-  if( nByte>=0 ){
+-    zTerm = &z[nByte];
+-  }else{
+-    zTerm = (const u8*)(-1);
+-  }
+-  assert( z<=zTerm );
+-  while( *z!=0 && z<zTerm ){
+-    SQLITE_SKIP_UTF8(z);
+-    r++;
+-  }
+-  return r;
++SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
++  static const sqlite3_mutex_methods sMutex = {
++    pthreadMutexInit,
++    pthreadMutexEnd,
++    pthreadMutexAlloc,
++    pthreadMutexFree,
++    pthreadMutexEnter,
++    pthreadMutexTry,
++    pthreadMutexLeave,
++#ifdef SQLITE_DEBUG
++    pthreadMutexHeld,
++    pthreadMutexNotheld
++#else
++    0,
++    0
++#endif
++  };
++
++  return &sMutex;
+ }
+ 
+-/* This test function is not currently used by the automated test-suite. 
+-** Hence it is only available in debug builds.
+-*/
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
++#endif /* SQLITE_MUTEX_PTHREADS */
++
++/************** End of mutex_unix.c ******************************************/
++/************** Begin file mutex_w32.c ***************************************/
+ /*
+-** Translate UTF-8 to UTF-8.
++** 2007 August 14
+ **
+-** This has the effect of making sure that the string is well-formed
+-** UTF-8.  Miscoded characters are removed.
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-** The translation is done in-place and aborted if the output
+-** overruns the input.
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This file contains the C functions that implement mutexes for win32
+ */
+-SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
+-  unsigned char *zOut = zIn;
+-  unsigned char *zStart = zIn;
+-  u32 c;
+-
+-  while( zIn[0] && zOut<=zIn ){
+-    c = sqlite3Utf8Read((const u8**)&zIn);
+-    if( c!=0xfffd ){
+-      WRITE_UTF8(zOut, c);
+-    }
+-  }
+-  *zOut = 0;
+-  return (int)(zOut - zStart);
+-}
+-#endif
+ 
+-#ifndef SQLITE_OMIT_UTF16
+ /*
+-** Convert a UTF-16 string in the native encoding into a UTF-8 string.
+-** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
+-** be freed by the calling function.
++** The code in this file is only used if we are compiling multithreaded
++** on a win32 system.
++*/
++#ifdef SQLITE_MUTEX_W32
++
++/*
++** Each recursive mutex is an instance of the following structure.
++*/
++struct sqlite3_mutex {
++  CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
++  int id;                    /* Mutex type */
++#ifdef SQLITE_DEBUG
++  volatile int nRef;         /* Number of enterances */
++  volatile DWORD owner;      /* Thread holding this mutex */
++  int trace;                 /* True to trace changes */
++#endif
++};
++#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
++#ifdef SQLITE_DEBUG
++#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
++#else
++#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
++#endif
++
++/*
++** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
++** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
+ **
+-** NULL is returned if there is an allocation error.
++** Here is an interesting observation:  Win95, Win98, and WinME lack
++** the LockFileEx() API.  But we can still statically link against that
++** API as long as we don't call it win running Win95/98/ME.  A call to
++** this routine is used to determine if the host is Win95/98/ME or
++** WinNT/2K/XP so that we will know whether or not we can safely call
++** the LockFileEx() API.
++**
++** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
++** which is only available if your application was compiled with 
++** _WIN32_WINNT defined to a value >= 0x0400.  Currently, the only
++** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef 
++** this out as well.
+ */
+-SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
+-  Mem m;
+-  memset(&m, 0, sizeof(m));
+-  m.db = db;
+-  sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
+-  sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
+-  if( db->mallocFailed ){
+-    sqlite3VdbeMemRelease(&m);
+-    m.z = 0;
++#if 0
++#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
++# define mutexIsNT()  (1)
++#else
++  static int mutexIsNT(void){
++    static int osType = 0;
++    if( osType==0 ){
++      OSVERSIONINFO sInfo;
++      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
++      GetVersionEx(&sInfo);
++      osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
++    }
++    return osType==2;
+   }
+-  assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
+-  assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
+-  assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
+-  assert( m.z || db->mallocFailed );
+-  return m.z;
+-}
++#endif /* SQLITE_OS_WINCE */
++#endif
+ 
++#ifdef SQLITE_DEBUG
+ /*
+-** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
+-** enc. A pointer to the new string is returned, and the value of *pnOut
+-** is set to the length of the returned string in bytes. The call should
+-** arrange to call sqlite3DbFree() on the returned pointer when it is
+-** no longer required.
+-** 
+-** If a malloc failure occurs, NULL is returned and the db.mallocFailed
+-** flag set.
++** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
++** intended for use only inside assert() statements.
+ */
+-#ifdef SQLITE_ENABLE_STAT3
+-SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
+-  Mem m;
+-  memset(&m, 0, sizeof(m));
+-  m.db = db;
+-  sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
+-  if( sqlite3VdbeMemTranslate(&m, enc) ){
+-    assert( db->mallocFailed );
+-    return 0;
+-  }
+-  assert( m.z==m.zMalloc );
+-  *pnOut = m.n;
+-  return m.z;
++static int winMutexHeld(sqlite3_mutex *p){
++  return p->nRef!=0 && p->owner==GetCurrentThreadId();
++}
++static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
++  return p->nRef==0 || p->owner!=tid;
++}
++static int winMutexNotheld(sqlite3_mutex *p){
++  DWORD tid = GetCurrentThreadId(); 
++  return winMutexNotheld2(p, tid);
+ }
+ #endif
+ 
++
+ /*
+-** zIn is a UTF-16 encoded unicode string at least nChar characters long.
+-** Return the number of bytes in the first nChar unicode characters
+-** in pZ.  nChar must be non-negative.
++** Initialize and deinitialize the mutex subsystem.
+ */
+-SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
+-  int c;
+-  unsigned char const *z = zIn;
+-  int n = 0;
+-  
+-  if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
+-    while( n<nChar ){
+-      READ_UTF16BE(z, 1, c);
+-      n++;
++static sqlite3_mutex winMutex_staticMutexes[6] = {
++  SQLITE3_MUTEX_INITIALIZER,
++  SQLITE3_MUTEX_INITIALIZER,
++  SQLITE3_MUTEX_INITIALIZER,
++  SQLITE3_MUTEX_INITIALIZER,
++  SQLITE3_MUTEX_INITIALIZER,
++  SQLITE3_MUTEX_INITIALIZER
++};
++static int winMutex_isInit = 0;
++/* As winMutexInit() and winMutexEnd() are called as part
++** of the sqlite3_initialize and sqlite3_shutdown()
++** processing, the "interlocked" magic is probably not
++** strictly necessary.
++*/
++static long winMutex_lock = 0;
++
++SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
++
++static int winMutexInit(void){ 
++  /* The first to increment to 1 does actual initialization */
++  if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
++    int i;
++    for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
++#if SQLITE_OS_WINRT
++      InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
++#else
++      InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
++#endif
+     }
++    winMutex_isInit = 1;
+   }else{
+-    while( n<nChar ){
+-      READ_UTF16LE(z, 1, c);
+-      n++;
++    /* Someone else is in the process of initing the static mutexes */
++    while( !winMutex_isInit ){
++      sqlite3_win32_sleep(1);
+     }
+   }
+-  return (int)(z-(unsigned char const *)zIn);
++  return SQLITE_OK; 
+ }
+ 
+-#if defined(SQLITE_TEST)
+-/*
+-** This routine is called from the TCL test function "translate_selftest".
+-** It checks that the primitives for serializing and deserializing
+-** characters in each encoding are inverses of each other.
+-*/
+-SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
+-  unsigned int i, t;
+-  unsigned char zBuf[20];
+-  unsigned char *z;
+-  int n;
+-  unsigned int c;
+-
+-  for(i=0; i<0x00110000; i++){
+-    z = zBuf;
+-    WRITE_UTF8(z, i);
+-    n = (int)(z-zBuf);
+-    assert( n>0 && n<=4 );
+-    z[0] = 0;
+-    z = zBuf;
+-    c = sqlite3Utf8Read((const u8**)&z);
+-    t = i;
+-    if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
+-    if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
+-    assert( c==t );
+-    assert( (z-zBuf)==n );
+-  }
+-  for(i=0; i<0x00110000; i++){
+-    if( i>=0xD800 && i<0xE000 ) continue;
+-    z = zBuf;
+-    WRITE_UTF16LE(z, i);
+-    n = (int)(z-zBuf);
+-    assert( n>0 && n<=4 );
+-    z[0] = 0;
+-    z = zBuf;
+-    READ_UTF16LE(z, 1, c);
+-    assert( c==i );
+-    assert( (z-zBuf)==n );
+-  }
+-  for(i=0; i<0x00110000; i++){
+-    if( i>=0xD800 && i<0xE000 ) continue;
+-    z = zBuf;
+-    WRITE_UTF16BE(z, i);
+-    n = (int)(z-zBuf);
+-    assert( n>0 && n<=4 );
+-    z[0] = 0;
+-    z = zBuf;
+-    READ_UTF16BE(z, 1, c);
+-    assert( c==i );
+-    assert( (z-zBuf)==n );
++static int winMutexEnd(void){ 
++  /* The first to decrement to 0 does actual shutdown 
++  ** (which should be the last to shutdown.) */
++  if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
++    if( winMutex_isInit==1 ){
++      int i;
++      for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
++        DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
++      }
++      winMutex_isInit = 0;
++    }
+   }
++  return SQLITE_OK; 
+ }
+-#endif /* SQLITE_TEST */
+-#endif /* SQLITE_OMIT_UTF16 */
+ 
+-/************** End of utf.c *************************************************/
+-/************** Begin file util.c ********************************************/
+ /*
+-** 2001 September 15
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
++** The sqlite3_mutex_alloc() routine allocates a new
++** mutex and returns a pointer to it.  If it returns NULL
++** that means that a mutex could not be allocated.  SQLite
++** will unwind its stack and return an error.  The argument
++** to sqlite3_mutex_alloc() is one of these integer constants:
+ **
+-**    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.
++** <ul>
++** <li>  SQLITE_MUTEX_FAST
++** <li>  SQLITE_MUTEX_RECURSIVE
++** <li>  SQLITE_MUTEX_STATIC_MASTER
++** <li>  SQLITE_MUTEX_STATIC_MEM
++** <li>  SQLITE_MUTEX_STATIC_MEM2
++** <li>  SQLITE_MUTEX_STATIC_PRNG
++** <li>  SQLITE_MUTEX_STATIC_LRU
++** <li>  SQLITE_MUTEX_STATIC_PMEM
++** </ul>
+ **
+-*************************************************************************
+-** Utility functions used throughout sqlite.
++** The first two constants cause sqlite3_mutex_alloc() to create
++** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
++** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
++** The mutex implementation does not need to make a distinction
++** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
++** not want to.  But SQLite will only request a recursive mutex in
++** cases where it really needs one.  If a faster non-recursive mutex
++** implementation is available on the host platform, the mutex subsystem
++** might return such a mutex in response to SQLITE_MUTEX_FAST.
+ **
+-** This file contains functions for allocating memory, comparing
+-** strings, and stuff like that.
++** The other allowed parameters to sqlite3_mutex_alloc() each return
++** a pointer to a static preexisting mutex.  Six static mutexes are
++** used by the current version of SQLite.  Future versions of SQLite
++** may add additional static mutexes.  Static mutexes are for internal
++** use by SQLite only.  Applications that use SQLite mutexes should
++** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
++** SQLITE_MUTEX_RECURSIVE.
+ **
++** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
++** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
++** returns a different mutex on every call.  But for the static 
++** mutex types, the same mutex is returned on every call that has
++** the same type number.
+ */
+-/* #include <stdarg.h> */
+-#ifdef SQLITE_HAVE_ISNAN
+-# include <math.h>
++static sqlite3_mutex *winMutexAlloc(int iType){
++  sqlite3_mutex *p;
++
++  switch( iType ){
++    case SQLITE_MUTEX_FAST:
++    case SQLITE_MUTEX_RECURSIVE: {
++      p = sqlite3MallocZero( sizeof(*p) );
++      if( p ){  
++#ifdef SQLITE_DEBUG
++        p->id = iType;
++#endif
++#if SQLITE_OS_WINRT
++        InitializeCriticalSectionEx(&p->mutex, 0, 0);
++#else
++        InitializeCriticalSection(&p->mutex);
++#endif
++      }
++      break;
++    }
++    default: {
++      assert( winMutex_isInit==1 );
++      assert( iType-2 >= 0 );
++      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
++      p = &winMutex_staticMutexes[iType-2];
++#ifdef SQLITE_DEBUG
++      p->id = iType;
+ #endif
++      break;
++    }
++  }
++  return p;
++}
++
+ 
+ /*
+-** Routine needed to support the testcase() macro.
++** This routine deallocates a previously
++** allocated mutex.  SQLite is careful to deallocate every
++** mutex that it allocates.
+ */
+-#ifdef SQLITE_COVERAGE_TEST
+-SQLITE_PRIVATE void sqlite3Coverage(int x){
+-  static unsigned dummy = 0;
+-  dummy += (unsigned)x;
++static void winMutexFree(sqlite3_mutex *p){
++  assert( p );
++  assert( p->nRef==0 && p->owner==0 );
++  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
++  DeleteCriticalSection(&p->mutex);
++  sqlite3_free(p);
+ }
+-#endif
+ 
+-#ifndef SQLITE_OMIT_FLOATING_POINT
+ /*
+-** Return true if the floating point value is Not a Number (NaN).
+-**
+-** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
+-** Otherwise, we have our own implementation that works on most systems.
++** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
++** to enter a mutex.  If another thread is already within the mutex,
++** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
++** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
++** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
++** be entered multiple times by the same thread.  In such cases the,
++** mutex must be exited an equal number of times before another thread
++** can enter.  If the same thread tries to enter any other kind of mutex
++** more than once, the behavior is undefined.
+ */
+-SQLITE_PRIVATE int sqlite3IsNaN(double x){
+-  int rc;   /* The value return */
+-#if !defined(SQLITE_HAVE_ISNAN)
++static void winMutexEnter(sqlite3_mutex *p){
++#ifdef SQLITE_DEBUG
++  DWORD tid = GetCurrentThreadId(); 
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
++#endif
++  EnterCriticalSection(&p->mutex);
++#ifdef SQLITE_DEBUG
++  assert( p->nRef>0 || p->owner==0 );
++  p->owner = tid; 
++  p->nRef++;
++  if( p->trace ){
++    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++  }
++#endif
++}
++static int winMutexTry(sqlite3_mutex *p){
++#ifndef NDEBUG
++  DWORD tid = GetCurrentThreadId(); 
++#endif
++  int rc = SQLITE_BUSY;
++  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+   /*
+-  ** Systems that support the isnan() library function should probably
+-  ** make use of it by compiling with -DSQLITE_HAVE_ISNAN.  But we have
+-  ** found that many systems do not have a working isnan() function so
+-  ** this implementation is provided as an alternative.
+-  **
+-  ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
+-  ** On the other hand, the use of -ffast-math comes with the following
+-  ** warning:
+-  **
+-  **      This option [-ffast-math] should never be turned on by any
+-  **      -O option since it can result in incorrect output for programs
+-  **      which depend on an exact implementation of IEEE or ISO 
+-  **      rules/specifications for math functions.
+-  **
+-  ** Under MSVC, this NaN test may fail if compiled with a floating-
+-  ** point precision mode other than /fp:precise.  From the MSDN 
+-  ** documentation:
++  ** The sqlite3_mutex_try() routine is very rarely used, and when it
++  ** is used it is merely an optimization.  So it is OK for it to always
++  ** fail.  
+   **
+-  **      The compiler [with /fp:precise] will properly handle comparisons 
+-  **      involving NaN. For example, x != x evaluates to true if x is NaN 
+-  **      ...
++  ** The TryEnterCriticalSection() interface is only available on WinNT.
++  ** And some windows compilers complain if you try to use it without
++  ** first doing some #defines that prevent SQLite from building on Win98.
++  ** For that reason, we will omit this optimization for now.  See
++  ** ticket #2685.
+   */
+-#ifdef __FAST_MATH__
+-# error SQLite will not work correctly with the -ffast-math option of GCC.
++#if 0
++  if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
++    p->owner = tid;
++    p->nRef++;
++    rc = SQLITE_OK;
++  }
++#else
++  UNUSED_PARAMETER(p);
++#endif
++#ifdef SQLITE_DEBUG
++  if( rc==SQLITE_OK && p->trace ){
++    printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++  }
+ #endif
+-  volatile double y = x;
+-  volatile double z = y;
+-  rc = (y!=z);
+-#else  /* if defined(SQLITE_HAVE_ISNAN) */
+-  rc = isnan(x);
+-#endif /* SQLITE_HAVE_ISNAN */
+-  testcase( rc );
+   return rc;
+ }
+-#endif /* SQLITE_OMIT_FLOATING_POINT */
+ 
+ /*
+-** Compute a string length that is limited to what can be stored in
+-** lower 30 bits of a 32-bit signed integer.
+-**
+-** The value returned will never be negative.  Nor will it ever be greater
+-** than the actual length of the string.  For very long strings (greater
+-** than 1GiB) the value returned might be less than the true string length.
++** The sqlite3_mutex_leave() routine exits a mutex that was
++** previously entered by the same thread.  The behavior
++** is undefined if the mutex is not currently entered or
++** is not currently allocated.  SQLite will never do either.
+ */
+-SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
+-  const char *z2 = z;
+-  if( z==0 ) return 0;
+-  while( *z2 ){ z2++; }
+-  return 0x3fffffff & (int)(z2 - z);
++static void winMutexLeave(sqlite3_mutex *p){
++#ifndef NDEBUG
++  DWORD tid = GetCurrentThreadId();
++  assert( p->nRef>0 );
++  assert( p->owner==tid );
++  p->nRef--;
++  if( p->nRef==0 ) p->owner = 0;
++  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
++#endif
++  LeaveCriticalSection(&p->mutex);
++#ifdef SQLITE_DEBUG
++  if( p->trace ){
++    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
++  }
++#endif
++}
++
++SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
++  static const sqlite3_mutex_methods sMutex = {
++    winMutexInit,
++    winMutexEnd,
++    winMutexAlloc,
++    winMutexFree,
++    winMutexEnter,
++    winMutexTry,
++    winMutexLeave,
++#ifdef SQLITE_DEBUG
++    winMutexHeld,
++    winMutexNotheld
++#else
++    0,
++    0
++#endif
++  };
++
++  return &sMutex;
+ }
++#endif /* SQLITE_MUTEX_W32 */
+ 
++/************** End of mutex_w32.c *******************************************/
++/************** Begin file malloc.c ******************************************/
+ /*
+-** Set the most recent error code and error string for the sqlite
+-** handle "db". The error code is set to "err_code".
++** 2001 September 15
+ **
+-** If it is not NULL, string zFormat specifies the format of the
+-** error string in the style of the printf functions: The following
+-** format characters are allowed:
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-**      %s      Insert a string
+-**      %z      A string that should be freed after use
+-**      %d      Insert an integer
+-**      %T      Insert a token
+-**      %S      Insert the first element of a SrcList
++**    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.
+ **
+-** zFormat and any string tokens that follow it are assumed to be
+-** encoded in UTF-8.
++*************************************************************************
+ **
+-** To clear the most recent error for sqlite handle "db", sqlite3Error
+-** should be called with err_code set to SQLITE_OK and zFormat set
+-** to NULL.
++** Memory allocation functions used throughout sqlite.
+ */
+-SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
+-  if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
+-    db->errCode = err_code;
+-    if( zFormat ){
+-      char *z;
+-      va_list ap;
+-      va_start(ap, zFormat);
+-      z = sqlite3VMPrintf(db, zFormat, ap);
+-      va_end(ap);
+-      sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
+-    }else{
+-      sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
+-    }
+-  }
+-}
++/* #include <stdarg.h> */
+ 
+ /*
+-** Add an error message to pParse->zErrMsg and increment pParse->nErr.
+-** The following formatting characters are allowed:
+-**
+-**      %s      Insert a string
+-**      %z      A string that should be freed after use
+-**      %d      Insert an integer
+-**      %T      Insert a token
+-**      %S      Insert the first element of a SrcList
+-**
+-** This function should be used to report any error that occurs whilst
+-** compiling an SQL statement (i.e. within sqlite3_prepare()). The
+-** last thing the sqlite3_prepare() function does is copy the error
+-** stored by this function into the database handle using sqlite3Error().
+-** Function sqlite3Error() should be used during statement execution
+-** (sqlite3_step() etc.).
++** Attempt to release up to n bytes of non-essential memory currently
++** held by SQLite. An example of non-essential memory is memory used to
++** cache database pages that are not currently in use.
+ */
+-SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
+-  char *zMsg;
+-  va_list ap;
+-  sqlite3 *db = pParse->db;
+-  va_start(ap, zFormat);
+-  zMsg = sqlite3VMPrintf(db, zFormat, ap);
+-  va_end(ap);
+-  if( db->suppressErr ){
+-    sqlite3DbFree(db, zMsg);
+-  }else{
+-    pParse->nErr++;
+-    sqlite3DbFree(db, pParse->zErrMsg);
+-    pParse->zErrMsg = zMsg;
+-    pParse->rc = SQLITE_ERROR;
+-  }
++SQLITE_API int sqlite3_release_memory(int n){
++#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
++  return sqlite3PcacheReleaseMemory(n);
++#else
++  /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
++  ** is a no-op returning zero if SQLite is not compiled with
++  ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
++  UNUSED_PARAMETER(n);
++  return 0;
++#endif
+ }
+ 
+ /*
+-** Convert an SQL-style quoted string into a normal string by removing
+-** the quote characters.  The conversion is done in-place.  If the
+-** input does not begin with a quote character, then this routine
+-** is a no-op.
+-**
+-** The input string must be zero-terminated.  A new zero-terminator
+-** is added to the dequoted string.
+-**
+-** The return value is -1 if no dequoting occurs or the length of the
+-** dequoted string, exclusive of the zero terminator, if dequoting does
+-** occur.
+-**
+-** 2002-Feb-14: This routine is extended to remove MS-Access style
+-** brackets from around identifers.  For example:  "[a-b-c]" becomes
+-** "a-b-c".
++** An instance of the following object records the location of
++** each unused scratch buffer.
+ */
+-SQLITE_PRIVATE int sqlite3Dequote(char *z){
+-  char quote;
+-  int i, j;
+-  if( z==0 ) return -1;
+-  quote = z[0];
+-  switch( quote ){
+-    case '\'':  break;
+-    case '"':   break;
+-    case '`':   break;                /* For MySQL compatibility */
+-    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
+-    default:    return -1;
+-  }
+-  for(i=1, j=0; ALWAYS(z[i]); i++){
+-    if( z[i]==quote ){
+-      if( z[i+1]==quote ){
+-        z[j++] = quote;
+-        i++;
+-      }else{
+-        break;
+-      }
+-    }else{
+-      z[j++] = z[i];
+-    }
+-  }
+-  z[j] = 0;
+-  return j;
+-}
++typedef struct ScratchFreeslot {
++  struct ScratchFreeslot *pNext;   /* Next unused scratch buffer */
++} ScratchFreeslot;
+ 
+-/* Convenient short-hand */
+-#define UpperToLower sqlite3UpperToLower
++/*
++** State information local to the memory allocation subsystem.
++*/
++static SQLITE_WSD struct Mem0Global {
++  sqlite3_mutex *mutex;         /* Mutex to serialize access */
++
++  /*
++  ** The alarm callback and its arguments.  The mem0.mutex lock will
++  ** be held while the callback is running.  Recursive calls into
++  ** the memory subsystem are allowed, but no new callbacks will be
++  ** issued.
++  */
++  sqlite3_int64 alarmThreshold;
++  void (*alarmCallback)(void*, sqlite3_int64,int);
++  void *alarmArg;
++
++  /*
++  ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
++  ** (so that a range test can be used to determine if an allocation
++  ** being freed came from pScratch) and a pointer to the list of
++  ** unused scratch allocations.
++  */
++  void *pScratchEnd;
++  ScratchFreeslot *pScratchFree;
++  u32 nScratchFree;
++
++  /*
++  ** True if heap is nearly "full" where "full" is defined by the
++  ** sqlite3_soft_heap_limit() setting.
++  */
++  int nearlyFull;
++} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
++
++#define mem0 GLOBAL(struct Mem0Global, mem0)
+ 
+ /*
+-** Some systems have stricmp().  Others have strcasecmp().  Because
+-** there is no consistency, we will define our own.
+-**
+-** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
+-** sqlite3_strnicmp() APIs allow applications and extensions to compare
+-** the contents of two buffers containing UTF-8 strings in a
+-** case-independent fashion, using the same definition of "case
+-** independence" that SQLite uses internally when comparing identifiers.
++** This routine runs when the memory allocator sees that the
++** total memory allocation is about to exceed the soft heap
++** limit.
+ */
+-SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
+-  register unsigned char *a, *b;
+-  a = (unsigned char *)zLeft;
+-  b = (unsigned char *)zRight;
+-  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
+-  return UpperToLower[*a] - UpperToLower[*b];
+-}
+-SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
+-  register unsigned char *a, *b;
+-  a = (unsigned char *)zLeft;
+-  b = (unsigned char *)zRight;
+-  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
+-  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
++static void softHeapLimitEnforcer(
++  void *NotUsed, 
++  sqlite3_int64 NotUsed2,
++  int allocSize
++){
++  UNUSED_PARAMETER2(NotUsed, NotUsed2);
++  sqlite3_release_memory(allocSize);
+ }
+ 
+ /*
+-** The string z[] is an text representation of a real number.
+-** Convert this string to a double and write it into *pResult.
+-**
+-** The string z[] is length bytes in length (bytes, not characters) and
+-** uses the encoding enc.  The string is not necessarily zero-terminated.
+-**
+-** Return TRUE if the result is a valid real number (or integer) and FALSE
+-** if the string is empty or contains extraneous text.  Valid numbers
+-** are in one of these formats:
+-**
+-**    [+-]digits[E[+-]digits]
+-**    [+-]digits.[digits][E[+-]digits]
+-**    [+-].digits[E[+-]digits]
+-**
+-** Leading and trailing whitespace is ignored for the purpose of determining
+-** validity.
+-**
+-** If some prefix of the input string is a valid number, this routine
+-** returns FALSE but it still converts the prefix and writes the result
+-** into *pResult.
++** Change the alarm callback
+ */
+-SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
+-#ifndef SQLITE_OMIT_FLOATING_POINT
+-  int incr;
+-  const char *zEnd = z + length;
+-  /* sign * significand * (10 ^ (esign * exponent)) */
+-  int sign = 1;    /* sign of significand */
+-  i64 s = 0;       /* significand */
+-  int d = 0;       /* adjust exponent for shifting decimal point */
+-  int esign = 1;   /* sign of exponent */
+-  int e = 0;       /* exponent */
+-  int eValid = 1;  /* True exponent is either not used or is well-formed */
+-  double result;
+-  int nDigits = 0;
+-  int nonNum = 0;
++static int sqlite3MemoryAlarm(
++  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
++  void *pArg,
++  sqlite3_int64 iThreshold
++){
++  int nUsed;
++  sqlite3_mutex_enter(mem0.mutex);
++  mem0.alarmCallback = xCallback;
++  mem0.alarmArg = pArg;
++  mem0.alarmThreshold = iThreshold;
++  nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
++  mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed);
++  sqlite3_mutex_leave(mem0.mutex);
++  return SQLITE_OK;
++}
+ 
+-  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+-  *pResult = 0.0;   /* Default return value, in case of an error */
++#ifndef SQLITE_OMIT_DEPRECATED
++/*
++** Deprecated external interface.  Internal/core SQLite code
++** should call sqlite3MemoryAlarm.
++*/
++SQLITE_API int sqlite3_memory_alarm(
++  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
++  void *pArg,
++  sqlite3_int64 iThreshold
++){
++  return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
++}
++#endif
+ 
+-  if( enc==SQLITE_UTF8 ){
+-    incr = 1;
++/*
++** Set the soft heap-size limit for the library. Passing a zero or 
++** negative value indicates no limit.
++*/
++SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
++  sqlite3_int64 priorLimit;
++  sqlite3_int64 excess;
++#ifndef SQLITE_OMIT_AUTOINIT
++  int rc = sqlite3_initialize();
++  if( rc ) return -1;
++#endif
++  sqlite3_mutex_enter(mem0.mutex);
++  priorLimit = mem0.alarmThreshold;
++  sqlite3_mutex_leave(mem0.mutex);
++  if( n<0 ) return priorLimit;
++  if( n>0 ){
++    sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
+   }else{
+-    int i;
+-    incr = 2;
+-    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+-    for(i=3-enc; i<length && z[i]==0; i+=2){}
+-    nonNum = i<length;
+-    zEnd = z+i+enc-3;
+-    z += (enc&1);
+-  }
+-
+-  /* skip leading spaces */
+-  while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
+-  if( z>=zEnd ) return 0;
+-
+-  /* get sign of significand */
+-  if( *z=='-' ){
+-    sign = -1;
+-    z+=incr;
+-  }else if( *z=='+' ){
+-    z+=incr;
++    sqlite3MemoryAlarm(0, 0, 0);
+   }
++  excess = sqlite3_memory_used() - n;
++  if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
++  return priorLimit;
++}
++SQLITE_API void sqlite3_soft_heap_limit(int n){
++  if( n<0 ) n = 0;
++  sqlite3_soft_heap_limit64(n);
++}
+ 
+-  /* skip leading zeroes */
+-  while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
+-
+-  /* copy max significant digits to significand */
+-  while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
+-    s = s*10 + (*z - '0');
+-    z+=incr, nDigits++;
++/*
++** Initialize the memory allocation subsystem.
++*/
++SQLITE_PRIVATE int sqlite3MallocInit(void){
++  if( sqlite3GlobalConfig.m.xMalloc==0 ){
++    sqlite3MemSetDefault();
+   }
+-
+-  /* skip non-significant significand digits
+-  ** (increase exponent by d to shift decimal left) */
+-  while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
+-  if( z>=zEnd ) goto do_atof_calc;
+-
+-  /* if decimal point is present */
+-  if( *z=='.' ){
+-    z+=incr;
+-    /* copy digits from after decimal to significand
+-    ** (decrease exponent by d to shift decimal right) */
+-    while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
+-      s = s*10 + (*z - '0');
+-      z+=incr, nDigits++, d--;
+-    }
+-    /* skip non-significant digits */
+-    while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
++  memset(&mem0, 0, sizeof(mem0));
++  if( sqlite3GlobalConfig.bCoreMutex ){
++    mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+   }
+-  if( z>=zEnd ) goto do_atof_calc;
+-
+-  /* if exponent is present */
+-  if( *z=='e' || *z=='E' ){
+-    z+=incr;
+-    eValid = 0;
+-    if( z>=zEnd ) goto do_atof_calc;
+-    /* get sign of exponent */
+-    if( *z=='-' ){
+-      esign = -1;
+-      z+=incr;
+-    }else if( *z=='+' ){
+-      z+=incr;
+-    }
+-    /* copy digits to exponent */
+-    while( z<zEnd && sqlite3Isdigit(*z) ){
+-      e = e<10000 ? (e*10 + (*z - '0')) : 10000;
+-      z+=incr;
+-      eValid = 1;
++  if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
++      && sqlite3GlobalConfig.nScratch>0 ){
++    int i, n, sz;
++    ScratchFreeslot *pSlot;
++    sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
++    sqlite3GlobalConfig.szScratch = sz;
++    pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
++    n = sqlite3GlobalConfig.nScratch;
++    mem0.pScratchFree = pSlot;
++    mem0.nScratchFree = n;
++    for(i=0; i<n-1; i++){
++      pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
++      pSlot = pSlot->pNext;
+     }
++    pSlot->pNext = 0;
++    mem0.pScratchEnd = (void*)&pSlot[1];
++  }else{
++    mem0.pScratchEnd = 0;
++    sqlite3GlobalConfig.pScratch = 0;
++    sqlite3GlobalConfig.szScratch = 0;
++    sqlite3GlobalConfig.nScratch = 0;
+   }
+-
+-  /* skip trailing spaces */
+-  if( nDigits && eValid ){
+-    while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
+-  }
+-
+-do_atof_calc:
+-  /* adjust exponent by d, and update sign */
+-  e = (e*esign) + d;
+-  if( e<0 ) {
+-    esign = -1;
+-    e *= -1;
+-  } else {
+-    esign = 1;
++  if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
++      || sqlite3GlobalConfig.nPage<1 ){
++    sqlite3GlobalConfig.pPage = 0;
++    sqlite3GlobalConfig.szPage = 0;
++    sqlite3GlobalConfig.nPage = 0;
+   }
++  return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
++}
+ 
+-  /* if 0 significand */
+-  if( !s ) {
+-    /* In the IEEE 754 standard, zero is signed.
+-    ** Add the sign if we've seen at least one digit */
+-    result = (sign<0 && nDigits) ? -(double)0 : (double)0;
+-  } else {
+-    /* attempt to reduce exponent */
+-    if( esign>0 ){
+-      while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
+-    }else{
+-      while( !(s%10) && e>0 ) e--,s/=10;
+-    }
+-
+-    /* adjust the sign of significand */
+-    s = sign<0 ? -s : s;
++/*
++** Return true if the heap is currently under memory pressure - in other
++** words if the amount of heap used is close to the limit set by
++** sqlite3_soft_heap_limit().
++*/
++SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
++  return mem0.nearlyFull;
++}
+ 
+-    /* if exponent, scale significand as appropriate
+-    ** and store in result. */
+-    if( e ){
+-      LONGDOUBLE_TYPE scale = 1.0;
+-      /* attempt to handle extremely small/large numbers better */
+-      if( e>307 && e<342 ){
+-        while( e%308 ) { scale *= 1.0e+1; e -= 1; }
+-        if( esign<0 ){
+-          result = s / scale;
+-          result /= 1.0e+308;
+-        }else{
+-          result = s * scale;
+-          result *= 1.0e+308;
+-        }
+-      }else if( e>=342 ){
+-        if( esign<0 ){
+-          result = 0.0*s;
+-        }else{
+-          result = 1e308*1e308*s;  /* Infinity */
+-        }
+-      }else{
+-        /* 1.0e+22 is the largest power of 10 than can be 
+-        ** represented exactly. */
+-        while( e%22 ) { scale *= 1.0e+1; e -= 1; }
+-        while( e>0 ) { scale *= 1.0e+22; e -= 22; }
+-        if( esign<0 ){
+-          result = s / scale;
+-        }else{
+-          result = s * scale;
+-        }
+-      }
+-    } else {
+-      result = (double)s;
+-    }
++/*
++** Deinitialize the memory allocation subsystem.
++*/
++SQLITE_PRIVATE void sqlite3MallocEnd(void){
++  if( sqlite3GlobalConfig.m.xShutdown ){
++    sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
+   }
++  memset(&mem0, 0, sizeof(mem0));
++}
+ 
+-  /* store the result */
+-  *pResult = result;
+-
+-  /* return true if number and no extra non-whitespace chracters after */
+-  return z>=zEnd && nDigits>0 && eValid && nonNum==0;
+-#else
+-  return !sqlite3Atoi64(z, pResult, length, enc);
+-#endif /* SQLITE_OMIT_FLOATING_POINT */
++/*
++** Return the amount of memory currently checked out.
++*/
++SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
++  int n, mx;
++  sqlite3_int64 res;
++  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
++  res = (sqlite3_int64)n;  /* Work around bug in Borland C. Ticket #3216 */
++  return res;
+ }
+ 
+ /*
+-** Compare the 19-character string zNum against the text representation
+-** value 2^63:  9223372036854775808.  Return negative, zero, or positive
+-** if zNum is less than, equal to, or greater than the string.
+-** Note that zNum must contain exactly 19 characters.
+-**
+-** Unlike memcmp() this routine is guaranteed to return the difference
+-** in the values of the last digit if the only difference is in the
+-** last digit.  So, for example,
+-**
+-**      compare2pow63("9223372036854775800", 1)
+-**
+-** will return -8.
++** Return the maximum amount of memory that has ever been
++** checked out since either the beginning of this process
++** or since the most recent reset.
+ */
+-static int compare2pow63(const char *zNum, int incr){
+-  int c = 0;
+-  int i;
+-                    /* 012345678901234567 */
+-  const char *pow63 = "922337203685477580";
+-  for(i=0; c==0 && i<18; i++){
+-    c = (zNum[i*incr]-pow63[i])*10;
+-  }
+-  if( c==0 ){
+-    c = zNum[18*incr] - '8';
+-    testcase( c==(-1) );
+-    testcase( c==0 );
+-    testcase( c==(+1) );
+-  }
+-  return c;
++SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
++  int n, mx;
++  sqlite3_int64 res;
++  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
++  res = (sqlite3_int64)mx;  /* Work around bug in Borland C. Ticket #3216 */
++  return res;
+ }
+ 
++/*
++** Trigger the alarm 
++*/
++static void sqlite3MallocAlarm(int nByte){
++  void (*xCallback)(void*,sqlite3_int64,int);
++  sqlite3_int64 nowUsed;
++  void *pArg;
++  if( mem0.alarmCallback==0 ) return;
++  xCallback = mem0.alarmCallback;
++  nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
++  pArg = mem0.alarmArg;
++  mem0.alarmCallback = 0;
++  sqlite3_mutex_leave(mem0.mutex);
++  xCallback(pArg, nowUsed, nByte);
++  sqlite3_mutex_enter(mem0.mutex);
++  mem0.alarmCallback = xCallback;
++  mem0.alarmArg = pArg;
++}
+ 
+ /*
+-** Convert zNum to a 64-bit signed integer.
+-**
+-** If the zNum value is representable as a 64-bit twos-complement 
+-** integer, then write that value into *pNum and return 0.
+-**
+-** If zNum is exactly 9223372036854665808, return 2.  This special
+-** case is broken out because while 9223372036854665808 cannot be a 
+-** signed 64-bit integer, its negative -9223372036854665808 can be.
+-**
+-** If zNum is too big for a 64-bit integer and is not
+-** 9223372036854665808  or if zNum contains any non-numeric text,
+-** then return 1.
+-**
+-** length is the number of bytes in the string (bytes, not characters).
+-** The string is not necessarily zero-terminated.  The encoding is
+-** given by enc.
++** Do a memory allocation with statistics and alarms.  Assume the
++** lock is already held.
+ */
+-SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
+-  int incr;
+-  u64 u = 0;
+-  int neg = 0; /* assume positive */
+-  int i;
+-  int c = 0;
+-  int nonNum = 0;
+-  const char *zStart;
+-  const char *zEnd = zNum + length;
+-  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+-  if( enc==SQLITE_UTF8 ){
+-    incr = 1;
+-  }else{
+-    incr = 2;
+-    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+-    for(i=3-enc; i<length && zNum[i]==0; i+=2){}
+-    nonNum = i<length;
+-    zEnd = zNum+i+enc-3;
+-    zNum += (enc&1);
+-  }
+-  while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
+-  if( zNum<zEnd ){
+-    if( *zNum=='-' ){
+-      neg = 1;
+-      zNum+=incr;
+-    }else if( *zNum=='+' ){
+-      zNum+=incr;
++static int mallocWithAlarm(int n, void **pp){
++  int nFull;
++  void *p;
++  assert( sqlite3_mutex_held(mem0.mutex) );
++  nFull = sqlite3GlobalConfig.m.xRoundup(n);
++  sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
++  if( mem0.alarmCallback!=0 ){
++    int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
++    if( nUsed >= mem0.alarmThreshold - nFull ){
++      mem0.nearlyFull = 1;
++      sqlite3MallocAlarm(nFull);
++    }else{
++      mem0.nearlyFull = 0;
+     }
+   }
+-  zStart = zNum;
+-  while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
+-  for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
+-    u = u*10 + c - '0';
++  p = sqlite3GlobalConfig.m.xMalloc(nFull);
++#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
++  if( p==0 && mem0.alarmCallback ){
++    sqlite3MallocAlarm(nFull);
++    p = sqlite3GlobalConfig.m.xMalloc(nFull);
+   }
+-  if( u>LARGEST_INT64 ){
+-    *pNum = SMALLEST_INT64;
+-  }else if( neg ){
+-    *pNum = -(i64)u;
+-  }else{
+-    *pNum = (i64)u;
++#endif
++  if( p ){
++    nFull = sqlite3MallocSize(p);
++    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
++    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
+   }
+-  testcase( i==18 );
+-  testcase( i==19 );
+-  testcase( i==20 );
+-  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
+-    /* zNum is empty or contains non-numeric text or is longer
+-    ** than 19 digits (thus guaranteeing that it is too large) */
+-    return 1;
+-  }else if( i<19*incr ){
+-    /* Less than 19 digits, so we know that it fits in 64 bits */
+-    assert( u<=LARGEST_INT64 );
+-    return 0;
++  *pp = p;
++  return nFull;
++}
++
++/*
++** Allocate memory.  This routine is like sqlite3_malloc() except that it
++** assumes the memory subsystem has already been initialized.
++*/
++SQLITE_PRIVATE void *sqlite3Malloc(int n){
++  void *p;
++  if( n<=0               /* IMP: R-65312-04917 */ 
++   || n>=0x7fffff00
++  ){
++    /* A memory allocation of a number of bytes which is near the maximum
++    ** signed integer value might cause an integer overflow inside of the
++    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
++    ** 255 bytes of overhead.  SQLite itself will never use anything near
++    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
++    p = 0;
++  }else if( sqlite3GlobalConfig.bMemstat ){
++    sqlite3_mutex_enter(mem0.mutex);
++    mallocWithAlarm(n, &p);
++    sqlite3_mutex_leave(mem0.mutex);
+   }else{
+-    /* zNum is a 19-digit numbers.  Compare it against 9223372036854775808. */
+-    c = compare2pow63(zNum, incr);
+-    if( c<0 ){
+-      /* zNum is less than 9223372036854775808 so it fits */
+-      assert( u<=LARGEST_INT64 );
+-      return 0;
+-    }else if( c>0 ){
+-      /* zNum is greater than 9223372036854775808 so it overflows */
+-      return 1;
+-    }else{
+-      /* zNum is exactly 9223372036854775808.  Fits if negative.  The
+-      ** special case 2 overflow if positive */
+-      assert( u-1==LARGEST_INT64 );
+-      assert( (*pNum)==SMALLEST_INT64 );
+-      return neg ? 0 : 2;
+-    }
++    p = sqlite3GlobalConfig.m.xMalloc(n);
+   }
++  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
++  return p;
+ }
+ 
+ /*
+-** If zNum represents an integer that will fit in 32-bits, then set
+-** *pValue to that integer and return true.  Otherwise return false.
+-**
+-** Any non-numeric characters that following zNum are ignored.
+-** This is different from sqlite3Atoi64() which requires the
+-** input number to be zero-terminated.
++** This version of the memory allocation is for use by the application.
++** First make sure the memory subsystem is initialized, then do the
++** allocation.
+ */
+-SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
+-  sqlite_int64 v = 0;
+-  int i, c;
+-  int neg = 0;
+-  if( zNum[0]=='-' ){
+-    neg = 1;
+-    zNum++;
+-  }else if( zNum[0]=='+' ){
+-    zNum++;
+-  }
+-  while( zNum[0]=='0' ) zNum++;
+-  for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
+-    v = v*10 + c;
+-  }
++SQLITE_API void *sqlite3_malloc(int n){
++#ifndef SQLITE_OMIT_AUTOINIT
++  if( sqlite3_initialize() ) return 0;
++#endif
++  return sqlite3Malloc(n);
++}
+ 
+-  /* The longest decimal representation of a 32 bit integer is 10 digits:
+-  **
+-  **             1234567890
+-  **     2^31 -> 2147483648
+-  */
+-  testcase( i==10 );
+-  if( i>10 ){
+-    return 0;
+-  }
+-  testcase( v-neg==2147483647 );
+-  if( v-neg>2147483647 ){
+-    return 0;
++/*
++** Each thread may only have a single outstanding allocation from
++** xScratchMalloc().  We verify this constraint in the single-threaded
++** case by setting scratchAllocOut to 1 when an allocation
++** is outstanding clearing it when the allocation is freed.
++*/
++#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
++static int scratchAllocOut = 0;
++#endif
++
++
++/*
++** Allocate memory that is to be used and released right away.
++** This routine is similar to alloca() in that it is not intended
++** for situations where the memory might be held long-term.  This
++** routine is intended to get memory to old large transient data
++** structures that would not normally fit on the stack of an
++** embedded processor.
++*/
++SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
++  void *p;
++  assert( n>0 );
++
++  sqlite3_mutex_enter(mem0.mutex);
++  if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
++    p = mem0.pScratchFree;
++    mem0.pScratchFree = mem0.pScratchFree->pNext;
++    mem0.nScratchFree--;
++    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
++    sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
++    sqlite3_mutex_leave(mem0.mutex);
++  }else{
++    if( sqlite3GlobalConfig.bMemstat ){
++      sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
++      n = mallocWithAlarm(n, &p);
++      if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
++      sqlite3_mutex_leave(mem0.mutex);
++    }else{
++      sqlite3_mutex_leave(mem0.mutex);
++      p = sqlite3GlobalConfig.m.xMalloc(n);
++    }
++    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
+   }
+-  if( neg ){
+-    v = -v;
++  assert( sqlite3_mutex_notheld(mem0.mutex) );
++
++
++#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
++  /* Verify that no more than two scratch allocations per thread
++  ** are outstanding at one time.  (This is only checked in the
++  ** single-threaded case since checking in the multi-threaded case
++  ** would be much more complicated.) */
++  assert( scratchAllocOut<=1 );
++  if( p ) scratchAllocOut++;
++#endif
++
++  return p;
++}
++SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
++  if( p ){
++
++#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
++    /* Verify that no more than two scratch allocation per thread
++    ** is outstanding at one time.  (This is only checked in the
++    ** single-threaded case since checking in the multi-threaded case
++    ** would be much more complicated.) */
++    assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
++    scratchAllocOut--;
++#endif
++
++    if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){
++      /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
++      ScratchFreeslot *pSlot;
++      pSlot = (ScratchFreeslot*)p;
++      sqlite3_mutex_enter(mem0.mutex);
++      pSlot->pNext = mem0.pScratchFree;
++      mem0.pScratchFree = pSlot;
++      mem0.nScratchFree++;
++      assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
++      sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
++      sqlite3_mutex_leave(mem0.mutex);
++    }else{
++      /* Release memory back to the heap */
++      assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
++      assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
++      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
++      if( sqlite3GlobalConfig.bMemstat ){
++        int iSize = sqlite3MallocSize(p);
++        sqlite3_mutex_enter(mem0.mutex);
++        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
++        sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
++        sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
++        sqlite3GlobalConfig.m.xFree(p);
++        sqlite3_mutex_leave(mem0.mutex);
++      }else{
++        sqlite3GlobalConfig.m.xFree(p);
++      }
++    }
+   }
+-  *pValue = (int)v;
+-  return 1;
+ }
+ 
+ /*
+-** Return a 32-bit integer value extracted from a string.  If the
+-** string is not an integer, just return 0.
++** TRUE if p is a lookaside memory allocation from db
+ */
+-SQLITE_PRIVATE int sqlite3Atoi(const char *z){
+-  int x = 0;
+-  if( z ) sqlite3GetInt32(z, &x);
+-  return x;
++#ifndef SQLITE_OMIT_LOOKASIDE
++static int isLookaside(sqlite3 *db, void *p){
++  return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
+ }
++#else
++#define isLookaside(A,B) 0
++#endif
+ 
+ /*
+-** The variable-length integer encoding is as follows:
+-**
+-** KEY:
+-**         A = 0xxxxxxx    7 bits of data and one flag bit
+-**         B = 1xxxxxxx    7 bits of data and one flag bit
+-**         C = xxxxxxxx    8 bits of data
+-**
+-**  7 bits - A
+-** 14 bits - BA
+-** 21 bits - BBA
+-** 28 bits - BBBA
+-** 35 bits - BBBBA
+-** 42 bits - BBBBBA
+-** 49 bits - BBBBBBA
+-** 56 bits - BBBBBBBA
+-** 64 bits - BBBBBBBBC
++** Return the size of a memory allocation previously obtained from
++** sqlite3Malloc() or sqlite3_malloc().
+ */
++SQLITE_PRIVATE int sqlite3MallocSize(void *p){
++  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
++  assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
++  return sqlite3GlobalConfig.m.xSize(p);
++}
++SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
++  assert( db==0 || sqlite3_mutex_held(db->mutex) );
++  if( db && isLookaside(db, p) ){
++    return db->lookaside.sz;
++  }else{
++    assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
++    assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
++    assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
++    return sqlite3GlobalConfig.m.xSize(p);
++  }
++}
+ 
+ /*
+-** Write a 64-bit variable-length integer to memory starting at p[0].
+-** The length of data write will be between 1 and 9 bytes.  The number
+-** of bytes written is returned.
+-**
+-** A variable-length integer consists of the lower 7 bits of each byte
+-** for all bytes that have the 8th bit set and one byte with the 8th
+-** bit clear.  Except, if we get to the 9th byte, it stores the full
+-** 8 bits and is the last byte.
++** Free memory previously obtained from sqlite3Malloc().
+ */
+-SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
+-  int i, j, n;
+-  u8 buf[10];
+-  if( v & (((u64)0xff000000)<<32) ){
+-    p[8] = (u8)v;
+-    v >>= 8;
+-    for(i=7; i>=0; i--){
+-      p[i] = (u8)((v & 0x7f) | 0x80);
+-      v >>= 7;
+-    }
+-    return 9;
+-  }    
+-  n = 0;
+-  do{
+-    buf[n++] = (u8)((v & 0x7f) | 0x80);
+-    v >>= 7;
+-  }while( v!=0 );
+-  buf[0] &= 0x7f;
+-  assert( n<=9 );
+-  for(i=0, j=n-1; j>=0; j--, i++){
+-    p[i] = buf[j];
++SQLITE_API void sqlite3_free(void *p){
++  if( p==0 ) return;  /* IMP: R-49053-54554 */
++  assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
++  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
++  if( sqlite3GlobalConfig.bMemstat ){
++    sqlite3_mutex_enter(mem0.mutex);
++    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
++    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
++    sqlite3GlobalConfig.m.xFree(p);
++    sqlite3_mutex_leave(mem0.mutex);
++  }else{
++    sqlite3GlobalConfig.m.xFree(p);
+   }
+-  return n;
+ }
+ 
+ /*
+-** This routine is a faster version of sqlite3PutVarint() that only
+-** works for 32-bit positive integers and which is optimized for
+-** the common case of small integers.  A MACRO version, putVarint32,
+-** is provided which inlines the single-byte case.  All code should use
+-** the MACRO version as this function assumes the single-byte case has
+-** already been handled.
++** Free memory that might be associated with a particular database
++** connection.
+ */
+-SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
+-#ifndef putVarint32
+-  if( (v & ~0x7f)==0 ){
+-    p[0] = v;
+-    return 1;
+-  }
++SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
++  assert( db==0 || sqlite3_mutex_held(db->mutex) );
++  if( db ){
++    if( db->pnBytesFreed ){
++      *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
++      return;
++    }
++    if( isLookaside(db, p) ){
++      LookasideSlot *pBuf = (LookasideSlot*)p;
++#if SQLITE_DEBUG
++      /* Trash all content in the buffer being freed */
++      memset(p, 0xaa, db->lookaside.sz);
+ #endif
+-  if( (v & ~0x3fff)==0 ){
+-    p[0] = (u8)((v>>7) | 0x80);
+-    p[1] = (u8)(v & 0x7f);
+-    return 2;
++      pBuf->pNext = db->lookaside.pFree;
++      db->lookaside.pFree = pBuf;
++      db->lookaside.nOut--;
++      return;
++    }
+   }
+-  return sqlite3PutVarint(p, v);
++  assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
++  assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
++  assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
++  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
++  sqlite3_free(p);
+ }
+ 
+ /*
+-** Bitmasks used by sqlite3GetVarint().  These precomputed constants
+-** are defined here rather than simply putting the constant expressions
+-** inline in order to work around bugs in the RVT compiler.
+-**
+-** SLOT_2_0     A mask for  (0x7f<<14) | 0x7f
+-**
+-** SLOT_4_2_0   A mask for  (0x7f<<28) | SLOT_2_0
++** Change the size of an existing memory allocation
+ */
+-#define SLOT_2_0     0x001fc07f
+-#define SLOT_4_2_0   0xf01fc07f
+-
++SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
++  int nOld, nNew, nDiff;
++  void *pNew;
++  if( pOld==0 ){
++    return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
++  }
++  if( nBytes<=0 ){
++    sqlite3_free(pOld); /* IMP: R-31593-10574 */
++    return 0;
++  }
++  if( nBytes>=0x7fffff00 ){
++    /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
++    return 0;
++  }
++  nOld = sqlite3MallocSize(pOld);
++  /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
++  ** argument to xRealloc is always a value returned by a prior call to
++  ** xRoundup. */
++  nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
++  if( nOld==nNew ){
++    pNew = pOld;
++  }else if( sqlite3GlobalConfig.bMemstat ){
++    sqlite3_mutex_enter(mem0.mutex);
++    sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
++    nDiff = nNew - nOld;
++    if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
++          mem0.alarmThreshold-nDiff ){
++      sqlite3MallocAlarm(nDiff);
++    }
++    assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
++    assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
++    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
++    if( pNew==0 && mem0.alarmCallback ){
++      sqlite3MallocAlarm(nBytes);
++      pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
++    }
++    if( pNew ){
++      nNew = sqlite3MallocSize(pNew);
++      sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
++    }
++    sqlite3_mutex_leave(mem0.mutex);
++  }else{
++    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
++  }
++  assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
++  return pNew;
++}
+ 
+ /*
+-** Read a 64-bit variable-length integer from memory starting at p[0].
+-** Return the number of bytes read.  The value is stored in *v.
++** The public interface to sqlite3Realloc.  Make sure that the memory
++** subsystem is initialized prior to invoking sqliteRealloc.
+ */
+-SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
+-  u32 a,b,s;
++SQLITE_API void *sqlite3_realloc(void *pOld, int n){
++#ifndef SQLITE_OMIT_AUTOINIT
++  if( sqlite3_initialize() ) return 0;
++#endif
++  return sqlite3Realloc(pOld, n);
++}
+ 
+-  a = *p;
+-  /* a: p0 (unmasked) */
+-  if (!(a&0x80))
+-  {
+-    *v = a;
+-    return 1;
+-  }
+ 
+-  p++;
+-  b = *p;
+-  /* b: p1 (unmasked) */
+-  if (!(b&0x80))
+-  {
+-    a &= 0x7f;
+-    a = a<<7;
+-    a |= b;
+-    *v = a;
+-    return 2;
++/*
++** Allocate and zero memory.
++*/ 
++SQLITE_PRIVATE void *sqlite3MallocZero(int n){
++  void *p = sqlite3Malloc(n);
++  if( p ){
++    memset(p, 0, n);
+   }
++  return p;
++}
+ 
+-  /* Verify that constants are precomputed correctly */
+-  assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
+-  assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
+-
+-  p++;
+-  a = a<<14;
+-  a |= *p;
+-  /* a: p0<<14 | p2 (unmasked) */
+-  if (!(a&0x80))
+-  {
+-    a &= SLOT_2_0;
+-    b &= 0x7f;
+-    b = b<<7;
+-    a |= b;
+-    *v = a;
+-    return 3;
++/*
++** Allocate and zero memory.  If the allocation fails, make
++** the mallocFailed flag in the connection pointer.
++*/
++SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){
++  void *p = sqlite3DbMallocRaw(db, n);
++  if( p ){
++    memset(p, 0, n);
+   }
++  return p;
++}
+ 
+-  /* CSE1 from below */
+-  a &= SLOT_2_0;
+-  p++;
+-  b = b<<14;
+-  b |= *p;
+-  /* b: p1<<14 | p3 (unmasked) */
+-  if (!(b&0x80))
+-  {
+-    b &= SLOT_2_0;
+-    /* moved CSE1 up */
+-    /* a &= (0x7f<<14)|(0x7f); */
+-    a = a<<7;
+-    a |= b;
+-    *v = a;
+-    return 4;
++/*
++** Allocate and zero memory.  If the allocation fails, make
++** the mallocFailed flag in the connection pointer.
++**
++** If db!=0 and db->mallocFailed is true (indicating a prior malloc
++** failure on the same database connection) then always return 0.
++** Hence for a particular database connection, once malloc starts
++** failing, it fails consistently until mallocFailed is reset.
++** This is an important assumption.  There are many places in the
++** code that do things like this:
++**
++**         int *a = (int*)sqlite3DbMallocRaw(db, 100);
++**         int *b = (int*)sqlite3DbMallocRaw(db, 200);
++**         if( b ) a[10] = 9;
++**
++** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
++** that all prior mallocs (ex: "a") worked too.
++*/
++SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
++  void *p;
++  assert( db==0 || sqlite3_mutex_held(db->mutex) );
++  assert( db==0 || db->pnBytesFreed==0 );
++#ifndef SQLITE_OMIT_LOOKASIDE
++  if( db ){
++    LookasideSlot *pBuf;
++    if( db->mallocFailed ){
++      return 0;
++    }
++    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;
++      }
++    }
+   }
+-
+-  /* a: p0<<14 | p2 (masked) */
+-  /* b: p1<<14 | p3 (unmasked) */
+-  /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
+-  /* moved CSE1 up */
+-  /* a &= (0x7f<<14)|(0x7f); */
+-  b &= SLOT_2_0;
+-  s = a;
+-  /* s: p0<<14 | p2 (masked) */
+-
+-  p++;
+-  a = a<<14;
+-  a |= *p;
+-  /* a: p0<<28 | p2<<14 | p4 (unmasked) */
+-  if (!(a&0x80))
+-  {
+-    /* we can skip these cause they were (effectively) done above in calc'ing s */
+-    /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
+-    /* b &= (0x7f<<14)|(0x7f); */
+-    b = b<<7;
+-    a |= b;
+-    s = s>>18;
+-    *v = ((u64)s)<<32 | a;
+-    return 5;
++#else
++  if( db && db->mallocFailed ){
++    return 0;
+   }
+-
+-  /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
+-  s = s<<7;
+-  s |= b;
+-  /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
+-
+-  p++;
+-  b = b<<14;
+-  b |= *p;
+-  /* b: p1<<28 | p3<<14 | p5 (unmasked) */
+-  if (!(b&0x80))
+-  {
+-    /* we can skip this cause it was (effectively) done above in calc'ing s */
+-    /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
+-    a &= SLOT_2_0;
+-    a = a<<7;
+-    a |= b;
+-    s = s>>18;
+-    *v = ((u64)s)<<32 | a;
+-    return 6;
++#endif
++  p = sqlite3Malloc(n);
++  if( !p && db ){
++    db->mallocFailed = 1;
+   }
++  sqlite3MemdebugSetType(p, MEMTYPE_DB |
++         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
++  return p;
++}
+ 
+-  p++;
+-  a = a<<14;
+-  a |= *p;
+-  /* a: p2<<28 | p4<<14 | p6 (unmasked) */
+-  if (!(a&0x80))
+-  {
+-    a &= SLOT_4_2_0;
+-    b &= SLOT_2_0;
+-    b = b<<7;
+-    a |= b;
+-    s = s>>11;
+-    *v = ((u64)s)<<32 | a;
+-    return 7;
++/*
++** Resize the block of memory pointed to by p to n bytes. If the
++** resize fails, set the mallocFailed flag in the connection object.
++*/
++SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
++  void *pNew = 0;
++  assert( db!=0 );
++  assert( sqlite3_mutex_held(db->mutex) );
++  if( db->mallocFailed==0 ){
++    if( p==0 ){
++      return sqlite3DbMallocRaw(db, n);
++    }
++    if( isLookaside(db, p) ){
++      if( n<=db->lookaside.sz ){
++        return p;
++      }
++      pNew = sqlite3DbMallocRaw(db, n);
++      if( pNew ){
++        memcpy(pNew, p, db->lookaside.sz);
++        sqlite3DbFree(db, p);
++      }
++    }else{
++      assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
++      assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
++      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
++      pNew = sqlite3_realloc(p, n);
++      if( !pNew ){
++        sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
++        db->mallocFailed = 1;
++      }
++      sqlite3MemdebugSetType(pNew, MEMTYPE_DB | 
++            (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
++    }
+   }
++  return pNew;
++}
+ 
+-  /* CSE2 from below */
+-  a &= SLOT_2_0;
+-  p++;
+-  b = b<<14;
+-  b |= *p;
+-  /* b: p3<<28 | p5<<14 | p7 (unmasked) */
+-  if (!(b&0x80))
+-  {
+-    b &= SLOT_4_2_0;
+-    /* moved CSE2 up */
+-    /* a &= (0x7f<<14)|(0x7f); */
+-    a = a<<7;
+-    a |= b;
+-    s = s>>4;
+-    *v = ((u64)s)<<32 | a;
+-    return 8;
++/*
++** Attempt to reallocate p.  If the reallocation fails, then free p
++** and set the mallocFailed flag in the database connection.
++*/
++SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
++  void *pNew;
++  pNew = sqlite3DbRealloc(db, p, n);
++  if( !pNew ){
++    sqlite3DbFree(db, p);
+   }
+-
+-  p++;
+-  a = a<<15;
+-  a |= *p;
+-  /* a: p4<<29 | p6<<15 | p8 (unmasked) */
+-
+-  /* moved CSE2 up */
+-  /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
+-  b &= SLOT_2_0;
+-  b = b<<8;
+-  a |= b;
+-
+-  s = s<<4;
+-  b = p[-4];
+-  b &= 0x7f;
+-  b = b>>3;
+-  s |= b;
+-
+-  *v = ((u64)s)<<32 | a;
+-
+-  return 9;
++  return pNew;
+ }
+ 
+ /*
+-** Read a 32-bit variable-length integer from memory starting at p[0].
+-** Return the number of bytes read.  The value is stored in *v.
+-**
+-** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
+-** integer, then set *v to 0xffffffff.
+-**
+-** A MACRO version, getVarint32, is provided which inlines the 
+-** single-byte case.  All code should use the MACRO version as 
+-** this function assumes the single-byte case has already been handled.
++** Make a copy of a string in memory obtained from sqliteMalloc(). These 
++** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
++** is because when memory debugging is turned on, these two functions are 
++** called via macros that record the current file and line number in the
++** ThreadData structure.
+ */
+-SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
+-  u32 a,b;
+-
+-  /* The 1-byte case.  Overwhelmingly the most common.  Handled inline
+-  ** by the getVarin32() macro */
+-  a = *p;
+-  /* a: p0 (unmasked) */
+-#ifndef getVarint32
+-  if (!(a&0x80))
+-  {
+-    /* Values between 0 and 127 */
+-    *v = a;
+-    return 1;
++SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
++  char *zNew;
++  size_t n;
++  if( z==0 ){
++    return 0;
+   }
+-#endif
+-
+-  /* The 2-byte case */
+-  p++;
+-  b = *p;
+-  /* b: p1 (unmasked) */
+-  if (!(b&0x80))
+-  {
+-    /* Values between 128 and 16383 */
+-    a &= 0x7f;
+-    a = a<<7;
+-    *v = a | b;
+-    return 2;
++  n = sqlite3Strlen30(z) + 1;
++  assert( (n&0x7fffffff)==n );
++  zNew = sqlite3DbMallocRaw(db, (int)n);
++  if( zNew ){
++    memcpy(zNew, z, n);
+   }
+-
+-  /* The 3-byte case */
+-  p++;
+-  a = a<<14;
+-  a |= *p;
+-  /* a: p0<<14 | p2 (unmasked) */
+-  if (!(a&0x80))
+-  {
+-    /* Values between 16384 and 2097151 */
+-    a &= (0x7f<<14)|(0x7f);
+-    b &= 0x7f;
+-    b = b<<7;
+-    *v = a | b;
+-    return 3;
++  return zNew;
++}
++SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
++  char *zNew;
++  if( z==0 ){
++    return 0;
+   }
+-
+-  /* A 32-bit varint is used to store size information in btrees.
+-  ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
+-  ** A 3-byte varint is sufficient, for example, to record the size
+-  ** of a 1048569-byte BLOB or string.
+-  **
+-  ** We only unroll the first 1-, 2-, and 3- byte cases.  The very
+-  ** rare larger cases can be handled by the slower 64-bit varint
+-  ** routine.
+-  */
+-#if 1
+-  {
+-    u64 v64;
+-    u8 n;
+-
+-    p -= 2;
+-    n = sqlite3GetVarint(p, &v64);
+-    assert( n>3 && n<=9 );
+-    if( (v64 & SQLITE_MAX_U32)!=v64 ){
+-      *v = 0xffffffff;
+-    }else{
+-      *v = (u32)v64;
+-    }
+-    return n;
++  assert( (n&0x7fffffff)==n );
++  zNew = sqlite3DbMallocRaw(db, n+1);
++  if( zNew ){
++    memcpy(zNew, z, n);
++    zNew[n] = 0;
+   }
++  return zNew;
++}
+ 
+-#else
+-  /* For following code (kept for historical record only) shows an
+-  ** unrolling for the 3- and 4-byte varint cases.  This code is
+-  ** slightly faster, but it is also larger and much harder to test.
+-  */
+-  p++;
+-  b = b<<14;
+-  b |= *p;
+-  /* b: p1<<14 | p3 (unmasked) */
+-  if (!(b&0x80))
+-  {
+-    /* Values between 2097152 and 268435455 */
+-    b &= (0x7f<<14)|(0x7f);
+-    a &= (0x7f<<14)|(0x7f);
+-    a = a<<7;
+-    *v = a | b;
+-    return 4;
+-  }
++/*
++** Create a string from the zFromat argument and the va_list that follows.
++** Store the string in memory obtained from sqliteMalloc() and make *pz
++** point to that string.
++*/
++SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
++  va_list ap;
++  char *z;
+ 
+-  p++;
+-  a = a<<14;
+-  a |= *p;
+-  /* a: p0<<28 | p2<<14 | p4 (unmasked) */
+-  if (!(a&0x80))
+-  {
+-    /* Values  between 268435456 and 34359738367 */
+-    a &= SLOT_4_2_0;
+-    b &= SLOT_4_2_0;
+-    b = b<<7;
+-    *v = a | b;
+-    return 5;
+-  }
++  va_start(ap, zFormat);
++  z = sqlite3VMPrintf(db, zFormat, ap);
++  va_end(ap);
++  sqlite3DbFree(db, *pz);
++  *pz = z;
++}
+ 
+-  /* We can only reach this point when reading a corrupt database
+-  ** file.  In that case we are not in any hurry.  Use the (relatively
+-  ** slow) general-purpose sqlite3GetVarint() routine to extract the
+-  ** value. */
+-  {
+-    u64 v64;
+-    u8 n;
+ 
+-    p -= 4;
+-    n = sqlite3GetVarint(p, &v64);
+-    assert( n>5 && n<=9 );
+-    *v = (u32)v64;
+-    return n;
++/*
++** This function must be called before exiting any API function (i.e. 
++** returning control to the user) that has called sqlite3_malloc or
++** sqlite3_realloc.
++**
++** The returned value is normally a copy of the second argument to this
++** function. However, if a malloc() failure has occurred since the previous
++** invocation SQLITE_NOMEM is returned instead. 
++**
++** If the first argument, db, is not NULL and a malloc() error has occurred,
++** then the connection error-code (the value returned by sqlite3_errcode())
++** is set to SQLITE_NOMEM.
++*/
++SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
++  /* If the db handle is not NULL, then we must hold the connection handle
++  ** mutex here. Otherwise the read (and possible write) of db->mallocFailed 
++  ** is unsafe, as is the call to sqlite3Error().
++  */
++  assert( !db || sqlite3_mutex_held(db->mutex) );
++  if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
++    sqlite3Error(db, SQLITE_NOMEM, 0);
++    db->mallocFailed = 0;
++    rc = SQLITE_NOMEM;
+   }
+-#endif
++  return rc & (db ? db->errMask : 0xff);
+ }
+ 
++/************** End of malloc.c **********************************************/
++/************** Begin file printf.c ******************************************/
+ /*
+-** Return the number of bytes that will be needed to store the given
+-** 64-bit integer.
++** The "printf" code that follows dates from the 1980's.  It is in
++** the public domain.  The original comments are included here for
++** completeness.  They are very out-of-date but might be useful as
++** an historical reference.  Most of the "enhancements" have been backed
++** out so that the functionality is now the same as standard printf().
++**
++**************************************************************************
++**
++** This file contains code for a set of "printf"-like routines.  These
++** routines format strings much like the printf() from the standard C
++** library, though the implementation here has enhancements to support
++** SQLlite.
+ */
+-SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
+-  int i = 0;
+-  do{
+-    i++;
+-    v >>= 7;
+-  }while( v!=0 && ALWAYS(i<9) );
+-  return i;
+-}
+-
+ 
+ /*
+-** Read or write a four-byte big-endian integer value.
++** Conversion types fall into various categories as defined by the
++** following enumeration.
+ */
+-SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
+-  return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+-}
+-SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
+-  p[0] = (u8)(v>>24);
+-  p[1] = (u8)(v>>16);
+-  p[2] = (u8)(v>>8);
+-  p[3] = (u8)v;
+-}
++#define etRADIX       1 /* Integer types.  %d, %x, %o, and so forth */
++#define etFLOAT       2 /* Floating point.  %f */
++#define etEXP         3 /* Exponentional notation. %e and %E */
++#define etGENERIC     4 /* Floating or exponential, depending on exponent. %g */
++#define etSIZE        5 /* Return number of characters processed so far. %n */
++#define etSTRING      6 /* Strings. %s */
++#define etDYNSTRING   7 /* Dynamically allocated strings. %z */
++#define etPERCENT     8 /* Percent symbol. %% */
++#define etCHARX       9 /* Characters. %c */
++/* The rest are extensions, not normally found in printf() */
++#define etSQLESCAPE  10 /* Strings with '\'' doubled.  %q */
++#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
++                          NULL pointers replaced by SQL NULL.  %Q */
++#define etTOKEN      12 /* a pointer to a Token structure */
++#define etSRCLIST    13 /* a pointer to a SrcList */
++#define etPOINTER    14 /* The %p conversion */
++#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
++#define etORDINAL    16 /* %r -> 1st, 2nd, 3rd, 4th, etc.  English only */
+ 
++#define etINVALID     0 /* Any unrecognized conversion type */
+ 
+ 
+ /*
+-** Translate a single byte of Hex into an integer.
+-** This routine only works if h really is a valid hexadecimal
+-** character:  0..9a..fA..F
++** An "etByte" is an 8-bit unsigned value.
+ */
+-SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
+-  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
+-#ifdef SQLITE_ASCII
+-  h += 9*(1&(h>>6));
+-#endif
+-#ifdef SQLITE_EBCDIC
+-  h += 9*(1&~(h>>4));
+-#endif
+-  return (u8)(h & 0xf);
+-}
++typedef unsigned char etByte;
+ 
+-#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
+ /*
+-** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
+-** value.  Return a pointer to its binary value.  Space to hold the
+-** binary value has been obtained from malloc and must be freed by
+-** the calling routine.
++** Each builtin conversion character (ex: the 'd' in "%d") is described
++** by an instance of the following structure
+ */
+-SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
+-  char *zBlob;
+-  int i;
+-
+-  zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
+-  n--;
+-  if( zBlob ){
+-    for(i=0; i<n; i+=2){
+-      zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
+-    }
+-    zBlob[i/2] = 0;
+-  }
+-  return zBlob;
+-}
+-#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
++typedef struct et_info {   /* Information about each format field */
++  char fmttype;            /* The format field code letter */
++  etByte base;             /* The base for radix conversion */
++  etByte flags;            /* One or more of FLAG_ constants below */
++  etByte type;             /* Conversion paradigm */
++  etByte charset;          /* Offset into aDigits[] of the digits string */
++  etByte prefix;           /* Offset into aPrefix[] of the prefix string */
++} et_info;
+ 
+ /*
+-** Log an error that is an API call on a connection pointer that should
+-** not have been used.  The "type" of connection pointer is given as the
+-** argument.  The zType is a word like "NULL" or "closed" or "invalid".
++** Allowed values for et_info.flags
+ */
+-static void logBadConnection(const char *zType){
+-  sqlite3_log(SQLITE_MISUSE, 
+-     "API call with %s database connection pointer",
+-     zType
+-  );
+-}
++#define FLAG_SIGNED  1     /* True if the value to convert is signed */
++#define FLAG_INTERN  2     /* True if for internal use only */
++#define FLAG_STRING  4     /* Allow infinity precision */
++
+ 
+ /*
+-** Check to make sure we have a valid db pointer.  This test is not
+-** foolproof but it does provide some measure of protection against
+-** misuse of the interface such as passing in db pointers that are
+-** NULL or which have been previously closed.  If this routine returns
+-** 1 it means that the db pointer is valid and 0 if it should not be
+-** dereferenced for any reason.  The calling function should invoke
+-** SQLITE_MISUSE immediately.
+-**
+-** sqlite3SafetyCheckOk() requires that the db pointer be valid for
+-** use.  sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
+-** open properly and is not fit for general use but which can be
+-** used as an argument to sqlite3_errmsg() or sqlite3_close().
++** The following table is searched linearly, so it is good to put the
++** most frequently used conversion types first.
+ */
+-SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
+-  u32 magic;
+-  if( db==0 ){
+-    logBadConnection("NULL");
+-    return 0;
+-  }
+-  magic = db->magic;
+-  if( magic!=SQLITE_MAGIC_OPEN ){
+-    if( sqlite3SafetyCheckSickOrOk(db) ){
+-      testcase( sqlite3GlobalConfig.xLog!=0 );
+-      logBadConnection("unopened");
+-    }
+-    return 0;
+-  }else{
+-    return 1;
+-  }
+-}
+-SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
+-  u32 magic;
+-  magic = db->magic;
+-  if( magic!=SQLITE_MAGIC_SICK &&
+-      magic!=SQLITE_MAGIC_OPEN &&
+-      magic!=SQLITE_MAGIC_BUSY ){
+-    testcase( sqlite3GlobalConfig.xLog!=0 );
+-    logBadConnection("invalid");
+-    return 0;
+-  }else{
+-    return 1;
+-  }
+-}
+-
+-/*
+-** Attempt to add, substract, or multiply the 64-bit signed value iB against
+-** the other 64-bit signed integer at *pA and store the result in *pA.
+-** Return 0 on success.  Or if the operation would have resulted in an
+-** overflow, leave *pA unchanged and return 1.
+-*/
+-SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
+-  i64 iA = *pA;
+-  testcase( iA==0 ); testcase( iA==1 );
+-  testcase( iB==-1 ); testcase( iB==0 );
+-  if( iB>=0 ){
+-    testcase( iA>0 && LARGEST_INT64 - iA == iB );
+-    testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
+-    if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
+-    *pA += iB;
+-  }else{
+-    testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
+-    testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
+-    if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
+-    *pA += iB;
+-  }
+-  return 0; 
+-}
+-SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
+-  testcase( iB==SMALLEST_INT64+1 );
+-  if( iB==SMALLEST_INT64 ){
+-    testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
+-    if( (*pA)>=0 ) return 1;
+-    *pA -= iB;
+-    return 0;
+-  }else{
+-    return sqlite3AddInt64(pA, -iB);
+-  }
+-}
+-#define TWOPOWER32 (((i64)1)<<32)
+-#define TWOPOWER31 (((i64)1)<<31)
+-SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
+-  i64 iA = *pA;
+-  i64 iA1, iA0, iB1, iB0, r;
++static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
++static const char aPrefix[] = "-x0\000X0";
++static const et_info fmtinfo[] = {
++  {  'd', 10, 1, etRADIX,      0,  0 },
++  {  's',  0, 4, etSTRING,     0,  0 },
++  {  'g',  0, 1, etGENERIC,    30, 0 },
++  {  'z',  0, 4, etDYNSTRING,  0,  0 },
++  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
++  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
++  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
++  {  'c',  0, 0, etCHARX,      0,  0 },
++  {  'o',  8, 0, etRADIX,      0,  2 },
++  {  'u', 10, 0, etRADIX,      0,  0 },
++  {  'x', 16, 0, etRADIX,      16, 1 },
++  {  'X', 16, 0, etRADIX,      0,  4 },
++#ifndef SQLITE_OMIT_FLOATING_POINT
++  {  'f',  0, 1, etFLOAT,      0,  0 },
++  {  'e',  0, 1, etEXP,        30, 0 },
++  {  'E',  0, 1, etEXP,        14, 0 },
++  {  'G',  0, 1, etGENERIC,    14, 0 },
++#endif
++  {  'i', 10, 1, etRADIX,      0,  0 },
++  {  'n',  0, 0, etSIZE,       0,  0 },
++  {  '%',  0, 0, etPERCENT,    0,  0 },
++  {  'p', 16, 0, etPOINTER,    0,  1 },
+ 
+-  iA1 = iA/TWOPOWER32;
+-  iA0 = iA % TWOPOWER32;
+-  iB1 = iB/TWOPOWER32;
+-  iB0 = iB % TWOPOWER32;
+-  if( iA1*iB1 != 0 ) return 1;
+-  assert( iA1*iB0==0 || iA0*iB1==0 );
+-  r = iA1*iB0 + iA0*iB1;
+-  testcase( r==(-TWOPOWER31)-1 );
+-  testcase( r==(-TWOPOWER31) );
+-  testcase( r==TWOPOWER31 );
+-  testcase( r==TWOPOWER31-1 );
+-  if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
+-  r *= TWOPOWER32;
+-  if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
+-  *pA = r;
+-  return 0;
+-}
++/* All the rest have the FLAG_INTERN bit set and are thus for internal
++** use only */
++  {  'T',  0, 2, etTOKEN,      0,  0 },
++  {  'S',  0, 2, etSRCLIST,    0,  0 },
++  {  'r', 10, 3, etORDINAL,    0,  0 },
++};
+ 
+ /*
+-** Compute the absolute value of a 32-bit signed integer, of possible.  Or 
+-** if the integer has a value of -2147483648, return +2147483647
++** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
++** conversions will work.
+ */
+-SQLITE_PRIVATE int sqlite3AbsInt32(int x){
+-  if( x>=0 ) return x;
+-  if( x==(int)0x80000000 ) return 0x7fffffff;
+-  return -x;
+-}
+-
+-#ifdef SQLITE_ENABLE_8_3_NAMES
++#ifndef SQLITE_OMIT_FLOATING_POINT
+ /*
+-** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
+-** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
+-** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
+-** three characters, then shorten the suffix on z[] to be the last three
+-** characters of the original suffix.
+-**
+-** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
+-** do the suffix shortening regardless of URI parameter.
++** "*val" is a double such that 0.1 <= *val < 10.0
++** Return the ascii code for the leading digit of *val, then
++** multiply "*val" by 10.0 to renormalize.
+ **
+-** Examples:
++** Example:
++**     input:     *val = 3.14159
++**     output:    *val = 1.4159    function return = '3'
+ **
+-**     test.db-journal    =>   test.nal
+-**     test.db-wal        =>   test.wal
+-**     test.db-shm        =>   test.shm
+-**     test.db-mj7f3319fa =>   test.9fa
++** The counter *cnt is incremented each time.  After counter exceeds
++** 16 (the number of significant digits in a 64-bit float) '0' is
++** always returned.
+ */
+-SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
+-#if SQLITE_ENABLE_8_3_NAMES<2
+-  if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
+-#endif
+-  {
+-    int i, sz;
+-    sz = sqlite3Strlen30(z);
+-    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
+-    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
+-  }
++static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
++  int digit;
++  LONGDOUBLE_TYPE d;
++  if( (*cnt)<=0 ) return '0';
++  (*cnt)--;
++  digit = (int)*val;
++  d = digit;
++  digit += '0';
++  *val = (*val - d)*10.0;
++  return (char)digit;
+ }
+-#endif
++#endif /* SQLITE_OMIT_FLOATING_POINT */
+ 
+-/************** End of util.c ************************************************/
+-/************** Begin file hash.c ********************************************/
+ /*
+-** 2001 September 22
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-** This is the implementation of generic hash-tables
+-** used in SQLite.
+-*/
+-/* #include <assert.h> */
+-
+-/* Turn bulk memory into a hash table object by initializing the
+-** fields of the Hash structure.
+-**
+-** "pNew" is a pointer to the hash table that is to be initialized.
+-*/
+-SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
+-  assert( pNew!=0 );
+-  pNew->first = 0;
+-  pNew->count = 0;
+-  pNew->htsize = 0;
+-  pNew->ht = 0;
+-}
+-
+-/* Remove all entries from a hash table.  Reclaim all memory.
+-** Call this routine to delete a hash table or to reset a hash table
+-** to the empty state.
++** Append N space characters to the given string buffer.
+ */
+-SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
+-  HashElem *elem;         /* For looping over all elements of the table */
+-
+-  assert( pH!=0 );
+-  elem = pH->first;
+-  pH->first = 0;
+-  sqlite3_free(pH->ht);
+-  pH->ht = 0;
+-  pH->htsize = 0;
+-  while( elem ){
+-    HashElem *next_elem = elem->next;
+-    sqlite3_free(elem);
+-    elem = next_elem;
++SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
++  static const char zSpaces[] = "                             ";
++  while( N>=(int)sizeof(zSpaces)-1 ){
++    sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
++    N -= sizeof(zSpaces)-1;
++  }
++  if( N>0 ){
++    sqlite3StrAccumAppend(pAccum, zSpaces, N);
+   }
+-  pH->count = 0;
+ }
+ 
+ /*
+-** The hashing function.
++** On machines with a small stack size, you can redefine the
++** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
+ */
+-static unsigned int strHash(const char *z, int nKey){
+-  int h = 0;
+-  assert( nKey>=0 );
+-  while( nKey > 0  ){
+-    h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
+-    nKey--;
+-  }
+-  return h;
+-}
+-
++#ifndef SQLITE_PRINT_BUF_SIZE
++# define SQLITE_PRINT_BUF_SIZE 70
++#endif
++#define etBUFSIZE SQLITE_PRINT_BUF_SIZE  /* Size of the output buffer */
+ 
+-/* Link pNew element into the hash table pH.  If pEntry!=0 then also
+-** insert pNew into the pEntry hash bucket.
++/*
++** Render a string given by "fmt" into the StrAccum object.
+ */
+-static void insertElement(
+-  Hash *pH,              /* The complete hash table */
+-  struct _ht *pEntry,    /* The entry into which pNew is inserted */
+-  HashElem *pNew         /* The element to be inserted */
++SQLITE_PRIVATE void sqlite3VXPrintf(
++  StrAccum *pAccum,                  /* Accumulate results here */
++  int useExtended,                   /* Allow extended %-conversions */
++  const char *fmt,                   /* Format string */
++  va_list ap                         /* arguments */
+ ){
+-  HashElem *pHead;       /* First element already in pEntry */
+-  if( pEntry ){
+-    pHead = pEntry->count ? pEntry->chain : 0;
+-    pEntry->count++;
+-    pEntry->chain = pNew;
+-  }else{
+-    pHead = 0;
+-  }
+-  if( pHead ){
+-    pNew->next = pHead;
+-    pNew->prev = pHead->prev;
+-    if( pHead->prev ){ pHead->prev->next = pNew; }
+-    else             { pH->first = pNew; }
+-    pHead->prev = pNew;
+-  }else{
+-    pNew->next = pH->first;
+-    if( pH->first ){ pH->first->prev = pNew; }
+-    pNew->prev = 0;
+-    pH->first = pNew;
+-  }
+-}
+-
+-
+-/* Resize the hash table so that it cantains "new_size" buckets.
+-**
+-** The hash table might fail to resize if sqlite3_malloc() fails or
+-** if the new size is the same as the prior size.
+-** Return TRUE if the resize occurs and false if not.
+-*/
+-static int rehash(Hash *pH, unsigned int new_size){
+-  struct _ht *new_ht;            /* The new hash table */
+-  HashElem *elem, *next_elem;    /* For looping over existing elements */
+-
+-#if SQLITE_MALLOC_SOFT_LIMIT>0
+-  if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
+-    new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
+-  }
+-  if( new_size==pH->htsize ) return 0;
++  int c;                     /* Next character in the format string */
++  char *bufpt;               /* Pointer to the conversion buffer */
++  int precision;             /* Precision of the current field */
++  int length;                /* Length of the field */
++  int idx;                   /* A general purpose loop counter */
++  int width;                 /* Width of the current field */
++  etByte flag_leftjustify;   /* True if "-" flag is present */
++  etByte flag_plussign;      /* True if "+" flag is present */
++  etByte flag_blanksign;     /* True if " " flag is present */
++  etByte flag_alternateform; /* True if "#" flag is present */
++  etByte flag_altform2;      /* True if "!" flag is present */
++  etByte flag_zeropad;       /* True if field width constant starts with zero */
++  etByte flag_long;          /* True if "l" flag is present */
++  etByte flag_longlong;      /* True if the "ll" flag is present */
++  etByte done;               /* Loop termination flag */
++  etByte xtype = 0;          /* Conversion paradigm */
++  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
++  sqlite_uint64 longvalue;   /* Value for integer types */
++  LONGDOUBLE_TYPE realvalue; /* Value for real types */
++  const et_info *infop;      /* Pointer to the appropriate info structure */
++  char *zOut;                /* Rendering buffer */
++  int nOut;                  /* Size of the rendering buffer */
++  char *zExtra;              /* Malloced memory used by some conversion */
++#ifndef SQLITE_OMIT_FLOATING_POINT
++  int  exp, e2;              /* exponent of real numbers */
++  int nsd;                   /* Number of significant digits returned */
++  double rounder;            /* Used for rounding floating point values */
++  etByte flag_dp;            /* True if decimal point should be shown */
++  etByte flag_rtz;           /* True if trailing zeros should be removed */
+ #endif
++  char buf[etBUFSIZE];       /* Conversion buffer */
+ 
+-  /* The inability to allocates space for a larger hash table is
+-  ** a performance hit but it is not a fatal error.  So mark the
+-  ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of 
+-  ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
+-  ** only zeroes the requested number of bytes whereas this module will
+-  ** use the actual amount of space allocated for the hash table (which
+-  ** may be larger than the requested amount).
+-  */
+-  sqlite3BeginBenignMalloc();
+-  new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
+-  sqlite3EndBenignMalloc();
++  bufpt = 0;
++  for(; (c=(*fmt))!=0; ++fmt){
++    if( c!='%' ){
++      int amt;
++      bufpt = (char *)fmt;
++      amt = 1;
++      while( (c=(*++fmt))!='%' && c!=0 ) amt++;
++      sqlite3StrAccumAppend(pAccum, bufpt, amt);
++      if( c==0 ) break;
++    }
++    if( (c=(*++fmt))==0 ){
++      sqlite3StrAccumAppend(pAccum, "%", 1);
++      break;
++    }
++    /* Find out what flags are present */
++    flag_leftjustify = flag_plussign = flag_blanksign = 
++     flag_alternateform = flag_altform2 = flag_zeropad = 0;
++    done = 0;
++    do{
++      switch( c ){
++        case '-':   flag_leftjustify = 1;     break;
++        case '+':   flag_plussign = 1;        break;
++        case ' ':   flag_blanksign = 1;       break;
++        case '#':   flag_alternateform = 1;   break;
++        case '!':   flag_altform2 = 1;        break;
++        case '0':   flag_zeropad = 1;         break;
++        default:    done = 1;                 break;
++      }
++    }while( !done && (c=(*++fmt))!=0 );
++    /* Get the field width */
++    width = 0;
++    if( c=='*' ){
++      width = va_arg(ap,int);
++      if( width<0 ){
++        flag_leftjustify = 1;
++        width = -width;
++      }
++      c = *++fmt;
++    }else{
++      while( c>='0' && c<='9' ){
++        width = width*10 + c - '0';
++        c = *++fmt;
++      }
++    }
++    /* Get the precision */
++    if( c=='.' ){
++      precision = 0;
++      c = *++fmt;
++      if( c=='*' ){
++        precision = va_arg(ap,int);
++        if( precision<0 ) precision = -precision;
++        c = *++fmt;
++      }else{
++        while( c>='0' && c<='9' ){
++          precision = precision*10 + c - '0';
++          c = *++fmt;
++        }
++      }
++    }else{
++      precision = -1;
++    }
++    /* Get the conversion type modifier */
++    if( c=='l' ){
++      flag_long = 1;
++      c = *++fmt;
++      if( c=='l' ){
++        flag_longlong = 1;
++        c = *++fmt;
++      }else{
++        flag_longlong = 0;
++      }
++    }else{
++      flag_long = flag_longlong = 0;
++    }
++    /* Fetch the info entry for the field */
++    infop = &fmtinfo[0];
++    xtype = etINVALID;
++    for(idx=0; idx<ArraySize(fmtinfo); idx++){
++      if( c==fmtinfo[idx].fmttype ){
++        infop = &fmtinfo[idx];
++        if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
++          xtype = infop->type;
++        }else{
++          return;
++        }
++        break;
++      }
++    }
++    zExtra = 0;
+ 
+-  if( new_ht==0 ) return 0;
+-  sqlite3_free(pH->ht);
+-  pH->ht = new_ht;
+-  pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
+-  memset(new_ht, 0, new_size*sizeof(struct _ht));
+-  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
+-    unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
+-    next_elem = elem->next;
+-    insertElement(pH, &new_ht[h], elem);
+-  }
+-  return 1;
+-}
++    /*
++    ** At this point, variables are initialized as follows:
++    **
++    **   flag_alternateform          TRUE if a '#' is present.
++    **   flag_altform2               TRUE if a '!' is present.
++    **   flag_plussign               TRUE if a '+' is present.
++    **   flag_leftjustify            TRUE if a '-' is present or if the
++    **                               field width was negative.
++    **   flag_zeropad                TRUE if the width began with 0.
++    **   flag_long                   TRUE if the letter 'l' (ell) prefixed
++    **                               the conversion character.
++    **   flag_longlong               TRUE if the letter 'll' (ell ell) prefixed
++    **                               the conversion character.
++    **   flag_blanksign              TRUE if a ' ' is present.
++    **   width                       The specified field width.  This is
++    **                               always non-negative.  Zero is the default.
++    **   precision                   The specified precision.  The default
++    **                               is -1.
++    **   xtype                       The class of the conversion.
++    **   infop                       Pointer to the appropriate info struct.
++    */
++    switch( xtype ){
++      case etPOINTER:
++        flag_longlong = sizeof(char*)==sizeof(i64);
++        flag_long = sizeof(char*)==sizeof(long int);
++        /* Fall through into the next case */
++      case etORDINAL:
++      case etRADIX:
++        if( infop->flags & FLAG_SIGNED ){
++          i64 v;
++          if( flag_longlong ){
++            v = va_arg(ap,i64);
++          }else if( flag_long ){
++            v = va_arg(ap,long int);
++          }else{
++            v = va_arg(ap,int);
++          }
++          if( v<0 ){
++            if( v==SMALLEST_INT64 ){
++              longvalue = ((u64)1)<<63;
++            }else{
++              longvalue = -v;
++            }
++            prefix = '-';
++          }else{
++            longvalue = v;
++            if( flag_plussign )        prefix = '+';
++            else if( flag_blanksign )  prefix = ' ';
++            else                       prefix = 0;
++          }
++        }else{
++          if( flag_longlong ){
++            longvalue = va_arg(ap,u64);
++          }else if( flag_long ){
++            longvalue = va_arg(ap,unsigned long int);
++          }else{
++            longvalue = va_arg(ap,unsigned int);
++          }
++          prefix = 0;
++        }
++        if( longvalue==0 ) flag_alternateform = 0;
++        if( flag_zeropad && precision<width-(prefix!=0) ){
++          precision = width-(prefix!=0);
++        }
++        if( precision<etBUFSIZE-10 ){
++          nOut = etBUFSIZE;
++          zOut = buf;
++        }else{
++          nOut = precision + 10;
++          zOut = zExtra = sqlite3Malloc( nOut );
++          if( zOut==0 ){
++            pAccum->mallocFailed = 1;
++            return;
++          }
++        }
++        bufpt = &zOut[nOut-1];
++        if( xtype==etORDINAL ){
++          static const char zOrd[] = "thstndrd";
++          int x = (int)(longvalue % 10);
++          if( x>=4 || (longvalue/10)%10==1 ){
++            x = 0;
++          }
++          *(--bufpt) = zOrd[x*2+1];
++          *(--bufpt) = zOrd[x*2];
++        }
++        {
++          register const char *cset;      /* Use registers for speed */
++          register int base;
++          cset = &aDigits[infop->charset];
++          base = infop->base;
++          do{                                           /* Convert to ascii */
++            *(--bufpt) = cset[longvalue%base];
++            longvalue = longvalue/base;
++          }while( longvalue>0 );
++        }
++        length = (int)(&zOut[nOut-1]-bufpt);
++        for(idx=precision-length; idx>0; idx--){
++          *(--bufpt) = '0';                             /* Zero pad */
++        }
++        if( prefix ) *(--bufpt) = prefix;               /* Add sign */
++        if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */
++          const char *pre;
++          char x;
++          pre = &aPrefix[infop->prefix];
++          for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
++        }
++        length = (int)(&zOut[nOut-1]-bufpt);
++        break;
++      case etFLOAT:
++      case etEXP:
++      case etGENERIC:
++        realvalue = va_arg(ap,double);
++#ifdef SQLITE_OMIT_FLOATING_POINT
++        length = 0;
++#else
++        if( precision<0 ) precision = 6;         /* Set default precision */
++        if( realvalue<0.0 ){
++          realvalue = -realvalue;
++          prefix = '-';
++        }else{
++          if( flag_plussign )          prefix = '+';
++          else if( flag_blanksign )    prefix = ' ';
++          else                         prefix = 0;
++        }
++        if( xtype==etGENERIC && precision>0 ) precision--;
++#if 0
++        /* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
++        for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
++#else
++        /* It makes more sense to use 0.5 */
++        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
++#endif
++        if( xtype==etFLOAT ) realvalue += rounder;
++        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
++        exp = 0;
++        if( sqlite3IsNaN((double)realvalue) ){
++          bufpt = "NaN";
++          length = 3;
++          break;
++        }
++        if( realvalue>0.0 ){
++          LONGDOUBLE_TYPE scale = 1.0;
++          while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
++          while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
++          while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
++          while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
++          realvalue /= scale;
++          while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
++          while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
++          if( exp>350 ){
++            if( prefix=='-' ){
++              bufpt = "-Inf";
++            }else if( prefix=='+' ){
++              bufpt = "+Inf";
++            }else{
++              bufpt = "Inf";
++            }
++            length = sqlite3Strlen30(bufpt);
++            break;
++          }
++        }
++        bufpt = buf;
++        /*
++        ** If the field type is etGENERIC, then convert to either etEXP
++        ** or etFLOAT, as appropriate.
++        */
++        if( xtype!=etFLOAT ){
++          realvalue += rounder;
++          if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
++        }
++        if( xtype==etGENERIC ){
++          flag_rtz = !flag_alternateform;
++          if( exp<-4 || exp>precision ){
++            xtype = etEXP;
++          }else{
++            precision = precision - exp;
++            xtype = etFLOAT;
++          }
++        }else{
++          flag_rtz = flag_altform2;
++        }
++        if( xtype==etEXP ){
++          e2 = 0;
++        }else{
++          e2 = exp;
++        }
++        if( e2+precision+width > etBUFSIZE - 15 ){
++          bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
++          if( bufpt==0 ){
++            pAccum->mallocFailed = 1;
++            return;
++          }
++        }
++        zOut = bufpt;
++        nsd = 16 + flag_altform2*10;
++        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
++        /* The sign in front of the number */
++        if( prefix ){
++          *(bufpt++) = prefix;
++        }
++        /* Digits prior to the decimal point */
++        if( e2<0 ){
++          *(bufpt++) = '0';
++        }else{
++          for(; e2>=0; e2--){
++            *(bufpt++) = et_getdigit(&realvalue,&nsd);
++          }
++        }
++        /* The decimal point */
++        if( flag_dp ){
++          *(bufpt++) = '.';
++        }
++        /* "0" digits after the decimal point but before the first
++        ** significant digit of the number */
++        for(e2++; e2<0; precision--, e2++){
++          assert( precision>0 );
++          *(bufpt++) = '0';
++        }
++        /* Significant digits after the decimal point */
++        while( (precision--)>0 ){
++          *(bufpt++) = et_getdigit(&realvalue,&nsd);
++        }
++        /* Remove trailing zeros and the "." if no digits follow the "." */
++        if( flag_rtz && flag_dp ){
++          while( bufpt[-1]=='0' ) *(--bufpt) = 0;
++          assert( bufpt>zOut );
++          if( bufpt[-1]=='.' ){
++            if( flag_altform2 ){
++              *(bufpt++) = '0';
++            }else{
++              *(--bufpt) = 0;
++            }
++          }
++        }
++        /* Add the "eNNN" suffix */
++        if( xtype==etEXP ){
++          *(bufpt++) = aDigits[infop->charset];
++          if( exp<0 ){
++            *(bufpt++) = '-'; exp = -exp;
++          }else{
++            *(bufpt++) = '+';
++          }
++          if( exp>=100 ){
++            *(bufpt++) = (char)((exp/100)+'0');        /* 100's digit */
++            exp %= 100;
++          }
++          *(bufpt++) = (char)(exp/10+'0');             /* 10's digit */
++          *(bufpt++) = (char)(exp%10+'0');             /* 1's digit */
++        }
++        *bufpt = 0;
+ 
+-/* This function (for internal use only) locates an element in an
+-** hash table that matches the given key.  The hash for this key has
+-** already been computed and is passed as the 4th parameter.
+-*/
+-static HashElem *findElementGivenHash(
+-  const Hash *pH,     /* The pH to be searched */
+-  const char *pKey,   /* The key we are searching for */
+-  int nKey,           /* Bytes in key (not counting zero terminator) */
+-  unsigned int h      /* The hash for this key. */
+-){
+-  HashElem *elem;                /* Used to loop thru the element list */
+-  int count;                     /* Number of elements left to test */
++        /* The converted number is in buf[] and zero terminated. Output it.
++        ** Note that the number is in the usual order, not reversed as with
++        ** integer conversions. */
++        length = (int)(bufpt-zOut);
++        bufpt = zOut;
+ 
+-  if( pH->ht ){
+-    struct _ht *pEntry = &pH->ht[h];
+-    elem = pEntry->chain;
+-    count = pEntry->count;
+-  }else{
+-    elem = pH->first;
+-    count = pH->count;
+-  }
+-  while( count-- && ALWAYS(elem) ){
+-    if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ 
+-      return elem;
++        /* Special case:  Add leading zeros if the flag_zeropad flag is
++        ** set and we are not left justified */
++        if( flag_zeropad && !flag_leftjustify && length < width){
++          int i;
++          int nPad = width - length;
++          for(i=width; i>=nPad; i--){
++            bufpt[i] = bufpt[i-nPad];
++          }
++          i = prefix!=0;
++          while( nPad-- ) bufpt[i++] = '0';
++          length = width;
++        }
++#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
++        break;
++      case etSIZE:
++        *(va_arg(ap,int*)) = pAccum->nChar;
++        length = width = 0;
++        break;
++      case etPERCENT:
++        buf[0] = '%';
++        bufpt = buf;
++        length = 1;
++        break;
++      case etCHARX:
++        c = va_arg(ap,int);
++        buf[0] = (char)c;
++        if( precision>=0 ){
++          for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
++          length = precision;
++        }else{
++          length =1;
++        }
++        bufpt = buf;
++        break;
++      case etSTRING:
++      case etDYNSTRING:
++        bufpt = va_arg(ap,char*);
++        if( bufpt==0 ){
++          bufpt = "";
++        }else if( xtype==etDYNSTRING ){
++          zExtra = bufpt;
++        }
++        if( precision>=0 ){
++          for(length=0; length<precision && bufpt[length]; length++){}
++        }else{
++          length = sqlite3Strlen30(bufpt);
++        }
++        break;
++      case etSQLESCAPE:
++      case etSQLESCAPE2:
++      case etSQLESCAPE3: {
++        int i, j, k, n, isnull;
++        int needQuote;
++        char ch;
++        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
++        char *escarg = va_arg(ap,char*);
++        isnull = escarg==0;
++        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
++        k = precision;
++        for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
++          if( ch==q )  n++;
++        }
++        needQuote = !isnull && xtype==etSQLESCAPE2;
++        n += i + 1 + needQuote*2;
++        if( n>etBUFSIZE ){
++          bufpt = zExtra = sqlite3Malloc( n );
++          if( bufpt==0 ){
++            pAccum->mallocFailed = 1;
++            return;
++          }
++        }else{
++          bufpt = buf;
++        }
++        j = 0;
++        if( needQuote ) bufpt[j++] = q;
++        k = i;
++        for(i=0; i<k; i++){
++          bufpt[j++] = ch = escarg[i];
++          if( ch==q ) bufpt[j++] = ch;
++        }
++        if( needQuote ) bufpt[j++] = q;
++        bufpt[j] = 0;
++        length = j;
++        /* The precision in %q and %Q means how many input characters to
++        ** consume, not the length of the output...
++        ** if( precision>=0 && precision<length ) length = precision; */
++        break;
++      }
++      case etTOKEN: {
++        Token *pToken = va_arg(ap, Token*);
++        if( pToken ){
++          sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
++        }
++        length = width = 0;
++        break;
++      }
++      case etSRCLIST: {
++        SrcList *pSrc = va_arg(ap, SrcList*);
++        int k = va_arg(ap, int);
++        struct SrcList_item *pItem = &pSrc->a[k];
++        assert( k>=0 && k<pSrc->nSrc );
++        if( pItem->zDatabase ){
++          sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
++          sqlite3StrAccumAppend(pAccum, ".", 1);
++        }
++        sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
++        length = width = 0;
++        break;
++      }
++      default: {
++        assert( xtype==etINVALID );
++        return;
++      }
++    }/* End switch over the format type */
++    /*
++    ** The text of the conversion is pointed to by "bufpt" and is
++    ** "length" characters long.  The field width is "width".  Do
++    ** the output.
++    */
++    if( !flag_leftjustify ){
++      register int nspace;
++      nspace = width-length;
++      if( nspace>0 ){
++        sqlite3AppendSpace(pAccum, nspace);
++      }
+     }
+-    elem = elem->next;
+-  }
+-  return 0;
+-}
++    if( length>0 ){
++      sqlite3StrAccumAppend(pAccum, bufpt, length);
++    }
++    if( flag_leftjustify ){
++      register int nspace;
++      nspace = width-length;
++      if( nspace>0 ){
++        sqlite3AppendSpace(pAccum, nspace);
++      }
++    }
++    sqlite3_free(zExtra);
++  }/* End for loop over the format string */
++} /* End of function */
+ 
+-/* Remove a single entry from the hash table given a pointer to that
+-** element and a hash on the element's key.
++/*
++** Append N bytes of text from z to the StrAccum object.
+ */
+-static void removeElementGivenHash(
+-  Hash *pH,         /* The pH containing "elem" */
+-  HashElem* elem,   /* The element to be removed from the pH */
+-  unsigned int h    /* Hash value for the element */
+-){
+-  struct _ht *pEntry;
+-  if( elem->prev ){
+-    elem->prev->next = elem->next; 
+-  }else{
+-    pH->first = elem->next;
++SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
++  assert( z!=0 || N==0 );
++  if( p->tooBig | p->mallocFailed ){
++    testcase(p->tooBig);
++    testcase(p->mallocFailed);
++    return;
+   }
+-  if( elem->next ){
+-    elem->next->prev = elem->prev;
++  assert( p->zText!=0 || p->nChar==0 );
++  if( N<0 ){
++    N = sqlite3Strlen30(z);
+   }
+-  if( pH->ht ){
+-    pEntry = &pH->ht[h];
+-    if( pEntry->chain==elem ){
+-      pEntry->chain = elem->next;
+-    }
+-    pEntry->count--;
+-    assert( pEntry->count>=0 );
++  if( N==0 || NEVER(z==0) ){
++    return;
+   }
+-  sqlite3_free( elem );
+-  pH->count--;
+-  if( pH->count==0 ){
+-    assert( pH->first==0 );
+-    assert( pH->count==0 );
+-    sqlite3HashClear(pH);
++  if( p->nChar+N >= p->nAlloc ){
++    char *zNew;
++    if( !p->useMalloc ){
++      p->tooBig = 1;
++      N = p->nAlloc - p->nChar - 1;
++      if( N<=0 ){
++        return;
++      }
++    }else{
++      char *zOld = (p->zText==p->zBase ? 0 : p->zText);
++      i64 szNew = p->nChar;
++      szNew += N + 1;
++      if( szNew > p->mxAlloc ){
++        sqlite3StrAccumReset(p);
++        p->tooBig = 1;
++        return;
++      }else{
++        p->nAlloc = (int)szNew;
++      }
++      if( p->useMalloc==1 ){
++        zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
++      }else{
++        zNew = sqlite3_realloc(zOld, p->nAlloc);
++      }
++      if( zNew ){
++        if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
++        p->zText = zNew;
++      }else{
++        p->mallocFailed = 1;
++        sqlite3StrAccumReset(p);
++        return;
++      }
++    }
+   }
++  assert( p->zText );
++  memcpy(&p->zText[p->nChar], z, N);
++  p->nChar += N;
+ }
+ 
+-/* Attempt to locate an element of the hash table pH with a key
+-** that matches pKey,nKey.  Return the data for this element if it is
+-** found, or NULL if there is no match.
++/*
++** Finish off a string by making sure it is zero-terminated.
++** Return a pointer to the resulting string.  Return a NULL
++** pointer if any kind of error was encountered.
+ */
+-SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
+-  HashElem *elem;    /* The element that matches key */
+-  unsigned int h;    /* A hash on key */
+-
+-  assert( pH!=0 );
+-  assert( pKey!=0 );
+-  assert( nKey>=0 );
+-  if( pH->ht ){
+-    h = strHash(pKey, nKey) % pH->htsize;
+-  }else{
+-    h = 0;
++SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
++  if( p->zText ){
++    p->zText[p->nChar] = 0;
++    if( p->useMalloc && p->zText==p->zBase ){
++      if( p->useMalloc==1 ){
++        p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
++      }else{
++        p->zText = sqlite3_malloc(p->nChar+1);
++      }
++      if( p->zText ){
++        memcpy(p->zText, p->zBase, p->nChar+1);
++      }else{
++        p->mallocFailed = 1;
++      }
++    }
+   }
+-  elem = findElementGivenHash(pH, pKey, nKey, h);
+-  return elem ? elem->data : 0;
++  return p->zText;
+ }
+ 
+-/* Insert an element into the hash table pH.  The key is pKey,nKey
+-** and the data is "data".
+-**
+-** If no element exists with a matching key, then a new
+-** element is created and NULL is returned.
+-**
+-** If another element already exists with the same key, then the
+-** new data replaces the old data and the old data is returned.
+-** The key is not copied in this instance.  If a malloc fails, then
+-** the new data is returned and the hash table is unchanged.
+-**
+-** If the "data" parameter to this function is NULL, then the
+-** element corresponding to "key" is removed from the hash table.
++/*
++** Reset an StrAccum string.  Reclaim all malloced memory.
+ */
+-SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
+-  unsigned int h;       /* the hash of the key modulo hash table size */
+-  HashElem *elem;       /* Used to loop thru the element list */
+-  HashElem *new_elem;   /* New element added to the pH */
+-
+-  assert( pH!=0 );
+-  assert( pKey!=0 );
+-  assert( nKey>=0 );
+-  if( pH->htsize ){
+-    h = strHash(pKey, nKey) % pH->htsize;
+-  }else{
+-    h = 0;
+-  }
+-  elem = findElementGivenHash(pH,pKey,nKey,h);
+-  if( elem ){
+-    void *old_data = elem->data;
+-    if( data==0 ){
+-      removeElementGivenHash(pH,elem,h);
++SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
++  if( p->zText!=p->zBase ){
++    if( p->useMalloc==1 ){
++      sqlite3DbFree(p->db, p->zText);
+     }else{
+-      elem->data = data;
+-      elem->pKey = pKey;
+-      assert(nKey==elem->nKey);
+-    }
+-    return old_data;
+-  }
+-  if( data==0 ) return 0;
+-  new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
+-  if( new_elem==0 ) return data;
+-  new_elem->pKey = pKey;
+-  new_elem->nKey = nKey;
+-  new_elem->data = data;
+-  pH->count++;
+-  if( pH->count>=10 && pH->count > 2*pH->htsize ){
+-    if( rehash(pH, pH->count*2) ){
+-      assert( pH->htsize>0 );
+-      h = strHash(pKey, nKey) % pH->htsize;
++      sqlite3_free(p->zText);
+     }
+   }
+-  if( pH->ht ){
+-    insertElement(pH, &pH->ht[h], new_elem);
+-  }else{
+-    insertElement(pH, 0, new_elem);
+-  }
+-  return 0;
++  p->zText = 0;
+ }
+ 
+-/************** End of hash.c ************************************************/
+-/************** Begin file opcodes.c *****************************************/
+-/* Automatically generated.  Do not edit */
+-/* See the mkopcodec.awk script for details. */
+-#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+-SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
+- static const char *const azName[] = { "?",
+-     /*   1 */ "Goto",
+-     /*   2 */ "Gosub",
+-     /*   3 */ "Return",
+-     /*   4 */ "Yield",
+-     /*   5 */ "HaltIfNull",
+-     /*   6 */ "Halt",
+-     /*   7 */ "Integer",
+-     /*   8 */ "Int64",
+-     /*   9 */ "String",
+-     /*  10 */ "Null",
+-     /*  11 */ "Blob",
+-     /*  12 */ "Variable",
+-     /*  13 */ "Move",
+-     /*  14 */ "Copy",
+-     /*  15 */ "SCopy",
+-     /*  16 */ "ResultRow",
+-     /*  17 */ "CollSeq",
+-     /*  18 */ "Function",
+-     /*  19 */ "Not",
+-     /*  20 */ "AddImm",
+-     /*  21 */ "MustBeInt",
+-     /*  22 */ "RealAffinity",
+-     /*  23 */ "Permutation",
+-     /*  24 */ "Compare",
+-     /*  25 */ "Jump",
+-     /*  26 */ "Once",
+-     /*  27 */ "If",
+-     /*  28 */ "IfNot",
+-     /*  29 */ "Column",
+-     /*  30 */ "Affinity",
+-     /*  31 */ "MakeRecord",
+-     /*  32 */ "Count",
+-     /*  33 */ "Savepoint",
+-     /*  34 */ "AutoCommit",
+-     /*  35 */ "Transaction",
+-     /*  36 */ "ReadCookie",
+-     /*  37 */ "SetCookie",
+-     /*  38 */ "VerifyCookie",
+-     /*  39 */ "OpenRead",
+-     /*  40 */ "OpenWrite",
+-     /*  41 */ "OpenAutoindex",
+-     /*  42 */ "OpenEphemeral",
+-     /*  43 */ "SorterOpen",
+-     /*  44 */ "OpenPseudo",
+-     /*  45 */ "Close",
+-     /*  46 */ "SeekLt",
+-     /*  47 */ "SeekLe",
+-     /*  48 */ "SeekGe",
+-     /*  49 */ "SeekGt",
+-     /*  50 */ "Seek",
+-     /*  51 */ "NotFound",
+-     /*  52 */ "Found",
+-     /*  53 */ "IsUnique",
+-     /*  54 */ "NotExists",
+-     /*  55 */ "Sequence",
+-     /*  56 */ "NewRowid",
+-     /*  57 */ "Insert",
+-     /*  58 */ "InsertInt",
+-     /*  59 */ "Delete",
+-     /*  60 */ "ResetCount",
+-     /*  61 */ "SorterCompare",
+-     /*  62 */ "SorterData",
+-     /*  63 */ "RowKey",
+-     /*  64 */ "RowData",
+-     /*  65 */ "Rowid",
+-     /*  66 */ "NullRow",
+-     /*  67 */ "Last",
+-     /*  68 */ "Or",
+-     /*  69 */ "And",
+-     /*  70 */ "SorterSort",
+-     /*  71 */ "Sort",
+-     /*  72 */ "Rewind",
+-     /*  73 */ "IsNull",
+-     /*  74 */ "NotNull",
+-     /*  75 */ "Ne",
+-     /*  76 */ "Eq",
+-     /*  77 */ "Gt",
+-     /*  78 */ "Le",
+-     /*  79 */ "Lt",
+-     /*  80 */ "Ge",
+-     /*  81 */ "SorterNext",
+-     /*  82 */ "BitAnd",
+-     /*  83 */ "BitOr",
+-     /*  84 */ "ShiftLeft",
+-     /*  85 */ "ShiftRight",
+-     /*  86 */ "Add",
+-     /*  87 */ "Subtract",
+-     /*  88 */ "Multiply",
+-     /*  89 */ "Divide",
+-     /*  90 */ "Remainder",
+-     /*  91 */ "Concat",
+-     /*  92 */ "Prev",
+-     /*  93 */ "BitNot",
+-     /*  94 */ "String8",
+-     /*  95 */ "Next",
+-     /*  96 */ "SorterInsert",
+-     /*  97 */ "IdxInsert",
+-     /*  98 */ "IdxDelete",
+-     /*  99 */ "IdxRowid",
+-     /* 100 */ "IdxLT",
+-     /* 101 */ "IdxGE",
+-     /* 102 */ "Destroy",
+-     /* 103 */ "Clear",
+-     /* 104 */ "CreateIndex",
+-     /* 105 */ "CreateTable",
+-     /* 106 */ "ParseSchema",
+-     /* 107 */ "LoadAnalysis",
+-     /* 108 */ "DropTable",
+-     /* 109 */ "DropIndex",
+-     /* 110 */ "DropTrigger",
+-     /* 111 */ "IntegrityCk",
+-     /* 112 */ "RowSetAdd",
+-     /* 113 */ "RowSetRead",
+-     /* 114 */ "RowSetTest",
+-     /* 115 */ "Program",
+-     /* 116 */ "Param",
+-     /* 117 */ "FkCounter",
+-     /* 118 */ "FkIfZero",
+-     /* 119 */ "MemMax",
+-     /* 120 */ "IfPos",
+-     /* 121 */ "IfNeg",
+-     /* 122 */ "IfZero",
+-     /* 123 */ "AggStep",
+-     /* 124 */ "AggFinal",
+-     /* 125 */ "Checkpoint",
+-     /* 126 */ "JournalMode",
+-     /* 127 */ "Vacuum",
+-     /* 128 */ "IncrVacuum",
+-     /* 129 */ "Expire",
+-     /* 130 */ "Real",
+-     /* 131 */ "TableLock",
+-     /* 132 */ "VBegin",
+-     /* 133 */ "VCreate",
+-     /* 134 */ "VDestroy",
+-     /* 135 */ "VOpen",
+-     /* 136 */ "VFilter",
+-     /* 137 */ "VColumn",
+-     /* 138 */ "VNext",
+-     /* 139 */ "VRename",
+-     /* 140 */ "VUpdate",
+-     /* 141 */ "ToText",
+-     /* 142 */ "ToBlob",
+-     /* 143 */ "ToNumeric",
+-     /* 144 */ "ToInt",
+-     /* 145 */ "ToReal",
+-     /* 146 */ "Pagecount",
+-     /* 147 */ "MaxPgcnt",
+-     /* 148 */ "Trace",
+-     /* 149 */ "Noop",
+-     /* 150 */ "Explain",
+-  };
+-  return azName[i];
++/*
++** Initialize a string accumulator
++*/
++SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
++  p->zText = p->zBase = zBase;
++  p->db = 0;
++  p->nChar = 0;
++  p->nAlloc = n;
++  p->mxAlloc = mx;
++  p->useMalloc = 1;
++  p->tooBig = 0;
++  p->mallocFailed = 0;
+ }
+-#endif
+ 
+-/************** End of opcodes.c *********************************************/
+-/************** Begin file os_unix.c *****************************************/
+ /*
+-** 2004 May 22
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-******************************************************************************
+-**
+-** This file contains the VFS implementation for unix-like operating systems
+-** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
+-**
+-** There are actually several different VFS implementations in this file.
+-** The differences are in the way that file locking is done.  The default
+-** implementation uses Posix Advisory Locks.  Alternative implementations
+-** use flock(), dot-files, various proprietary locking schemas, or simply
+-** skip locking all together.
+-**
+-** This source file is organized into divisions where the logic for various
+-** subfunctions is contained within the appropriate division.  PLEASE
+-** KEEP THE STRUCTURE OF THIS FILE INTACT.  New code should be placed
+-** in the correct division and should be clearly labeled.
+-**
+-** The layout of divisions is as follows:
+-**
+-**   *  General-purpose declarations and utility functions.
+-**   *  Unique file ID logic used by VxWorks.
+-**   *  Various locking primitive implementations (all except proxy locking):
+-**      + for Posix Advisory Locks
+-**      + for no-op locks
+-**      + for dot-file locks
+-**      + for flock() locking
+-**      + for named semaphore locks (VxWorks only)
+-**      + for AFP filesystem locks (MacOSX only)
+-**   *  sqlite3_file methods not associated with locking.
+-**   *  Definitions of sqlite3_io_methods objects for all locking
+-**      methods plus "finder" functions for each locking method.
+-**   *  sqlite3_vfs method implementations.
+-**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
+-**   *  Definitions of sqlite3_vfs objects for all locking methods
+-**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
++** Print into memory obtained from sqliteMalloc().  Use the internal
++** %-conversion extensions.
+ */
+-#if SQLITE_OS_UNIX              /* This file is used on unix only */
++SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
++  char *z;
++  char zBase[SQLITE_PRINT_BUF_SIZE];
++  StrAccum acc;
++  assert( db!=0 );
++  sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
++                      db->aLimit[SQLITE_LIMIT_LENGTH]);
++  acc.db = db;
++  sqlite3VXPrintf(&acc, 1, zFormat, ap);
++  z = sqlite3StrAccumFinish(&acc);
++  if( acc.mallocFailed ){
++    db->mallocFailed = 1;
++  }
++  return z;
++}
+ 
+-/* Use posix_fallocate() if it is available
++/*
++** Print into memory obtained from sqliteMalloc().  Use the internal
++** %-conversion extensions.
+ */
+-#if !defined(HAVE_POSIX_FALLOCATE) \
+-      && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+-# define HAVE_POSIX_FALLOCATE 1
+-#endif
++SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
++  va_list ap;
++  char *z;
++  va_start(ap, zFormat);
++  z = sqlite3VMPrintf(db, zFormat, ap);
++  va_end(ap);
++  return z;
++}
+ 
+ /*
+-** There are various methods for file locking used for concurrency
+-** control:
++** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
++** the string and before returnning.  This routine is intended to be used
++** to modify an existing string.  For example:
+ **
+-**   1. POSIX locking (the default),
+-**   2. No locking,
+-**   3. Dot-file locking,
+-**   4. flock() locking,
+-**   5. AFP locking (OSX only),
+-**   6. Named POSIX semaphores (VXWorks only),
+-**   7. proxy locking. (OSX only)
++**       x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
+ **
+-** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
+-** is defined to 1.  The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
+-** selection of the appropriate locking style based on the filesystem
+-** where the database is located.  
+ */
+-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
+-#  if defined(__APPLE__)
+-#    define SQLITE_ENABLE_LOCKING_STYLE 1
+-#  else
+-#    define SQLITE_ENABLE_LOCKING_STYLE 0
+-#  endif
++SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
++  va_list ap;
++  char *z;
++  va_start(ap, zFormat);
++  z = sqlite3VMPrintf(db, zFormat, ap);
++  va_end(ap);
++  sqlite3DbFree(db, zStr);
++  return z;
++}
++
++/*
++** Print into memory obtained from sqlite3_malloc().  Omit the internal
++** %-conversion extensions.
++*/
++SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
++  char *z;
++  char zBase[SQLITE_PRINT_BUF_SIZE];
++  StrAccum acc;
++#ifndef SQLITE_OMIT_AUTOINIT
++  if( sqlite3_initialize() ) return 0;
+ #endif
++  sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
++  acc.useMalloc = 2;
++  sqlite3VXPrintf(&acc, 0, zFormat, ap);
++  z = sqlite3StrAccumFinish(&acc);
++  return z;
++}
+ 
+ /*
+-** Define the OS_VXWORKS pre-processor macro to 1 if building on 
+-** vxworks, or 0 otherwise.
++** Print into memory obtained from sqlite3_malloc()().  Omit the internal
++** %-conversion extensions.
+ */
+-#ifndef OS_VXWORKS
+-#  if defined(__RTP__) || defined(_WRS_KERNEL)
+-#    define OS_VXWORKS 1
+-#  else
+-#    define OS_VXWORKS 0
+-#  endif
++SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
++  va_list ap;
++  char *z;
++#ifndef SQLITE_OMIT_AUTOINIT
++  if( sqlite3_initialize() ) return 0;
+ #endif
++  va_start(ap, zFormat);
++  z = sqlite3_vmprintf(zFormat, ap);
++  va_end(ap);
++  return z;
++}
+ 
+ /*
+-** These #defines should enable >2GB file support on Posix if the
+-** underlying operating system supports it.  If the OS lacks
+-** large file support, these should be no-ops.
++** sqlite3_snprintf() works like snprintf() except that it ignores the
++** 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.
+ **
+-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
+-** on the compiler command line.  This is necessary if you are compiling
+-** on a recent machine (ex: RedHat 7.2) but you want your code to work
+-** on an older machine (ex: RedHat 6.0).  If you compile on RedHat 7.2
+-** without this option, LFS is enable.  But LFS does not exist in the kernel
+-** in RedHat 6.0, so the code won't work.  Hence, for maximum binary
+-** portability you should omit LFS.
++** 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.
+ **
+-** The previous paragraph was written in 2005.  (This paragraph is written
+-** on 2008-11-28.) These days, all Linux kernels support large files, so
+-** you should probably leave LFS enabled.  But some embedded platforms might
+-** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
++** sqlite3_vsnprintf() is the varargs version.
+ */
+-#ifndef SQLITE_DISABLE_LFS
+-# define _LARGE_FILE       1
+-# ifndef _FILE_OFFSET_BITS
+-#   define _FILE_OFFSET_BITS 64
+-# endif
+-# define _LARGEFILE_SOURCE 1
+-#endif
++SQLITE_API 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);
++}
++SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
++  char *z;
++  va_list ap;
++  va_start(ap,zFormat);
++  z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
++  va_end(ap);
++  return z;
++}
+ 
+ /*
+-** standard include files.
++** This is the routine that actually formats the sqlite3_log() message.
++** We house it in a separate routine from sqlite3_log() to avoid using
++** stack space on small-stack systems when logging is disabled.
++**
++** sqlite3_log() must render into a static buffer.  It cannot dynamically
++** allocate memory because it might be called while the memory allocator
++** mutex is held.
+ */
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <fcntl.h>
+-#include <unistd.h>
+-/* #include <time.h> */
+-#include <sys/time.h>
+-#include <errno.h>
+-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
 -#include <sys/mman.h>
+-#endif
+-
+-
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-# include <sys/ioctl.h>
+-# if OS_VXWORKS
+-#  include <semaphore.h>
+-#  include <limits.h>
+-# else
+-#  include <sys/file.h>
+-#  include <sys/param.h>
+-# endif
+-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+-
+-#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
+-# include <sys/mount.h>
+-#endif
++static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
++  StrAccum acc;                          /* String accumulator */
++  char zMsg[SQLITE_PRINT_BUF_SIZE*3];    /* Complete log message */
+ 
+-#ifdef HAVE_UTIME
+-# include <utime.h>
+-#endif
++  sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
++  acc.useMalloc = 0;
++  sqlite3VXPrintf(&acc, 0, zFormat, ap);
++  sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
++                           sqlite3StrAccumFinish(&acc));
++}
+ 
+ /*
+-** Allowed values of unixFile.fsFlags
++** Format and write a message to the log if logging is enabled.
+ */
+-#define SQLITE_FSFLAGS_IS_MSDOS     0x1
++SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
++  va_list ap;                             /* Vararg list */
++  if( sqlite3GlobalConfig.xLog ){
++    va_start(ap, zFormat);
++    renderLogMsg(iErrCode, zFormat, ap);
++    va_end(ap);
++  }
++}
+ 
++#if defined(SQLITE_DEBUG)
+ /*
+-** If we are to be thread-safe, include the pthreads header and define
+-** the SQLITE_UNIX_THREADS macro.
++** A version of printf() that understands %lld.  Used for debugging.
++** The printf() built into some versions of windows does not understand %lld
++** and segfaults if you give it a long long int.
+ */
+-#if SQLITE_THREADSAFE
+-/* # include <pthread.h> */
+-# define SQLITE_UNIX_THREADS 1
++SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
++  va_list ap;
++  StrAccum acc;
++  char zBuf[500];
++  sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
++  acc.useMalloc = 0;
++  va_start(ap,zFormat);
++  sqlite3VXPrintf(&acc, 0, zFormat, ap);
++  va_end(ap);
++  sqlite3StrAccumFinish(&acc);
++  fprintf(stdout,"%s", zBuf);
++  fflush(stdout);
++}
+ #endif
+ 
++#ifndef SQLITE_OMIT_TRACE
+ /*
+-** Default permissions when creating a new file
++** variable-argument wrapper around sqlite3VXPrintf().
+ */
+-#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
+-# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
++SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
++  va_list ap;
++  va_start(ap,zFormat);
++  sqlite3VXPrintf(p, 1, zFormat, ap);
++  va_end(ap);
++}
+ #endif
+ 
++/************** End of printf.c **********************************************/
++/************** Begin file random.c ******************************************/
+ /*
+-** Default permissions when creating auto proxy dir
++** 2001 September 15
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This file contains code to implement a pseudo-random number
++** generator (PRNG) for SQLite.
++**
++** Random numbers are used by some of the database backends in order
++** to generate random integer keys for tables or random filenames.
+ */
+-#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+-# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
+-#endif
+ 
+-/*
+-** Maximum supported path-length.
+-*/
+-#define MAX_PATHNAME 512
+ 
+-/*
+-** Only set the lastErrno if the error code is a real error and not 
+-** a normal expected return code of SQLITE_BUSY or SQLITE_OK
++/* All threads share a single random number generator.
++** This structure is the current state of the generator.
+ */
+-#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
+-
+-/* Forward references */
+-typedef struct unixShm unixShm;               /* Connection shared memory */
+-typedef struct unixShmNode unixShmNode;       /* Shared memory instance */
+-typedef struct unixInodeInfo unixInodeInfo;   /* An i-node */
+-typedef struct UnixUnusedFd UnixUnusedFd;     /* An unused file descriptor */
++static SQLITE_WSD struct sqlite3PrngType {
++  unsigned char isInit;          /* True if initialized */
++  unsigned char i, j;            /* State variables */
++  unsigned char s[256];          /* State variables */
++} sqlite3Prng;
+ 
+ /*
+-** Sometimes, after a file handle is closed by SQLite, the file descriptor
+-** cannot be closed immediately. In these cases, instances of the following
+-** structure are used to store the file descriptor while waiting for an
+-** opportunity to either close or reuse it.
++** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
++** must be held while executing this routine.
++**
++** Why not just use a library random generator like lrand48() for this?
++** Because the OP_NewRowid opcode in the VDBE depends on having a very
++** good source of random numbers.  The lrand48() library function may
++** well be good enough.  But maybe not.  Or maybe lrand48() has some
++** subtle problems on some systems that could cause problems.  It is hard
++** to know.  To minimize the risk of problems due to bad lrand48()
++** implementations, SQLite uses this random number generator based
++** on RC4, which we know works very well.
++**
++** (Later):  Actually, OP_NewRowid does not depend on a good source of
++** randomness any more.  But we will leave this code in all the same.
+ */
+-struct UnixUnusedFd {
+-  int fd;                   /* File descriptor to close */
+-  int flags;                /* Flags this file descriptor was opened with */
+-  UnixUnusedFd *pNext;      /* Next unused file descriptor on same file */
+-};
++static u8 randomByte(void){
++  unsigned char t;
+ 
+-/*
+-** The unixFile structure is subclass of sqlite3_file specific to the unix
+-** VFS implementations.
+-*/
+-typedef struct unixFile unixFile;
+-struct unixFile {
+-  sqlite3_io_methods const *pMethod;  /* Always the first entry */
+-  sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
+-  unixInodeInfo *pInode;              /* Info about locks on this inode */
+-  int h;                              /* The file descriptor */
+-  unsigned char eFileLock;            /* The type of lock held on this fd */
+-  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
+-  int lastErrno;                      /* The unix errno from last I/O error */
+-  void *lockingContext;               /* Locking style specific state */
+-  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
+-  const char *zPath;                  /* Name of the file */
+-  unixShm *pShm;                      /* Shared memory segment information */
+-  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
+-  int nFetchOut;                      /* Number of outstanding xFetch refs */
+-  sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
+-  sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
+-  sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
+-  void *pMapRegion;                   /* Memory mapped region */
+-#ifdef __QNXNTO__
+-  int sectorSize;                     /* Device sector size */
+-  int deviceCharacteristics;          /* Precomputed device characteristics */
+-#endif
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-  int openFlags;                      /* The flags specified at open() */
+-#endif
+-#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
+-  unsigned fsFlags;                   /* cached details from statfs() */
+-#endif
+-#if OS_VXWORKS
+-  struct vxworksFileId *pId;          /* Unique file ID */
+-#endif
+-#ifdef SQLITE_DEBUG
+-  /* The next group of variables are used to track whether or not the
+-  ** transaction counter in bytes 24-27 of database files are updated
+-  ** whenever any part of the database changes.  An assertion fault will
+-  ** occur if a file is updated without also updating the transaction
+-  ** counter.  This test is made to avoid new problems similar to the
+-  ** one described by ticket #3584. 
+-  */
+-  unsigned char transCntrChng;   /* True if the transaction counter changed */
+-  unsigned char dbUpdate;        /* True if any part of database file changed */
+-  unsigned char inNormalWrite;   /* True if in a normal write operation */
+ 
++  /* The "wsdPrng" macro will resolve to the pseudo-random number generator
++  ** state vector.  If writable static data is unsupported on the target,
++  ** we have to locate the state vector at run-time.  In the more common
++  ** case where writable static data is supported, wsdPrng can refer directly
++  ** to the "sqlite3Prng" state vector declared above.
++  */
++#ifdef SQLITE_OMIT_WSD
++  struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
++# define wsdPrng p[0]
++#else
++# define wsdPrng sqlite3Prng
+ #endif
+ 
+-#ifdef SQLITE_TEST
+-  /* In test mode, increase the size of this structure a bit so that 
+-  ** it is larger than the struct CrashFile defined in test6.c.
++
++  /* Initialize the state of the random number generator once,
++  ** the first time this routine is called.  The seed value does
++  ** not need to contain a lot of randomness since we are not
++  ** trying to do secure encryption or anything like that...
++  **
++  ** Nothing in this file or anywhere else in SQLite does any kind of
++  ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
++  ** number generator) not as an encryption device.
+   */
+-  char aPadding[32];
+-#endif
+-};
++  if( !wsdPrng.isInit ){
++    int i;
++    char k[256];
++    wsdPrng.j = 0;
++    wsdPrng.i = 0;
++    sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
++    for(i=0; i<256; i++){
++      wsdPrng.s[i] = (u8)i;
++    }
++    for(i=0; i<256; i++){
++      wsdPrng.j += wsdPrng.s[i] + k[i];
++      t = wsdPrng.s[wsdPrng.j];
++      wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
++      wsdPrng.s[i] = t;
++    }
++    wsdPrng.isInit = 1;
++  }
++
++  /* Generate and return single random byte
++  */
++  wsdPrng.i++;
++  t = wsdPrng.s[wsdPrng.i];
++  wsdPrng.j += t;
++  wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
++  wsdPrng.s[wsdPrng.j] = t;
++  t += wsdPrng.s[wsdPrng.i];
++  return wsdPrng.s[t];
++}
+ 
+ /*
+-** Allowed values for the unixFile.ctrlFlags bitmask:
++** Return N random bytes.
+ */
+-#define UNIXFILE_EXCL        0x01     /* Connections from one process only */
+-#define UNIXFILE_RDONLY      0x02     /* Connection is read only */
+-#define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
+-#ifndef SQLITE_DISABLE_DIRSYNC
+-# define UNIXFILE_DIRSYNC    0x08     /* Directory sync needed */
+-#else
+-# define UNIXFILE_DIRSYNC    0x00
++SQLITE_API void sqlite3_randomness(int N, void *pBuf){
++  unsigned char *zBuf = pBuf;
++#if SQLITE_THREADSAFE
++  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
+ #endif
+-#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
+-#define UNIXFILE_DELETE      0x20     /* Delete on close */
+-#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
+-#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
+-#define UNIXFILE_WARNED    0x0100     /* verifyDbFile() warnings have been issued */
++  sqlite3_mutex_enter(mutex);
++  while( N-- ){
++    *(zBuf++) = randomByte();
++  }
++  sqlite3_mutex_leave(mutex);
++}
+ 
++#ifndef SQLITE_OMIT_BUILTIN_TEST
+ /*
+-** Include code that is common to all os_*.c files
++** For testing purposes, we sometimes want to preserve the state of
++** PRNG and restore the PRNG to its saved state at a later time, or
++** to reset the PRNG to its initial state.  These routines accomplish
++** those tasks.
++**
++** The sqlite3_test_control() interface calls these routines to
++** control the PRNG.
+ */
+-/************** Include os_common.h in the middle of os_unix.c ***************/
+-/************** Begin file os_common.h ***************************************/
++static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
++SQLITE_PRIVATE void sqlite3PrngSaveState(void){
++  memcpy(
++    &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
++    &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
++    sizeof(sqlite3Prng)
++  );
++}
++SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
++  memcpy(
++    &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
++    &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
++    sizeof(sqlite3Prng)
++  );
++}
++SQLITE_PRIVATE void sqlite3PrngResetState(void){
++  GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
++}
++#endif /* SQLITE_OMIT_BUILTIN_TEST */
++
++/************** End of random.c **********************************************/
++/************** Begin file utf.c *********************************************/
+ /*
+-** 2004 May 22
++** 2004 April 13
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -23182,13485 +23650,14956 @@
+ **    May you find forgiveness for yourself and forgive others.
+ **    May you share freely, never taking more than you give.
+ **
+-******************************************************************************
++*************************************************************************
++** This file contains routines used to translate between UTF-8, 
++** UTF-16, UTF-16BE, and UTF-16LE.
+ **
+-** This file contains macros and a little bit of code that is common to
+-** all of the platform-specific files (os_*.c) and is #included into those
+-** files.
++** Notes on UTF-8:
++**
++**   Byte-0    Byte-1    Byte-2    Byte-3    Value
++**  0xxxxxxx                                 00000000 00000000 0xxxxxxx
++**  110yyyyy  10xxxxxx                       00000000 00000yyy yyxxxxxx
++**  1110zzzz  10yyyyyy  10xxxxxx             00000000 zzzzyyyy yyxxxxxx
++**  11110uuu  10uuzzzz  10yyyyyy  10xxxxxx   000uuuuu zzzzyyyy yyxxxxxx
++**
++**
++** Notes on UTF-16:  (with wwww+1==uuuuu)
++**
++**      Word-0               Word-1          Value
++**  110110ww wwzzzzyy   110111yy yyxxxxxx    000uuuuu zzzzyyyy yyxxxxxx
++**  zzzzyyyy yyxxxxxx                        00000000 zzzzyyyy yyxxxxxx
++**
++**
++** BOM or Byte Order Mark:
++**     0xff 0xfe   little-endian utf-16 follows
++**     0xfe 0xff   big-endian utf-16 follows
+ **
+-** This file should be #included by the os_*.c files only.  It is not a
+-** general purpose header file.
+ */
+-#ifndef _OS_COMMON_H_
+-#define _OS_COMMON_H_
++/* #include <assert.h> */
+ 
++#ifndef SQLITE_AMALGAMATION
+ /*
+-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
+-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
+-** switch.  The following code should catch this problem at compile-time.
++** The following constant value is used by the SQLITE_BIGENDIAN and
++** SQLITE_LITTLEENDIAN macros.
+ */
+-#ifdef MEMORY_DEBUG
+-# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
+-#endif
+-
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+-# ifndef SQLITE_DEBUG_OS_TRACE
+-#   define SQLITE_DEBUG_OS_TRACE 0
+-# endif
+-  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+-# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
+-#else
+-# define OSTRACE(X)
+-#endif
++SQLITE_PRIVATE const int sqlite3one = 1;
++#endif /* SQLITE_AMALGAMATION */
+ 
+ /*
+-** Macros for performance tracing.  Normally turned off.  Only works
+-** on i486 hardware.
++** This lookup table is used to help decode the first byte of
++** a multi-byte UTF8 character.
+ */
+-#ifdef SQLITE_PERFORMANCE_TRACE
++static const unsigned char sqlite3Utf8Trans1[] = {
++  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++  0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
++};
++
++
++#define WRITE_UTF8(zOut, c) {                          \
++  if( c<0x00080 ){                                     \
++    *zOut++ = (u8)(c&0xFF);                            \
++  }                                                    \
++  else if( c<0x00800 ){                                \
++    *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);                \
++    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
++  }                                                    \
++  else if( c<0x10000 ){                                \
++    *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);               \
++    *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);              \
++    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
++  }else{                                               \
++    *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);             \
++    *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);             \
++    *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);              \
++    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
++  }                                                    \
++}
++
++#define WRITE_UTF16LE(zOut, c) {                                    \
++  if( c<=0xFFFF ){                                                  \
++    *zOut++ = (u8)(c&0x00FF);                                       \
++    *zOut++ = (u8)((c>>8)&0x00FF);                                  \
++  }else{                                                            \
++    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
++    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
++    *zOut++ = (u8)(c&0x00FF);                                       \
++    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
++  }                                                                 \
++}
++
++#define WRITE_UTF16BE(zOut, c) {                                    \
++  if( c<=0xFFFF ){                                                  \
++    *zOut++ = (u8)((c>>8)&0x00FF);                                  \
++    *zOut++ = (u8)(c&0x00FF);                                       \
++  }else{                                                            \
++    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
++    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
++    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
++    *zOut++ = (u8)(c&0x00FF);                                       \
++  }                                                                 \
++}
++
++#define READ_UTF16LE(zIn, TERM, c){                                   \
++  c = (*zIn++);                                                       \
++  c += ((*zIn++)<<8);                                                 \
++  if( c>=0xD800 && c<0xE000 && TERM ){                                \
++    int c2 = (*zIn++);                                                \
++    c2 += ((*zIn++)<<8);                                              \
++    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
++  }                                                                   \
++}
++
++#define READ_UTF16BE(zIn, TERM, c){                                   \
++  c = ((*zIn++)<<8);                                                  \
++  c += (*zIn++);                                                      \
++  if( c>=0xD800 && c<0xE000 && TERM ){                                \
++    int c2 = ((*zIn++)<<8);                                           \
++    c2 += (*zIn++);                                                   \
++    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
++  }                                                                   \
++}
+ 
+-/* 
+-** hwtime.h contains inline assembler code for implementing 
+-** high-performance timing routines.
+-*/
+-/************** Include hwtime.h in the middle of os_common.h ****************/
+-/************** Begin file hwtime.h ******************************************/
+ /*
+-** 2008 May 27
++** Translate a single UTF-8 character.  Return the unicode value.
+ **
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
++** During translation, assume that the byte that zTerm points
++** is a 0x00.
+ **
+-**    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.
++** Write a pointer to the next unread byte back into *pzNext.
+ **
+-******************************************************************************
++** Notes On Invalid UTF-8:
+ **
+-** This file contains inline asm code for retrieving "high-performance"
+-** counters for x86 class CPUs.
++**  *  This routine never allows a 7-bit character (0x00 through 0x7f) to
++**     be encoded as a multi-byte character.  Any multi-byte character that
++**     attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
++**
++**  *  This routine never allows a UTF16 surrogate value to be encoded.
++**     If a multi-byte character attempts to encode a value between
++**     0xd800 and 0xe000 then it is rendered as 0xfffd.
++**
++**  *  Bytes in the range of 0x80 through 0xbf which occur as the first
++**     byte of a character are interpreted as single-byte characters
++**     and rendered as themselves even though they are technically
++**     invalid characters.
++**
++**  *  This routine accepts an infinite number of different UTF8 encodings
++**     for unicode values 0x80 and greater.  It do not change over-length
++**     encodings to 0xfffd as some systems recommend.
+ */
+-#ifndef _HWTIME_H_
+-#define _HWTIME_H_
++#define READ_UTF8(zIn, zTerm, c)                           \
++  c = *(zIn++);                                            \
++  if( c>=0xc0 ){                                           \
++    c = sqlite3Utf8Trans1[c-0xc0];                         \
++    while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
++      c = (c<<6) + (0x3f & *(zIn++));                      \
++    }                                                      \
++    if( c<0x80                                             \
++        || (c&0xFFFFF800)==0xD800                          \
++        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
++  }
++SQLITE_PRIVATE u32 sqlite3Utf8Read(
++  const unsigned char **pz    /* Pointer to string from which to read char */
++){
++  unsigned int c;
++
++  /* Same as READ_UTF8() above but without the zTerm parameter.
++  ** For this routine, we assume the UTF8 string is always zero-terminated.
++  */
++  c = *((*pz)++);
++  if( c>=0xc0 ){
++    c = sqlite3Utf8Trans1[c-0xc0];
++    while( (*(*pz) & 0xc0)==0x80 ){
++      c = (c<<6) + (0x3f & *((*pz)++));
++    }
++    if( c<0x80
++        || (c&0xFFFFF800)==0xD800
++        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
++  }
++  return c;
++}
++
++
++
+ 
+ /*
+-** The following routine only works on pentium-class (or newer) processors.
+-** It uses the RDTSC opcode to read the cycle count value out of the
+-** processor and returns that value.  This can be used for high-res
+-** profiling.
++** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
++** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
++*/ 
++/* #define TRANSLATE_TRACE 1 */
++
++#ifndef SQLITE_OMIT_UTF16
++/*
++** This routine transforms the internal text encoding used by pMem to
++** desiredEnc. It is an error if the string is already of the desired
++** encoding, or if *pMem does not contain a string value.
+ */
+-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
+-      (defined(i386) || defined(__i386__) || defined(_M_IX86))
++SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
++  int len;                    /* Maximum length of output string in bytes */
++  unsigned char *zOut;                  /* Output buffer */
++  unsigned char *zIn;                   /* Input iterator */
++  unsigned char *zTerm;                 /* End of input */
++  unsigned char *z;                     /* Output iterator */
++  unsigned int c;
+ 
+-  #if defined(__GNUC__)
++  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
++  assert( pMem->flags&MEM_Str );
++  assert( pMem->enc!=desiredEnc );
++  assert( pMem->enc!=0 );
++  assert( pMem->n>=0 );
+ 
+-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+-     unsigned int lo, hi;
+-     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+-     return (sqlite_uint64)hi << 32 | lo;
++#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
++  {
++    char zBuf[100];
++    sqlite3VdbeMemPrettyPrint(pMem, zBuf);
++    fprintf(stderr, "INPUT:  %s\n", zBuf);
+   }
++#endif
+ 
+-  #elif defined(_MSC_VER)
+-
+-  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+-     __asm {
+-        rdtsc
+-        ret       ; return value at EDX:EAX
+-     }
++  /* If the translation is between UTF-16 little and big endian, then 
++  ** all that is required is to swap the byte order. This case is handled
++  ** differently from the others.
++  */
++  if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
++    u8 temp;
++    int rc;
++    rc = sqlite3VdbeMemMakeWriteable(pMem);
++    if( rc!=SQLITE_OK ){
++      assert( rc==SQLITE_NOMEM );
++      return SQLITE_NOMEM;
++    }
++    zIn = (u8*)pMem->z;
++    zTerm = &zIn[pMem->n&~1];
++    while( zIn<zTerm ){
++      temp = *zIn;
++      *zIn = *(zIn+1);
++      zIn++;
++      *zIn++ = temp;
++    }
++    pMem->enc = desiredEnc;
++    goto translate_out;
+   }
+ 
+-  #endif
+-
+-#elif (defined(__GNUC__) && defined(__x86_64__))
++  /* Set len to the maximum number of bytes required in the output buffer. */
++  if( desiredEnc==SQLITE_UTF8 ){
++    /* When converting from UTF-16, the maximum growth results from
++    ** translating a 2-byte character to a 4-byte UTF-8 character.
++    ** A single byte is required for the output string
++    ** nul-terminator.
++    */
++    pMem->n &= ~1;
++    len = pMem->n * 2 + 1;
++  }else{
++    /* When converting from UTF-8 to UTF-16 the maximum growth is caused
++    ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
++    ** character. Two bytes are required in the output buffer for the
++    ** nul-terminator.
++    */
++    len = pMem->n * 2 + 2;
++  }
+ 
+-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+-      unsigned long val;
+-      __asm__ __volatile__ ("rdtsc" : "=A" (val));
+-      return val;
++  /* Set zIn to point at the start of the input buffer and zTerm to point 1
++  ** byte past the end.
++  **
++  ** Variable zOut is set to point at the output buffer, space obtained
++  ** from sqlite3_malloc().
++  */
++  zIn = (u8*)pMem->z;
++  zTerm = &zIn[pMem->n];
++  zOut = sqlite3DbMallocRaw(pMem->db, len);
++  if( !zOut ){
++    return SQLITE_NOMEM;
+   }
+- 
+-#elif (defined(__GNUC__) && defined(__ppc__))
++  z = zOut;
+ 
+-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+-      unsigned long long retval;
+-      unsigned long junk;
+-      __asm__ __volatile__ ("\n\
+-          1:      mftbu   %1\n\
+-                  mftb    %L0\n\
+-                  mftbu   %0\n\
+-                  cmpw    %0,%1\n\
+-                  bne     1b"
+-                  : "=r" (retval), "=r" (junk));
+-      return retval;
++  if( pMem->enc==SQLITE_UTF8 ){
++    if( desiredEnc==SQLITE_UTF16LE ){
++      /* UTF-8 -> UTF-16 Little-endian */
++      while( zIn<zTerm ){
++        READ_UTF8(zIn, zTerm, c);
++        WRITE_UTF16LE(z, c);
++      }
++    }else{
++      assert( desiredEnc==SQLITE_UTF16BE );
++      /* UTF-8 -> UTF-16 Big-endian */
++      while( zIn<zTerm ){
++        READ_UTF8(zIn, zTerm, c);
++        WRITE_UTF16BE(z, c);
++      }
++    }
++    pMem->n = (int)(z - zOut);
++    *z++ = 0;
++  }else{
++    assert( desiredEnc==SQLITE_UTF8 );
++    if( pMem->enc==SQLITE_UTF16LE ){
++      /* UTF-16 Little-endian -> UTF-8 */
++      while( zIn<zTerm ){
++        READ_UTF16LE(zIn, zIn<zTerm, c); 
++        WRITE_UTF8(z, c);
++      }
++    }else{
++      /* UTF-16 Big-endian -> UTF-8 */
++      while( zIn<zTerm ){
++        READ_UTF16BE(zIn, zIn<zTerm, c); 
++        WRITE_UTF8(z, c);
++      }
++    }
++    pMem->n = (int)(z - zOut);
+   }
++  *z = 0;
++  assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
+ 
+-#else
++  sqlite3VdbeMemRelease(pMem);
++  pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
++  pMem->enc = desiredEnc;
++  pMem->flags |= (MEM_Term|MEM_Dyn);
++  pMem->z = (char*)zOut;
++  pMem->zMalloc = pMem->z;
+ 
+-  #error Need implementation of sqlite3Hwtime() for your platform.
++translate_out:
++#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
++  {
++    char zBuf[100];
++    sqlite3VdbeMemPrettyPrint(pMem, zBuf);
++    fprintf(stderr, "OUTPUT: %s\n", zBuf);
++  }
++#endif
++  return SQLITE_OK;
++}
+ 
+-  /*
+-  ** To compile without implementing sqlite3Hwtime() for your platform,
+-  ** you can remove the above #error and use the following
+-  ** stub function.  You will lose timing support for many
+-  ** of the debugging and testing utilities, but it should at
+-  ** least compile and run.
+-  */
+-SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
++/*
++** This routine checks for a byte-order mark at the beginning of the 
++** UTF-16 string stored in *pMem. If one is present, it is removed and
++** the encoding of the Mem adjusted. This routine does not do any
++** byte-swapping, it just sets Mem.enc appropriately.
++**
++** The allocation (static, dynamic etc.) and encoding of the Mem may be
++** changed by this function.
++*/
++SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
++  int rc = SQLITE_OK;
++  u8 bom = 0;
+ 
+-#endif
++  assert( pMem->n>=0 );
++  if( pMem->n>1 ){
++    u8 b1 = *(u8 *)pMem->z;
++    u8 b2 = *(((u8 *)pMem->z) + 1);
++    if( b1==0xFE && b2==0xFF ){
++      bom = SQLITE_UTF16BE;
++    }
++    if( b1==0xFF && b2==0xFE ){
++      bom = SQLITE_UTF16LE;
++    }
++  }
++  
++  if( bom ){
++    rc = sqlite3VdbeMemMakeWriteable(pMem);
++    if( rc==SQLITE_OK ){
++      pMem->n -= 2;
++      memmove(pMem->z, &pMem->z[2], pMem->n);
++      pMem->z[pMem->n] = '\0';
++      pMem->z[pMem->n+1] = '\0';
++      pMem->flags |= MEM_Term;
++      pMem->enc = bom;
++    }
++  }
++  return rc;
++}
++#endif /* SQLITE_OMIT_UTF16 */
+ 
+-#endif /* !defined(_HWTIME_H_) */
++/*
++** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
++** return the number of unicode characters in pZ up to (but not including)
++** the first 0x00 byte. If nByte is not less than zero, return the
++** number of unicode characters in the first nByte of pZ (or up to 
++** the first 0x00, whichever comes first).
++*/
++SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
++  int r = 0;
++  const u8 *z = (const u8*)zIn;
++  const u8 *zTerm;
++  if( nByte>=0 ){
++    zTerm = &z[nByte];
++  }else{
++    zTerm = (const u8*)(-1);
++  }
++  assert( z<=zTerm );
++  while( *z!=0 && z<zTerm ){
++    SQLITE_SKIP_UTF8(z);
++    r++;
++  }
++  return r;
++}
+ 
+-/************** End of hwtime.h **********************************************/
+-/************** Continuing where we left off in os_common.h ******************/
++/* This test function is not currently used by the automated test-suite. 
++** Hence it is only available in debug builds.
++*/
++#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
++/*
++** Translate UTF-8 to UTF-8.
++**
++** This has the effect of making sure that the string is well-formed
++** UTF-8.  Miscoded characters are removed.
++**
++** The translation is done in-place and aborted if the output
++** overruns the input.
++*/
++SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
++  unsigned char *zOut = zIn;
++  unsigned char *zStart = zIn;
++  u32 c;
+ 
+-static sqlite_uint64 g_start;
+-static sqlite_uint64 g_elapsed;
+-#define TIMER_START       g_start=sqlite3Hwtime()
+-#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
+-#define TIMER_ELAPSED     g_elapsed
+-#else
+-#define TIMER_START
+-#define TIMER_END
+-#define TIMER_ELAPSED     ((sqlite_uint64)0)
++  while( zIn[0] && zOut<=zIn ){
++    c = sqlite3Utf8Read((const u8**)&zIn);
++    if( c!=0xfffd ){
++      WRITE_UTF8(zOut, c);
++    }
++  }
++  *zOut = 0;
++  return (int)(zOut - zStart);
++}
+ #endif
+ 
++#ifndef SQLITE_OMIT_UTF16
+ /*
+-** If we compile with the SQLITE_TEST macro set, then the following block
+-** of code will give us the ability to simulate a disk I/O error.  This
+-** is used for testing the I/O recovery logic.
++** Convert a UTF-16 string in the native encoding into a UTF-8 string.
++** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
++** be freed by the calling function.
++**
++** NULL is returned if there is an allocation error.
+ */
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
+-SQLITE_API int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
+-SQLITE_API int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
+-SQLITE_API int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
+-SQLITE_API int sqlite3_io_error_benign = 0;         /* True if errors are benign */
+-SQLITE_API int sqlite3_diskfull_pending = 0;
+-SQLITE_API int sqlite3_diskfull = 0;
+-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
+-#define SimulateIOError(CODE)  \
+-  if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+-       || sqlite3_io_error_pending-- == 1 )  \
+-              { local_ioerr(); CODE; }
+-static void local_ioerr(){
+-  IOTRACE(("IOERR\n"));
+-  sqlite3_io_error_hit++;
+-  if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
++SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
++  Mem m;
++  memset(&m, 0, sizeof(m));
++  m.db = db;
++  sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
++  sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
++  if( db->mallocFailed ){
++    sqlite3VdbeMemRelease(&m);
++    m.z = 0;
++  }
++  assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
++  assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
++  assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
++  assert( m.z || db->mallocFailed );
++  return m.z;
++}
++
++/*
++** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
++** enc. A pointer to the new string is returned, and the value of *pnOut
++** is set to the length of the returned string in bytes. The call should
++** arrange to call sqlite3DbFree() on the returned pointer when it is
++** no longer required.
++** 
++** If a malloc failure occurs, NULL is returned and the db.mallocFailed
++** flag set.
++*/
++#ifdef SQLITE_ENABLE_STAT3
++SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
++  Mem m;
++  memset(&m, 0, sizeof(m));
++  m.db = db;
++  sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
++  if( sqlite3VdbeMemTranslate(&m, enc) ){
++    assert( db->mallocFailed );
++    return 0;
++  }
++  assert( m.z==m.zMalloc );
++  *pnOut = m.n;
++  return m.z;
+ }
+-#define SimulateDiskfullError(CODE) \
+-   if( sqlite3_diskfull_pending ){ \
+-     if( sqlite3_diskfull_pending == 1 ){ \
+-       local_ioerr(); \
+-       sqlite3_diskfull = 1; \
+-       sqlite3_io_error_hit = 1; \
+-       CODE; \
+-     }else{ \
+-       sqlite3_diskfull_pending--; \
+-     } \
+-   }
+-#else
+-#define SimulateIOErrorBenign(X)
+-#define SimulateIOError(A)
+-#define SimulateDiskfullError(A)
+ #endif
+ 
+ /*
+-** When testing, keep a count of the number of open files.
++** zIn is a UTF-16 encoded unicode string at least nChar characters long.
++** Return the number of bytes in the first nChar unicode characters
++** in pZ.  nChar must be non-negative.
++*/
++SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
++  int c;
++  unsigned char const *z = zIn;
++  int n = 0;
++  
++  if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
++    while( n<nChar ){
++      READ_UTF16BE(z, 1, c);
++      n++;
++    }
++  }else{
++    while( n<nChar ){
++      READ_UTF16LE(z, 1, c);
++      n++;
++    }
++  }
++  return (int)(z-(unsigned char const *)zIn);
++}
++
++#if defined(SQLITE_TEST)
++/*
++** This routine is called from the TCL test function "translate_selftest".
++** It checks that the primitives for serializing and deserializing
++** characters in each encoding are inverses of each other.
++*/
++SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
++  unsigned int i, t;
++  unsigned char zBuf[20];
++  unsigned char *z;
++  int n;
++  unsigned int c;
++
++  for(i=0; i<0x00110000; i++){
++    z = zBuf;
++    WRITE_UTF8(z, i);
++    n = (int)(z-zBuf);
++    assert( n>0 && n<=4 );
++    z[0] = 0;
++    z = zBuf;
++    c = sqlite3Utf8Read((const u8**)&z);
++    t = i;
++    if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
++    if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
++    assert( c==t );
++    assert( (z-zBuf)==n );
++  }
++  for(i=0; i<0x00110000; i++){
++    if( i>=0xD800 && i<0xE000 ) continue;
++    z = zBuf;
++    WRITE_UTF16LE(z, i);
++    n = (int)(z-zBuf);
++    assert( n>0 && n<=4 );
++    z[0] = 0;
++    z = zBuf;
++    READ_UTF16LE(z, 1, c);
++    assert( c==i );
++    assert( (z-zBuf)==n );
++  }
++  for(i=0; i<0x00110000; i++){
++    if( i>=0xD800 && i<0xE000 ) continue;
++    z = zBuf;
++    WRITE_UTF16BE(z, i);
++    n = (int)(z-zBuf);
++    assert( n>0 && n<=4 );
++    z[0] = 0;
++    z = zBuf;
++    READ_UTF16BE(z, 1, c);
++    assert( c==i );
++    assert( (z-zBuf)==n );
++  }
++}
++#endif /* SQLITE_TEST */
++#endif /* SQLITE_OMIT_UTF16 */
++
++/************** End of utf.c *************************************************/
++/************** Begin file util.c ********************************************/
++/*
++** 2001 September 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.
++**
++*************************************************************************
++** Utility functions used throughout sqlite.
++**
++** This file contains functions for allocating memory, comparing
++** strings, and stuff like that.
++**
+ */
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_open_file_count = 0;
+-#define OpenCounter(X)  sqlite3_open_file_count+=(X)
+-#else
+-#define OpenCounter(X)
++/* #include <stdarg.h> */
++#ifdef SQLITE_HAVE_ISNAN
++# include <math.h>
+ #endif
+ 
+-#endif /* !defined(_OS_COMMON_H_) */
+-
+-/************** End of os_common.h *******************************************/
+-/************** Continuing where we left off in os_unix.c ********************/
+-
+ /*
+-** Define various macros that are missing from some systems.
++** Routine needed to support the testcase() macro.
+ */
+-#ifndef O_LARGEFILE
+-# define O_LARGEFILE 0
+-#endif
+-#ifdef SQLITE_DISABLE_LFS
+-# undef O_LARGEFILE
+-# define O_LARGEFILE 0
+-#endif
+-#ifndef O_NOFOLLOW
+-# define O_NOFOLLOW 0
+-#endif
+-#ifndef O_BINARY
+-# define O_BINARY 0
++#ifdef SQLITE_COVERAGE_TEST
++SQLITE_PRIVATE void sqlite3Coverage(int x){
++  static unsigned dummy = 0;
++  dummy += (unsigned)x;
++}
+ #endif
+ 
++#ifndef SQLITE_OMIT_FLOATING_POINT
+ /*
+-** The threadid macro resolves to the thread-id or to 0.  Used for
+-** testing and debugging only.
++** Return true if the floating point value is Not a Number (NaN).
++**
++** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
++** Otherwise, we have our own implementation that works on most systems.
+ */
+-#if SQLITE_THREADSAFE
+-#define threadid pthread_self()
+-#else
+-#define threadid 0
++SQLITE_PRIVATE int sqlite3IsNaN(double x){
++  int rc;   /* The value return */
++#if !defined(SQLITE_HAVE_ISNAN)
++  /*
++  ** Systems that support the isnan() library function should probably
++  ** make use of it by compiling with -DSQLITE_HAVE_ISNAN.  But we have
++  ** found that many systems do not have a working isnan() function so
++  ** this implementation is provided as an alternative.
++  **
++  ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
++  ** On the other hand, the use of -ffast-math comes with the following
++  ** warning:
++  **
++  **      This option [-ffast-math] should never be turned on by any
++  **      -O option since it can result in incorrect output for programs
++  **      which depend on an exact implementation of IEEE or ISO 
++  **      rules/specifications for math functions.
++  **
++  ** Under MSVC, this NaN test may fail if compiled with a floating-
++  ** point precision mode other than /fp:precise.  From the MSDN 
++  ** documentation:
++  **
++  **      The compiler [with /fp:precise] will properly handle comparisons 
++  **      involving NaN. For example, x != x evaluates to true if x is NaN 
++  **      ...
++  */
++#ifdef __FAST_MATH__
++# error SQLite will not work correctly with the -ffast-math option of GCC.
+ #endif
++  volatile double y = x;
++  volatile double z = y;
++  rc = (y!=z);
++#else  /* if defined(SQLITE_HAVE_ISNAN) */
++  rc = isnan(x);
++#endif /* SQLITE_HAVE_ISNAN */
++  testcase( rc );
++  return rc;
++}
++#endif /* SQLITE_OMIT_FLOATING_POINT */
+ 
+ /*
+-** HAVE_MREMAP defaults to true on Linux and false everywhere else.
++** Compute a string length that is limited to what can be stored in
++** lower 30 bits of a 32-bit signed integer.
++**
++** The value returned will never be negative.  Nor will it ever be greater
++** than the actual length of the string.  For very long strings (greater
++** than 1GiB) the value returned might be less than the true string length.
+ */
+-#if !defined(HAVE_MREMAP)
+-# if defined(__linux__) && defined(_GNU_SOURCE)
+-#  define HAVE_MREMAP 1
+-# else
+-#  define HAVE_MREMAP 0
+-# endif
+-#endif
++SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
++  const char *z2 = z;
++  if( z==0 ) return 0;
++  while( *z2 ){ z2++; }
++  return 0x3fffffff & (int)(z2 - z);
++}
+ 
+ /*
+-** Different Unix systems declare open() in different ways.  Same use
+-** open(const char*,int,mode_t).  Others use open(const char*,int,...).
+-** The difference is important when using a pointer to the function.
++** Set the most recent error code and error string for the sqlite
++** handle "db". The error code is set to "err_code".
+ **
+-** The safest way to deal with the problem is to always use this wrapper
+-** which always has the same well-defined interface.
++** If it is not NULL, string zFormat specifies the format of the
++** error string in the style of the printf functions: The following
++** format characters are allowed:
++**
++**      %s      Insert a string
++**      %z      A string that should be freed after use
++**      %d      Insert an integer
++**      %T      Insert a token
++**      %S      Insert the first element of a SrcList
++**
++** zFormat and any string tokens that follow it are assumed to be
++** encoded in UTF-8.
++**
++** To clear the most recent error for sqlite handle "db", sqlite3Error
++** should be called with err_code set to SQLITE_OK and zFormat set
++** to NULL.
+ */
+-static int posixOpen(const char *zFile, int flags, int mode){
+-  return open(zFile, flags, mode);
++SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
++  if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
++    db->errCode = err_code;
++    if( zFormat ){
++      char *z;
++      va_list ap;
++      va_start(ap, zFormat);
++      z = sqlite3VMPrintf(db, zFormat, ap);
++      va_end(ap);
++      sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
++    }else{
++      sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
++    }
++  }
+ }
+ 
+ /*
+-** On some systems, calls to fchown() will trigger a message in a security
+-** log if they come from non-root processes.  So avoid calling fchown() if
+-** we are not running as root.
++** Add an error message to pParse->zErrMsg and increment pParse->nErr.
++** The following formatting characters are allowed:
++**
++**      %s      Insert a string
++**      %z      A string that should be freed after use
++**      %d      Insert an integer
++**      %T      Insert a token
++**      %S      Insert the first element of a SrcList
++**
++** This function should be used to report any error that occurs whilst
++** compiling an SQL statement (i.e. within sqlite3_prepare()). The
++** last thing the sqlite3_prepare() function does is copy the error
++** stored by this function into the database handle using sqlite3Error().
++** Function sqlite3Error() should be used during statement execution
++** (sqlite3_step() etc.).
+ */
+-static int posixFchown(int fd, uid_t uid, gid_t gid){
+-  return geteuid() ? 0 : fchown(fd,uid,gid);
++SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
++  char *zMsg;
++  va_list ap;
++  sqlite3 *db = pParse->db;
++  va_start(ap, zFormat);
++  zMsg = sqlite3VMPrintf(db, zFormat, ap);
++  va_end(ap);
++  if( db->suppressErr ){
++    sqlite3DbFree(db, zMsg);
++  }else{
++    pParse->nErr++;
++    sqlite3DbFree(db, pParse->zErrMsg);
++    pParse->zErrMsg = zMsg;
++    pParse->rc = SQLITE_ERROR;
++  }
+ }
+ 
+-/* Forward reference */
+-static int openDirectory(const char*, int*);
+-
+ /*
+-** Many system calls are accessed through pointer-to-functions so that
+-** they may be overridden at runtime to facilitate fault injection during
+-** testing and sandboxing.  The following array holds the names and pointers
+-** to all overrideable system calls.
++** Convert an SQL-style quoted string into a normal string by removing
++** the quote characters.  The conversion is done in-place.  If the
++** input does not begin with a quote character, then this routine
++** is a no-op.
++**
++** The input string must be zero-terminated.  A new zero-terminator
++** is added to the dequoted string.
++**
++** The return value is -1 if no dequoting occurs or the length of the
++** dequoted string, exclusive of the zero terminator, if dequoting does
++** occur.
++**
++** 2002-Feb-14: This routine is extended to remove MS-Access style
++** brackets from around identifers.  For example:  "[a-b-c]" becomes
++** "a-b-c".
+ */
+-static struct unix_syscall {
+-  const char *zName;            /* Name of the system call */
+-  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
+-  sqlite3_syscall_ptr pDefault; /* Default value */
+-} aSyscall[] = {
+-  { "open",         (sqlite3_syscall_ptr)posixOpen,  0  },
+-#define osOpen      ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
+-
+-  { "close",        (sqlite3_syscall_ptr)close,      0  },
+-#define osClose     ((int(*)(int))aSyscall[1].pCurrent)
+-
+-  { "access",       (sqlite3_syscall_ptr)access,     0  },
+-#define osAccess    ((int(*)(const char*,int))aSyscall[2].pCurrent)
+-
+-  { "getcwd",       (sqlite3_syscall_ptr)getcwd,     0  },
+-#define osGetcwd    ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
++SQLITE_PRIVATE int sqlite3Dequote(char *z){
++  char quote;
++  int i, j;
++  if( z==0 ) return -1;
++  quote = z[0];
++  switch( quote ){
++    case '\'':  break;
++    case '"':   break;
++    case '`':   break;                /* For MySQL compatibility */
++    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
++    default:    return -1;
++  }
++  for(i=1, j=0; ALWAYS(z[i]); i++){
++    if( z[i]==quote ){
++      if( z[i+1]==quote ){
++        z[j++] = quote;
++        i++;
++      }else{
++        break;
++      }
++    }else{
++      z[j++] = z[i];
++    }
++  }
++  z[j] = 0;
++  return j;
++}
+ 
+-  { "stat",         (sqlite3_syscall_ptr)stat,       0  },
+-#define osStat      ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
++/* Convenient short-hand */
++#define UpperToLower sqlite3UpperToLower
+ 
+ /*
+-** The DJGPP compiler environment looks mostly like Unix, but it
+-** lacks the fcntl() system call.  So redefine fcntl() to be something
+-** that always succeeds.  This means that locking does not occur under
+-** DJGPP.  But it is DOS - what did you expect?
++** Some systems have stricmp().  Others have strcasecmp().  Because
++** there is no consistency, we will define our own.
++**
++** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
++** sqlite3_strnicmp() APIs allow applications and extensions to compare
++** the contents of two buffers containing UTF-8 strings in a
++** case-independent fashion, using the same definition of "case
++** independence" that SQLite uses internally when comparing identifiers.
+ */
+-#ifdef __DJGPP__
+-  { "fstat",        0,                 0  },
+-#define osFstat(a,b,c)    0
+-#else     
+-  { "fstat",        (sqlite3_syscall_ptr)fstat,      0  },
+-#define osFstat     ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
+-#endif
+-
+-  { "ftruncate",    (sqlite3_syscall_ptr)ftruncate,  0  },
+-#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
+-
+-  { "fcntl",        (sqlite3_syscall_ptr)fcntl,      0  },
+-#define osFcntl     ((int(*)(int,int,...))aSyscall[7].pCurrent)
+-
+-  { "read",         (sqlite3_syscall_ptr)read,       0  },
+-#define osRead      ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
+-
+-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
+-  { "pread",        (sqlite3_syscall_ptr)pread,      0  },
+-#else
+-  { "pread",        (sqlite3_syscall_ptr)0,          0  },
+-#endif
+-#define osPread     ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
+-
+-#if defined(USE_PREAD64)
+-  { "pread64",      (sqlite3_syscall_ptr)pread64,    0  },
+-#else
+-  { "pread64",      (sqlite3_syscall_ptr)0,          0  },
+-#endif
+-#define osPread64   ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
+-
+-  { "write",        (sqlite3_syscall_ptr)write,      0  },
+-#define osWrite     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
+-
+-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
+-  { "pwrite",       (sqlite3_syscall_ptr)pwrite,     0  },
+-#else
+-  { "pwrite",       (sqlite3_syscall_ptr)0,          0  },
+-#endif
+-#define osPwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
+-                    aSyscall[12].pCurrent)
+-
+-#if defined(USE_PREAD64)
+-  { "pwrite64",     (sqlite3_syscall_ptr)pwrite64,   0  },
+-#else
+-  { "pwrite64",     (sqlite3_syscall_ptr)0,          0  },
+-#endif
+-#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
+-                    aSyscall[13].pCurrent)
+-
+-  { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },
+-#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
+-
+-#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+-  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
+-#else
+-  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
+-#endif
+-#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
+-
+-  { "unlink",       (sqlite3_syscall_ptr)unlink,           0 },
+-#define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)
+-
+-  { "openDirectory",    (sqlite3_syscall_ptr)openDirectory,      0 },
+-#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
++SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
++  register unsigned char *a, *b;
++  a = (unsigned char *)zLeft;
++  b = (unsigned char *)zRight;
++  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
++  return UpperToLower[*a] - UpperToLower[*b];
++}
++SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
++  register unsigned char *a, *b;
++  a = (unsigned char *)zLeft;
++  b = (unsigned char *)zRight;
++  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
++  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
++}
+ 
+-  { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
+-#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
++/*
++** The string z[] is an text representation of a real number.
++** Convert this string to a double and write it into *pResult.
++**
++** The string z[] is length bytes in length (bytes, not characters) and
++** uses the encoding enc.  The string is not necessarily zero-terminated.
++**
++** Return TRUE if the result is a valid real number (or integer) and FALSE
++** if the string is empty or contains extraneous text.  Valid numbers
++** are in one of these formats:
++**
++**    [+-]digits[E[+-]digits]
++**    [+-]digits.[digits][E[+-]digits]
++**    [+-].digits[E[+-]digits]
++**
++** Leading and trailing whitespace is ignored for the purpose of determining
++** validity.
++**
++** If some prefix of the input string is a valid number, this routine
++** returns FALSE but it still converts the prefix and writes the result
++** into *pResult.
++*/
++SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
++#ifndef SQLITE_OMIT_FLOATING_POINT
++  int incr;
++  const char *zEnd = z + length;
++  /* sign * significand * (10 ^ (esign * exponent)) */
++  int sign = 1;    /* sign of significand */
++  i64 s = 0;       /* significand */
++  int d = 0;       /* adjust exponent for shifting decimal point */
++  int esign = 1;   /* sign of exponent */
++  int e = 0;       /* exponent */
++  int eValid = 1;  /* True exponent is either not used or is well-formed */
++  double result;
++  int nDigits = 0;
++  int nonNum = 0;
+ 
+-  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
+-#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
++  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
++  *pResult = 0.0;   /* Default return value, in case of an error */
+ 
+-  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
+-#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
++  if( enc==SQLITE_UTF8 ){
++    incr = 1;
++  }else{
++    int i;
++    incr = 2;
++    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
++    for(i=3-enc; i<length && z[i]==0; i+=2){}
++    nonNum = i<length;
++    zEnd = z+i+enc-3;
++    z += (enc&1);
++  }
+ 
+-  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
+-#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
++  /* skip leading spaces */
++  while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
++  if( z>=zEnd ) return 0;
+ 
+-  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
+-#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
++  /* get sign of significand */
++  if( *z=='-' ){
++    sign = -1;
++    z+=incr;
++  }else if( *z=='+' ){
++    z+=incr;
++  }
+ 
+-#if HAVE_MREMAP
+-  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
+-#else
+-  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
+-#endif
+-#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
++  /* skip leading zeroes */
++  while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
+ 
+-}; /* End of the overrideable system calls */
++  /* copy max significant digits to significand */
++  while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
++    s = s*10 + (*z - '0');
++    z+=incr, nDigits++;
++  }
+ 
+-/*
+-** This is the xSetSystemCall() method of sqlite3_vfs for all of the
+-** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
+-** system call pointer, or SQLITE_NOTFOUND if there is no configurable
+-** system call named zName.
+-*/
+-static int unixSetSystemCall(
+-  sqlite3_vfs *pNotUsed,        /* The VFS pointer.  Not used */
+-  const char *zName,            /* Name of system call to override */
+-  sqlite3_syscall_ptr pNewFunc  /* Pointer to new system call value */
+-){
+-  unsigned int i;
+-  int rc = SQLITE_NOTFOUND;
++  /* skip non-significant significand digits
++  ** (increase exponent by d to shift decimal left) */
++  while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
++  if( z>=zEnd ) goto do_atof_calc;
+ 
+-  UNUSED_PARAMETER(pNotUsed);
+-  if( zName==0 ){
+-    /* If no zName is given, restore all system calls to their default
+-    ** settings and return NULL
+-    */
+-    rc = SQLITE_OK;
+-    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+-      if( aSyscall[i].pDefault ){
+-        aSyscall[i].pCurrent = aSyscall[i].pDefault;
+-      }
++  /* if decimal point is present */
++  if( *z=='.' ){
++    z+=incr;
++    /* copy digits from after decimal to significand
++    ** (decrease exponent by d to shift decimal right) */
++    while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
++      s = s*10 + (*z - '0');
++      z+=incr, nDigits++, d--;
+     }
+-  }else{
+-    /* If zName is specified, operate on only the one system call
+-    ** specified.
+-    */
+-    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+-      if( strcmp(zName, aSyscall[i].zName)==0 ){
+-        if( aSyscall[i].pDefault==0 ){
+-          aSyscall[i].pDefault = aSyscall[i].pCurrent;
+-        }
+-        rc = SQLITE_OK;
+-        if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
+-        aSyscall[i].pCurrent = pNewFunc;
+-        break;
+-      }
++    /* skip non-significant digits */
++    while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
++  }
++  if( z>=zEnd ) goto do_atof_calc;
++
++  /* if exponent is present */
++  if( *z=='e' || *z=='E' ){
++    z+=incr;
++    eValid = 0;
++    if( z>=zEnd ) goto do_atof_calc;
++    /* get sign of exponent */
++    if( *z=='-' ){
++      esign = -1;
++      z+=incr;
++    }else if( *z=='+' ){
++      z+=incr;
++    }
++    /* copy digits to exponent */
++    while( z<zEnd && sqlite3Isdigit(*z) ){
++      e = e<10000 ? (e*10 + (*z - '0')) : 10000;
++      z+=incr;
++      eValid = 1;
+     }
+   }
+-  return rc;
+-}
+-
+-/*
+-** Return the value of a system call.  Return NULL if zName is not a
+-** recognized system call name.  NULL is also returned if the system call
+-** is currently undefined.
+-*/
+-static sqlite3_syscall_ptr unixGetSystemCall(
+-  sqlite3_vfs *pNotUsed,
+-  const char *zName
+-){
+-  unsigned int i;
+ 
+-  UNUSED_PARAMETER(pNotUsed);
+-  for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+-    if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
++  /* skip trailing spaces */
++  if( nDigits && eValid ){
++    while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
+   }
+-  return 0;
+-}
+ 
+-/*
+-** Return the name of the first system call after zName.  If zName==NULL
+-** then return the name of the first system call.  Return NULL if zName
+-** is the last system call or if zName is not the name of a valid
+-** system call.
+-*/
+-static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
+-  int i = -1;
++do_atof_calc:
++  /* adjust exponent by d, and update sign */
++  e = (e*esign) + d;
++  if( e<0 ) {
++    esign = -1;
++    e *= -1;
++  } else {
++    esign = 1;
++  }
+ 
+-  UNUSED_PARAMETER(p);
+-  if( zName ){
+-    for(i=0; i<ArraySize(aSyscall)-1; i++){
+-      if( strcmp(zName, aSyscall[i].zName)==0 ) break;
++  /* if 0 significand */
++  if( !s ) {
++    /* In the IEEE 754 standard, zero is signed.
++    ** Add the sign if we've seen at least one digit */
++    result = (sign<0 && nDigits) ? -(double)0 : (double)0;
++  } else {
++    /* attempt to reduce exponent */
++    if( esign>0 ){
++      while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
++    }else{
++      while( !(s%10) && e>0 ) e--,s/=10;
+     }
+-  }
+-  for(i++; i<ArraySize(aSyscall); i++){
+-    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
+-  }
+-  return 0;
+-}
+ 
+-/*
+-** Invoke open().  Do so multiple times, until it either succeeds or
+-** fails for some reason other than EINTR.
+-**
+-** If the file creation mode "m" is 0 then set it to the default for
+-** SQLite.  The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
+-** 0644) as modified by the system umask.  If m is not 0, then
+-** make the file creation mode be exactly m ignoring the umask.
+-**
+-** The m parameter will be non-zero only when creating -wal, -journal,
+-** and -shm files.  We want those files to have *exactly* the same
+-** permissions as their original database, unadulterated by the umask.
+-** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
+-** transaction crashes and leaves behind hot journals, then any
+-** process that is able to write to the database will also be able to
+-** recover the hot journals.
+-*/
+-static int robust_open(const char *z, int f, mode_t m){
+-  int fd;
+-  mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
+-  do{
+-#if defined(O_CLOEXEC)
+-    fd = osOpen(z,f|O_CLOEXEC,m2);
+-#else
+-    fd = osOpen(z,f,m2);
+-#endif
+-  }while( fd<0 && errno==EINTR );
+-  if( fd>=0 ){
+-    if( m!=0 ){
+-      struct stat statbuf;
+-      if( osFstat(fd, &statbuf)==0 
+-       && statbuf.st_size==0
+-       && (statbuf.st_mode&0777)!=m 
+-      ){
+-        osFchmod(fd, m);
++    /* adjust the sign of significand */
++    s = sign<0 ? -s : s;
++
++    /* if exponent, scale significand as appropriate
++    ** and store in result. */
++    if( e ){
++      LONGDOUBLE_TYPE scale = 1.0;
++      /* attempt to handle extremely small/large numbers better */
++      if( e>307 && e<342 ){
++        while( e%308 ) { scale *= 1.0e+1; e -= 1; }
++        if( esign<0 ){
++          result = s / scale;
++          result /= 1.0e+308;
++        }else{
++          result = s * scale;
++          result *= 1.0e+308;
++        }
++      }else if( e>=342 ){
++        if( esign<0 ){
++          result = 0.0*s;
++        }else{
++          result = 1e308*1e308*s;  /* Infinity */
++        }
++      }else{
++        /* 1.0e+22 is the largest power of 10 than can be 
++        ** represented exactly. */
++        while( e%22 ) { scale *= 1.0e+1; e -= 1; }
++        while( e>0 ) { scale *= 1.0e+22; e -= 22; }
++        if( esign<0 ){
++          result = s / scale;
++        }else{
++          result = s * scale;
++        }
+       }
++    } else {
++      result = (double)s;
+     }
+-#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
+-    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+-#endif
+   }
+-  return fd;
++
++  /* store the result */
++  *pResult = result;
++
++  /* return true if number and no extra non-whitespace chracters after */
++  return z>=zEnd && nDigits>0 && eValid && nonNum==0;
++#else
++  return !sqlite3Atoi64(z, pResult, length, enc);
++#endif /* SQLITE_OMIT_FLOATING_POINT */
+ }
+ 
+ /*
+-** Helper functions to obtain and relinquish the global mutex. The
+-** global mutex is used to protect the unixInodeInfo and
+-** vxworksFileId objects used by this file, all of which may be 
+-** shared by multiple threads.
++** Compare the 19-character string zNum against the text representation
++** value 2^63:  9223372036854775808.  Return negative, zero, or positive
++** if zNum is less than, equal to, or greater than the string.
++** Note that zNum must contain exactly 19 characters.
+ **
+-** Function unixMutexHeld() is used to assert() that the global mutex 
+-** is held when required. This function is only used as part of assert() 
+-** statements. e.g.
++** Unlike memcmp() this routine is guaranteed to return the difference
++** in the values of the last digit if the only difference is in the
++** last digit.  So, for example,
+ **
+-**   unixEnterMutex()
+-**     assert( unixMutexHeld() );
+-**   unixEnterLeave()
++**      compare2pow63("9223372036854775800", 1)
++**
++** will return -8.
+ */
+-static void unixEnterMutex(void){
+-  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-}
+-static void unixLeaveMutex(void){
+-  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-}
+-#ifdef SQLITE_DEBUG
+-static int unixMutexHeld(void) {
+-  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++static int compare2pow63(const char *zNum, int incr){
++  int c = 0;
++  int i;
++                    /* 012345678901234567 */
++  const char *pow63 = "922337203685477580";
++  for(i=0; c==0 && i<18; i++){
++    c = (zNum[i*incr]-pow63[i])*10;
++  }
++  if( c==0 ){
++    c = zNum[18*incr] - '8';
++    testcase( c==(-1) );
++    testcase( c==0 );
++    testcase( c==(+1) );
++  }
++  return c;
+ }
+-#endif
+ 
+ 
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+ /*
+-** Helper function for printing out trace information from debugging
+-** binaries. This returns the string represetation of the supplied
+-** integer lock-type.
++** Convert zNum to a 64-bit signed integer.
++**
++** If the zNum value is representable as a 64-bit twos-complement 
++** integer, then write that value into *pNum and return 0.
++**
++** If zNum is exactly 9223372036854665808, return 2.  This special
++** case is broken out because while 9223372036854665808 cannot be a 
++** signed 64-bit integer, its negative -9223372036854665808 can be.
++**
++** If zNum is too big for a 64-bit integer and is not
++** 9223372036854665808  or if zNum contains any non-numeric text,
++** then return 1.
++**
++** length is the number of bytes in the string (bytes, not characters).
++** The string is not necessarily zero-terminated.  The encoding is
++** given by enc.
+ */
+-static const char *azFileLock(int eFileLock){
+-  switch( eFileLock ){
+-    case NO_LOCK: return "NONE";
+-    case SHARED_LOCK: return "SHARED";
+-    case RESERVED_LOCK: return "RESERVED";
+-    case PENDING_LOCK: return "PENDING";
+-    case EXCLUSIVE_LOCK: return "EXCLUSIVE";
++SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
++  int incr;
++  u64 u = 0;
++  int neg = 0; /* assume positive */
++  int i;
++  int c = 0;
++  int nonNum = 0;
++  const char *zStart;
++  const char *zEnd = zNum + length;
++  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
++  if( enc==SQLITE_UTF8 ){
++    incr = 1;
++  }else{
++    incr = 2;
++    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
++    for(i=3-enc; i<length && zNum[i]==0; i+=2){}
++    nonNum = i<length;
++    zEnd = zNum+i+enc-3;
++    zNum += (enc&1);
++  }
++  while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
++  if( zNum<zEnd ){
++    if( *zNum=='-' ){
++      neg = 1;
++      zNum+=incr;
++    }else if( *zNum=='+' ){
++      zNum+=incr;
++    }
++  }
++  zStart = zNum;
++  while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
++  for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
++    u = u*10 + c - '0';
++  }
++  if( u>LARGEST_INT64 ){
++    *pNum = SMALLEST_INT64;
++  }else if( neg ){
++    *pNum = -(i64)u;
++  }else{
++    *pNum = (i64)u;
++  }
++  testcase( i==18 );
++  testcase( i==19 );
++  testcase( i==20 );
++  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
++    /* zNum is empty or contains non-numeric text or is longer
++    ** than 19 digits (thus guaranteeing that it is too large) */
++    return 1;
++  }else if( i<19*incr ){
++    /* Less than 19 digits, so we know that it fits in 64 bits */
++    assert( u<=LARGEST_INT64 );
++    return 0;
++  }else{
++    /* zNum is a 19-digit numbers.  Compare it against 9223372036854775808. */
++    c = compare2pow63(zNum, incr);
++    if( c<0 ){
++      /* zNum is less than 9223372036854775808 so it fits */
++      assert( u<=LARGEST_INT64 );
++      return 0;
++    }else if( c>0 ){
++      /* zNum is greater than 9223372036854775808 so it overflows */
++      return 1;
++    }else{
++      /* zNum is exactly 9223372036854775808.  Fits if negative.  The
++      ** special case 2 overflow if positive */
++      assert( u-1==LARGEST_INT64 );
++      assert( (*pNum)==SMALLEST_INT64 );
++      return neg ? 0 : 2;
++    }
+   }
+-  return "ERROR";
+ }
+-#endif
+ 
+-#ifdef SQLITE_LOCK_TRACE
+ /*
+-** Print out information about all locking operations.
++** If zNum represents an integer that will fit in 32-bits, then set
++** *pValue to that integer and return true.  Otherwise return false.
+ **
+-** This routine is used for troubleshooting locks on multithreaded
+-** platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
+-** command-line option on the compiler.  This code is normally
+-** turned off.
++** Any non-numeric characters that following zNum are ignored.
++** This is different from sqlite3Atoi64() which requires the
++** input number to be zero-terminated.
+ */
+-static int lockTrace(int fd, int op, struct flock *p){
+-  char *zOpName, *zType;
+-  int s;
+-  int savedErrno;
+-  if( op==F_GETLK ){
+-    zOpName = "GETLK";
+-  }else if( op==F_SETLK ){
+-    zOpName = "SETLK";
+-  }else{
+-    s = osFcntl(fd, op, p);
+-    sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
+-    return s;
++SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
++  sqlite_int64 v = 0;
++  int i, c;
++  int neg = 0;
++  if( zNum[0]=='-' ){
++    neg = 1;
++    zNum++;
++  }else if( zNum[0]=='+' ){
++    zNum++;
+   }
+-  if( p->l_type==F_RDLCK ){
+-    zType = "RDLCK";
+-  }else if( p->l_type==F_WRLCK ){
+-    zType = "WRLCK";
+-  }else if( p->l_type==F_UNLCK ){
+-    zType = "UNLCK";
+-  }else{
+-    assert( 0 );
++  while( zNum[0]=='0' ) zNum++;
++  for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
++    v = v*10 + c;
+   }
+-  assert( p->l_whence==SEEK_SET );
+-  s = osFcntl(fd, op, p);
+-  savedErrno = errno;
+-  sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
+-     threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
+-     (int)p->l_pid, s);
+-  if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
+-    struct flock l2;
+-    l2 = *p;
+-    osFcntl(fd, F_GETLK, &l2);
+-    if( l2.l_type==F_RDLCK ){
+-      zType = "RDLCK";
+-    }else if( l2.l_type==F_WRLCK ){
+-      zType = "WRLCK";
+-    }else if( l2.l_type==F_UNLCK ){
+-      zType = "UNLCK";
+-    }else{
+-      assert( 0 );
+-    }
+-    sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
+-       zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
++
++  /* The longest decimal representation of a 32 bit integer is 10 digits:
++  **
++  **             1234567890
++  **     2^31 -> 2147483648
++  */
++  testcase( i==10 );
++  if( i>10 ){
++    return 0;
+   }
+-  errno = savedErrno;
+-  return s;
++  testcase( v-neg==2147483647 );
++  if( v-neg>2147483647 ){
++    return 0;
++  }
++  if( neg ){
++    v = -v;
++  }
++  *pValue = (int)v;
++  return 1;
+ }
+-#undef osFcntl
+-#define osFcntl lockTrace
+-#endif /* SQLITE_LOCK_TRACE */
+ 
+ /*
+-** Retry ftruncate() calls that fail due to EINTR
++** Return a 32-bit integer value extracted from a string.  If the
++** string is not an integer, just return 0.
+ */
+-static int robust_ftruncate(int h, sqlite3_int64 sz){
+-  int rc;
+-  do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
+-  return rc;
++SQLITE_PRIVATE int sqlite3Atoi(const char *z){
++  int x = 0;
++  if( z ) sqlite3GetInt32(z, &x);
++  return x;
+ }
+ 
+ /*
+-** This routine translates a standard POSIX errno code into something
+-** useful to the clients of the sqlite3 functions.  Specifically, it is
+-** intended to translate a variety of "try again" errors into SQLITE_BUSY
+-** and a variety of "please close the file descriptor NOW" errors into 
+-** SQLITE_IOERR
+-** 
+-** Errors during initialization of locks, or file system support for locks,
+-** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
++** The variable-length integer encoding is as follows:
++**
++** KEY:
++**         A = 0xxxxxxx    7 bits of data and one flag bit
++**         B = 1xxxxxxx    7 bits of data and one flag bit
++**         C = xxxxxxxx    8 bits of data
++**
++**  7 bits - A
++** 14 bits - BA
++** 21 bits - BBA
++** 28 bits - BBBA
++** 35 bits - BBBBA
++** 42 bits - BBBBBA
++** 49 bits - BBBBBBA
++** 56 bits - BBBBBBBA
++** 64 bits - BBBBBBBBC
+ */
+-static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
+-  switch (posixError) {
+-#if 0
+-  /* At one point this code was not commented out. In theory, this branch
+-  ** should never be hit, as this function should only be called after
+-  ** a locking-related function (i.e. fcntl()) has returned non-zero with
+-  ** the value of errno as the first argument. Since a system call has failed,
+-  ** errno should be non-zero.
+-  **
+-  ** Despite this, if errno really is zero, we still don't want to return
+-  ** SQLITE_OK. The system call failed, and *some* SQLite error should be
+-  ** propagated back to the caller. Commenting this branch out means errno==0
+-  ** will be handled by the "default:" case below.
+-  */
+-  case 0: 
+-    return SQLITE_OK;
+-#endif
+ 
+-  case EAGAIN:
+-  case ETIMEDOUT:
+-  case EBUSY:
+-  case EINTR:
+-  case ENOLCK:  
+-    /* random NFS retry error, unless during file system support 
+-     * introspection, in which it actually means what it says */
+-    return SQLITE_BUSY;
+-    
+-  case EACCES: 
+-    /* EACCES is like EAGAIN during locking operations, but not any other time*/
+-    if( (sqliteIOErr == SQLITE_IOERR_LOCK) || 
+-        (sqliteIOErr == SQLITE_IOERR_UNLOCK) || 
+-        (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+-        (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
+-      return SQLITE_BUSY;
++/*
++** Write a 64-bit variable-length integer to memory starting at p[0].
++** The length of data write will be between 1 and 9 bytes.  The number
++** of bytes written is returned.
++**
++** A variable-length integer consists of the lower 7 bits of each byte
++** for all bytes that have the 8th bit set and one byte with the 8th
++** bit clear.  Except, if we get to the 9th byte, it stores the full
++** 8 bits and is the last byte.
++*/
++SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
++  int i, j, n;
++  u8 buf[10];
++  if( v & (((u64)0xff000000)<<32) ){
++    p[8] = (u8)v;
++    v >>= 8;
++    for(i=7; i>=0; i--){
++      p[i] = (u8)((v & 0x7f) | 0x80);
++      v >>= 7;
+     }
+-    /* else fall through */
+-  case EPERM: 
+-    return SQLITE_PERM;
+-    
+-  /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
+-  ** this module never makes such a call. And the code in SQLite itself 
+-  ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
+-  ** this case is also commented out. If the system does set errno to EDEADLK,
+-  ** the default SQLITE_IOERR_XXX code will be returned. */
+-#if 0
+-  case EDEADLK:
+-    return SQLITE_IOERR_BLOCKED;
+-#endif
+-    
+-#if EOPNOTSUPP!=ENOTSUP
+-  case EOPNOTSUPP: 
+-    /* something went terribly awry, unless during file system support 
+-     * introspection, in which it actually means what it says */
+-#endif
+-#ifdef ENOTSUP
+-  case ENOTSUP: 
+-    /* invalid fd, unless during file system support introspection, in which 
+-     * it actually means what it says */
+-#endif
+-  case EIO:
+-  case EBADF:
+-  case EINVAL:
+-  case ENOTCONN:
+-  case ENODEV:
+-  case ENXIO:
+-  case ENOENT:
+-#ifdef ESTALE                     /* ESTALE is not defined on Interix systems */
+-  case ESTALE:
+-#endif
+-  case ENOSYS:
+-    /* these should force the client to close the file and reconnect */
+-    
+-  default: 
+-    return sqliteIOErr;
++    return 9;
++  }    
++  n = 0;
++  do{
++    buf[n++] = (u8)((v & 0x7f) | 0x80);
++    v >>= 7;
++  }while( v!=0 );
++  buf[0] &= 0x7f;
++  assert( n<=9 );
++  for(i=0, j=n-1; j>=0; j--, i++){
++    p[i] = buf[j];
+   }
++  return n;
+ }
+ 
++/*
++** This routine is a faster version of sqlite3PutVarint() that only
++** works for 32-bit positive integers and which is optimized for
++** the common case of small integers.  A MACRO version, putVarint32,
++** is provided which inlines the single-byte case.  All code should use
++** the MACRO version as this function assumes the single-byte case has
++** already been handled.
++*/
++SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
++#ifndef putVarint32
++  if( (v & ~0x7f)==0 ){
++    p[0] = v;
++    return 1;
++  }
++#endif
++  if( (v & ~0x3fff)==0 ){
++    p[0] = (u8)((v>>7) | 0x80);
++    p[1] = (u8)(v & 0x7f);
++    return 2;
++  }
++  return sqlite3PutVarint(p, v);
++}
+ 
+-/******************************************************************************
+-****************** Begin Unique File ID Utility Used By VxWorks ***************
+-**
+-** On most versions of unix, we can get a unique ID for a file by concatenating
+-** the device number and the inode number.  But this does not work on VxWorks.
+-** On VxWorks, a unique file id must be based on the canonical filename.
++/*
++** Bitmasks used by sqlite3GetVarint().  These precomputed constants
++** are defined here rather than simply putting the constant expressions
++** inline in order to work around bugs in the RVT compiler.
+ **
+-** A pointer to an instance of the following structure can be used as a
+-** unique file ID in VxWorks.  Each instance of this structure contains
+-** a copy of the canonical filename.  There is also a reference count.  
+-** The structure is reclaimed when the number of pointers to it drops to
+-** zero.
++** SLOT_2_0     A mask for  (0x7f<<14) | 0x7f
+ **
+-** There are never very many files open at one time and lookups are not
+-** a performance-critical path, so it is sufficient to put these
+-** structures on a linked list.
++** SLOT_4_2_0   A mask for  (0x7f<<28) | SLOT_2_0
+ */
+-struct vxworksFileId {
+-  struct vxworksFileId *pNext;  /* Next in a list of them all */
+-  int nRef;                     /* Number of references to this one */
+-  int nName;                    /* Length of the zCanonicalName[] string */
+-  char *zCanonicalName;         /* Canonical filename */
+-};
++#define SLOT_2_0     0x001fc07f
++#define SLOT_4_2_0   0xf01fc07f
+ 
+-#if OS_VXWORKS
+-/* 
+-** All unique filenames are held on a linked list headed by this
+-** variable:
+-*/
+-static struct vxworksFileId *vxworksFileList = 0;
+ 
+ /*
+-** Simplify a filename into its canonical form
+-** by making the following changes:
+-**
+-**  * removing any trailing and duplicate /
+-**  * convert /./ into just /
+-**  * convert /A/../ where A is any simple name into just /
+-**
+-** Changes are made in-place.  Return the new name length.
+-**
+-** The original filename is in z[0..n-1].  Return the number of
+-** characters in the simplified name.
++** Read a 64-bit variable-length integer from memory starting at p[0].
++** Return the number of bytes read.  The value is stored in *v.
+ */
+-static int vxworksSimplifyName(char *z, int n){
+-  int i, j;
+-  while( n>1 && z[n-1]=='/' ){ n--; }
+-  for(i=j=0; i<n; i++){
+-    if( z[i]=='/' ){
+-      if( z[i+1]=='/' ) continue;
+-      if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
+-        i += 1;
+-        continue;
+-      }
+-      if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
+-        while( j>0 && z[j-1]!='/' ){ j--; }
+-        if( j>0 ){ j--; }
+-        i += 2;
+-        continue;
+-      }
+-    }
+-    z[j++] = z[i];
++SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
++  u32 a,b,s;
++
++  a = *p;
++  /* a: p0 (unmasked) */
++  if (!(a&0x80))
++  {
++    *v = a;
++    return 1;
+   }
+-  z[j] = 0;
+-  return j;
++
++  p++;
++  b = *p;
++  /* b: p1 (unmasked) */
++  if (!(b&0x80))
++  {
++    a &= 0x7f;
++    a = a<<7;
++    a |= b;
++    *v = a;
++    return 2;
++  }
++
++  /* Verify that constants are precomputed correctly */
++  assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
++  assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
++
++  p++;
++  a = a<<14;
++  a |= *p;
++  /* a: p0<<14 | p2 (unmasked) */
++  if (!(a&0x80))
++  {
++    a &= SLOT_2_0;
++    b &= 0x7f;
++    b = b<<7;
++    a |= b;
++    *v = a;
++    return 3;
++  }
++
++  /* CSE1 from below */
++  a &= SLOT_2_0;
++  p++;
++  b = b<<14;
++  b |= *p;
++  /* b: p1<<14 | p3 (unmasked) */
++  if (!(b&0x80))
++  {
++    b &= SLOT_2_0;
++    /* moved CSE1 up */
++    /* a &= (0x7f<<14)|(0x7f); */
++    a = a<<7;
++    a |= b;
++    *v = a;
++    return 4;
++  }
++
++  /* a: p0<<14 | p2 (masked) */
++  /* b: p1<<14 | p3 (unmasked) */
++  /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
++  /* moved CSE1 up */
++  /* a &= (0x7f<<14)|(0x7f); */
++  b &= SLOT_2_0;
++  s = a;
++  /* s: p0<<14 | p2 (masked) */
++
++  p++;
++  a = a<<14;
++  a |= *p;
++  /* a: p0<<28 | p2<<14 | p4 (unmasked) */
++  if (!(a&0x80))
++  {
++    /* we can skip these cause they were (effectively) done above in calc'ing s */
++    /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
++    /* b &= (0x7f<<14)|(0x7f); */
++    b = b<<7;
++    a |= b;
++    s = s>>18;
++    *v = ((u64)s)<<32 | a;
++    return 5;
++  }
++
++  /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
++  s = s<<7;
++  s |= b;
++  /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
++
++  p++;
++  b = b<<14;
++  b |= *p;
++  /* b: p1<<28 | p3<<14 | p5 (unmasked) */
++  if (!(b&0x80))
++  {
++    /* we can skip this cause it was (effectively) done above in calc'ing s */
++    /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
++    a &= SLOT_2_0;
++    a = a<<7;
++    a |= b;
++    s = s>>18;
++    *v = ((u64)s)<<32 | a;
++    return 6;
++  }
++
++  p++;
++  a = a<<14;
++  a |= *p;
++  /* a: p2<<28 | p4<<14 | p6 (unmasked) */
++  if (!(a&0x80))
++  {
++    a &= SLOT_4_2_0;
++    b &= SLOT_2_0;
++    b = b<<7;
++    a |= b;
++    s = s>>11;
++    *v = ((u64)s)<<32 | a;
++    return 7;
++  }
++
++  /* CSE2 from below */
++  a &= SLOT_2_0;
++  p++;
++  b = b<<14;
++  b |= *p;
++  /* b: p3<<28 | p5<<14 | p7 (unmasked) */
++  if (!(b&0x80))
++  {
++    b &= SLOT_4_2_0;
++    /* moved CSE2 up */
++    /* a &= (0x7f<<14)|(0x7f); */
++    a = a<<7;
++    a |= b;
++    s = s>>4;
++    *v = ((u64)s)<<32 | a;
++    return 8;
++  }
++
++  p++;
++  a = a<<15;
++  a |= *p;
++  /* a: p4<<29 | p6<<15 | p8 (unmasked) */
++
++  /* moved CSE2 up */
++  /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
++  b &= SLOT_2_0;
++  b = b<<8;
++  a |= b;
++
++  s = s<<4;
++  b = p[-4];
++  b &= 0x7f;
++  b = b>>3;
++  s |= b;
++
++  *v = ((u64)s)<<32 | a;
++
++  return 9;
+ }
+ 
+ /*
+-** Find a unique file ID for the given absolute pathname.  Return
+-** a pointer to the vxworksFileId object.  This pointer is the unique
+-** file ID.
++** Read a 32-bit variable-length integer from memory starting at p[0].
++** Return the number of bytes read.  The value is stored in *v.
+ **
+-** The nRef field of the vxworksFileId object is incremented before
+-** the object is returned.  A new vxworksFileId object is created
+-** and added to the global list if necessary.
++** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
++** integer, then set *v to 0xffffffff.
+ **
+-** If a memory allocation error occurs, return NULL.
++** A MACRO version, getVarint32, is provided which inlines the 
++** single-byte case.  All code should use the MACRO version as 
++** this function assumes the single-byte case has already been handled.
+ */
+-static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
+-  struct vxworksFileId *pNew;         /* search key and new file ID */
+-  struct vxworksFileId *pCandidate;   /* For looping over existing file IDs */
+-  int n;                              /* Length of zAbsoluteName string */
++SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
++  u32 a,b;
+ 
+-  assert( zAbsoluteName[0]=='/' );
+-  n = (int)strlen(zAbsoluteName);
+-  pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
+-  if( pNew==0 ) return 0;
+-  pNew->zCanonicalName = (char*)&pNew[1];
+-  memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
+-  n = vxworksSimplifyName(pNew->zCanonicalName, n);
++  /* The 1-byte case.  Overwhelmingly the most common.  Handled inline
++  ** by the getVarin32() macro */
++  a = *p;
++  /* a: p0 (unmasked) */
++#ifndef getVarint32
++  if (!(a&0x80))
++  {
++    /* Values between 0 and 127 */
++    *v = a;
++    return 1;
++  }
++#endif
+ 
+-  /* Search for an existing entry that matching the canonical name.
+-  ** If found, increment the reference count and return a pointer to
+-  ** the existing file ID.
++  /* The 2-byte case */
++  p++;
++  b = *p;
++  /* b: p1 (unmasked) */
++  if (!(b&0x80))
++  {
++    /* Values between 128 and 16383 */
++    a &= 0x7f;
++    a = a<<7;
++    *v = a | b;
++    return 2;
++  }
++
++  /* The 3-byte case */
++  p++;
++  a = a<<14;
++  a |= *p;
++  /* a: p0<<14 | p2 (unmasked) */
++  if (!(a&0x80))
++  {
++    /* Values between 16384 and 2097151 */
++    a &= (0x7f<<14)|(0x7f);
++    b &= 0x7f;
++    b = b<<7;
++    *v = a | b;
++    return 3;
++  }
++
++  /* A 32-bit varint is used to store size information in btrees.
++  ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
++  ** A 3-byte varint is sufficient, for example, to record the size
++  ** of a 1048569-byte BLOB or string.
++  **
++  ** We only unroll the first 1-, 2-, and 3- byte cases.  The very
++  ** rare larger cases can be handled by the slower 64-bit varint
++  ** routine.
+   */
+-  unixEnterMutex();
+-  for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
+-    if( pCandidate->nName==n 
+-     && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
+-    ){
+-       sqlite3_free(pNew);
+-       pCandidate->nRef++;
+-       unixLeaveMutex();
+-       return pCandidate;
++#if 1
++  {
++    u64 v64;
++    u8 n;
++
++    p -= 2;
++    n = sqlite3GetVarint(p, &v64);
++    assert( n>3 && n<=9 );
++    if( (v64 & SQLITE_MAX_U32)!=v64 ){
++      *v = 0xffffffff;
++    }else{
++      *v = (u32)v64;
+     }
++    return n;
+   }
+ 
+-  /* No match was found.  We will make a new file ID */
+-  pNew->nRef = 1;
+-  pNew->nName = n;
+-  pNew->pNext = vxworksFileList;
+-  vxworksFileList = pNew;
+-  unixLeaveMutex();
+-  return pNew;
+-}
++#else
++  /* For following code (kept for historical record only) shows an
++  ** unrolling for the 3- and 4-byte varint cases.  This code is
++  ** slightly faster, but it is also larger and much harder to test.
++  */
++  p++;
++  b = b<<14;
++  b |= *p;
++  /* b: p1<<14 | p3 (unmasked) */
++  if (!(b&0x80))
++  {
++    /* Values between 2097152 and 268435455 */
++    b &= (0x7f<<14)|(0x7f);
++    a &= (0x7f<<14)|(0x7f);
++    a = a<<7;
++    *v = a | b;
++    return 4;
++  }
+ 
+-/*
+-** Decrement the reference count on a vxworksFileId object.  Free
+-** the object when the reference count reaches zero.
+-*/
+-static void vxworksReleaseFileId(struct vxworksFileId *pId){
+-  unixEnterMutex();
+-  assert( pId->nRef>0 );
+-  pId->nRef--;
+-  if( pId->nRef==0 ){
+-    struct vxworksFileId **pp;
+-    for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
+-    assert( *pp==pId );
+-    *pp = pId->pNext;
+-    sqlite3_free(pId);
++  p++;
++  a = a<<14;
++  a |= *p;
++  /* a: p0<<28 | p2<<14 | p4 (unmasked) */
++  if (!(a&0x80))
++  {
++    /* Values  between 268435456 and 34359738367 */
++    a &= SLOT_4_2_0;
++    b &= SLOT_4_2_0;
++    b = b<<7;
++    *v = a | b;
++    return 5;
+   }
+-  unixLeaveMutex();
+-}
+-#endif /* OS_VXWORKS */
+-/*************** End of Unique File ID Utility Used By VxWorks ****************
+-******************************************************************************/
+ 
++  /* We can only reach this point when reading a corrupt database
++  ** file.  In that case we are not in any hurry.  Use the (relatively
++  ** slow) general-purpose sqlite3GetVarint() routine to extract the
++  ** value. */
++  {
++    u64 v64;
++    u8 n;
+ 
+-/******************************************************************************
+-*************************** Posix Advisory Locking ****************************
+-**
+-** POSIX advisory locks are broken by design.  ANSI STD 1003.1 (1996)
+-** section 6.5.2.2 lines 483 through 490 specify that when a process
+-** sets or clears a lock, that operation overrides any prior locks set
+-** by the same process.  It does not explicitly say so, but this implies
+-** that it overrides locks set by the same process using a different
+-** file descriptor.  Consider this test case:
+-**
+-**       int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
+-**       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
+-**
+-** Suppose ./file1 and ./file2 are really the same file (because
+-** one is a hard or symbolic link to the other) then if you set
+-** an exclusive lock on fd1, then try to get an exclusive lock
+-** on fd2, it works.  I would have expected the second lock to
+-** fail since there was already a lock on the file due to fd1.
+-** But not so.  Since both locks came from the same process, the
+-** second overrides the first, even though they were on different
+-** file descriptors opened on different file names.
+-**
+-** This means that we cannot use POSIX locks to synchronize file access
+-** among competing threads of the same process.  POSIX locks will work fine
+-** to synchronize access for threads in separate processes, but not
+-** threads within the same process.
+-**
+-** To work around the problem, SQLite has to manage file locks internally
+-** on its own.  Whenever a new database is opened, we have to find the
+-** specific inode of the database file (the inode is determined by the
+-** st_dev and st_ino fields of the stat structure that fstat() fills in)
+-** and check for locks already existing on that inode.  When locks are
+-** created or removed, we have to look at our own internal record of the
+-** locks to see if another thread has previously set a lock on that same
+-** inode.
+-**
+-** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
+-** For VxWorks, we have to use the alternative unique ID system based on
+-** canonical filename and implemented in the previous division.)
+-**
+-** The sqlite3_file structure for POSIX is no longer just an integer file
+-** descriptor.  It is now a structure that holds the integer file
+-** descriptor and a pointer to a structure that describes the internal
+-** locks on the corresponding inode.  There is one locking structure
+-** per inode, so if the same inode is opened twice, both unixFile structures
+-** point to the same locking structure.  The locking structure keeps
+-** a reference count (so we will know when to delete it) and a "cnt"
+-** field that tells us its internal lock status.  cnt==0 means the
+-** file is unlocked.  cnt==-1 means the file has an exclusive lock.
+-** cnt>0 means there are cnt shared locks on the file.
+-**
+-** Any attempt to lock or unlock a file first checks the locking
+-** structure.  The fcntl() system call is only invoked to set a 
+-** POSIX lock if the internal lock structure transitions between
+-** a locked and an unlocked state.
+-**
+-** But wait:  there are yet more problems with POSIX advisory locks.
+-**
+-** If you close a file descriptor that points to a file that has locks,
+-** all locks on that file that are owned by the current process are
+-** released.  To work around this problem, each unixInodeInfo object
+-** maintains a count of the number of pending locks on tha inode.
+-** When an attempt is made to close an unixFile, if there are
+-** other unixFile open on the same inode that are holding locks, the call
+-** to close() the file descriptor is deferred until all of the locks clear.
+-** The unixInodeInfo structure keeps a list of file descriptors that need to
+-** be closed and that list is walked (and cleared) when the last lock
+-** clears.
+-**
+-** Yet another problem:  LinuxThreads do not play well with posix locks.
+-**
+-** Many older versions of linux use the LinuxThreads library which is
+-** not posix compliant.  Under LinuxThreads, a lock created by thread
+-** A cannot be modified or overridden by a different thread B.
+-** Only thread A can modify the lock.  Locking behavior is correct
+-** if the appliation uses the newer Native Posix Thread Library (NPTL)
+-** on linux - with NPTL a lock created by thread A can override locks
+-** in thread B.  But there is no way to know at compile-time which
+-** threading library is being used.  So there is no way to know at
+-** compile-time whether or not thread A can override locks on thread B.
+-** One has to do a run-time check to discover the behavior of the
+-** current process.
+-**
+-** SQLite used to support LinuxThreads.  But support for LinuxThreads
+-** was dropped beginning with version 3.7.0.  SQLite will still work with
+-** LinuxThreads provided that (1) there is no more than one connection 
+-** per database file in the same process and (2) database connections
+-** do not move across threads.
++    p -= 4;
++    n = sqlite3GetVarint(p, &v64);
++    assert( n>5 && n<=9 );
++    *v = (u32)v64;
++    return n;
++  }
++#endif
++}
++
++/*
++** Return the number of bytes that will be needed to store the given
++** 64-bit integer.
+ */
++SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
++  int i = 0;
++  do{
++    i++;
++    v >>= 7;
++  }while( v!=0 && ALWAYS(i<9) );
++  return i;
++}
++
+ 
+ /*
+-** An instance of the following structure serves as the key used
+-** to locate a particular unixInodeInfo object.
++** Read or write a four-byte big-endian integer value.
+ */
+-struct unixFileId {
+-  dev_t dev;                  /* Device number */
+-#if OS_VXWORKS
+-  struct vxworksFileId *pId;  /* Unique file ID for vxworks. */
+-#else
+-  ino_t ino;                  /* Inode number */
+-#endif
+-};
++SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
++  return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
++}
++SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
++  p[0] = (u8)(v>>24);
++  p[1] = (u8)(v>>16);
++  p[2] = (u8)(v>>8);
++  p[3] = (u8)v;
++}
++
++
+ 
+ /*
+-** An instance of the following structure is allocated for each open
+-** inode.  Or, on LinuxThreads, there is one of these structures for
+-** each inode opened by each thread.
+-**
+-** A single inode can have multiple file descriptors, so each unixFile
+-** structure contains a pointer to an instance of this object and this
+-** object keeps a count of the number of unixFile pointing to it.
++** Translate a single byte of Hex into an integer.
++** This routine only works if h really is a valid hexadecimal
++** character:  0..9a..fA..F
+ */
+-struct unixInodeInfo {
+-  struct unixFileId fileId;       /* The lookup key */
+-  int nShared;                    /* Number of SHARED locks held */
+-  unsigned char eFileLock;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
+-  unsigned char bProcessLock;     /* An exclusive process lock is held */
+-  int nRef;                       /* Number of pointers to this structure */
+-  unixShmNode *pShmNode;          /* Shared memory associated with this inode */
+-  int nLock;                      /* Number of outstanding file locks */
+-  UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
+-  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
+-  unixInodeInfo *pPrev;           /*    .... doubly linked */
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-  unsigned long long sharedByte;  /* for AFP simulated shared lock */
++SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
++  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
++#ifdef SQLITE_ASCII
++  h += 9*(1&(h>>6));
+ #endif
+-#if OS_VXWORKS
+-  sem_t *pSem;                    /* Named POSIX semaphore */
+-  char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
++#ifdef SQLITE_EBCDIC
++  h += 9*(1&~(h>>4));
+ #endif
+-};
++  return (u8)(h & 0xf);
++}
+ 
++#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
+ /*
+-** A lists of all unixInodeInfo objects.
++** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
++** value.  Return a pointer to its binary value.  Space to hold the
++** binary value has been obtained from malloc and must be freed by
++** the calling routine.
+ */
+-static unixInodeInfo *inodeList = 0;
++SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
++  char *zBlob;
++  int i;
++
++  zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
++  n--;
++  if( zBlob ){
++    for(i=0; i<n; i+=2){
++      zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
++    }
++    zBlob[i/2] = 0;
++  }
++  return zBlob;
++}
++#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
+ 
+ /*
+-**
+-** This function - unixLogError_x(), is only ever called via the macro
+-** unixLogError().
+-**
+-** It is invoked after an error occurs in an OS function and errno has been
+-** set. It logs a message using sqlite3_log() containing the current value of
+-** errno and, if possible, the human-readable equivalent from strerror() or
+-** strerror_r().
+-**
+-** The first argument passed to the macro should be the error code that
+-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). 
+-** The two subsequent arguments should be the name of the OS function that
+-** failed (e.g. "unlink", "open") and the associated file-system path,
+-** if any.
++** Log an error that is an API call on a connection pointer that should
++** not have been used.  The "type" of connection pointer is given as the
++** argument.  The zType is a word like "NULL" or "closed" or "invalid".
+ */
+-#define unixLogError(a,b,c)     unixLogErrorAtLine(a,b,c,__LINE__)
+-static int unixLogErrorAtLine(
+-  int errcode,                    /* SQLite error code */
+-  const char *zFunc,              /* Name of OS function that failed */
+-  const char *zPath,              /* File path associated with error */
+-  int iLine                       /* Source line number where error occurred */
+-){
+-  char *zErr;                     /* Message from strerror() or equivalent */
+-  int iErrno = errno;             /* Saved syscall error number */
+-
+-  /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
+-  ** the strerror() function to obtain the human-readable error message
+-  ** equivalent to errno. Otherwise, use strerror_r().
+-  */ 
+-#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
+-  char aErr[80];
+-  memset(aErr, 0, sizeof(aErr));
+-  zErr = aErr;
+-
+-  /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
+-  ** assume that the system provides the GNU version of strerror_r() that
+-  ** returns a pointer to a buffer containing the error message. That pointer 
+-  ** may point to aErr[], or it may point to some static storage somewhere. 
+-  ** Otherwise, assume that the system provides the POSIX version of 
+-  ** strerror_r(), which always writes an error message into aErr[].
+-  **
+-  ** If the code incorrectly assumes that it is the POSIX version that is
+-  ** available, the error message will often be an empty string. Not a
+-  ** huge problem. Incorrectly concluding that the GNU version is available 
+-  ** could lead to a segfault though.
+-  */
+-#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
+-  zErr = 
+-# endif
+-  strerror_r(iErrno, aErr, sizeof(aErr)-1);
+-
+-#elif SQLITE_THREADSAFE
+-  /* This is a threadsafe build, but strerror_r() is not available. */
+-  zErr = "";
+-#else
+-  /* Non-threadsafe build, use strerror(). */
+-  zErr = strerror(iErrno);
+-#endif
+-
+-  if( zPath==0 ) zPath = "";
+-  sqlite3_log(errcode,
+-      "os_unix.c:%d: (%d) %s(%s) - %s",
+-      iLine, iErrno, zFunc, zPath, zErr
++static void logBadConnection(const char *zType){
++  sqlite3_log(SQLITE_MISUSE, 
++     "API call with %s database connection pointer",
++     zType
+   );
+-
+-  return errcode;
+ }
+ 
+ /*
+-** Close a file descriptor.
+-**
+-** We assume that close() almost always works, since it is only in a
+-** very sick application or on a very sick platform that it might fail.
+-** If it does fail, simply leak the file descriptor, but do log the
+-** error.
++** Check to make sure we have a valid db pointer.  This test is not
++** foolproof but it does provide some measure of protection against
++** misuse of the interface such as passing in db pointers that are
++** NULL or which have been previously closed.  If this routine returns
++** 1 it means that the db pointer is valid and 0 if it should not be
++** dereferenced for any reason.  The calling function should invoke
++** SQLITE_MISUSE immediately.
+ **
+-** Note that it is not safe to retry close() after EINTR since the
+-** file descriptor might have already been reused by another thread.
+-** So we don't even try to recover from an EINTR.  Just log the error
+-** and move on.
++** sqlite3SafetyCheckOk() requires that the db pointer be valid for
++** use.  sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
++** open properly and is not fit for general use but which can be
++** used as an argument to sqlite3_errmsg() or sqlite3_close().
+ */
+-static void robust_close(unixFile *pFile, int h, int lineno){
+-  if( osClose(h) ){
+-    unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
+-                       pFile ? pFile->zPath : 0, lineno);
++SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
++  u32 magic;
++  if( db==0 ){
++    logBadConnection("NULL");
++    return 0;
++  }
++  magic = db->magic;
++  if( magic!=SQLITE_MAGIC_OPEN ){
++    if( sqlite3SafetyCheckSickOrOk(db) ){
++      testcase( sqlite3GlobalConfig.xLog!=0 );
++      logBadConnection("unopened");
++    }
++    return 0;
++  }else{
++    return 1;
++  }
++}
++SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
++  u32 magic;
++  magic = db->magic;
++  if( magic!=SQLITE_MAGIC_SICK &&
++      magic!=SQLITE_MAGIC_OPEN &&
++      magic!=SQLITE_MAGIC_BUSY ){
++    testcase( sqlite3GlobalConfig.xLog!=0 );
++    logBadConnection("invalid");
++    return 0;
++  }else{
++    return 1;
+   }
+ }
+ 
+ /*
+-** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
+-*/ 
+-static void closePendingFds(unixFile *pFile){
+-  unixInodeInfo *pInode = pFile->pInode;
+-  UnixUnusedFd *p;
+-  UnixUnusedFd *pNext;
+-  for(p=pInode->pUnused; p; p=pNext){
+-    pNext = p->pNext;
+-    robust_close(pFile, p->fd, __LINE__);
+-    sqlite3_free(p);
++** Attempt to add, substract, or multiply the 64-bit signed value iB against
++** the other 64-bit signed integer at *pA and store the result in *pA.
++** Return 0 on success.  Or if the operation would have resulted in an
++** overflow, leave *pA unchanged and return 1.
++*/
++SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
++  i64 iA = *pA;
++  testcase( iA==0 ); testcase( iA==1 );
++  testcase( iB==-1 ); testcase( iB==0 );
++  if( iB>=0 ){
++    testcase( iA>0 && LARGEST_INT64 - iA == iB );
++    testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
++    if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
++    *pA += iB;
++  }else{
++    testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
++    testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
++    if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
++    *pA += iB;
+   }
+-  pInode->pUnused = 0;
++  return 0; 
++}
++SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
++  testcase( iB==SMALLEST_INT64+1 );
++  if( iB==SMALLEST_INT64 ){
++    testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
++    if( (*pA)>=0 ) return 1;
++    *pA -= iB;
++    return 0;
++  }else{
++    return sqlite3AddInt64(pA, -iB);
++  }
++}
++#define TWOPOWER32 (((i64)1)<<32)
++#define TWOPOWER31 (((i64)1)<<31)
++SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
++  i64 iA = *pA;
++  i64 iA1, iA0, iB1, iB0, r;
++
++  iA1 = iA/TWOPOWER32;
++  iA0 = iA % TWOPOWER32;
++  iB1 = iB/TWOPOWER32;
++  iB0 = iB % TWOPOWER32;
++  if( iA1*iB1 != 0 ) return 1;
++  assert( iA1*iB0==0 || iA0*iB1==0 );
++  r = iA1*iB0 + iA0*iB1;
++  testcase( r==(-TWOPOWER31)-1 );
++  testcase( r==(-TWOPOWER31) );
++  testcase( r==TWOPOWER31 );
++  testcase( r==TWOPOWER31-1 );
++  if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
++  r *= TWOPOWER32;
++  if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
++  *pA = r;
++  return 0;
+ }
+ 
+ /*
+-** Release a unixInodeInfo structure previously allocated by findInodeInfo().
++** Compute the absolute value of a 32-bit signed integer, of possible.  Or 
++** if the integer has a value of -2147483648, return +2147483647
++*/
++SQLITE_PRIVATE int sqlite3AbsInt32(int x){
++  if( x>=0 ) return x;
++  if( x==(int)0x80000000 ) return 0x7fffffff;
++  return -x;
++}
++
++#ifdef SQLITE_ENABLE_8_3_NAMES
++/*
++** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
++** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
++** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
++** three characters, then shorten the suffix on z[] to be the last three
++** characters of the original suffix.
+ **
+-** The mutex entered using the unixEnterMutex() function must be held
+-** when this function is called.
++** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
++** do the suffix shortening regardless of URI parameter.
++**
++** Examples:
++**
++**     test.db-journal    =>   test.nal
++**     test.db-wal        =>   test.wal
++**     test.db-shm        =>   test.shm
++**     test.db-mj7f3319fa =>   test.9fa
+ */
+-static void releaseInodeInfo(unixFile *pFile){
+-  unixInodeInfo *pInode = pFile->pInode;
+-  assert( unixMutexHeld() );
+-  if( ALWAYS(pInode) ){
+-    pInode->nRef--;
+-    if( pInode->nRef==0 ){
+-      assert( pInode->pShmNode==0 );
+-      closePendingFds(pFile);
+-      if( pInode->pPrev ){
+-        assert( pInode->pPrev->pNext==pInode );
+-        pInode->pPrev->pNext = pInode->pNext;
+-      }else{
+-        assert( inodeList==pInode );
+-        inodeList = pInode->pNext;
+-      }
+-      if( pInode->pNext ){
+-        assert( pInode->pNext->pPrev==pInode );
+-        pInode->pNext->pPrev = pInode->pPrev;
+-      }
+-      sqlite3_free(pInode);
+-    }
++SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
++#if SQLITE_ENABLE_8_3_NAMES<2
++  if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
++#endif
++  {
++    int i, sz;
++    sz = sqlite3Strlen30(z);
++    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
++    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
+   }
+ }
++#endif
+ 
++/************** End of util.c ************************************************/
++/************** Begin file hash.c ********************************************/
+ /*
+-** Given a file descriptor, locate the unixInodeInfo object that
+-** describes that file descriptor.  Create a new one if necessary.  The
+-** return value might be uninitialized if an error occurs.
++** 2001 September 22
+ **
+-** The mutex entered using the unixEnterMutex() function must be held
+-** when this function is called.
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-** Return an appropriate error code.
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++** This is the implementation of generic hash-tables
++** used in SQLite.
+ */
+-static int findInodeInfo(
+-  unixFile *pFile,               /* Unix file with file desc used in the key */
+-  unixInodeInfo **ppInode        /* Return the unixInodeInfo object here */
+-){
+-  int rc;                        /* System call return code */
+-  int fd;                        /* The file descriptor for pFile */
+-  struct unixFileId fileId;      /* Lookup key for the unixInodeInfo */
+-  struct stat statbuf;           /* Low-level file information */
+-  unixInodeInfo *pInode = 0;     /* Candidate unixInodeInfo object */
++/* #include <assert.h> */
+ 
+-  assert( unixMutexHeld() );
++/* Turn bulk memory into a hash table object by initializing the
++** fields of the Hash structure.
++**
++** "pNew" is a pointer to the hash table that is to be initialized.
++*/
++SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
++  assert( pNew!=0 );
++  pNew->first = 0;
++  pNew->count = 0;
++  pNew->htsize = 0;
++  pNew->ht = 0;
++}
+ 
+-  /* Get low-level information about the file that we can used to
+-  ** create a unique name for the file.
+-  */
+-  fd = pFile->h;
+-  rc = osFstat(fd, &statbuf);
+-  if( rc!=0 ){
+-    pFile->lastErrno = errno;
+-#ifdef EOVERFLOW
+-    if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
+-#endif
+-    return SQLITE_IOERR;
+-  }
++/* Remove all entries from a hash table.  Reclaim all memory.
++** Call this routine to delete a hash table or to reset a hash table
++** to the empty state.
++*/
++SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
++  HashElem *elem;         /* For looping over all elements of the table */
+ 
+-#ifdef __APPLE__
+-  /* On OS X on an msdos filesystem, the inode number is reported
+-  ** incorrectly for zero-size files.  See ticket #3260.  To work
+-  ** around this problem (we consider it a bug in OS X, not SQLite)
+-  ** we always increase the file size to 1 by writing a single byte
+-  ** prior to accessing the inode number.  The one byte written is
+-  ** an ASCII 'S' character which also happens to be the first byte
+-  ** in the header of every SQLite database.  In this way, if there
+-  ** is a race condition such that another thread has already populated
+-  ** the first page of the database, no damage is done.
+-  */
+-  if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
+-    do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
+-    if( rc!=1 ){
+-      pFile->lastErrno = errno;
+-      return SQLITE_IOERR;
+-    }
+-    rc = osFstat(fd, &statbuf);
+-    if( rc!=0 ){
+-      pFile->lastErrno = errno;
+-      return SQLITE_IOERR;
+-    }
++  assert( pH!=0 );
++  elem = pH->first;
++  pH->first = 0;
++  sqlite3_free(pH->ht);
++  pH->ht = 0;
++  pH->htsize = 0;
++  while( elem ){
++    HashElem *next_elem = elem->next;
++    sqlite3_free(elem);
++    elem = next_elem;
+   }
+-#endif
++  pH->count = 0;
++}
+ 
+-  memset(&fileId, 0, sizeof(fileId));
+-  fileId.dev = statbuf.st_dev;
+-#if OS_VXWORKS
+-  fileId.pId = pFile->pId;
+-#else
+-  fileId.ino = statbuf.st_ino;
+-#endif
+-  pInode = inodeList;
+-  while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
+-    pInode = pInode->pNext;
+-  }
+-  if( pInode==0 ){
+-    pInode = sqlite3_malloc( sizeof(*pInode) );
+-    if( pInode==0 ){
+-      return SQLITE_NOMEM;
+-    }
+-    memset(pInode, 0, sizeof(*pInode));
+-    memcpy(&pInode->fileId, &fileId, sizeof(fileId));
+-    pInode->nRef = 1;
+-    pInode->pNext = inodeList;
+-    pInode->pPrev = 0;
+-    if( inodeList ) inodeList->pPrev = pInode;
+-    inodeList = pInode;
+-  }else{
+-    pInode->nRef++;
++/*
++** The hashing function.
++*/
++static unsigned int strHash(const char *z, int nKey){
++  int h = 0;
++  assert( nKey>=0 );
++  while( nKey > 0  ){
++    h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
++    nKey--;
+   }
+-  *ppInode = pInode;
+-  return SQLITE_OK;
++  return h;
+ }
+ 
+ 
+-/*
+-** Check a unixFile that is a database.  Verify the following:
+-**
+-** (1) There is exactly one hard link on the file
+-** (2) The file is not a symbolic link
+-** (3) The file has not been renamed or unlinked
+-**
+-** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
++/* Link pNew element into the hash table pH.  If pEntry!=0 then also
++** insert pNew into the pEntry hash bucket.
+ */
+-static void verifyDbFile(unixFile *pFile){
+-  struct stat buf;
+-  int rc;
+-  if( pFile->ctrlFlags & UNIXFILE_WARNED ){
+-    /* One or more of the following warnings have already been issued.  Do not
+-    ** repeat them so as not to clutter the error log */
+-    return;
+-  }
+-  rc = osFstat(pFile->h, &buf);
+-  if( rc!=0 ){
+-    sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
+-    pFile->ctrlFlags |= UNIXFILE_WARNED;
+-    return;
+-  }
+-  if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
+-    sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
+-    pFile->ctrlFlags |= UNIXFILE_WARNED;
+-    return;
+-  }
+-  if( buf.st_nlink>1 ){
+-    sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
+-    pFile->ctrlFlags |= UNIXFILE_WARNED;
+-    return;
++static void insertElement(
++  Hash *pH,              /* The complete hash table */
++  struct _ht *pEntry,    /* The entry into which pNew is inserted */
++  HashElem *pNew         /* The element to be inserted */
++){
++  HashElem *pHead;       /* First element already in pEntry */
++  if( pEntry ){
++    pHead = pEntry->count ? pEntry->chain : 0;
++    pEntry->count++;
++    pEntry->chain = pNew;
++  }else{
++    pHead = 0;
+   }
+-  if( pFile->pInode!=0
+-   && ((rc = osStat(pFile->zPath, &buf))!=0
+-       || buf.st_ino!=pFile->pInode->fileId.ino)
+-  ){
+-    sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
+-    pFile->ctrlFlags |= UNIXFILE_WARNED;
+-    return;
++  if( pHead ){
++    pNew->next = pHead;
++    pNew->prev = pHead->prev;
++    if( pHead->prev ){ pHead->prev->next = pNew; }
++    else             { pH->first = pNew; }
++    pHead->prev = pNew;
++  }else{
++    pNew->next = pH->first;
++    if( pH->first ){ pH->first->prev = pNew; }
++    pNew->prev = 0;
++    pH->first = pNew;
+   }
+ }
+ 
+ 
+-/*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, set *pResOut
+-** to a non-zero value otherwise *pResOut is set to zero.  The return value
+-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++/* Resize the hash table so that it cantains "new_size" buckets.
++**
++** The hash table might fail to resize if sqlite3_malloc() fails or
++** if the new size is the same as the prior size.
++** Return TRUE if the resize occurs and false if not.
+ */
+-static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
+-  int rc = SQLITE_OK;
+-  int reserved = 0;
+-  unixFile *pFile = (unixFile*)id;
++static int rehash(Hash *pH, unsigned int new_size){
++  struct _ht *new_ht;            /* The new hash table */
++  HashElem *elem, *next_elem;    /* For looping over existing elements */
+ 
+-  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
++#if SQLITE_MALLOC_SOFT_LIMIT>0
++  if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
++    new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
++  }
++  if( new_size==pH->htsize ) return 0;
++#endif
+ 
+-  assert( pFile );
+-  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
++  /* The inability to allocates space for a larger hash table is
++  ** a performance hit but it is not a fatal error.  So mark the
++  ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of 
++  ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
++  ** only zeroes the requested number of bytes whereas this module will
++  ** use the actual amount of space allocated for the hash table (which
++  ** may be larger than the requested amount).
++  */
++  sqlite3BeginBenignMalloc();
++  new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
++  sqlite3EndBenignMalloc();
+ 
+-  /* Check if a thread in this process holds such a lock */
+-  if( pFile->pInode->eFileLock>SHARED_LOCK ){
+-    reserved = 1;
++  if( new_ht==0 ) return 0;
++  sqlite3_free(pH->ht);
++  pH->ht = new_ht;
++  pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
++  memset(new_ht, 0, new_size*sizeof(struct _ht));
++  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
++    unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
++    next_elem = elem->next;
++    insertElement(pH, &new_ht[h], elem);
+   }
++  return 1;
++}
+ 
+-  /* Otherwise see if some other process holds it.
+-  */
+-#ifndef __DJGPP__
+-  if( !reserved && !pFile->pInode->bProcessLock ){
+-    struct flock lock;
+-    lock.l_whence = SEEK_SET;
+-    lock.l_start = RESERVED_BYTE;
+-    lock.l_len = 1;
+-    lock.l_type = F_WRLCK;
+-    if( osFcntl(pFile->h, F_GETLK, &lock) ){
+-      rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
+-      pFile->lastErrno = errno;
+-    } else if( lock.l_type!=F_UNLCK ){
+-      reserved = 1;
++/* This function (for internal use only) locates an element in an
++** hash table that matches the given key.  The hash for this key has
++** already been computed and is passed as the 4th parameter.
++*/
++static HashElem *findElementGivenHash(
++  const Hash *pH,     /* The pH to be searched */
++  const char *pKey,   /* The key we are searching for */
++  int nKey,           /* Bytes in key (not counting zero terminator) */
++  unsigned int h      /* The hash for this key. */
++){
++  HashElem *elem;                /* Used to loop thru the element list */
++  int count;                     /* Number of elements left to test */
++
++  if( pH->ht ){
++    struct _ht *pEntry = &pH->ht[h];
++    elem = pEntry->chain;
++    count = pEntry->count;
++  }else{
++    elem = pH->first;
++    count = pH->count;
++  }
++  while( count-- && ALWAYS(elem) ){
++    if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ 
++      return elem;
+     }
++    elem = elem->next;
+   }
+-#endif
+-  
+-  unixLeaveMutex();
+-  OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
+-
+-  *pResOut = reserved;
+-  return rc;
++  return 0;
+ }
+ 
+-/*
+-** Attempt to set a system-lock on the file pFile.  The lock is 
+-** described by pLock.
+-**
+-** If the pFile was opened read/write from unix-excl, then the only lock
+-** ever obtained is an exclusive lock, and it is obtained exactly once
+-** the first time any lock is attempted.  All subsequent system locking
+-** operations become no-ops.  Locking operations still happen internally,
+-** in order to coordinate access between separate database connections
+-** within this process, but all of that is handled in memory and the
+-** operating system does not participate.
+-**
+-** This function is a pass-through to fcntl(F_SETLK) if pFile is using
+-** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
+-** and is read-only.
+-**
+-** Zero is returned if the call completes successfully, or -1 if a call
+-** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
++/* Remove a single entry from the hash table given a pointer to that
++** element and a hash on the element's key.
+ */
+-static int unixFileLock(unixFile *pFile, struct flock *pLock){
+-  int rc;
+-  unixInodeInfo *pInode = pFile->pInode;
+-  assert( unixMutexHeld() );
+-  assert( pInode!=0 );
+-  if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
+-   && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
+-  ){
+-    if( pInode->bProcessLock==0 ){
+-      struct flock lock;
+-      assert( pInode->nLock==0 );
+-      lock.l_whence = SEEK_SET;
+-      lock.l_start = SHARED_FIRST;
+-      lock.l_len = SHARED_SIZE;
+-      lock.l_type = F_WRLCK;
+-      rc = osFcntl(pFile->h, F_SETLK, &lock);
+-      if( rc<0 ) return rc;
+-      pInode->bProcessLock = 1;
+-      pInode->nLock++;
+-    }else{
+-      rc = 0;
++static void removeElementGivenHash(
++  Hash *pH,         /* The pH containing "elem" */
++  HashElem* elem,   /* The element to be removed from the pH */
++  unsigned int h    /* Hash value for the element */
++){
++  struct _ht *pEntry;
++  if( elem->prev ){
++    elem->prev->next = elem->next; 
++  }else{
++    pH->first = elem->next;
++  }
++  if( elem->next ){
++    elem->next->prev = elem->prev;
++  }
++  if( pH->ht ){
++    pEntry = &pH->ht[h];
++    if( pEntry->chain==elem ){
++      pEntry->chain = elem->next;
+     }
++    pEntry->count--;
++    assert( pEntry->count>=0 );
++  }
++  sqlite3_free( elem );
++  pH->count--;
++  if( pH->count==0 ){
++    assert( pH->first==0 );
++    assert( pH->count==0 );
++    sqlite3HashClear(pH);
++  }
++}
++
++/* Attempt to locate an element of the hash table pH with a key
++** that matches pKey,nKey.  Return the data for this element if it is
++** found, or NULL if there is no match.
++*/
++SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
++  HashElem *elem;    /* The element that matches key */
++  unsigned int h;    /* A hash on key */
++
++  assert( pH!=0 );
++  assert( pKey!=0 );
++  assert( nKey>=0 );
++  if( pH->ht ){
++    h = strHash(pKey, nKey) % pH->htsize;
+   }else{
+-    rc = osFcntl(pFile->h, F_SETLK, pLock);
++    h = 0;
+   }
+-  return rc;
++  elem = findElementGivenHash(pH, pKey, nKey, h);
++  return elem ? elem->data : 0;
+ }
+ 
+-/*
+-** Lock the file with the lock specified by parameter eFileLock - one
+-** of the following:
+-**
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
++/* Insert an element into the hash table pH.  The key is pKey,nKey
++** and the data is "data".
+ **
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
++** If no element exists with a matching key, then a new
++** element is created and NULL is returned.
+ **
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
++** If another element already exists with the same key, then the
++** new data replaces the old data and the old data is returned.
++** The key is not copied in this instance.  If a malloc fails, then
++** the new data is returned and the hash table is unchanged.
+ **
+-** This routine will only increase a lock.  Use the sqlite3OsUnlock()
+-** routine to lower a locking level.
++** If the "data" parameter to this function is NULL, then the
++** element corresponding to "key" is removed from the hash table.
+ */
+-static int unixLock(sqlite3_file *id, int eFileLock){
+-  /* The following describes the implementation of the various locks and
+-  ** lock transitions in terms of the POSIX advisory shared and exclusive
+-  ** lock primitives (called read-locks and write-locks below, to avoid
+-  ** confusion with SQLite lock names). The algorithms are complicated
+-  ** slightly in order to be compatible with windows systems simultaneously
+-  ** accessing the same database file, in case that is ever required.
+-  **
+-  ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
+-  ** byte', each single bytes at well known offsets, and the 'shared byte
+-  ** range', a range of 510 bytes at a well known offset.
+-  **
+-  ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
+-  ** byte'.  If this is successful, a random byte from the 'shared byte
+-  ** range' is read-locked and the lock on the 'pending byte' released.
+-  **
+-  ** A process may only obtain a RESERVED lock after it has a SHARED lock.
+-  ** A RESERVED lock is implemented by grabbing a write-lock on the
+-  ** 'reserved byte'. 
+-  **
+-  ** A process may only obtain a PENDING lock after it has obtained a
+-  ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
+-  ** on the 'pending byte'. This ensures that no new SHARED locks can be
+-  ** obtained, but existing SHARED locks are allowed to persist. A process
+-  ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
+-  ** This property is used by the algorithm for rolling back a journal file
+-  ** after a crash.
+-  **
+-  ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
+-  ** implemented by obtaining a write-lock on the entire 'shared byte
+-  ** range'. Since all other locks require a read-lock on one of the bytes
+-  ** within this range, this ensures that no other locks are held on the
+-  ** database. 
+-  **
+-  ** The reason a single byte cannot be used instead of the 'shared byte
+-  ** range' is that some versions of windows do not support read-locks. By
+-  ** locking a random byte from a range, concurrent SHARED locks may exist
+-  ** even if the locking primitive used is always a write-lock.
+-  */
+-  int rc = SQLITE_OK;
+-  unixFile *pFile = (unixFile*)id;
+-  unixInodeInfo *pInode;
+-  struct flock lock;
+-  int tErrno = 0;
+-
+-  assert( pFile );
+-  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
+-      azFileLock(eFileLock), azFileLock(pFile->eFileLock),
+-      azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
++SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
++  unsigned int h;       /* the hash of the key modulo hash table size */
++  HashElem *elem;       /* Used to loop thru the element list */
++  HashElem *new_elem;   /* New element added to the pH */
+ 
+-  /* If there is already a lock of this type or more restrictive on the
+-  ** unixFile, do nothing. Don't use the end_lock: exit path, as
+-  ** unixEnterMutex() hasn't been called yet.
+-  */
+-  if( pFile->eFileLock>=eFileLock ){
+-    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
+-            azFileLock(eFileLock)));
+-    return SQLITE_OK;
++  assert( pH!=0 );
++  assert( pKey!=0 );
++  assert( nKey>=0 );
++  if( pH->htsize ){
++    h = strHash(pKey, nKey) % pH->htsize;
++  }else{
++    h = 0;
+   }
+-
+-  /* Make sure the locking sequence is correct.
+-  **  (1) We never move from unlocked to anything higher than shared lock.
+-  **  (2) SQLite never explicitly requests a pendig lock.
+-  **  (3) A shared lock is always held when a reserve lock is requested.
+-  */
+-  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
+-  assert( eFileLock!=PENDING_LOCK );
+-  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
+-
+-  /* This mutex is needed because pFile->pInode is shared across threads
+-  */
+-  unixEnterMutex();
+-  pInode = pFile->pInode;
+-
+-  /* If some thread using this PID has a lock via a different unixFile*
+-  ** handle that precludes the requested lock, return BUSY.
+-  */
+-  if( (pFile->eFileLock!=pInode->eFileLock && 
+-          (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
+-  ){
+-    rc = SQLITE_BUSY;
+-    goto end_lock;
++  elem = findElementGivenHash(pH,pKey,nKey,h);
++  if( elem ){
++    void *old_data = elem->data;
++    if( data==0 ){
++      removeElementGivenHash(pH,elem,h);
++    }else{
++      elem->data = data;
++      elem->pKey = pKey;
++      assert(nKey==elem->nKey);
++    }
++    return old_data;
+   }
+-
+-  /* If a SHARED lock is requested, and some thread using this PID already
+-  ** has a SHARED or RESERVED lock, then increment reference counts and
+-  ** return SQLITE_OK.
+-  */
+-  if( eFileLock==SHARED_LOCK && 
+-      (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
+-    assert( eFileLock==SHARED_LOCK );
+-    assert( pFile->eFileLock==0 );
+-    assert( pInode->nShared>0 );
+-    pFile->eFileLock = SHARED_LOCK;
+-    pInode->nShared++;
+-    pInode->nLock++;
+-    goto end_lock;
++  if( data==0 ) return 0;
++  new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
++  if( new_elem==0 ) return data;
++  new_elem->pKey = pKey;
++  new_elem->nKey = nKey;
++  new_elem->data = data;
++  pH->count++;
++  if( pH->count>=10 && pH->count > 2*pH->htsize ){
++    if( rehash(pH, pH->count*2) ){
++      assert( pH->htsize>0 );
++      h = strHash(pKey, nKey) % pH->htsize;
++    }
++  }
++  if( pH->ht ){
++    insertElement(pH, &pH->ht[h], new_elem);
++  }else{
++    insertElement(pH, 0, new_elem);
+   }
++  return 0;
++}
+ 
++/************** End of hash.c ************************************************/
++/************** Begin file opcodes.c *****************************************/
++/* Automatically generated.  Do not edit */
++/* See the mkopcodec.awk script for details. */
++#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
++SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
++ static const char *const azName[] = { "?",
++     /*   1 */ "Goto",
++     /*   2 */ "Gosub",
++     /*   3 */ "Return",
++     /*   4 */ "Yield",
++     /*   5 */ "HaltIfNull",
++     /*   6 */ "Halt",
++     /*   7 */ "Integer",
++     /*   8 */ "Int64",
++     /*   9 */ "String",
++     /*  10 */ "Null",
++     /*  11 */ "Blob",
++     /*  12 */ "Variable",
++     /*  13 */ "Move",
++     /*  14 */ "Copy",
++     /*  15 */ "SCopy",
++     /*  16 */ "ResultRow",
++     /*  17 */ "CollSeq",
++     /*  18 */ "Function",
++     /*  19 */ "Not",
++     /*  20 */ "AddImm",
++     /*  21 */ "MustBeInt",
++     /*  22 */ "RealAffinity",
++     /*  23 */ "Permutation",
++     /*  24 */ "Compare",
++     /*  25 */ "Jump",
++     /*  26 */ "Once",
++     /*  27 */ "If",
++     /*  28 */ "IfNot",
++     /*  29 */ "Column",
++     /*  30 */ "Affinity",
++     /*  31 */ "MakeRecord",
++     /*  32 */ "Count",
++     /*  33 */ "Savepoint",
++     /*  34 */ "AutoCommit",
++     /*  35 */ "Transaction",
++     /*  36 */ "ReadCookie",
++     /*  37 */ "SetCookie",
++     /*  38 */ "VerifyCookie",
++     /*  39 */ "OpenRead",
++     /*  40 */ "OpenWrite",
++     /*  41 */ "OpenAutoindex",
++     /*  42 */ "OpenEphemeral",
++     /*  43 */ "SorterOpen",
++     /*  44 */ "OpenPseudo",
++     /*  45 */ "Close",
++     /*  46 */ "SeekLt",
++     /*  47 */ "SeekLe",
++     /*  48 */ "SeekGe",
++     /*  49 */ "SeekGt",
++     /*  50 */ "Seek",
++     /*  51 */ "NotFound",
++     /*  52 */ "Found",
++     /*  53 */ "IsUnique",
++     /*  54 */ "NotExists",
++     /*  55 */ "Sequence",
++     /*  56 */ "NewRowid",
++     /*  57 */ "Insert",
++     /*  58 */ "InsertInt",
++     /*  59 */ "Delete",
++     /*  60 */ "ResetCount",
++     /*  61 */ "SorterCompare",
++     /*  62 */ "SorterData",
++     /*  63 */ "RowKey",
++     /*  64 */ "RowData",
++     /*  65 */ "Rowid",
++     /*  66 */ "NullRow",
++     /*  67 */ "Last",
++     /*  68 */ "Or",
++     /*  69 */ "And",
++     /*  70 */ "SorterSort",
++     /*  71 */ "Sort",
++     /*  72 */ "Rewind",
++     /*  73 */ "IsNull",
++     /*  74 */ "NotNull",
++     /*  75 */ "Ne",
++     /*  76 */ "Eq",
++     /*  77 */ "Gt",
++     /*  78 */ "Le",
++     /*  79 */ "Lt",
++     /*  80 */ "Ge",
++     /*  81 */ "SorterNext",
++     /*  82 */ "BitAnd",
++     /*  83 */ "BitOr",
++     /*  84 */ "ShiftLeft",
++     /*  85 */ "ShiftRight",
++     /*  86 */ "Add",
++     /*  87 */ "Subtract",
++     /*  88 */ "Multiply",
++     /*  89 */ "Divide",
++     /*  90 */ "Remainder",
++     /*  91 */ "Concat",
++     /*  92 */ "Prev",
++     /*  93 */ "BitNot",
++     /*  94 */ "String8",
++     /*  95 */ "Next",
++     /*  96 */ "SorterInsert",
++     /*  97 */ "IdxInsert",
++     /*  98 */ "IdxDelete",
++     /*  99 */ "IdxRowid",
++     /* 100 */ "IdxLT",
++     /* 101 */ "IdxGE",
++     /* 102 */ "Destroy",
++     /* 103 */ "Clear",
++     /* 104 */ "CreateIndex",
++     /* 105 */ "CreateTable",
++     /* 106 */ "ParseSchema",
++     /* 107 */ "LoadAnalysis",
++     /* 108 */ "DropTable",
++     /* 109 */ "DropIndex",
++     /* 110 */ "DropTrigger",
++     /* 111 */ "IntegrityCk",
++     /* 112 */ "RowSetAdd",
++     /* 113 */ "RowSetRead",
++     /* 114 */ "RowSetTest",
++     /* 115 */ "Program",
++     /* 116 */ "Param",
++     /* 117 */ "FkCounter",
++     /* 118 */ "FkIfZero",
++     /* 119 */ "MemMax",
++     /* 120 */ "IfPos",
++     /* 121 */ "IfNeg",
++     /* 122 */ "IfZero",
++     /* 123 */ "AggStep",
++     /* 124 */ "AggFinal",
++     /* 125 */ "Checkpoint",
++     /* 126 */ "JournalMode",
++     /* 127 */ "Vacuum",
++     /* 128 */ "IncrVacuum",
++     /* 129 */ "Expire",
++     /* 130 */ "Real",
++     /* 131 */ "TableLock",
++     /* 132 */ "VBegin",
++     /* 133 */ "VCreate",
++     /* 134 */ "VDestroy",
++     /* 135 */ "VOpen",
++     /* 136 */ "VFilter",
++     /* 137 */ "VColumn",
++     /* 138 */ "VNext",
++     /* 139 */ "VRename",
++     /* 140 */ "VUpdate",
++     /* 141 */ "ToText",
++     /* 142 */ "ToBlob",
++     /* 143 */ "ToNumeric",
++     /* 144 */ "ToInt",
++     /* 145 */ "ToReal",
++     /* 146 */ "Pagecount",
++     /* 147 */ "MaxPgcnt",
++     /* 148 */ "Trace",
++     /* 149 */ "Noop",
++     /* 150 */ "Explain",
++  };
++  return azName[i];
++}
++#endif
+ 
+-  /* A PENDING lock is needed before acquiring a SHARED lock and before
+-  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
+-  ** be released.
+-  */
+-  lock.l_len = 1L;
+-  lock.l_whence = SEEK_SET;
+-  if( eFileLock==SHARED_LOCK 
+-      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
+-  ){
+-    lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
+-    lock.l_start = PENDING_BYTE;
+-    if( unixFileLock(pFile, &lock) ){
+-      tErrno = errno;
+-      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+-      if( rc!=SQLITE_BUSY ){
+-        pFile->lastErrno = tErrno;
+-      }
+-      goto end_lock;
+-    }
+-  }
++/************** End of opcodes.c *********************************************/
++/************** Begin file os_unix.c *****************************************/
++/*
++** 2004 May 22
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++******************************************************************************
++**
++** This file contains the VFS implementation for unix-like operating systems
++** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
++**
++** There are actually several different VFS implementations in this file.
++** The differences are in the way that file locking is done.  The default
++** implementation uses Posix Advisory Locks.  Alternative implementations
++** use flock(), dot-files, various proprietary locking schemas, or simply
++** skip locking all together.
++**
++** This source file is organized into divisions where the logic for various
++** subfunctions is contained within the appropriate division.  PLEASE
++** KEEP THE STRUCTURE OF THIS FILE INTACT.  New code should be placed
++** in the correct division and should be clearly labeled.
++**
++** The layout of divisions is as follows:
++**
++**   *  General-purpose declarations and utility functions.
++**   *  Unique file ID logic used by VxWorks.
++**   *  Various locking primitive implementations (all except proxy locking):
++**      + for Posix Advisory Locks
++**      + for no-op locks
++**      + for dot-file locks
++**      + for flock() locking
++**      + for named semaphore locks (VxWorks only)
++**      + for AFP filesystem locks (MacOSX only)
++**   *  sqlite3_file methods not associated with locking.
++**   *  Definitions of sqlite3_io_methods objects for all locking
++**      methods plus "finder" functions for each locking method.
++**   *  sqlite3_vfs method implementations.
++**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
++**   *  Definitions of sqlite3_vfs objects for all locking methods
++**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
++*/
++#if SQLITE_OS_UNIX              /* This file is used on unix only */
+ 
++/* Use posix_fallocate() if it is available
++*/
++#if !defined(HAVE_POSIX_FALLOCATE) \
++      && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
++# define HAVE_POSIX_FALLOCATE 1
++#endif
+ 
+-  /* If control gets to this point, then actually go ahead and make
+-  ** operating system calls for the specified lock.
+-  */
+-  if( eFileLock==SHARED_LOCK ){
+-    assert( pInode->nShared==0 );
+-    assert( pInode->eFileLock==0 );
+-    assert( rc==SQLITE_OK );
++/*
++** There are various methods for file locking used for concurrency
++** control:
++**
++**   1. POSIX locking (the default),
++**   2. No locking,
++**   3. Dot-file locking,
++**   4. flock() locking,
++**   5. AFP locking (OSX only),
++**   6. Named POSIX semaphores (VXWorks only),
++**   7. proxy locking. (OSX only)
++**
++** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
++** is defined to 1.  The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
++** selection of the appropriate locking style based on the filesystem
++** where the database is located.  
++*/
++#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
++#  if defined(__APPLE__)
++#    define SQLITE_ENABLE_LOCKING_STYLE 1
++#  else
++#    define SQLITE_ENABLE_LOCKING_STYLE 0
++#  endif
++#endif
+ 
+-    /* Now get the read-lock */
+-    lock.l_start = SHARED_FIRST;
+-    lock.l_len = SHARED_SIZE;
+-    if( unixFileLock(pFile, &lock) ){
+-      tErrno = errno;
+-      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+-    }
++/*
++** Define the OS_VXWORKS pre-processor macro to 1 if building on 
++** vxworks, or 0 otherwise.
++*/
++#ifndef OS_VXWORKS
++#  if defined(__RTP__) || defined(_WRS_KERNEL)
++#    define OS_VXWORKS 1
++#  else
++#    define OS_VXWORKS 0
++#  endif
++#endif
+ 
+-    /* Drop the temporary PENDING lock */
+-    lock.l_start = PENDING_BYTE;
+-    lock.l_len = 1L;
+-    lock.l_type = F_UNLCK;
+-    if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
+-      /* This could happen with a network mount */
+-      tErrno = errno;
+-      rc = SQLITE_IOERR_UNLOCK; 
+-    }
++/*
++** These #defines should enable >2GB file support on Posix if the
++** underlying operating system supports it.  If the OS lacks
++** large file support, these should be no-ops.
++**
++** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
++** on the compiler command line.  This is necessary if you are compiling
++** on a recent machine (ex: RedHat 7.2) but you want your code to work
++** on an older machine (ex: RedHat 6.0).  If you compile on RedHat 7.2
++** without this option, LFS is enable.  But LFS does not exist in the kernel
++** in RedHat 6.0, so the code won't work.  Hence, for maximum binary
++** portability you should omit LFS.
++**
++** The previous paragraph was written in 2005.  (This paragraph is written
++** on 2008-11-28.) These days, all Linux kernels support large files, so
++** you should probably leave LFS enabled.  But some embedded platforms might
++** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
++*/
++#ifndef SQLITE_DISABLE_LFS
++# define _LARGE_FILE       1
++# ifndef _FILE_OFFSET_BITS
++#   define _FILE_OFFSET_BITS 64
++# endif
++# define _LARGEFILE_SOURCE 1
++#endif
+ 
+-    if( rc ){
+-      if( rc!=SQLITE_BUSY ){
+-        pFile->lastErrno = tErrno;
+-      }
+-      goto end_lock;
+-    }else{
+-      pFile->eFileLock = SHARED_LOCK;
+-      pInode->nLock++;
+-      pInode->nShared = 1;
+-    }
+-  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
+-    /* We are trying for an exclusive lock but another thread in this
+-    ** same process is still holding a shared lock. */
+-    rc = SQLITE_BUSY;
+-  }else{
+-    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
+-    ** assumed that there is a SHARED or greater lock on the file
+-    ** already.
+-    */
+-    assert( 0!=pFile->eFileLock );
+-    lock.l_type = F_WRLCK;
++/*
++** standard include files.
++*/
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++/* #include <time.h> */
++#include <sys/time.h>
++#include <errno.h>
++#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
 +/* #include <sys/mman.h> */
++#endif
+ 
+-    assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
+-    if( eFileLock==RESERVED_LOCK ){
+-      lock.l_start = RESERVED_BYTE;
+-      lock.l_len = 1L;
+-    }else{
+-      lock.l_start = SHARED_FIRST;
+-      lock.l_len = SHARED_SIZE;
+-    }
+ 
+-    if( unixFileLock(pFile, &lock) ){
+-      tErrno = errno;
+-      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+-      if( rc!=SQLITE_BUSY ){
+-        pFile->lastErrno = tErrno;
+-      }
+-    }
+-  }
+-  
++#if SQLITE_ENABLE_LOCKING_STYLE
++# include <sys/ioctl.h>
++# if OS_VXWORKS
++#  include <semaphore.h>
++#  include <limits.h>
++# else
++#  include <sys/file.h>
++#  include <sys/param.h>
++# endif
++#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+ 
+-#ifdef SQLITE_DEBUG
+-  /* Set up the transaction-counter change checking flags when
+-  ** transitioning from a SHARED to a RESERVED lock.  The change
+-  ** from SHARED to RESERVED marks the beginning of a normal
+-  ** write operation (not a hot journal rollback).
+-  */
+-  if( rc==SQLITE_OK
+-   && pFile->eFileLock<=SHARED_LOCK
+-   && eFileLock==RESERVED_LOCK
+-  ){
+-    pFile->transCntrChng = 0;
+-    pFile->dbUpdate = 0;
+-    pFile->inNormalWrite = 1;
+-  }
++#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
++# include <sys/mount.h>
+ #endif
+ 
+-
+-  if( rc==SQLITE_OK ){
+-    pFile->eFileLock = eFileLock;
+-    pInode->eFileLock = eFileLock;
+-  }else if( eFileLock==EXCLUSIVE_LOCK ){
+-    pFile->eFileLock = PENDING_LOCK;
+-    pInode->eFileLock = PENDING_LOCK;
+-  }
+-
+-end_lock:
+-  unixLeaveMutex();
+-  OSTRACE(("LOCK    %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), 
+-      rc==SQLITE_OK ? "ok" : "failed"));
+-  return rc;
+-}
++#ifdef HAVE_UTIME
++# include <utime.h>
++#endif
+ 
+ /*
+-** Add the file descriptor used by file handle pFile to the corresponding
+-** pUnused list.
++** Allowed values of unixFile.fsFlags
+ */
+-static void setPendingFd(unixFile *pFile){
+-  unixInodeInfo *pInode = pFile->pInode;
+-  UnixUnusedFd *p = pFile->pUnused;
+-  p->pNext = pInode->pUnused;
+-  pInode->pUnused = p;
+-  pFile->h = -1;
+-  pFile->pUnused = 0;
+-}
++#define SQLITE_FSFLAGS_IS_MSDOS     0x1
+ 
+ /*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
+-** 
+-** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
+-** the byte range is divided into 2 parts and the first part is unlocked then
+-** set to a read lock, then the other part is simply unlocked.  This works 
+-** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to 
+-** remove the write lock on a region when a read lock is set.
++** If we are to be thread-safe, include the pthreads header and define
++** the SQLITE_UNIX_THREADS macro.
+ */
+-static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
+-  unixFile *pFile = (unixFile*)id;
+-  unixInodeInfo *pInode;
+-  struct flock lock;
+-  int rc = SQLITE_OK;
+-
+-  assert( pFile );
+-  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
+-      pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
+-      getpid()));
+-
+-  assert( eFileLock<=SHARED_LOCK );
+-  if( pFile->eFileLock<=eFileLock ){
+-    return SQLITE_OK;
+-  }
+-  unixEnterMutex();
+-  pInode = pFile->pInode;
+-  assert( pInode->nShared!=0 );
+-  if( pFile->eFileLock>SHARED_LOCK ){
+-    assert( pInode->eFileLock==pFile->eFileLock );
+-
+-#ifdef SQLITE_DEBUG
+-    /* When reducing a lock such that other processes can start
+-    ** reading the database file again, make sure that the
+-    ** transaction counter was updated if any part of the database
+-    ** file changed.  If the transaction counter is not updated,
+-    ** other connections to the same file might not realize that
+-    ** the file has changed and hence might not know to flush their
+-    ** cache.  The use of a stale cache can lead to database corruption.
+-    */
+-    pFile->inNormalWrite = 0;
++#if SQLITE_THREADSAFE
++/* # include <pthread.h> */
++# define SQLITE_UNIX_THREADS 1
+ #endif
+ 
+-    /* downgrading to a shared lock on NFS involves clearing the write lock
+-    ** before establishing the readlock - to avoid a race condition we downgrade
+-    ** the lock in 2 blocks, so that part of the range will be covered by a 
+-    ** write lock until the rest is covered by a read lock:
+-    **  1:   [WWWWW]
+-    **  2:   [....W]
+-    **  3:   [RRRRW]
+-    **  4:   [RRRR.]
+-    */
+-    if( eFileLock==SHARED_LOCK ){
+-
+-#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
+-      (void)handleNFSUnlock;
+-      assert( handleNFSUnlock==0 );
++/*
++** Default permissions when creating a new file
++*/
++#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
++# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
+ #endif
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-      if( handleNFSUnlock ){
+-        int tErrno;               /* Error code from system call errors */
+-        off_t divSize = SHARED_SIZE - 1;
+-        
+-        lock.l_type = F_UNLCK;
+-        lock.l_whence = SEEK_SET;
+-        lock.l_start = SHARED_FIRST;
+-        lock.l_len = divSize;
+-        if( unixFileLock(pFile, &lock)==(-1) ){
+-          tErrno = errno;
+-          rc = SQLITE_IOERR_UNLOCK;
+-          if( IS_LOCK_ERROR(rc) ){
+-            pFile->lastErrno = tErrno;
+-          }
+-          goto end_unlock;
+-        }
+-        lock.l_type = F_RDLCK;
+-        lock.l_whence = SEEK_SET;
+-        lock.l_start = SHARED_FIRST;
+-        lock.l_len = divSize;
+-        if( unixFileLock(pFile, &lock)==(-1) ){
+-          tErrno = errno;
+-          rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
+-          if( IS_LOCK_ERROR(rc) ){
+-            pFile->lastErrno = tErrno;
+-          }
+-          goto end_unlock;
+-        }
+-        lock.l_type = F_UNLCK;
+-        lock.l_whence = SEEK_SET;
+-        lock.l_start = SHARED_FIRST+divSize;
+-        lock.l_len = SHARED_SIZE-divSize;
+-        if( unixFileLock(pFile, &lock)==(-1) ){
+-          tErrno = errno;
+-          rc = SQLITE_IOERR_UNLOCK;
+-          if( IS_LOCK_ERROR(rc) ){
+-            pFile->lastErrno = tErrno;
+-          }
+-          goto end_unlock;
+-        }
+-      }else
+-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+-      {
+-        lock.l_type = F_RDLCK;
+-        lock.l_whence = SEEK_SET;
+-        lock.l_start = SHARED_FIRST;
+-        lock.l_len = SHARED_SIZE;
+-        if( unixFileLock(pFile, &lock) ){
+-          /* In theory, the call to unixFileLock() cannot fail because another
+-          ** process is holding an incompatible lock. If it does, this 
+-          ** indicates that the other process is not following the locking
+-          ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
+-          ** SQLITE_BUSY would confuse the upper layer (in practice it causes 
+-          ** an assert to fail). */ 
+-          rc = SQLITE_IOERR_RDLOCK;
+-          pFile->lastErrno = errno;
+-          goto end_unlock;
+-        }
+-      }
+-    }
+-    lock.l_type = F_UNLCK;
+-    lock.l_whence = SEEK_SET;
+-    lock.l_start = PENDING_BYTE;
+-    lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
+-    if( unixFileLock(pFile, &lock)==0 ){
+-      pInode->eFileLock = SHARED_LOCK;
+-    }else{
+-      rc = SQLITE_IOERR_UNLOCK;
+-      pFile->lastErrno = errno;
+-      goto end_unlock;
+-    }
+-  }
+-  if( eFileLock==NO_LOCK ){
+-    /* Decrement the shared lock counter.  Release the lock using an
+-    ** OS call only when all threads in this same process have released
+-    ** the lock.
+-    */
+-    pInode->nShared--;
+-    if( pInode->nShared==0 ){
+-      lock.l_type = F_UNLCK;
+-      lock.l_whence = SEEK_SET;
+-      lock.l_start = lock.l_len = 0L;
+-      if( unixFileLock(pFile, &lock)==0 ){
+-        pInode->eFileLock = NO_LOCK;
+-      }else{
+-        rc = SQLITE_IOERR_UNLOCK;
+-        pFile->lastErrno = errno;
+-        pInode->eFileLock = NO_LOCK;
+-        pFile->eFileLock = NO_LOCK;
+-      }
+-    }
+-
+-    /* Decrement the count of locks against this same file.  When the
+-    ** count reaches zero, close any other file descriptors whose close
+-    ** was deferred because of outstanding locks.
+-    */
+-    pInode->nLock--;
+-    assert( pInode->nLock>=0 );
+-    if( pInode->nLock==0 ){
+-      closePendingFds(pFile);
+-    }
+-  }
+-
+-end_unlock:
+-  unixLeaveMutex();
+-  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+-  return rc;
+-}
+ 
+ /*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
++** Default permissions when creating auto proxy dir
+ */
+-static int unixUnlock(sqlite3_file *id, int eFileLock){
+-  assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
+-  return posixUnlock(id, eFileLock, 0);
+-}
++#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
++# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
++#endif
+ 
+-static int unixMapfile(unixFile *pFd, i64 nByte);
+-static void unixUnmapfile(unixFile *pFd);
++/*
++** Maximum supported path-length.
++*/
++#define MAX_PATHNAME 512
+ 
+ /*
+-** This function performs the parts of the "close file" operation 
+-** common to all locking schemes. It closes the directory and file
+-** handles, if they are valid, and sets all fields of the unixFile
+-** structure to 0.
+-**
+-** It is *not* necessary to hold the mutex when this routine is called,
+-** even on VxWorks.  A mutex will be acquired on VxWorks by the
+-** vxworksReleaseFileId() routine.
++** Only set the lastErrno if the error code is a real error and not 
++** a normal expected return code of SQLITE_BUSY or SQLITE_OK
+ */
+-static int closeUnixFile(sqlite3_file *id){
+-  unixFile *pFile = (unixFile*)id;
+-  unixUnmapfile(pFile);
+-  if( pFile->h>=0 ){
+-    robust_close(pFile, pFile->h, __LINE__);
+-    pFile->h = -1;
+-  }
+-#if OS_VXWORKS
+-  if( pFile->pId ){
+-    if( pFile->ctrlFlags & UNIXFILE_DELETE ){
+-      osUnlink(pFile->pId->zCanonicalName);
+-    }
+-    vxworksReleaseFileId(pFile->pId);
+-    pFile->pId = 0;
+-  }
+-#endif
+-  OSTRACE(("CLOSE   %-3d\n", pFile->h));
+-  OpenCounter(-1);
+-  sqlite3_free(pFile->pUnused);
+-  memset(pFile, 0, sizeof(unixFile));
+-  return SQLITE_OK;
+-}
++#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
++
++/* Forward references */
++typedef struct unixShm unixShm;               /* Connection shared memory */
++typedef struct unixShmNode unixShmNode;       /* Shared memory instance */
++typedef struct unixInodeInfo unixInodeInfo;   /* An i-node */
++typedef struct UnixUnusedFd UnixUnusedFd;     /* An unused file descriptor */
+ 
+ /*
+-** Close a file.
++** Sometimes, after a file handle is closed by SQLite, the file descriptor
++** cannot be closed immediately. In these cases, instances of the following
++** structure are used to store the file descriptor while waiting for an
++** opportunity to either close or reuse it.
+ */
+-static int unixClose(sqlite3_file *id){
+-  int rc = SQLITE_OK;
+-  unixFile *pFile = (unixFile *)id;
+-  verifyDbFile(pFile);
+-  unixUnlock(id, NO_LOCK);
+-  unixEnterMutex();
++struct UnixUnusedFd {
++  int fd;                   /* File descriptor to close */
++  int flags;                /* Flags this file descriptor was opened with */
++  UnixUnusedFd *pNext;      /* Next unused file descriptor on same file */
++};
+ 
+-  /* unixFile.pInode is always valid here. Otherwise, a different close
+-  ** routine (e.g. nolockClose()) would be called instead.
++/*
++** The unixFile structure is subclass of sqlite3_file specific to the unix
++** VFS implementations.
++*/
++typedef struct unixFile unixFile;
++struct unixFile {
++  sqlite3_io_methods const *pMethod;  /* Always the first entry */
++  sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
++  unixInodeInfo *pInode;              /* Info about locks on this inode */
++  int h;                              /* The file descriptor */
++  unsigned char eFileLock;            /* The type of lock held on this fd */
++  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
++  int lastErrno;                      /* The unix errno from last I/O error */
++  void *lockingContext;               /* Locking style specific state */
++  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
++  const char *zPath;                  /* Name of the file */
++  unixShm *pShm;                      /* Shared memory segment information */
++  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
++  int nFetchOut;                      /* Number of outstanding xFetch refs */
++  sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
++  sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
++  sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
++  void *pMapRegion;                   /* Memory mapped region */
++#ifdef __QNXNTO__
++  int sectorSize;                     /* Device sector size */
++  int deviceCharacteristics;          /* Precomputed device characteristics */
++#endif
++#if SQLITE_ENABLE_LOCKING_STYLE
++  int openFlags;                      /* The flags specified at open() */
++#endif
++#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
++  unsigned fsFlags;                   /* cached details from statfs() */
++#endif
++#if OS_VXWORKS
++  struct vxworksFileId *pId;          /* Unique file ID */
++#endif
++#ifdef SQLITE_DEBUG
++  /* The next group of variables are used to track whether or not the
++  ** transaction counter in bytes 24-27 of database files are updated
++  ** whenever any part of the database changes.  An assertion fault will
++  ** occur if a file is updated without also updating the transaction
++  ** counter.  This test is made to avoid new problems similar to the
++  ** one described by ticket #3584. 
+   */
+-  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
+-  if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
+-    /* If there are outstanding locks, do not actually close the file just
+-    ** yet because that would clear those locks.  Instead, add the file
+-    ** descriptor to pInode->pUnused list.  It will be automatically closed 
+-    ** when the last lock is cleared.
+-    */
+-    setPendingFd(pFile);
+-  }
+-  releaseInodeInfo(pFile);
+-  rc = closeUnixFile(id);
+-  unixLeaveMutex();
+-  return rc;
+-}
+-
+-/************** End of the posix advisory lock implementation *****************
+-******************************************************************************/
++  unsigned char transCntrChng;   /* True if the transaction counter changed */
++  unsigned char dbUpdate;        /* True if any part of database file changed */
++  unsigned char inNormalWrite;   /* True if in a normal write operation */
+ 
+-/******************************************************************************
+-****************************** No-op Locking **********************************
+-**
+-** Of the various locking implementations available, this is by far the
+-** simplest:  locking is ignored.  No attempt is made to lock the database
+-** file for reading or writing.
+-**
+-** This locking mode is appropriate for use on read-only databases
+-** (ex: databases that are burned into CD-ROM, for example.)  It can
+-** also be used if the application employs some external mechanism to
+-** prevent simultaneous access of the same database by two or more
+-** database connections.  But there is a serious risk of database
+-** corruption if this locking mode is used in situations where multiple
+-** database connections are accessing the same database file at the same
+-** time and one or more of those connections are writing.
+-*/
++#endif
+ 
+-static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
+-  UNUSED_PARAMETER(NotUsed);
+-  *pResOut = 0;
+-  return SQLITE_OK;
+-}
+-static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
+-  UNUSED_PARAMETER2(NotUsed, NotUsed2);
+-  return SQLITE_OK;
+-}
+-static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
+-  UNUSED_PARAMETER2(NotUsed, NotUsed2);
+-  return SQLITE_OK;
+-}
++#ifdef SQLITE_TEST
++  /* In test mode, increase the size of this structure a bit so that 
++  ** it is larger than the struct CrashFile defined in test6.c.
++  */
++  char aPadding[32];
++#endif
++};
+ 
+ /*
+-** Close the file.
++** Allowed values for the unixFile.ctrlFlags bitmask:
+ */
+-static int nolockClose(sqlite3_file *id) {
+-  return closeUnixFile(id);
+-}
+-
+-/******************* End of the no-op lock implementation *********************
+-******************************************************************************/
++#define UNIXFILE_EXCL        0x01     /* Connections from one process only */
++#define UNIXFILE_RDONLY      0x02     /* Connection is read only */
++#define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
++#ifndef SQLITE_DISABLE_DIRSYNC
++# define UNIXFILE_DIRSYNC    0x08     /* Directory sync needed */
++#else
++# define UNIXFILE_DIRSYNC    0x00
++#endif
++#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
++#define UNIXFILE_DELETE      0x20     /* Delete on close */
++#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
++#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
++#define UNIXFILE_WARNED    0x0100     /* verifyDbFile() warnings have been issued */
+ 
+-/******************************************************************************
+-************************* Begin dot-file Locking ******************************
++/*
++** Include code that is common to all os_*.c files
++*/
++/************** Include os_common.h in the middle of os_unix.c ***************/
++/************** Begin file os_common.h ***************************************/
++/*
++** 2004 May 22
+ **
+-** The dotfile locking implementation uses the existence of separate lock
+-** files (really a directory) to control access to the database.  This works
+-** on just about every filesystem imaginable.  But there are serious downsides:
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-**    (1)  There is zero concurrency.  A single reader blocks all other
+-**         connections from reading or writing the database.
++**    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.
+ **
+-**    (2)  An application crash or power loss can leave stale lock files
+-**         sitting around that need to be cleared manually.
++******************************************************************************
+ **
+-** Nevertheless, a dotlock is an appropriate locking mode for use if no
+-** other locking strategy is available.
++** This file contains macros and a little bit of code that is common to
++** all of the platform-specific files (os_*.c) and is #included into those
++** files.
+ **
+-** Dotfile locking works by creating a subdirectory in the same directory as
+-** the database and with the same name but with a ".lock" extension added.
+-** The existence of a lock directory implies an EXCLUSIVE lock.  All other
+-** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
++** This file should be #included by the os_*.c files only.  It is not a
++** general purpose header file.
+ */
++#ifndef _OS_COMMON_H_
++#define _OS_COMMON_H_
+ 
+ /*
+-** The file suffix added to the data base filename in order to create the
+-** lock directory.
++** At least two bugs have slipped in because we changed the MEMORY_DEBUG
++** macro to SQLITE_DEBUG and some older makefiles have not yet made the
++** switch.  The following code should catch this problem at compile-time.
+ */
+-#define DOTLOCK_SUFFIX ".lock"
++#ifdef MEMORY_DEBUG
++# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
++#endif
++
++#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
++# ifndef SQLITE_DEBUG_OS_TRACE
++#   define SQLITE_DEBUG_OS_TRACE 0
++# endif
++  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
++# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
++#else
++# define OSTRACE(X)
++#endif
+ 
+ /*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, set *pResOut
+-** to a non-zero value otherwise *pResOut is set to zero.  The return value
+-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+-**
+-** In dotfile locking, either a lock exists or it does not.  So in this
+-** variation of CheckReservedLock(), *pResOut is set to true if any lock
+-** is held on the file and false if the file is unlocked.
++** Macros for performance tracing.  Normally turned off.  Only works
++** on i486 hardware.
+ */
+-static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
+-  int rc = SQLITE_OK;
+-  int reserved = 0;
+-  unixFile *pFile = (unixFile*)id;
+-
+-  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+-  
+-  assert( pFile );
+-
+-  /* Check if a thread in this process holds such a lock */
+-  if( pFile->eFileLock>SHARED_LOCK ){
+-    /* Either this connection or some other connection in the same process
+-    ** holds a lock on the file.  No need to check further. */
+-    reserved = 1;
+-  }else{
+-    /* The lock is held if and only if the lockfile exists */
+-    const char *zLockFile = (const char*)pFile->lockingContext;
+-    reserved = osAccess(zLockFile, 0)==0;
+-  }
+-  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
+-  *pResOut = reserved;
+-  return rc;
+-}
++#ifdef SQLITE_PERFORMANCE_TRACE
+ 
++/* 
++** hwtime.h contains inline assembler code for implementing 
++** high-performance timing routines.
++*/
++/************** Include hwtime.h in the middle of os_common.h ****************/
++/************** Begin file hwtime.h ******************************************/
+ /*
+-** Lock the file with the lock specified by parameter eFileLock - one
+-** of the following:
+-**
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
++** 2008 May 27
+ **
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
++**    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 routine will only increase a lock.  Use the sqlite3OsUnlock()
+-** routine to lower a locking level.
++******************************************************************************
+ **
+-** With dotfile locking, we really only support state (4): EXCLUSIVE.
+-** But we track the other locking levels internally.
++** This file contains inline asm code for retrieving "high-performance"
++** counters for x86 class CPUs.
+ */
+-static int dotlockLock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  char *zLockFile = (char *)pFile->lockingContext;
+-  int rc = SQLITE_OK;
++#ifndef _HWTIME_H_
++#define _HWTIME_H_
+ 
++/*
++** The following routine only works on pentium-class (or newer) processors.
++** It uses the RDTSC opcode to read the cycle count value out of the
++** processor and returns that value.  This can be used for high-res
++** profiling.
++*/
++#if (defined(__GNUC__) || defined(_MSC_VER)) && \
++      (defined(i386) || defined(__i386__) || defined(_M_IX86))
+ 
+-  /* If we have any lock, then the lock file already exists.  All we have
+-  ** to do is adjust our internal record of the lock level.
+-  */
+-  if( pFile->eFileLock > NO_LOCK ){
+-    pFile->eFileLock = eFileLock;
+-    /* Always update the timestamp on the old file */
+-#ifdef HAVE_UTIME
+-    utime(zLockFile, NULL);
+-#else
+-    utimes(zLockFile, NULL);
+-#endif
+-    return SQLITE_OK;
++  #if defined(__GNUC__)
++
++  __inline__ sqlite_uint64 sqlite3Hwtime(void){
++     unsigned int lo, hi;
++     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++     return (sqlite_uint64)hi << 32 | lo;
+   }
+-  
+-  /* grab an exclusive lock */
+-  rc = osMkdir(zLockFile, 0777);
+-  if( rc<0 ){
+-    /* failed to open/create the lock directory */
+-    int tErrno = errno;
+-    if( EEXIST == tErrno ){
+-      rc = SQLITE_BUSY;
+-    } else {
+-      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+-      if( IS_LOCK_ERROR(rc) ){
+-        pFile->lastErrno = tErrno;
+-      }
+-    }
+-    return rc;
+-  } 
+-  
+-  /* got it, set the type and return ok */
+-  pFile->eFileLock = eFileLock;
+-  return rc;
+-}
+ 
+-/*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
+-**
+-** When the locking level reaches NO_LOCK, delete the lock file.
+-*/
+-static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  char *zLockFile = (char *)pFile->lockingContext;
+-  int rc;
++  #elif defined(_MSC_VER)
+ 
+-  assert( pFile );
+-  OSTRACE(("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
+-           pFile->eFileLock, getpid()));
+-  assert( eFileLock<=SHARED_LOCK );
+-  
+-  /* no-op if possible */
+-  if( pFile->eFileLock==eFileLock ){
+-    return SQLITE_OK;
++  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
++     __asm {
++        rdtsc
++        ret       ; return value at EDX:EAX
++     }
+   }
+ 
+-  /* To downgrade to shared, simply update our internal notion of the
+-  ** lock state.  No need to mess with the file on disk.
+-  */
+-  if( eFileLock==SHARED_LOCK ){
+-    pFile->eFileLock = SHARED_LOCK;
+-    return SQLITE_OK;
++  #endif
++
++#elif (defined(__GNUC__) && defined(__x86_64__))
++
++  __inline__ sqlite_uint64 sqlite3Hwtime(void){
++      unsigned long val;
++      __asm__ __volatile__ ("rdtsc" : "=A" (val));
++      return val;
+   }
+-  
+-  /* To fully unlock the database, delete the lock file */
+-  assert( eFileLock==NO_LOCK );
+-  rc = osRmdir(zLockFile);
+-  if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
+-  if( rc<0 ){
+-    int tErrno = errno;
+-    rc = 0;
+-    if( ENOENT != tErrno ){
+-      rc = SQLITE_IOERR_UNLOCK;
+-    }
+-    if( IS_LOCK_ERROR(rc) ){
+-      pFile->lastErrno = tErrno;
+-    }
+-    return rc; 
++ 
++#elif (defined(__GNUC__) && defined(__ppc__))
++
++  __inline__ sqlite_uint64 sqlite3Hwtime(void){
++      unsigned long long retval;
++      unsigned long junk;
++      __asm__ __volatile__ ("\n\
++          1:      mftbu   %1\n\
++                  mftb    %L0\n\
++                  mftbu   %0\n\
++                  cmpw    %0,%1\n\
++                  bne     1b"
++                  : "=r" (retval), "=r" (junk));
++      return retval;
+   }
+-  pFile->eFileLock = NO_LOCK;
+-  return SQLITE_OK;
+-}
++
++#else
++
++  #error Need implementation of sqlite3Hwtime() for your platform.
++
++  /*
++  ** To compile without implementing sqlite3Hwtime() for your platform,
++  ** you can remove the above #error and use the following
++  ** stub function.  You will lose timing support for many
++  ** of the debugging and testing utilities, but it should at
++  ** least compile and run.
++  */
++SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
++
++#endif
++
++#endif /* !defined(_HWTIME_H_) */
++
++/************** End of hwtime.h **********************************************/
++/************** Continuing where we left off in os_common.h ******************/
++
++static sqlite_uint64 g_start;
++static sqlite_uint64 g_elapsed;
++#define TIMER_START       g_start=sqlite3Hwtime()
++#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
++#define TIMER_ELAPSED     g_elapsed
++#else
++#define TIMER_START
++#define TIMER_END
++#define TIMER_ELAPSED     ((sqlite_uint64)0)
++#endif
+ 
+ /*
+-** Close a file.  Make sure the lock has been released before closing.
++** If we compile with the SQLITE_TEST macro set, then the following block
++** of code will give us the ability to simulate a disk I/O error.  This
++** is used for testing the I/O recovery logic.
+ */
+-static int dotlockClose(sqlite3_file *id) {
+-  int rc = SQLITE_OK;
+-  if( id ){
+-    unixFile *pFile = (unixFile*)id;
+-    dotlockUnlock(id, NO_LOCK);
+-    sqlite3_free(pFile->lockingContext);
+-    rc = closeUnixFile(id);
+-  }
+-  return rc;
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
++SQLITE_API int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
++SQLITE_API int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
++SQLITE_API int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
++SQLITE_API int sqlite3_io_error_benign = 0;         /* True if errors are benign */
++SQLITE_API int sqlite3_diskfull_pending = 0;
++SQLITE_API int sqlite3_diskfull = 0;
++#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
++#define SimulateIOError(CODE)  \
++  if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
++       || sqlite3_io_error_pending-- == 1 )  \
++              { local_ioerr(); CODE; }
++static void local_ioerr(){
++  IOTRACE(("IOERR\n"));
++  sqlite3_io_error_hit++;
++  if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
+ }
+-/****************** End of the dot-file lock implementation *******************
+-******************************************************************************/
++#define SimulateDiskfullError(CODE) \
++   if( sqlite3_diskfull_pending ){ \
++     if( sqlite3_diskfull_pending == 1 ){ \
++       local_ioerr(); \
++       sqlite3_diskfull = 1; \
++       sqlite3_io_error_hit = 1; \
++       CODE; \
++     }else{ \
++       sqlite3_diskfull_pending--; \
++     } \
++   }
++#else
++#define SimulateIOErrorBenign(X)
++#define SimulateIOError(A)
++#define SimulateDiskfullError(A)
++#endif
+ 
+-/******************************************************************************
+-************************** Begin flock Locking ********************************
+-**
+-** Use the flock() system call to do file locking.
+-**
+-** flock() locking is like dot-file locking in that the various
+-** fine-grain locking levels supported by SQLite are collapsed into
+-** a single exclusive lock.  In other words, SHARED, RESERVED, and
+-** PENDING locks are the same thing as an EXCLUSIVE lock.  SQLite
+-** still works when you do this, but concurrency is reduced since
+-** only a single process can be reading the database at a time.
+-**
+-** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
+-** compiling for VXWORKS.
++/*
++** When testing, keep a count of the number of open files.
+ */
+-#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_open_file_count = 0;
++#define OpenCounter(X)  sqlite3_open_file_count+=(X)
++#else
++#define OpenCounter(X)
++#endif
++
++#endif /* !defined(_OS_COMMON_H_) */
++
++/************** End of os_common.h *******************************************/
++/************** Continuing where we left off in os_unix.c ********************/
++
++/*
++** Define various macros that are missing from some systems.
++*/
++#ifndef O_LARGEFILE
++# define O_LARGEFILE 0
++#endif
++#ifdef SQLITE_DISABLE_LFS
++# undef O_LARGEFILE
++# define O_LARGEFILE 0
++#endif
++#ifndef O_NOFOLLOW
++# define O_NOFOLLOW 0
++#endif
++#ifndef O_BINARY
++# define O_BINARY 0
++#endif
+ 
+ /*
+-** Retry flock() calls that fail with EINTR
++** The threadid macro resolves to the thread-id or to 0.  Used for
++** testing and debugging only.
+ */
+-#ifdef EINTR
+-static int robust_flock(int fd, int op){
+-  int rc;
+-  do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
+-  return rc;
+-}
++#if SQLITE_THREADSAFE
++#define threadid pthread_self()
+ #else
+-# define robust_flock(a,b) flock(a,b)
++#define threadid 0
+ #endif
+-     
+ 
+ /*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, set *pResOut
+-** to a non-zero value otherwise *pResOut is set to zero.  The return value
+-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++** HAVE_MREMAP defaults to true on Linux and false everywhere else.
+ */
+-static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
+-  int rc = SQLITE_OK;
+-  int reserved = 0;
+-  unixFile *pFile = (unixFile*)id;
+-  
+-  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+-  
+-  assert( pFile );
+-  
+-  /* Check if a thread in this process holds such a lock */
+-  if( pFile->eFileLock>SHARED_LOCK ){
+-    reserved = 1;
+-  }
+-  
+-  /* Otherwise see if some other process holds it. */
+-  if( !reserved ){
+-    /* attempt to get the lock */
+-    int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
+-    if( !lrc ){
+-      /* got the lock, unlock it */
+-      lrc = robust_flock(pFile->h, LOCK_UN);
+-      if ( lrc ) {
+-        int tErrno = errno;
+-        /* unlock failed with an error */
+-        lrc = SQLITE_IOERR_UNLOCK; 
+-        if( IS_LOCK_ERROR(lrc) ){
+-          pFile->lastErrno = tErrno;
+-          rc = lrc;
+-        }
+-      }
+-    } else {
+-      int tErrno = errno;
+-      reserved = 1;
+-      /* someone else might have it reserved */
+-      lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); 
+-      if( IS_LOCK_ERROR(lrc) ){
+-        pFile->lastErrno = tErrno;
+-        rc = lrc;
+-      }
+-    }
+-  }
+-  OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
+-
+-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+-  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+-    rc = SQLITE_OK;
+-    reserved=1;
+-  }
+-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+-  *pResOut = reserved;
+-  return rc;
+-}
++#if !defined(HAVE_MREMAP)
++# if defined(__linux__) && defined(_GNU_SOURCE)
++#  define HAVE_MREMAP 1
++# else
++#  define HAVE_MREMAP 0
++# endif
++#endif
+ 
+ /*
+-** Lock the file with the lock specified by parameter eFileLock - one
+-** of the following:
+-**
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
+-**
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
+-**
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
+-**
+-** flock() only really support EXCLUSIVE locks.  We track intermediate
+-** lock states in the sqlite3_file structure, but all locks SHARED or
+-** above are really EXCLUSIVE locks and exclude all other processes from
+-** access the file.
++** Different Unix systems declare open() in different ways.  Same use
++** open(const char*,int,mode_t).  Others use open(const char*,int,...).
++** The difference is important when using a pointer to the function.
+ **
+-** This routine will only increase a lock.  Use the sqlite3OsUnlock()
+-** routine to lower a locking level.
++** The safest way to deal with the problem is to always use this wrapper
++** which always has the same well-defined interface.
+ */
+-static int flockLock(sqlite3_file *id, int eFileLock) {
+-  int rc = SQLITE_OK;
+-  unixFile *pFile = (unixFile*)id;
+-
+-  assert( pFile );
+-
+-  /* if we already have a lock, it is exclusive.  
+-  ** Just adjust level and punt on outta here. */
+-  if (pFile->eFileLock > NO_LOCK) {
+-    pFile->eFileLock = eFileLock;
+-    return SQLITE_OK;
+-  }
+-  
+-  /* grab an exclusive lock */
+-  
+-  if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
+-    int tErrno = errno;
+-    /* didn't get, must be busy */
+-    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+-    if( IS_LOCK_ERROR(rc) ){
+-      pFile->lastErrno = tErrno;
+-    }
+-  } else {
+-    /* got it, set the type and return ok */
+-    pFile->eFileLock = eFileLock;
+-  }
+-  OSTRACE(("LOCK    %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), 
+-           rc==SQLITE_OK ? "ok" : "failed"));
+-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+-  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+-    rc = SQLITE_BUSY;
+-  }
+-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+-  return rc;
++static int posixOpen(const char *zFile, int flags, int mode){
++  return open(zFile, flags, mode);
+ }
+ 
+-
+ /*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
++** On some systems, calls to fchown() will trigger a message in a security
++** log if they come from non-root processes.  So avoid calling fchown() if
++** we are not running as root.
+ */
+-static int flockUnlock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  
+-  assert( pFile );
+-  OSTRACE(("UNLOCK  %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
+-           pFile->eFileLock, getpid()));
+-  assert( eFileLock<=SHARED_LOCK );
+-  
+-  /* no-op if possible */
+-  if( pFile->eFileLock==eFileLock ){
+-    return SQLITE_OK;
+-  }
+-  
+-  /* shared can just be set because we always have an exclusive */
+-  if (eFileLock==SHARED_LOCK) {
+-    pFile->eFileLock = eFileLock;
+-    return SQLITE_OK;
+-  }
+-  
+-  /* no, really, unlock. */
+-  if( robust_flock(pFile->h, LOCK_UN) ){
+-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+-    return SQLITE_OK;
+-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+-    return SQLITE_IOERR_UNLOCK;
+-  }else{
+-    pFile->eFileLock = NO_LOCK;
+-    return SQLITE_OK;
+-  }
++static int posixFchown(int fd, uid_t uid, gid_t gid){
++  return geteuid() ? 0 : fchown(fd,uid,gid);
+ }
+ 
++/* Forward reference */
++static int openDirectory(const char*, int*);
++
+ /*
+-** Close a file.
++** Many system calls are accessed through pointer-to-functions so that
++** they may be overridden at runtime to facilitate fault injection during
++** testing and sandboxing.  The following array holds the names and pointers
++** to all overrideable system calls.
+ */
+-static int flockClose(sqlite3_file *id) {
+-  int rc = SQLITE_OK;
+-  if( id ){
+-    flockUnlock(id, NO_LOCK);
+-    rc = closeUnixFile(id);
+-  }
+-  return rc;
+-}
++static struct unix_syscall {
++  const char *zName;            /* Name of the system call */
++  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
++  sqlite3_syscall_ptr pDefault; /* Default value */
++} aSyscall[] = {
++  { "open",         (sqlite3_syscall_ptr)posixOpen,  0  },
++#define osOpen      ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
+ 
+-#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
++  { "close",        (sqlite3_syscall_ptr)close,      0  },
++#define osClose     ((int(*)(int))aSyscall[1].pCurrent)
+ 
+-/******************* End of the flock lock implementation *********************
+-******************************************************************************/
++  { "access",       (sqlite3_syscall_ptr)access,     0  },
++#define osAccess    ((int(*)(const char*,int))aSyscall[2].pCurrent)
+ 
+-/******************************************************************************
+-************************ Begin Named Semaphore Locking ************************
+-**
+-** Named semaphore locking is only supported on VxWorks.
+-**
+-** Semaphore locking is like dot-lock and flock in that it really only
+-** supports EXCLUSIVE locking.  Only a single process can read or write
+-** the database file at a time.  This reduces potential concurrency, but
+-** makes the lock implementation much easier.
+-*/
+-#if OS_VXWORKS
++  { "getcwd",       (sqlite3_syscall_ptr)getcwd,     0  },
++#define osGetcwd    ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
++
++  { "stat",         (sqlite3_syscall_ptr)stat,       0  },
++#define osStat      ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
+ 
+ /*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, set *pResOut
+-** to a non-zero value otherwise *pResOut is set to zero.  The return value
+-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++** The DJGPP compiler environment looks mostly like Unix, but it
++** lacks the fcntl() system call.  So redefine fcntl() to be something
++** that always succeeds.  This means that locking does not occur under
++** DJGPP.  But it is DOS - what did you expect?
+ */
+-static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
+-  int rc = SQLITE_OK;
+-  int reserved = 0;
+-  unixFile *pFile = (unixFile*)id;
++#ifdef __DJGPP__
++  { "fstat",        0,                 0  },
++#define osFstat(a,b,c)    0
++#else     
++  { "fstat",        (sqlite3_syscall_ptr)fstat,      0  },
++#define osFstat     ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
++#endif
+ 
+-  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+-  
+-  assert( pFile );
++  { "ftruncate",    (sqlite3_syscall_ptr)ftruncate,  0  },
++#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
+ 
+-  /* Check if a thread in this process holds such a lock */
+-  if( pFile->eFileLock>SHARED_LOCK ){
+-    reserved = 1;
+-  }
+-  
+-  /* Otherwise see if some other process holds it. */
+-  if( !reserved ){
+-    sem_t *pSem = pFile->pInode->pSem;
+-    struct stat statBuf;
++  { "fcntl",        (sqlite3_syscall_ptr)fcntl,      0  },
++#define osFcntl     ((int(*)(int,int,...))aSyscall[7].pCurrent)
+ 
+-    if( sem_trywait(pSem)==-1 ){
+-      int tErrno = errno;
+-      if( EAGAIN != tErrno ){
+-        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+-        pFile->lastErrno = tErrno;
+-      } else {
+-        /* someone else has the lock when we are in NO_LOCK */
+-        reserved = (pFile->eFileLock < SHARED_LOCK);
+-      }
+-    }else{
+-      /* we could have it if we want it */
+-      sem_post(pSem);
+-    }
+-  }
+-  OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
++  { "read",         (sqlite3_syscall_ptr)read,       0  },
++#define osRead      ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
+ 
+-  *pResOut = reserved;
+-  return rc;
+-}
++#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
++  { "pread",        (sqlite3_syscall_ptr)pread,      0  },
++#else
++  { "pread",        (sqlite3_syscall_ptr)0,          0  },
++#endif
++#define osPread     ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
++
++#if defined(USE_PREAD64)
++  { "pread64",      (sqlite3_syscall_ptr)pread64,    0  },
++#else
++  { "pread64",      (sqlite3_syscall_ptr)0,          0  },
++#endif
++#define osPread64   ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
++
++  { "write",        (sqlite3_syscall_ptr)write,      0  },
++#define osWrite     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
++
++#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
++  { "pwrite",       (sqlite3_syscall_ptr)pwrite,     0  },
++#else
++  { "pwrite",       (sqlite3_syscall_ptr)0,          0  },
++#endif
++#define osPwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
++                    aSyscall[12].pCurrent)
++
++#if defined(USE_PREAD64)
++  { "pwrite64",     (sqlite3_syscall_ptr)pwrite64,   0  },
++#else
++  { "pwrite64",     (sqlite3_syscall_ptr)0,          0  },
++#endif
++#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
++                    aSyscall[13].pCurrent)
++
++  { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },
++#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
++
++#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
++  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
++#else
++  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
++#endif
++#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
++
++  { "unlink",       (sqlite3_syscall_ptr)unlink,           0 },
++#define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)
++
++  { "openDirectory",    (sqlite3_syscall_ptr)openDirectory,      0 },
++#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
++
++  { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
++#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
++
++  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
++#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
++
++  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
++#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
++
++  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
++#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
++
++  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
++#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
++
++#if HAVE_MREMAP
++  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
++#else
++  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
++#endif
++#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
++
++}; /* End of the overrideable system calls */
+ 
+ /*
+-** Lock the file with the lock specified by parameter eFileLock - one
+-** of the following:
+-**
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
+-**
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
+-**
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
+-**
+-** Semaphore locks only really support EXCLUSIVE locks.  We track intermediate
+-** lock states in the sqlite3_file structure, but all locks SHARED or
+-** above are really EXCLUSIVE locks and exclude all other processes from
+-** access the file.
+-**
+-** This routine will only increase a lock.  Use the sqlite3OsUnlock()
+-** routine to lower a locking level.
++** This is the xSetSystemCall() method of sqlite3_vfs for all of the
++** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
++** system call pointer, or SQLITE_NOTFOUND if there is no configurable
++** system call named zName.
+ */
+-static int semLock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  int fd;
+-  sem_t *pSem = pFile->pInode->pSem;
+-  int rc = SQLITE_OK;
++static int unixSetSystemCall(
++  sqlite3_vfs *pNotUsed,        /* The VFS pointer.  Not used */
++  const char *zName,            /* Name of system call to override */
++  sqlite3_syscall_ptr pNewFunc  /* Pointer to new system call value */
++){
++  unsigned int i;
++  int rc = SQLITE_NOTFOUND;
+ 
+-  /* if we already have a lock, it is exclusive.  
+-  ** Just adjust level and punt on outta here. */
+-  if (pFile->eFileLock > NO_LOCK) {
+-    pFile->eFileLock = eFileLock;
++  UNUSED_PARAMETER(pNotUsed);
++  if( zName==0 ){
++    /* If no zName is given, restore all system calls to their default
++    ** settings and return NULL
++    */
+     rc = SQLITE_OK;
+-    goto sem_end_lock;
+-  }
+-  
+-  /* lock semaphore now but bail out when already locked. */
+-  if( sem_trywait(pSem)==-1 ){
+-    rc = SQLITE_BUSY;
+-    goto sem_end_lock;
++    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
++      if( aSyscall[i].pDefault ){
++        aSyscall[i].pCurrent = aSyscall[i].pDefault;
++      }
++    }
++  }else{
++    /* If zName is specified, operate on only the one system call
++    ** specified.
++    */
++    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
++      if( strcmp(zName, aSyscall[i].zName)==0 ){
++        if( aSyscall[i].pDefault==0 ){
++          aSyscall[i].pDefault = aSyscall[i].pCurrent;
++        }
++        rc = SQLITE_OK;
++        if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
++        aSyscall[i].pCurrent = pNewFunc;
++        break;
++      }
++    }
+   }
+-
+-  /* got it, set the type and return ok */
+-  pFile->eFileLock = eFileLock;
+-
+- sem_end_lock:
+   return rc;
+ }
+ 
+ /*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
++** Return the value of a system call.  Return NULL if zName is not a
++** recognized system call name.  NULL is also returned if the system call
++** is currently undefined.
+ */
+-static int semUnlock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  sem_t *pSem = pFile->pInode->pSem;
++static sqlite3_syscall_ptr unixGetSystemCall(
++  sqlite3_vfs *pNotUsed,
++  const char *zName
++){
++  unsigned int i;
+ 
+-  assert( pFile );
+-  assert( pSem );
+-  OSTRACE(("UNLOCK  %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
+-           pFile->eFileLock, getpid()));
+-  assert( eFileLock<=SHARED_LOCK );
+-  
+-  /* no-op if possible */
+-  if( pFile->eFileLock==eFileLock ){
+-    return SQLITE_OK;
+-  }
+-  
+-  /* shared can just be set because we always have an exclusive */
+-  if (eFileLock==SHARED_LOCK) {
+-    pFile->eFileLock = eFileLock;
+-    return SQLITE_OK;
+-  }
+-  
+-  /* no, really unlock. */
+-  if ( sem_post(pSem)==-1 ) {
+-    int rc, tErrno = errno;
+-    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+-    if( IS_LOCK_ERROR(rc) ){
+-      pFile->lastErrno = tErrno;
+-    }
+-    return rc; 
++  UNUSED_PARAMETER(pNotUsed);
++  for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
++    if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
+   }
+-  pFile->eFileLock = NO_LOCK;
+-  return SQLITE_OK;
++  return 0;
+ }
+ 
+ /*
+- ** Close a file.
+- */
+-static int semClose(sqlite3_file *id) {
+-  if( id ){
+-    unixFile *pFile = (unixFile*)id;
+-    semUnlock(id, NO_LOCK);
+-    assert( pFile );
+-    unixEnterMutex();
+-    releaseInodeInfo(pFile);
+-    unixLeaveMutex();
+-    closeUnixFile(id);
++** Return the name of the first system call after zName.  If zName==NULL
++** then return the name of the first system call.  Return NULL if zName
++** is the last system call or if zName is not the name of a valid
++** system call.
++*/
++static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
++  int i = -1;
++
++  UNUSED_PARAMETER(p);
++  if( zName ){
++    for(i=0; i<ArraySize(aSyscall)-1; i++){
++      if( strcmp(zName, aSyscall[i].zName)==0 ) break;
++    }
+   }
+-  return SQLITE_OK;
++  for(i++; i<ArraySize(aSyscall); i++){
++    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
++  }
++  return 0;
+ }
+ 
+-#endif /* OS_VXWORKS */
+ /*
+-** Named semaphore locking is only available on VxWorks.
+-**
+-*************** End of the named semaphore lock implementation ****************
+-******************************************************************************/
+-
+-
+-/******************************************************************************
+-*************************** Begin AFP Locking *********************************
++** Invoke open().  Do so multiple times, until it either succeeds or
++** fails for some reason other than EINTR.
+ **
+-** AFP is the Apple Filing Protocol.  AFP is a network filesystem found
+-** on Apple Macintosh computers - both OS9 and OSX.
++** If the file creation mode "m" is 0 then set it to the default for
++** SQLite.  The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
++** 0644) as modified by the system umask.  If m is not 0, then
++** make the file creation mode be exactly m ignoring the umask.
+ **
+-** Third-party implementations of AFP are available.  But this code here
+-** only works on OSX.
++** The m parameter will be non-zero only when creating -wal, -journal,
++** and -shm files.  We want those files to have *exactly* the same
++** permissions as their original database, unadulterated by the umask.
++** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
++** transaction crashes and leaves behind hot journals, then any
++** process that is able to write to the database will also be able to
++** recover the hot journals.
+ */
++static int robust_open(const char *z, int f, mode_t m){
++  int fd;
++  mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
++  do{
++#if defined(O_CLOEXEC)
++    fd = osOpen(z,f|O_CLOEXEC,m2);
++#else
++    fd = osOpen(z,f,m2);
++#endif
++  }while( fd<0 && errno==EINTR );
++  if( fd>=0 ){
++    if( m!=0 ){
++      struct stat statbuf;
++      if( osFstat(fd, &statbuf)==0 
++       && statbuf.st_size==0
++       && (statbuf.st_mode&0777)!=m 
++      ){
++        osFchmod(fd, m);
++      }
++    }
++#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
++    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
++#endif
++  }
++  return fd;
++}
+ 
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ /*
+-** The afpLockingContext structure contains all afp lock specific state
++** Helper functions to obtain and relinquish the global mutex. The
++** global mutex is used to protect the unixInodeInfo and
++** vxworksFileId objects used by this file, all of which may be 
++** shared by multiple threads.
++**
++** Function unixMutexHeld() is used to assert() that the global mutex 
++** is held when required. This function is only used as part of assert() 
++** statements. e.g.
++**
++**   unixEnterMutex()
++**     assert( unixMutexHeld() );
++**   unixEnterLeave()
+ */
+-typedef struct afpLockingContext afpLockingContext;
+-struct afpLockingContext {
+-  int reserved;
+-  const char *dbPath;             /* Name of the open file */
+-};
+-
+-struct ByteRangeLockPB2
+-{
+-  unsigned long long offset;        /* offset to first byte to lock */
+-  unsigned long long length;        /* nbr of bytes to lock */
+-  unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
+-  unsigned char unLockFlag;         /* 1 = unlock, 0 = lock */
+-  unsigned char startEndFlag;       /* 1=rel to end of fork, 0=rel to start */
+-  int fd;                           /* file desc to assoc this lock with */
+-};
++static void unixEnterMutex(void){
++  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++}
++static void unixLeaveMutex(void){
++  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++}
++#ifdef SQLITE_DEBUG
++static int unixMutexHeld(void) {
++  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++}
++#endif
+ 
+-#define afpfsByteRangeLock2FSCTL        _IOWR('z', 23, struct ByteRangeLockPB2)
+ 
++#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+ /*
+-** This is a utility for setting or clearing a bit-range lock on an
+-** AFP filesystem.
+-** 
+-** Return SQLITE_OK on success, SQLITE_BUSY on failure.
++** Helper function for printing out trace information from debugging
++** binaries. This returns the string represetation of the supplied
++** integer lock-type.
+ */
+-static int afpSetLock(
+-  const char *path,              /* Name of the file to be locked or unlocked */
+-  unixFile *pFile,               /* Open file descriptor on path */
+-  unsigned long long offset,     /* First byte to be locked */
+-  unsigned long long length,     /* Number of bytes to lock */
+-  int setLockFlag                /* True to set lock.  False to clear lock */
+-){
+-  struct ByteRangeLockPB2 pb;
+-  int err;
+-  
+-  pb.unLockFlag = setLockFlag ? 0 : 1;
+-  pb.startEndFlag = 0;
+-  pb.offset = offset;
+-  pb.length = length; 
+-  pb.fd = pFile->h;
+-  
+-  OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", 
+-    (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
+-    offset, length));
+-  err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
+-  if ( err==-1 ) {
+-    int rc;
+-    int tErrno = errno;
+-    OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
+-             path, tErrno, strerror(tErrno)));
+-#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+-    rc = SQLITE_BUSY;
+-#else
+-    rc = sqliteErrorFromPosixError(tErrno,
+-                    setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
+-#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
+-    if( IS_LOCK_ERROR(rc) ){
+-      pFile->lastErrno = tErrno;
+-    }
+-    return rc;
+-  } else {
+-    return SQLITE_OK;
++static const char *azFileLock(int eFileLock){
++  switch( eFileLock ){
++    case NO_LOCK: return "NONE";
++    case SHARED_LOCK: return "SHARED";
++    case RESERVED_LOCK: return "RESERVED";
++    case PENDING_LOCK: return "PENDING";
++    case EXCLUSIVE_LOCK: return "EXCLUSIVE";
+   }
++  return "ERROR";
+ }
++#endif
+ 
++#ifdef SQLITE_LOCK_TRACE
+ /*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, set *pResOut
+-** to a non-zero value otherwise *pResOut is set to zero.  The return value
+-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++** Print out information about all locking operations.
++**
++** This routine is used for troubleshooting locks on multithreaded
++** platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
++** command-line option on the compiler.  This code is normally
++** turned off.
+ */
+-static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
+-  int rc = SQLITE_OK;
+-  int reserved = 0;
+-  unixFile *pFile = (unixFile*)id;
+-  afpLockingContext *context;
+-  
+-  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+-  
+-  assert( pFile );
+-  context = (afpLockingContext *) pFile->lockingContext;
+-  if( context->reserved ){
+-    *pResOut = 1;
+-    return SQLITE_OK;
++static int lockTrace(int fd, int op, struct flock *p){
++  char *zOpName, *zType;
++  int s;
++  int savedErrno;
++  if( op==F_GETLK ){
++    zOpName = "GETLK";
++  }else if( op==F_SETLK ){
++    zOpName = "SETLK";
++  }else{
++    s = osFcntl(fd, op, p);
++    sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
++    return s;
+   }
+-  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
+-  
+-  /* Check if a thread in this process holds such a lock */
+-  if( pFile->pInode->eFileLock>SHARED_LOCK ){
+-    reserved = 1;
++  if( p->l_type==F_RDLCK ){
++    zType = "RDLCK";
++  }else if( p->l_type==F_WRLCK ){
++    zType = "WRLCK";
++  }else if( p->l_type==F_UNLCK ){
++    zType = "UNLCK";
++  }else{
++    assert( 0 );
+   }
+-  
+-  /* Otherwise see if some other process holds it.
+-   */
+-  if( !reserved ){
+-    /* lock the RESERVED byte */
+-    int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);  
+-    if( SQLITE_OK==lrc ){
+-      /* if we succeeded in taking the reserved lock, unlock it to restore
+-      ** the original state */
+-      lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
+-    } else {
+-      /* if we failed to get the lock then someone else must have it */
+-      reserved = 1;
+-    }
+-    if( IS_LOCK_ERROR(lrc) ){
+-      rc=lrc;
++  assert( p->l_whence==SEEK_SET );
++  s = osFcntl(fd, op, p);
++  savedErrno = errno;
++  sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
++     threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
++     (int)p->l_pid, s);
++  if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
++    struct flock l2;
++    l2 = *p;
++    osFcntl(fd, F_GETLK, &l2);
++    if( l2.l_type==F_RDLCK ){
++      zType = "RDLCK";
++    }else if( l2.l_type==F_WRLCK ){
++      zType = "WRLCK";
++    }else if( l2.l_type==F_UNLCK ){
++      zType = "UNLCK";
++    }else{
++      assert( 0 );
+     }
++    sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
++       zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
+   }
+-  
+-  unixLeaveMutex();
+-  OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
+-  
+-  *pResOut = reserved;
+-  return rc;
++  errno = savedErrno;
++  return s;
+ }
++#undef osFcntl
++#define osFcntl lockTrace
++#endif /* SQLITE_LOCK_TRACE */
+ 
+ /*
+-** Lock the file with the lock specified by parameter eFileLock - one
+-** of the following:
+-**
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
+-**
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
+-**
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
+-**
+-** This routine will only increase a lock.  Use the sqlite3OsUnlock()
+-** routine to lower a locking level.
++** Retry ftruncate() calls that fail due to EINTR
+ */
+-static int afpLock(sqlite3_file *id, int eFileLock){
+-  int rc = SQLITE_OK;
+-  unixFile *pFile = (unixFile*)id;
+-  unixInodeInfo *pInode = pFile->pInode;
+-  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+-  
+-  assert( pFile );
+-  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
+-           azFileLock(eFileLock), azFileLock(pFile->eFileLock),
+-           azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
++static int robust_ftruncate(int h, sqlite3_int64 sz){
++  int rc;
++  do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
++  return rc;
++}
+ 
+-  /* If there is already a lock of this type or more restrictive on the
+-  ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
+-  ** unixEnterMutex() hasn't been called yet.
++/*
++** This routine translates a standard POSIX errno code into something
++** useful to the clients of the sqlite3 functions.  Specifically, it is
++** intended to translate a variety of "try again" errors into SQLITE_BUSY
++** and a variety of "please close the file descriptor NOW" errors into 
++** SQLITE_IOERR
++** 
++** Errors during initialization of locks, or file system support for locks,
++** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
++*/
++static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
++  switch (posixError) {
++#if 0
++  /* At one point this code was not commented out. In theory, this branch
++  ** should never be hit, as this function should only be called after
++  ** a locking-related function (i.e. fcntl()) has returned non-zero with
++  ** the value of errno as the first argument. Since a system call has failed,
++  ** errno should be non-zero.
++  **
++  ** Despite this, if errno really is zero, we still don't want to return
++  ** SQLITE_OK. The system call failed, and *some* SQLite error should be
++  ** propagated back to the caller. Commenting this branch out means errno==0
++  ** will be handled by the "default:" case below.
+   */
+-  if( pFile->eFileLock>=eFileLock ){
+-    OSTRACE(("LOCK    %d %s ok (already held) (afp)\n", pFile->h,
+-           azFileLock(eFileLock)));
++  case 0: 
+     return SQLITE_OK;
+-  }
+-
+-  /* Make sure the locking sequence is correct
+-  **  (1) We never move from unlocked to anything higher than shared lock.
+-  **  (2) SQLite never explicitly requests a pendig lock.
+-  **  (3) A shared lock is always held when a reserve lock is requested.
+-  */
+-  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
+-  assert( eFileLock!=PENDING_LOCK );
+-  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
+-  
+-  /* This mutex is needed because pFile->pInode is shared across threads
+-  */
+-  unixEnterMutex();
+-  pInode = pFile->pInode;
++#endif
+ 
+-  /* If some thread using this PID has a lock via a different unixFile*
+-  ** handle that precludes the requested lock, return BUSY.
+-  */
+-  if( (pFile->eFileLock!=pInode->eFileLock && 
+-       (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
+-     ){
+-    rc = SQLITE_BUSY;
+-    goto afp_end_lock;
+-  }
+-  
+-  /* If a SHARED lock is requested, and some thread using this PID already
+-  ** has a SHARED or RESERVED lock, then increment reference counts and
+-  ** return SQLITE_OK.
+-  */
+-  if( eFileLock==SHARED_LOCK && 
+-     (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
+-    assert( eFileLock==SHARED_LOCK );
+-    assert( pFile->eFileLock==0 );
+-    assert( pInode->nShared>0 );
+-    pFile->eFileLock = SHARED_LOCK;
+-    pInode->nShared++;
+-    pInode->nLock++;
+-    goto afp_end_lock;
+-  }
++  case EAGAIN:
++  case ETIMEDOUT:
++  case EBUSY:
++  case EINTR:
++  case ENOLCK:  
++    /* random NFS retry error, unless during file system support 
++     * introspection, in which it actually means what it says */
++    return SQLITE_BUSY;
+     
+-  /* A PENDING lock is needed before acquiring a SHARED lock and before
+-  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
+-  ** be released.
+-  */
+-  if( eFileLock==SHARED_LOCK 
+-      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
+-  ){
+-    int failed;
+-    failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
+-    if (failed) {
+-      rc = failed;
+-      goto afp_end_lock;
++  case EACCES: 
++    /* EACCES is like EAGAIN during locking operations, but not any other time*/
++    if( (sqliteIOErr == SQLITE_IOERR_LOCK) || 
++        (sqliteIOErr == SQLITE_IOERR_UNLOCK) || 
++        (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
++        (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
++      return SQLITE_BUSY;
+     }
+-  }
+-  
+-  /* If control gets to this point, then actually go ahead and make
+-  ** operating system calls for the specified lock.
+-  */
+-  if( eFileLock==SHARED_LOCK ){
+-    int lrc1, lrc2, lrc1Errno = 0;
+-    long lk, mask;
++    /* else fall through */
++  case EPERM: 
++    return SQLITE_PERM;
+     
+-    assert( pInode->nShared==0 );
+-    assert( pInode->eFileLock==0 );
+-        
+-    mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
+-    /* Now get the read-lock SHARED_LOCK */
+-    /* note that the quality of the randomness doesn't matter that much */
+-    lk = random(); 
+-    pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
+-    lrc1 = afpSetLock(context->dbPath, pFile, 
+-          SHARED_FIRST+pInode->sharedByte, 1, 1);
+-    if( IS_LOCK_ERROR(lrc1) ){
+-      lrc1Errno = pFile->lastErrno;
+-    }
+-    /* Drop the temporary PENDING lock */
+-    lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
++  /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
++  ** this module never makes such a call. And the code in SQLite itself 
++  ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
++  ** this case is also commented out. If the system does set errno to EDEADLK,
++  ** the default SQLITE_IOERR_XXX code will be returned. */
++#if 0
++  case EDEADLK:
++    return SQLITE_IOERR_BLOCKED;
++#endif
+     
+-    if( IS_LOCK_ERROR(lrc1) ) {
+-      pFile->lastErrno = lrc1Errno;
+-      rc = lrc1;
+-      goto afp_end_lock;
+-    } else if( IS_LOCK_ERROR(lrc2) ){
+-      rc = lrc2;
+-      goto afp_end_lock;
+-    } else if( lrc1 != SQLITE_OK ) {
+-      rc = lrc1;
+-    } else {
+-      pFile->eFileLock = SHARED_LOCK;
+-      pInode->nLock++;
+-      pInode->nShared = 1;
+-    }
+-  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
+-    /* We are trying for an exclusive lock but another thread in this
+-     ** same process is still holding a shared lock. */
+-    rc = SQLITE_BUSY;
+-  }else{
+-    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
+-    ** assumed that there is a SHARED or greater lock on the file
+-    ** already.
+-    */
+-    int failed = 0;
+-    assert( 0!=pFile->eFileLock );
+-    if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
+-        /* Acquire a RESERVED lock */
+-        failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+-      if( !failed ){
+-        context->reserved = 1;
++#if EOPNOTSUPP!=ENOTSUP
++  case EOPNOTSUPP: 
++    /* something went terribly awry, unless during file system support 
++     * introspection, in which it actually means what it says */
++#endif
++#ifdef ENOTSUP
++  case ENOTSUP: 
++    /* invalid fd, unless during file system support introspection, in which 
++     * it actually means what it says */
++#endif
++  case EIO:
++  case EBADF:
++  case EINVAL:
++  case ENOTCONN:
++  case ENODEV:
++  case ENXIO:
++  case ENOENT:
++#ifdef ESTALE                     /* ESTALE is not defined on Interix systems */
++  case ESTALE:
++#endif
++  case ENOSYS:
++    /* these should force the client to close the file and reconnect */
++    
++  default: 
++    return sqliteIOErr;
++  }
++}
++
++
++/******************************************************************************
++****************** Begin Unique File ID Utility Used By VxWorks ***************
++**
++** On most versions of unix, we can get a unique ID for a file by concatenating
++** the device number and the inode number.  But this does not work on VxWorks.
++** On VxWorks, a unique file id must be based on the canonical filename.
++**
++** A pointer to an instance of the following structure can be used as a
++** unique file ID in VxWorks.  Each instance of this structure contains
++** a copy of the canonical filename.  There is also a reference count.  
++** The structure is reclaimed when the number of pointers to it drops to
++** zero.
++**
++** There are never very many files open at one time and lookups are not
++** a performance-critical path, so it is sufficient to put these
++** structures on a linked list.
++*/
++struct vxworksFileId {
++  struct vxworksFileId *pNext;  /* Next in a list of them all */
++  int nRef;                     /* Number of references to this one */
++  int nName;                    /* Length of the zCanonicalName[] string */
++  char *zCanonicalName;         /* Canonical filename */
++};
++
++#if OS_VXWORKS
++/* 
++** All unique filenames are held on a linked list headed by this
++** variable:
++*/
++static struct vxworksFileId *vxworksFileList = 0;
++
++/*
++** Simplify a filename into its canonical form
++** by making the following changes:
++**
++**  * removing any trailing and duplicate /
++**  * convert /./ into just /
++**  * convert /A/../ where A is any simple name into just /
++**
++** Changes are made in-place.  Return the new name length.
++**
++** The original filename is in z[0..n-1].  Return the number of
++** characters in the simplified name.
++*/
++static int vxworksSimplifyName(char *z, int n){
++  int i, j;
++  while( n>1 && z[n-1]=='/' ){ n--; }
++  for(i=j=0; i<n; i++){
++    if( z[i]=='/' ){
++      if( z[i+1]=='/' ) continue;
++      if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
++        i += 1;
++        continue;
+       }
+-    }
+-    if (!failed && eFileLock == EXCLUSIVE_LOCK) {
+-      /* Acquire an EXCLUSIVE lock */
+-        
+-      /* Remove the shared lock before trying the range.  we'll need to 
+-      ** reestablish the shared lock if we can't get the  afpUnlock
+-      */
+-      if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
+-                         pInode->sharedByte, 1, 0)) ){
+-        int failed2 = SQLITE_OK;
+-        /* now attemmpt to get the exclusive lock range */
+-        failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, 
+-                               SHARED_SIZE, 1);
+-        if( failed && (failed2 = afpSetLock(context->dbPath, pFile, 
+-                       SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
+-          /* Can't reestablish the shared lock.  Sqlite can't deal, this is
+-          ** a critical I/O error
+-          */
+-          rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : 
+-               SQLITE_IOERR_LOCK;
+-          goto afp_end_lock;
+-        } 
+-      }else{
+-        rc = failed; 
++      if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
++        while( j>0 && z[j-1]!='/' ){ j--; }
++        if( j>0 ){ j--; }
++        i += 2;
++        continue;
+       }
+     }
+-    if( failed ){
+-      rc = failed;
+-    }
+-  }
+-  
+-  if( rc==SQLITE_OK ){
+-    pFile->eFileLock = eFileLock;
+-    pInode->eFileLock = eFileLock;
+-  }else if( eFileLock==EXCLUSIVE_LOCK ){
+-    pFile->eFileLock = PENDING_LOCK;
+-    pInode->eFileLock = PENDING_LOCK;
++    z[j++] = z[i];
+   }
+-  
+-afp_end_lock:
+-  unixLeaveMutex();
+-  OSTRACE(("LOCK    %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), 
+-         rc==SQLITE_OK ? "ok" : "failed"));
+-  return rc;
++  z[j] = 0;
++  return j;
+ }
+ 
+ /*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
++** Find a unique file ID for the given absolute pathname.  Return
++** a pointer to the vxworksFileId object.  This pointer is the unique
++** file ID.
+ **
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
++** The nRef field of the vxworksFileId object is incremented before
++** the object is returned.  A new vxworksFileId object is created
++** and added to the global list if necessary.
++**
++** If a memory allocation error occurs, return NULL.
+ */
+-static int afpUnlock(sqlite3_file *id, int eFileLock) {
+-  int rc = SQLITE_OK;
+-  unixFile *pFile = (unixFile*)id;
+-  unixInodeInfo *pInode;
+-  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+-  int skipShared = 0;
+-#ifdef SQLITE_TEST
+-  int h = pFile->h;
+-#endif
++static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
++  struct vxworksFileId *pNew;         /* search key and new file ID */
++  struct vxworksFileId *pCandidate;   /* For looping over existing file IDs */
++  int n;                              /* Length of zAbsoluteName string */
+ 
+-  assert( pFile );
+-  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
+-           pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
+-           getpid()));
++  assert( zAbsoluteName[0]=='/' );
++  n = (int)strlen(zAbsoluteName);
++  pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
++  if( pNew==0 ) return 0;
++  pNew->zCanonicalName = (char*)&pNew[1];
++  memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
++  n = vxworksSimplifyName(pNew->zCanonicalName, n);
+ 
+-  assert( eFileLock<=SHARED_LOCK );
+-  if( pFile->eFileLock<=eFileLock ){
+-    return SQLITE_OK;
+-  }
++  /* Search for an existing entry that matching the canonical name.
++  ** If found, increment the reference count and return a pointer to
++  ** the existing file ID.
++  */
+   unixEnterMutex();
+-  pInode = pFile->pInode;
+-  assert( pInode->nShared!=0 );
+-  if( pFile->eFileLock>SHARED_LOCK ){
+-    assert( pInode->eFileLock==pFile->eFileLock );
+-    SimulateIOErrorBenign(1);
+-    SimulateIOError( h=(-1) )
+-    SimulateIOErrorBenign(0);
+-    
+-#ifdef SQLITE_DEBUG
+-    /* When reducing a lock such that other processes can start
+-    ** reading the database file again, make sure that the
+-    ** transaction counter was updated if any part of the database
+-    ** file changed.  If the transaction counter is not updated,
+-    ** other connections to the same file might not realize that
+-    ** the file has changed and hence might not know to flush their
+-    ** cache.  The use of a stale cache can lead to database corruption.
+-    */
+-    assert( pFile->inNormalWrite==0
+-           || pFile->dbUpdate==0
+-           || pFile->transCntrChng==1 );
+-    pFile->inNormalWrite = 0;
+-#endif
+-    
+-    if( pFile->eFileLock==EXCLUSIVE_LOCK ){
+-      rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
+-      if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
+-        /* only re-establish the shared lock if necessary */
+-        int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
+-        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
+-      } else {
+-        skipShared = 1;
+-      }
+-    }
+-    if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
+-      rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
+-    } 
+-    if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
+-      rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
+-      if( !rc ){ 
+-        context->reserved = 0; 
+-      }
+-    }
+-    if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
+-      pInode->eFileLock = SHARED_LOCK;
++  for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
++    if( pCandidate->nName==n 
++     && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
++    ){
++       sqlite3_free(pNew);
++       pCandidate->nRef++;
++       unixLeaveMutex();
++       return pCandidate;
+     }
+   }
+-  if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
+ 
+-    /* Decrement the shared lock counter.  Release the lock using an
+-    ** OS call only when all threads in this same process have released
+-    ** the lock.
+-    */
+-    unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
+-    pInode->nShared--;
+-    if( pInode->nShared==0 ){
+-      SimulateIOErrorBenign(1);
+-      SimulateIOError( h=(-1) )
+-      SimulateIOErrorBenign(0);
+-      if( !skipShared ){
+-        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
+-      }
+-      if( !rc ){
+-        pInode->eFileLock = NO_LOCK;
+-        pFile->eFileLock = NO_LOCK;
+-      }
+-    }
+-    if( rc==SQLITE_OK ){
+-      pInode->nLock--;
+-      assert( pInode->nLock>=0 );
+-      if( pInode->nLock==0 ){
+-        closePendingFds(pFile);
+-      }
+-    }
+-  }
+-  
++  /* No match was found.  We will make a new file ID */
++  pNew->nRef = 1;
++  pNew->nName = n;
++  pNew->pNext = vxworksFileList;
++  vxworksFileList = pNew;
+   unixLeaveMutex();
+-  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+-  return rc;
++  return pNew;
+ }
+ 
+ /*
+-** Close a file & cleanup AFP specific locking context 
++** Decrement the reference count on a vxworksFileId object.  Free
++** the object when the reference count reaches zero.
+ */
+-static int afpClose(sqlite3_file *id) {
+-  int rc = SQLITE_OK;
+-  if( id ){
+-    unixFile *pFile = (unixFile*)id;
+-    afpUnlock(id, NO_LOCK);
+-    unixEnterMutex();
+-    if( pFile->pInode && pFile->pInode->nLock ){
+-      /* If there are outstanding locks, do not actually close the file just
+-      ** yet because that would clear those locks.  Instead, add the file
+-      ** descriptor to pInode->aPending.  It will be automatically closed when
+-      ** the last lock is cleared.
+-      */
+-      setPendingFd(pFile);
+-    }
+-    releaseInodeInfo(pFile);
+-    sqlite3_free(pFile->lockingContext);
+-    rc = closeUnixFile(id);
+-    unixLeaveMutex();
++static void vxworksReleaseFileId(struct vxworksFileId *pId){
++  unixEnterMutex();
++  assert( pId->nRef>0 );
++  pId->nRef--;
++  if( pId->nRef==0 ){
++    struct vxworksFileId **pp;
++    for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
++    assert( *pp==pId );
++    *pp = pId->pNext;
++    sqlite3_free(pId);
+   }
+-  return rc;
++  unixLeaveMutex();
+ }
+-
+-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+-/*
+-** The code above is the AFP lock implementation.  The code is specific
+-** to MacOSX and does not work on other unix platforms.  No alternative
+-** is available.  If you don't compile for a mac, then the "unix-afp"
+-** VFS is not available.
+-**
+-********************* End of the AFP lock implementation **********************
++#endif /* OS_VXWORKS */
++/*************** End of Unique File ID Utility Used By VxWorks ****************
+ ******************************************************************************/
+ 
+-/******************************************************************************
+-*************************** Begin NFS Locking ********************************/
+-
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-/*
+- ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+- ** must be either NO_LOCK or SHARED_LOCK.
+- **
+- ** If the locking level of the file descriptor is already at or below
+- ** the requested locking level, this routine is a no-op.
+- */
+-static int nfsUnlock(sqlite3_file *id, int eFileLock){
+-  return posixUnlock(id, eFileLock, 1);
+-}
+-
+-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+-/*
+-** The code above is the NFS lock implementation.  The code is specific
+-** to MacOSX and does not work on other unix platforms.  No alternative
+-** is available.  
+-**
+-********************* End of the NFS lock implementation **********************
+-******************************************************************************/
+ 
+ /******************************************************************************
+-**************** Non-locking sqlite3_file methods *****************************
++*************************** Posix Advisory Locking ****************************
+ **
+-** The next division contains implementations for all methods of the 
+-** sqlite3_file object other than the locking methods.  The locking
+-** methods were defined in divisions above (one locking method per
+-** division).  Those methods that are common to all locking modes
+-** are gather together into this division.
++** POSIX advisory locks are broken by design.  ANSI STD 1003.1 (1996)
++** section 6.5.2.2 lines 483 through 490 specify that when a process
++** sets or clears a lock, that operation overrides any prior locks set
++** by the same process.  It does not explicitly say so, but this implies
++** that it overrides locks set by the same process using a different
++** file descriptor.  Consider this test case:
++**
++**       int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
++**       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
++**
++** Suppose ./file1 and ./file2 are really the same file (because
++** one is a hard or symbolic link to the other) then if you set
++** an exclusive lock on fd1, then try to get an exclusive lock
++** on fd2, it works.  I would have expected the second lock to
++** fail since there was already a lock on the file due to fd1.
++** But not so.  Since both locks came from the same process, the
++** second overrides the first, even though they were on different
++** file descriptors opened on different file names.
++**
++** This means that we cannot use POSIX locks to synchronize file access
++** among competing threads of the same process.  POSIX locks will work fine
++** to synchronize access for threads in separate processes, but not
++** threads within the same process.
++**
++** To work around the problem, SQLite has to manage file locks internally
++** on its own.  Whenever a new database is opened, we have to find the
++** specific inode of the database file (the inode is determined by the
++** st_dev and st_ino fields of the stat structure that fstat() fills in)
++** and check for locks already existing on that inode.  When locks are
++** created or removed, we have to look at our own internal record of the
++** locks to see if another thread has previously set a lock on that same
++** inode.
++**
++** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
++** For VxWorks, we have to use the alternative unique ID system based on
++** canonical filename and implemented in the previous division.)
++**
++** The sqlite3_file structure for POSIX is no longer just an integer file
++** descriptor.  It is now a structure that holds the integer file
++** descriptor and a pointer to a structure that describes the internal
++** locks on the corresponding inode.  There is one locking structure
++** per inode, so if the same inode is opened twice, both unixFile structures
++** point to the same locking structure.  The locking structure keeps
++** a reference count (so we will know when to delete it) and a "cnt"
++** field that tells us its internal lock status.  cnt==0 means the
++** file is unlocked.  cnt==-1 means the file has an exclusive lock.
++** cnt>0 means there are cnt shared locks on the file.
++**
++** Any attempt to lock or unlock a file first checks the locking
++** structure.  The fcntl() system call is only invoked to set a 
++** POSIX lock if the internal lock structure transitions between
++** a locked and an unlocked state.
++**
++** But wait:  there are yet more problems with POSIX advisory locks.
++**
++** If you close a file descriptor that points to a file that has locks,
++** all locks on that file that are owned by the current process are
++** released.  To work around this problem, each unixInodeInfo object
++** maintains a count of the number of pending locks on tha inode.
++** When an attempt is made to close an unixFile, if there are
++** other unixFile open on the same inode that are holding locks, the call
++** to close() the file descriptor is deferred until all of the locks clear.
++** The unixInodeInfo structure keeps a list of file descriptors that need to
++** be closed and that list is walked (and cleared) when the last lock
++** clears.
++**
++** Yet another problem:  LinuxThreads do not play well with posix locks.
++**
++** Many older versions of linux use the LinuxThreads library which is
++** not posix compliant.  Under LinuxThreads, a lock created by thread
++** A cannot be modified or overridden by a different thread B.
++** Only thread A can modify the lock.  Locking behavior is correct
++** if the appliation uses the newer Native Posix Thread Library (NPTL)
++** on linux - with NPTL a lock created by thread A can override locks
++** in thread B.  But there is no way to know at compile-time which
++** threading library is being used.  So there is no way to know at
++** compile-time whether or not thread A can override locks on thread B.
++** One has to do a run-time check to discover the behavior of the
++** current process.
++**
++** SQLite used to support LinuxThreads.  But support for LinuxThreads
++** was dropped beginning with version 3.7.0.  SQLite will still work with
++** LinuxThreads provided that (1) there is no more than one connection 
++** per database file in the same process and (2) database connections
++** do not move across threads.
+ */
+ 
+ /*
+-** Seek to the offset passed as the second argument, then read cnt 
+-** bytes into pBuf. Return the number of bytes actually read.
+-**
+-** NB:  If you define USE_PREAD or USE_PREAD64, then it might also
+-** be necessary to define _XOPEN_SOURCE to be 500.  This varies from
+-** one system to another.  Since SQLite does not define USE_PREAD
+-** any any form by default, we will not attempt to define _XOPEN_SOURCE.
+-** See tickets #2741 and #2681.
+-**
+-** To avoid stomping the errno value on a failed read the lastErrno value
+-** is set before returning.
++** An instance of the following structure serves as the key used
++** to locate a particular unixInodeInfo object.
+ */
+-static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
+-  int got;
+-  int prior = 0;
+-#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
+-  i64 newOffset;
+-#endif
+-  TIMER_START;
+-  assert( cnt==(cnt&0x1ffff) );
+-  cnt &= 0x1ffff;
+-  do{
+-#if defined(USE_PREAD)
+-    got = osPread(id->h, pBuf, cnt, offset);
+-    SimulateIOError( got = -1 );
+-#elif defined(USE_PREAD64)
+-    got = osPread64(id->h, pBuf, cnt, offset);
+-    SimulateIOError( got = -1 );
++struct unixFileId {
++  dev_t dev;                  /* Device number */
++#if OS_VXWORKS
++  struct vxworksFileId *pId;  /* Unique file ID for vxworks. */
+ #else
+-    newOffset = lseek(id->h, offset, SEEK_SET);
+-    SimulateIOError( newOffset-- );
+-    if( newOffset!=offset ){
+-      if( newOffset == -1 ){
+-        ((unixFile*)id)->lastErrno = errno;
+-      }else{
+-        ((unixFile*)id)->lastErrno = 0;
+-      }
+-      return -1;
+-    }
+-    got = osRead(id->h, pBuf, cnt);
++  ino_t ino;                  /* Inode number */
+ #endif
+-    if( got==cnt ) break;
+-    if( got<0 ){
+-      if( errno==EINTR ){ got = 1; continue; }
+-      prior = 0;
+-      ((unixFile*)id)->lastErrno = errno;
+-      break;
+-    }else if( got>0 ){
+-      cnt -= got;
+-      offset += got;
+-      prior += got;
+-      pBuf = (void*)(got + (char*)pBuf);
+-    }
+-  }while( got>0 );
+-  TIMER_END;
+-  OSTRACE(("READ    %-3d %5d %7lld %llu\n",
+-            id->h, got+prior, offset-prior, TIMER_ELAPSED));
+-  return got+prior;
+-}
++};
+ 
+ /*
+-** Read data from a file into a buffer.  Return SQLITE_OK if all
+-** bytes were read successfully and SQLITE_IOERR if anything goes
+-** wrong.
++** An instance of the following structure is allocated for each open
++** inode.  Or, on LinuxThreads, there is one of these structures for
++** each inode opened by each thread.
++**
++** A single inode can have multiple file descriptors, so each unixFile
++** structure contains a pointer to an instance of this object and this
++** object keeps a count of the number of unixFile pointing to it.
+ */
+-static int unixRead(
+-  sqlite3_file *id, 
+-  void *pBuf, 
+-  int amt,
+-  sqlite3_int64 offset
+-){
+-  unixFile *pFile = (unixFile *)id;
+-  int got;
+-  assert( id );
+-  assert( offset>=0 );
+-  assert( amt>0 );
+-
+-  /* If this is a database file (not a journal, master-journal or temp
+-  ** file), the bytes in the locking range should never be read or written. */
+-#if 0
+-  assert( pFile->pUnused==0
+-       || offset>=PENDING_BYTE+512
+-       || offset+amt<=PENDING_BYTE 
+-  );
++struct unixInodeInfo {
++  struct unixFileId fileId;       /* The lookup key */
++  int nShared;                    /* Number of SHARED locks held */
++  unsigned char eFileLock;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
++  unsigned char bProcessLock;     /* An exclusive process lock is held */
++  int nRef;                       /* Number of pointers to this structure */
++  unixShmNode *pShmNode;          /* Shared memory associated with this inode */
++  int nLock;                      /* Number of outstanding file locks */
++  UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
++  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
++  unixInodeInfo *pPrev;           /*    .... doubly linked */
++#if SQLITE_ENABLE_LOCKING_STYLE
++  unsigned long long sharedByte;  /* for AFP simulated shared lock */
+ #endif
+-
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  /* Deal with as much of this read request as possible by transfering
+-  ** data from the memory mapping using memcpy().  */
+-  if( offset<pFile->mmapSize ){
+-    if( offset+amt <= pFile->mmapSize ){
+-      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
+-      return SQLITE_OK;
+-    }else{
+-      int nCopy = pFile->mmapSize - offset;
+-      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
+-      pBuf = &((u8 *)pBuf)[nCopy];
+-      amt -= nCopy;
+-      offset += nCopy;
+-    }
+-  }
++#if OS_VXWORKS
++  sem_t *pSem;                    /* Named POSIX semaphore */
++  char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
+ #endif
++};
+ 
+-  got = seekAndRead(pFile, offset, pBuf, amt);
+-  if( got==amt ){
+-    return SQLITE_OK;
+-  }else if( got<0 ){
+-    /* lastErrno set by seekAndRead */
+-    return SQLITE_IOERR_READ;
+-  }else{
+-    pFile->lastErrno = 0; /* not a system error */
+-    /* Unread parts of the buffer must be zero-filled */
+-    memset(&((char*)pBuf)[got], 0, amt-got);
+-    return SQLITE_IOERR_SHORT_READ;
+-  }
+-}
++/*
++** A lists of all unixInodeInfo objects.
++*/
++static unixInodeInfo *inodeList = 0;
+ 
+ /*
+-** Attempt to seek the file-descriptor passed as the first argument to
+-** absolute offset iOff, then attempt to write nBuf bytes of data from
+-** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, 
+-** return the actual number of bytes written (which may be less than
+-** nBuf).
++**
++** This function - unixLogError_x(), is only ever called via the macro
++** unixLogError().
++**
++** It is invoked after an error occurs in an OS function and errno has been
++** set. It logs a message using sqlite3_log() containing the current value of
++** errno and, if possible, the human-readable equivalent from strerror() or
++** strerror_r().
++**
++** The first argument passed to the macro should be the error code that
++** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). 
++** The two subsequent arguments should be the name of the OS function that
++** failed (e.g. "unlink", "open") and the associated file-system path,
++** if any.
+ */
+-static int seekAndWriteFd(
+-  int fd,                         /* File descriptor to write to */
+-  i64 iOff,                       /* File offset to begin writing at */
+-  const void *pBuf,               /* Copy data from this buffer to the file */
+-  int nBuf,                       /* Size of buffer pBuf in bytes */
+-  int *piErrno                    /* OUT: Error number if error occurs */
++#define unixLogError(a,b,c)     unixLogErrorAtLine(a,b,c,__LINE__)
++static int unixLogErrorAtLine(
++  int errcode,                    /* SQLite error code */
++  const char *zFunc,              /* Name of OS function that failed */
++  const char *zPath,              /* File path associated with error */
++  int iLine                       /* Source line number where error occurred */
+ ){
+-  int rc = 0;                     /* Value returned by system call */
++  char *zErr;                     /* Message from strerror() or equivalent */
++  int iErrno = errno;             /* Saved syscall error number */
+ 
+-  assert( nBuf==(nBuf&0x1ffff) );
+-  nBuf &= 0x1ffff;
+-  TIMER_START;
++  /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
++  ** the strerror() function to obtain the human-readable error message
++  ** equivalent to errno. Otherwise, use strerror_r().
++  */ 
++#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
++  char aErr[80];
++  memset(aErr, 0, sizeof(aErr));
++  zErr = aErr;
+ 
+-#if defined(USE_PREAD)
+-  do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
+-#elif defined(USE_PREAD64)
+-  do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
+-#else
+-  do{
+-    i64 iSeek = lseek(fd, iOff, SEEK_SET);
+-    SimulateIOError( iSeek-- );
++  /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
++  ** assume that the system provides the GNU version of strerror_r() that
++  ** returns a pointer to a buffer containing the error message. That pointer 
++  ** may point to aErr[], or it may point to some static storage somewhere. 
++  ** Otherwise, assume that the system provides the POSIX version of 
++  ** strerror_r(), which always writes an error message into aErr[].
++  **
++  ** If the code incorrectly assumes that it is the POSIX version that is
++  ** available, the error message will often be an empty string. Not a
++  ** huge problem. Incorrectly concluding that the GNU version is available 
++  ** could lead to a segfault though.
++  */
++#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
++  zErr = 
++# endif
++  strerror_r(iErrno, aErr, sizeof(aErr)-1);
+ 
+-    if( iSeek!=iOff ){
+-      if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
+-      return -1;
+-    }
+-    rc = osWrite(fd, pBuf, nBuf);
+-  }while( rc<0 && errno==EINTR );
++#elif SQLITE_THREADSAFE
++  /* This is a threadsafe build, but strerror_r() is not available. */
++  zErr = "";
++#else
++  /* Non-threadsafe build, use strerror(). */
++  zErr = strerror(iErrno);
+ #endif
+ 
+-  TIMER_END;
+-  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
++  if( zPath==0 ) zPath = "";
++  sqlite3_log(errcode,
++      "os_unix.c:%d: (%d) %s(%s) - %s",
++      iLine, iErrno, zFunc, zPath, zErr
++  );
+ 
+-  if( rc<0 && piErrno ) *piErrno = errno;
+-  return rc;
++  return errcode;
+ }
+ 
+-
+ /*
+-** Seek to the offset in id->offset then read cnt bytes into pBuf.
+-** Return the number of bytes actually read.  Update the offset.
++** Close a file descriptor.
+ **
+-** To avoid stomping the errno value on a failed write the lastErrno value
+-** is set before returning.
++** We assume that close() almost always works, since it is only in a
++** very sick application or on a very sick platform that it might fail.
++** If it does fail, simply leak the file descriptor, but do log the
++** error.
++**
++** Note that it is not safe to retry close() after EINTR since the
++** file descriptor might have already been reused by another thread.
++** So we don't even try to recover from an EINTR.  Just log the error
++** and move on.
+ */
+-static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
+-  return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
++static void robust_close(unixFile *pFile, int h, int lineno){
++  if( osClose(h) ){
++    unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
++                       pFile ? pFile->zPath : 0, lineno);
++  }
+ }
+ 
++/*
++** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
++*/ 
++static void closePendingFds(unixFile *pFile){
++  unixInodeInfo *pInode = pFile->pInode;
++  UnixUnusedFd *p;
++  UnixUnusedFd *pNext;
++  for(p=pInode->pUnused; p; p=pNext){
++    pNext = p->pNext;
++    robust_close(pFile, p->fd, __LINE__);
++    sqlite3_free(p);
++  }
++  pInode->pUnused = 0;
++}
+ 
+ /*
+-** Write data from a buffer into a file.  Return SQLITE_OK on success
+-** or some other error code on failure.
++** Release a unixInodeInfo structure previously allocated by findInodeInfo().
++**
++** The mutex entered using the unixEnterMutex() function must be held
++** when this function is called.
+ */
+-static int unixWrite(
+-  sqlite3_file *id, 
+-  const void *pBuf, 
+-  int amt,
+-  sqlite3_int64 offset 
++static void releaseInodeInfo(unixFile *pFile){
++  unixInodeInfo *pInode = pFile->pInode;
++  assert( unixMutexHeld() );
++  if( ALWAYS(pInode) ){
++    pInode->nRef--;
++    if( pInode->nRef==0 ){
++      assert( pInode->pShmNode==0 );
++      closePendingFds(pFile);
++      if( pInode->pPrev ){
++        assert( pInode->pPrev->pNext==pInode );
++        pInode->pPrev->pNext = pInode->pNext;
++      }else{
++        assert( inodeList==pInode );
++        inodeList = pInode->pNext;
++      }
++      if( pInode->pNext ){
++        assert( pInode->pNext->pPrev==pInode );
++        pInode->pNext->pPrev = pInode->pPrev;
++      }
++      sqlite3_free(pInode);
++    }
++  }
++}
++
++/*
++** Given a file descriptor, locate the unixInodeInfo object that
++** describes that file descriptor.  Create a new one if necessary.  The
++** return value might be uninitialized if an error occurs.
++**
++** The mutex entered using the unixEnterMutex() function must be held
++** when this function is called.
++**
++** Return an appropriate error code.
++*/
++static int findInodeInfo(
++  unixFile *pFile,               /* Unix file with file desc used in the key */
++  unixInodeInfo **ppInode        /* Return the unixInodeInfo object here */
+ ){
+-  unixFile *pFile = (unixFile*)id;
+-  int wrote = 0;
+-  assert( id );
+-  assert( amt>0 );
++  int rc;                        /* System call return code */
++  int fd;                        /* The file descriptor for pFile */
++  struct unixFileId fileId;      /* Lookup key for the unixInodeInfo */
++  struct stat statbuf;           /* Low-level file information */
++  unixInodeInfo *pInode = 0;     /* Candidate unixInodeInfo object */
+ 
+-  /* If this is a database file (not a journal, master-journal or temp
+-  ** file), the bytes in the locking range should never be read or written. */
+-#if 0
+-  assert( pFile->pUnused==0
+-       || offset>=PENDING_BYTE+512
+-       || offset+amt<=PENDING_BYTE 
+-  );
+-#endif
++  assert( unixMutexHeld() );
+ 
+-#ifdef SQLITE_DEBUG
+-  /* If we are doing a normal write to a database file (as opposed to
+-  ** doing a hot-journal rollback or a write to some file other than a
+-  ** normal database file) then record the fact that the database
+-  ** has changed.  If the transaction counter is modified, record that
+-  ** fact too.
++  /* Get low-level information about the file that we can used to
++  ** create a unique name for the file.
+   */
+-  if( pFile->inNormalWrite ){
+-    pFile->dbUpdate = 1;  /* The database has been modified */
+-    if( offset<=24 && offset+amt>=27 ){
+-      int rc;
+-      char oldCntr[4];
+-      SimulateIOErrorBenign(1);
+-      rc = seekAndRead(pFile, 24, oldCntr, 4);
+-      SimulateIOErrorBenign(0);
+-      if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
+-        pFile->transCntrChng = 1;  /* The transaction counter has changed */
+-      }
+-    }
+-  }
++  fd = pFile->h;
++  rc = osFstat(fd, &statbuf);
++  if( rc!=0 ){
++    pFile->lastErrno = errno;
++#ifdef EOVERFLOW
++    if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
+ #endif
++    return SQLITE_IOERR;
++  }
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  /* Deal with as much of this write request as possible by transfering
+-  ** data from the memory mapping using memcpy().  */
+-  if( offset<pFile->mmapSize ){
+-    if( offset+amt <= pFile->mmapSize ){
+-      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
+-      return SQLITE_OK;
+-    }else{
+-      int nCopy = pFile->mmapSize - offset;
+-      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
+-      pBuf = &((u8 *)pBuf)[nCopy];
+-      amt -= nCopy;
+-      offset += nCopy;
++#ifdef __APPLE__
++  /* On OS X on an msdos filesystem, the inode number is reported
++  ** incorrectly for zero-size files.  See ticket #3260.  To work
++  ** around this problem (we consider it a bug in OS X, not SQLite)
++  ** we always increase the file size to 1 by writing a single byte
++  ** prior to accessing the inode number.  The one byte written is
++  ** an ASCII 'S' character which also happens to be the first byte
++  ** in the header of every SQLite database.  In this way, if there
++  ** is a race condition such that another thread has already populated
++  ** the first page of the database, no damage is done.
++  */
++  if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
++    do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
++    if( rc!=1 ){
++      pFile->lastErrno = errno;
++      return SQLITE_IOERR;
++    }
++    rc = osFstat(fd, &statbuf);
++    if( rc!=0 ){
++      pFile->lastErrno = errno;
++      return SQLITE_IOERR;
+     }
+   }
+ #endif
+ 
+-  while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
+-    amt -= wrote;
+-    offset += wrote;
+-    pBuf = &((char*)pBuf)[wrote];
++  memset(&fileId, 0, sizeof(fileId));
++  fileId.dev = statbuf.st_dev;
++#if OS_VXWORKS
++  fileId.pId = pFile->pId;
++#else
++  fileId.ino = statbuf.st_ino;
++#endif
++  pInode = inodeList;
++  while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
++    pInode = pInode->pNext;
+   }
+-  SimulateIOError(( wrote=(-1), amt=1 ));
+-  SimulateDiskfullError(( wrote=0, amt=1 ));
+-
+-  if( amt>0 ){
+-    if( wrote<0 && pFile->lastErrno!=ENOSPC ){
+-      /* lastErrno set by seekAndWrite */
+-      return SQLITE_IOERR_WRITE;
+-    }else{
+-      pFile->lastErrno = 0; /* not a system error */
+-      return SQLITE_FULL;
++  if( pInode==0 ){
++    pInode = sqlite3_malloc( sizeof(*pInode) );
++    if( pInode==0 ){
++      return SQLITE_NOMEM;
+     }
++    memset(pInode, 0, sizeof(*pInode));
++    memcpy(&pInode->fileId, &fileId, sizeof(fileId));
++    pInode->nRef = 1;
++    pInode->pNext = inodeList;
++    pInode->pPrev = 0;
++    if( inodeList ) inodeList->pPrev = pInode;
++    inodeList = pInode;
++  }else{
++    pInode->nRef++;
+   }
+-
++  *ppInode = pInode;
+   return SQLITE_OK;
+ }
+ 
+-#ifdef SQLITE_TEST
+-/*
+-** Count the number of fullsyncs and normal syncs.  This is used to test
+-** that syncs and fullsyncs are occurring at the right times.
+-*/
+-SQLITE_API int sqlite3_sync_count = 0;
+-SQLITE_API int sqlite3_fullsync_count = 0;
+-#endif
+-
+-/*
+-** We do not trust systems to provide a working fdatasync().  Some do.
+-** Others do no.  To be safe, we will stick with the (slightly slower)
+-** fsync(). If you know that your system does support fdatasync() correctly,
+-** then simply compile with -Dfdatasync=fdatasync
+-*/
+-#if !defined(fdatasync)
+-# define fdatasync fsync
+-#endif
+ 
+ /*
+-** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
+-** the F_FULLFSYNC macro is defined.  F_FULLFSYNC is currently
+-** only available on Mac OS X.  But that could change.
++** Check a unixFile that is a database.  Verify the following:
++**
++** (1) There is exactly one hard link on the file
++** (2) The file is not a symbolic link
++** (3) The file has not been renamed or unlinked
++**
++** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
+ */
+-#ifdef F_FULLFSYNC
+-# define HAVE_FULLFSYNC 1
+-#else
+-# define HAVE_FULLFSYNC 0
+-#endif
++static void verifyDbFile(unixFile *pFile){
++  struct stat buf;
++  int rc;
++  if( pFile->ctrlFlags & UNIXFILE_WARNED ){
++    /* One or more of the following warnings have already been issued.  Do not
++    ** repeat them so as not to clutter the error log */
++    return;
++  }
++  rc = osFstat(pFile->h, &buf);
++  if( rc!=0 ){
++    sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
++    pFile->ctrlFlags |= UNIXFILE_WARNED;
++    return;
++  }
++  if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
++    sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
++    pFile->ctrlFlags |= UNIXFILE_WARNED;
++    return;
++  }
++  if( buf.st_nlink>1 ){
++    sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
++    pFile->ctrlFlags |= UNIXFILE_WARNED;
++    return;
++  }
++  if( pFile->pInode!=0
++   && ((rc = osStat(pFile->zPath, &buf))!=0
++       || buf.st_ino!=pFile->pInode->fileId.ino)
++  ){
++    sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
++    pFile->ctrlFlags |= UNIXFILE_WARNED;
++    return;
++  }
++}
+ 
+ 
+ /*
+-** The fsync() system call does not work as advertised on many
+-** unix systems.  The following procedure is an attempt to make
+-** it work better.
+-**
+-** The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful
+-** for testing when we want to run through the test suite quickly.
+-** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
+-** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
+-** or power failure will likely corrupt the database file.
+-**
+-** SQLite sets the dataOnly flag if the size of the file is unchanged.
+-** The idea behind dataOnly is that it should only write the file content
+-** to disk, not the inode.  We only set dataOnly if the file size is 
+-** unchanged since the file size is part of the inode.  However, 
+-** Ted Ts'o tells us that fdatasync() will also write the inode if the
+-** file size has changed.  The only real difference between fdatasync()
+-** and fsync(), Ted tells us, is that fdatasync() will not flush the
+-** inode if the mtime or owner or other inode attributes have changed.
+-** We only care about the file size, not the other file attributes, so
+-** as far as SQLite is concerned, an fdatasync() is always adequate.
+-** So, we always use fdatasync() if it is available, regardless of
+-** the value of the dataOnly flag.
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, set *pResOut
++** to a non-zero value otherwise *pResOut is set to zero.  The return value
++** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+ */
+-static int full_fsync(int fd, int fullSync, int dataOnly){
+-  int rc;
++static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
++  int rc = SQLITE_OK;
++  int reserved = 0;
++  unixFile *pFile = (unixFile*)id;
+ 
+-  /* The following "ifdef/elif/else/" block has the same structure as
+-  ** the one below. It is replicated here solely to avoid cluttering 
+-  ** up the real code with the UNUSED_PARAMETER() macros.
+-  */
+-#ifdef SQLITE_NO_SYNC
+-  UNUSED_PARAMETER(fd);
+-  UNUSED_PARAMETER(fullSync);
+-  UNUSED_PARAMETER(dataOnly);
+-#elif HAVE_FULLFSYNC
+-  UNUSED_PARAMETER(dataOnly);
+-#else
+-  UNUSED_PARAMETER(fullSync);
+-  UNUSED_PARAMETER(dataOnly);
+-#endif
++  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+ 
+-  /* Record the number of times that we do a normal fsync() and 
+-  ** FULLSYNC.  This is used during testing to verify that this procedure
+-  ** gets called with the correct arguments.
+-  */
+-#ifdef SQLITE_TEST
+-  if( fullSync ) sqlite3_fullsync_count++;
+-  sqlite3_sync_count++;
+-#endif
++  assert( pFile );
++  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
+ 
+-  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
+-  ** no-op
+-  */
+-#ifdef SQLITE_NO_SYNC
+-  rc = SQLITE_OK;
+-#elif HAVE_FULLFSYNC
+-  if( fullSync ){
+-    rc = osFcntl(fd, F_FULLFSYNC, 0);
+-  }else{
+-    rc = 1;
++  /* Check if a thread in this process holds such a lock */
++  if( pFile->pInode->eFileLock>SHARED_LOCK ){
++    reserved = 1;
+   }
+-  /* If the FULLFSYNC failed, fall back to attempting an fsync().
+-  ** It shouldn't be possible for fullfsync to fail on the local 
+-  ** file system (on OSX), so failure indicates that FULLFSYNC
+-  ** isn't supported for this file system. So, attempt an fsync 
+-  ** and (for now) ignore the overhead of a superfluous fcntl call.  
+-  ** It'd be better to detect fullfsync support once and avoid 
+-  ** the fcntl call every time sync is called.
+-  */
+-  if( rc ) rc = fsync(fd);
+ 
+-#elif defined(__APPLE__)
+-  /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
+-  ** so currently we default to the macro that redefines fdatasync to fsync
++  /* Otherwise see if some other process holds it.
+   */
+-  rc = fsync(fd);
+-#else 
+-  rc = fdatasync(fd);
+-#if OS_VXWORKS
+-  if( rc==-1 && errno==ENOTSUP ){
+-    rc = fsync(fd);
++#ifndef __DJGPP__
++  if( !reserved && !pFile->pInode->bProcessLock ){
++    struct flock lock;
++    lock.l_whence = SEEK_SET;
++    lock.l_start = RESERVED_BYTE;
++    lock.l_len = 1;
++    lock.l_type = F_WRLCK;
++    if( osFcntl(pFile->h, F_GETLK, &lock) ){
++      rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
++      pFile->lastErrno = errno;
++    } else if( lock.l_type!=F_UNLCK ){
++      reserved = 1;
++    }
+   }
+-#endif /* OS_VXWORKS */
+-#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
++#endif
++  
++  unixLeaveMutex();
++  OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
+ 
+-  if( OS_VXWORKS && rc!= -1 ){
+-    rc = 0;
+-  }
++  *pResOut = reserved;
+   return rc;
+ }
+ 
+ /*
+-** Open a file descriptor to the directory containing file zFilename.
+-** If successful, *pFd is set to the opened file descriptor and
+-** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
+-** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
+-** value.
+-**
+-** The directory file descriptor is used for only one thing - to
+-** fsync() a directory to make sure file creation and deletion events
+-** are flushed to disk.  Such fsyncs are not needed on newer
+-** journaling filesystems, but are required on older filesystems.
++** Attempt to set a system-lock on the file pFile.  The lock is 
++** described by pLock.
+ **
+-** This routine can be overridden using the xSetSysCall interface.
+-** The ability to override this routine was added in support of the
+-** chromium sandbox.  Opening a directory is a security risk (we are
+-** told) so making it overrideable allows the chromium sandbox to
+-** replace this routine with a harmless no-op.  To make this routine
+-** a no-op, replace it with a stub that returns SQLITE_OK but leaves
+-** *pFd set to a negative number.
++** If the pFile was opened read/write from unix-excl, then the only lock
++** ever obtained is an exclusive lock, and it is obtained exactly once
++** the first time any lock is attempted.  All subsequent system locking
++** operations become no-ops.  Locking operations still happen internally,
++** in order to coordinate access between separate database connections
++** within this process, but all of that is handled in memory and the
++** operating system does not participate.
+ **
+-** If SQLITE_OK is returned, the caller is responsible for closing
+-** the file descriptor *pFd using close().
+-*/
+-static int openDirectory(const char *zFilename, int *pFd){
+-  int ii;
+-  int fd = -1;
+-  char zDirname[MAX_PATHNAME+1];
+-
+-  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
+-  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
+-  if( ii>0 ){
+-    zDirname[ii] = '\0';
+-    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
+-    if( fd>=0 ){
+-      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
++** This function is a pass-through to fcntl(F_SETLK) if pFile is using
++** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
++** and is read-only.
++**
++** Zero is returned if the call completes successfully, or -1 if a call
++** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
++*/
++static int unixFileLock(unixFile *pFile, struct flock *pLock){
++  int rc;
++  unixInodeInfo *pInode = pFile->pInode;
++  assert( unixMutexHeld() );
++  assert( pInode!=0 );
++  if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
++   && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
++  ){
++    if( pInode->bProcessLock==0 ){
++      struct flock lock;
++      assert( pInode->nLock==0 );
++      lock.l_whence = SEEK_SET;
++      lock.l_start = SHARED_FIRST;
++      lock.l_len = SHARED_SIZE;
++      lock.l_type = F_WRLCK;
++      rc = osFcntl(pFile->h, F_SETLK, &lock);
++      if( rc<0 ) return rc;
++      pInode->bProcessLock = 1;
++      pInode->nLock++;
++    }else{
++      rc = 0;
+     }
++  }else{
++    rc = osFcntl(pFile->h, F_SETLK, pLock);
+   }
+-  *pFd = fd;
+-  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
++  return rc;
+ }
+ 
+ /*
+-** Make sure all writes to a particular file are committed to disk.
++** Lock the file with the lock specified by parameter eFileLock - one
++** of the following:
+ **
+-** If dataOnly==0 then both the file itself and its metadata (file
+-** size, access time, etc) are synced.  If dataOnly!=0 then only the
+-** file data is synced.
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
+ **
+-** Under Unix, also make sure that the directory entry for the file
+-** has been created by fsync-ing the directory that contains the file.
+-** If we do not do this and we encounter a power failure, the directory
+-** entry for the journal might not exist after we reboot.  The next
+-** SQLite to access the file will not know that the journal exists (because
+-** the directory entry for the journal was never created) and the transaction
+-** will not roll back - possibly leading to database corruption.
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
++**
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
++**
++** This routine will only increase a lock.  Use the sqlite3OsUnlock()
++** routine to lower a locking level.
+ */
+-static int unixSync(sqlite3_file *id, int flags){
+-  int rc;
++static int unixLock(sqlite3_file *id, int eFileLock){
++  /* The following describes the implementation of the various locks and
++  ** lock transitions in terms of the POSIX advisory shared and exclusive
++  ** lock primitives (called read-locks and write-locks below, to avoid
++  ** confusion with SQLite lock names). The algorithms are complicated
++  ** slightly in order to be compatible with windows systems simultaneously
++  ** accessing the same database file, in case that is ever required.
++  **
++  ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
++  ** byte', each single bytes at well known offsets, and the 'shared byte
++  ** range', a range of 510 bytes at a well known offset.
++  **
++  ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
++  ** byte'.  If this is successful, a random byte from the 'shared byte
++  ** range' is read-locked and the lock on the 'pending byte' released.
++  **
++  ** A process may only obtain a RESERVED lock after it has a SHARED lock.
++  ** A RESERVED lock is implemented by grabbing a write-lock on the
++  ** 'reserved byte'. 
++  **
++  ** A process may only obtain a PENDING lock after it has obtained a
++  ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
++  ** on the 'pending byte'. This ensures that no new SHARED locks can be
++  ** obtained, but existing SHARED locks are allowed to persist. A process
++  ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
++  ** This property is used by the algorithm for rolling back a journal file
++  ** after a crash.
++  **
++  ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
++  ** implemented by obtaining a write-lock on the entire 'shared byte
++  ** range'. Since all other locks require a read-lock on one of the bytes
++  ** within this range, this ensures that no other locks are held on the
++  ** database. 
++  **
++  ** The reason a single byte cannot be used instead of the 'shared byte
++  ** range' is that some versions of windows do not support read-locks. By
++  ** locking a random byte from a range, concurrent SHARED locks may exist
++  ** even if the locking primitive used is always a write-lock.
++  */
++  int rc = SQLITE_OK;
+   unixFile *pFile = (unixFile*)id;
++  unixInodeInfo *pInode;
++  struct flock lock;
++  int tErrno = 0;
+ 
+-  int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
+-  int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
++  assert( pFile );
++  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
++      azFileLock(eFileLock), azFileLock(pFile->eFileLock),
++      azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
+ 
+-  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
+-  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
+-      || (flags&0x0F)==SQLITE_SYNC_FULL
+-  );
++  /* If there is already a lock of this type or more restrictive on the
++  ** unixFile, do nothing. Don't use the end_lock: exit path, as
++  ** unixEnterMutex() hasn't been called yet.
++  */
++  if( pFile->eFileLock>=eFileLock ){
++    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
++            azFileLock(eFileLock)));
++    return SQLITE_OK;
++  }
+ 
+-  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
+-  ** line is to test that doing so does not cause any problems.
++  /* Make sure the locking sequence is correct.
++  **  (1) We never move from unlocked to anything higher than shared lock.
++  **  (2) SQLite never explicitly requests a pendig lock.
++  **  (3) A shared lock is always held when a reserve lock is requested.
+   */
+-  SimulateDiskfullError( return SQLITE_FULL );
++  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
++  assert( eFileLock!=PENDING_LOCK );
++  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
+ 
+-  assert( pFile );
+-  OSTRACE(("SYNC    %-3d\n", pFile->h));
+-  rc = full_fsync(pFile->h, isFullsync, isDataOnly);
+-  SimulateIOError( rc=1 );
+-  if( rc ){
+-    pFile->lastErrno = errno;
+-    return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
++  /* This mutex is needed because pFile->pInode is shared across threads
++  */
++  unixEnterMutex();
++  pInode = pFile->pInode;
++
++  /* If some thread using this PID has a lock via a different unixFile*
++  ** handle that precludes the requested lock, return BUSY.
++  */
++  if( (pFile->eFileLock!=pInode->eFileLock && 
++          (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
++  ){
++    rc = SQLITE_BUSY;
++    goto end_lock;
+   }
+ 
+-  /* Also fsync the directory containing the file if the DIRSYNC flag
+-  ** is set.  This is a one-time occurrence.  Many systems (examples: AIX)
+-  ** are unable to fsync a directory, so ignore errors on the fsync.
++  /* If a SHARED lock is requested, and some thread using this PID already
++  ** has a SHARED or RESERVED lock, then increment reference counts and
++  ** return SQLITE_OK.
+   */
+-  if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
+-    int dirfd;
+-    OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
+-            HAVE_FULLFSYNC, isFullsync));
+-    rc = osOpenDirectory(pFile->zPath, &dirfd);
+-    if( rc==SQLITE_OK && dirfd>=0 ){
+-      full_fsync(dirfd, 0, 0);
+-      robust_close(pFile, dirfd, __LINE__);
+-    }else if( rc==SQLITE_CANTOPEN ){
+-      rc = SQLITE_OK;
+-    }
+-    pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
++  if( eFileLock==SHARED_LOCK && 
++      (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
++    assert( eFileLock==SHARED_LOCK );
++    assert( pFile->eFileLock==0 );
++    assert( pInode->nShared>0 );
++    pFile->eFileLock = SHARED_LOCK;
++    pInode->nShared++;
++    pInode->nLock++;
++    goto end_lock;
+   }
+-  return rc;
+-}
+ 
+-/*
+-** Truncate an open file to a specified size
+-*/
+-static int unixTruncate(sqlite3_file *id, i64 nByte){
+-  unixFile *pFile = (unixFile *)id;
+-  int rc;
+-  assert( pFile );
+-  SimulateIOError( return SQLITE_IOERR_TRUNCATE );
+ 
+-  /* If the user has configured a chunk-size for this file, truncate the
+-  ** file so that it consists of an integer number of chunks (i.e. the
+-  ** actual file size after the operation may be larger than the requested
+-  ** size).
++  /* A PENDING lock is needed before acquiring a SHARED lock and before
++  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
++  ** be released.
+   */
+-  if( pFile->szChunk>0 ){
+-    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
++  lock.l_len = 1L;
++  lock.l_whence = SEEK_SET;
++  if( eFileLock==SHARED_LOCK 
++      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
++  ){
++    lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
++    lock.l_start = PENDING_BYTE;
++    if( unixFileLock(pFile, &lock) ){
++      tErrno = errno;
++      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
++      if( rc!=SQLITE_BUSY ){
++        pFile->lastErrno = tErrno;
++      }
++      goto end_lock;
++    }
+   }
+ 
+-  rc = robust_ftruncate(pFile->h, (off_t)nByte);
+-  if( rc ){
+-    pFile->lastErrno = errno;
+-    return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
+-  }else{
+-#ifdef SQLITE_DEBUG
+-    /* If we are doing a normal write to a database file (as opposed to
+-    ** doing a hot-journal rollback or a write to some file other than a
+-    ** normal database file) and we truncate the file to zero length,
+-    ** that effectively updates the change counter.  This might happen
+-    ** when restoring a database using the backup API from a zero-length
+-    ** source.
+-    */
+-    if( pFile->inNormalWrite && nByte==0 ){
+-      pFile->transCntrChng = 1;
++
++  /* If control gets to this point, then actually go ahead and make
++  ** operating system calls for the specified lock.
++  */
++  if( eFileLock==SHARED_LOCK ){
++    assert( pInode->nShared==0 );
++    assert( pInode->eFileLock==0 );
++    assert( rc==SQLITE_OK );
++
++    /* Now get the read-lock */
++    lock.l_start = SHARED_FIRST;
++    lock.l_len = SHARED_SIZE;
++    if( unixFileLock(pFile, &lock) ){
++      tErrno = errno;
++      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+     }
+-#endif
+ 
+-    /* If the file was just truncated to a size smaller than the currently
+-    ** mapped region, reduce the effective mapping size as well. SQLite will
+-    ** use read() and write() to access data beyond this point from now on.  
++    /* Drop the temporary PENDING lock */
++    lock.l_start = PENDING_BYTE;
++    lock.l_len = 1L;
++    lock.l_type = F_UNLCK;
++    if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
++      /* This could happen with a network mount */
++      tErrno = errno;
++      rc = SQLITE_IOERR_UNLOCK; 
++    }
++
++    if( rc ){
++      if( rc!=SQLITE_BUSY ){
++        pFile->lastErrno = tErrno;
++      }
++      goto end_lock;
++    }else{
++      pFile->eFileLock = SHARED_LOCK;
++      pInode->nLock++;
++      pInode->nShared = 1;
++    }
++  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
++    /* We are trying for an exclusive lock but another thread in this
++    ** same process is still holding a shared lock. */
++    rc = SQLITE_BUSY;
++  }else{
++    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
++    ** assumed that there is a SHARED or greater lock on the file
++    ** already.
+     */
+-    if( nByte<pFile->mmapSize ){
+-      pFile->mmapSize = nByte;
++    assert( 0!=pFile->eFileLock );
++    lock.l_type = F_WRLCK;
++
++    assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
++    if( eFileLock==RESERVED_LOCK ){
++      lock.l_start = RESERVED_BYTE;
++      lock.l_len = 1L;
++    }else{
++      lock.l_start = SHARED_FIRST;
++      lock.l_len = SHARED_SIZE;
+     }
+ 
+-    return SQLITE_OK;
++    if( unixFileLock(pFile, &lock) ){
++      tErrno = errno;
++      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
++      if( rc!=SQLITE_BUSY ){
++        pFile->lastErrno = tErrno;
++      }
++    }
+   }
+-}
++  
+ 
+-/*
+-** Determine the current size of a file in bytes
+-*/
+-static int unixFileSize(sqlite3_file *id, i64 *pSize){
+-  int rc;
+-  struct stat buf;
+-  assert( id );
+-  rc = osFstat(((unixFile*)id)->h, &buf);
+-  SimulateIOError( rc=1 );
+-  if( rc!=0 ){
+-    ((unixFile*)id)->lastErrno = errno;
+-    return SQLITE_IOERR_FSTAT;
++#ifdef SQLITE_DEBUG
++  /* Set up the transaction-counter change checking flags when
++  ** transitioning from a SHARED to a RESERVED lock.  The change
++  ** from SHARED to RESERVED marks the beginning of a normal
++  ** write operation (not a hot journal rollback).
++  */
++  if( rc==SQLITE_OK
++   && pFile->eFileLock<=SHARED_LOCK
++   && eFileLock==RESERVED_LOCK
++  ){
++    pFile->transCntrChng = 0;
++    pFile->dbUpdate = 0;
++    pFile->inNormalWrite = 1;
+   }
+-  *pSize = buf.st_size;
++#endif
+ 
+-  /* When opening a zero-size database, the findInodeInfo() procedure
+-  ** writes a single byte into that file in order to work around a bug
+-  ** in the OS-X msdos filesystem.  In order to avoid problems with upper
+-  ** layers, we need to report this file size as zero even though it is
+-  ** really 1.   Ticket #3260.
+-  */
+-  if( *pSize==1 ) *pSize = 0;
+ 
++  if( rc==SQLITE_OK ){
++    pFile->eFileLock = eFileLock;
++    pInode->eFileLock = eFileLock;
++  }else if( eFileLock==EXCLUSIVE_LOCK ){
++    pFile->eFileLock = PENDING_LOCK;
++    pInode->eFileLock = PENDING_LOCK;
++  }
+ 
+-  return SQLITE_OK;
++end_lock:
++  unixLeaveMutex();
++  OSTRACE(("LOCK    %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), 
++      rc==SQLITE_OK ? "ok" : "failed"));
++  return rc;
+ }
+ 
+-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+ /*
+-** Handler for proxy-locking file-control verbs.  Defined below in the
+-** proxying locking division.
++** Add the file descriptor used by file handle pFile to the corresponding
++** pUnused list.
+ */
+-static int proxyFileControl(sqlite3_file*,int,void*);
+-#endif
++static void setPendingFd(unixFile *pFile){
++  unixInodeInfo *pInode = pFile->pInode;
++  UnixUnusedFd *p = pFile->pUnused;
++  p->pNext = pInode->pUnused;
++  pInode->pUnused = p;
++  pFile->h = -1;
++  pFile->pUnused = 0;
++}
+ 
+-/* 
+-** This function is called to handle the SQLITE_FCNTL_SIZE_HINT 
+-** file-control operation.  Enlarge the database to nBytes in size
+-** (rounded up to the next chunk-size).  If the database is already
+-** nBytes or larger, this routine is a no-op.
++/*
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
++**
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
++** 
++** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
++** the byte range is divided into 2 parts and the first part is unlocked then
++** set to a read lock, then the other part is simply unlocked.  This works 
++** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to 
++** remove the write lock on a region when a read lock is set.
+ */
+-static int fcntlSizeHint(unixFile *pFile, i64 nByte){
+-  if( pFile->szChunk>0 ){
+-    i64 nSize;                    /* Required file size */
+-    struct stat buf;              /* Used to hold return values of fstat() */
+-   
+-    if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
++static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
++  unixFile *pFile = (unixFile*)id;
++  unixInodeInfo *pInode;
++  struct flock lock;
++  int rc = SQLITE_OK;
+ 
+-    nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
+-    if( nSize>(i64)buf.st_size ){
++  assert( pFile );
++  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
++      pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
++      getpid()));
+ 
+-#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+-      /* The code below is handling the return value of osFallocate() 
+-      ** correctly. posix_fallocate() is defined to "returns zero on success, 
+-      ** or an error number on  failure". See the manpage for details. */
+-      int err;
+-      do{
+-        err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
+-      }while( err==EINTR );
+-      if( err ) return SQLITE_IOERR_WRITE;
+-#else
+-      /* If the OS does not have posix_fallocate(), fake it. First use
+-      ** ftruncate() to set the file size, then write a single byte to
+-      ** the last byte in each block within the extended region. This
+-      ** is the same technique used by glibc to implement posix_fallocate()
+-      ** on systems that do not have a real fallocate() system call.
+-      */
+-      int nBlk = buf.st_blksize;  /* File-system block size */
+-      i64 iWrite;                 /* Next offset to write to */
++  assert( eFileLock<=SHARED_LOCK );
++  if( pFile->eFileLock<=eFileLock ){
++    return SQLITE_OK;
++  }
++  unixEnterMutex();
++  pInode = pFile->pInode;
++  assert( pInode->nShared!=0 );
++  if( pFile->eFileLock>SHARED_LOCK ){
++    assert( pInode->eFileLock==pFile->eFileLock );
+ 
+-      if( robust_ftruncate(pFile->h, nSize) ){
+-        pFile->lastErrno = errno;
+-        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
+-      }
+-      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
+-      while( iWrite<nSize ){
+-        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
+-        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
+-        iWrite += nBlk;
++#ifdef SQLITE_DEBUG
++    /* When reducing a lock such that other processes can start
++    ** reading the database file again, make sure that the
++    ** transaction counter was updated if any part of the database
++    ** file changed.  If the transaction counter is not updated,
++    ** other connections to the same file might not realize that
++    ** the file has changed and hence might not know to flush their
++    ** cache.  The use of a stale cache can lead to database corruption.
++    */
++    pFile->inNormalWrite = 0;
++#endif
++
++    /* downgrading to a shared lock on NFS involves clearing the write lock
++    ** before establishing the readlock - to avoid a race condition we downgrade
++    ** the lock in 2 blocks, so that part of the range will be covered by a 
++    ** write lock until the rest is covered by a read lock:
++    **  1:   [WWWWW]
++    **  2:   [....W]
++    **  3:   [RRRRW]
++    **  4:   [RRRR.]
++    */
++    if( eFileLock==SHARED_LOCK ){
++
++#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
++      (void)handleNFSUnlock;
++      assert( handleNFSUnlock==0 );
++#endif
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++      if( handleNFSUnlock ){
++        int tErrno;               /* Error code from system call errors */
++        off_t divSize = SHARED_SIZE - 1;
++        
++        lock.l_type = F_UNLCK;
++        lock.l_whence = SEEK_SET;
++        lock.l_start = SHARED_FIRST;
++        lock.l_len = divSize;
++        if( unixFileLock(pFile, &lock)==(-1) ){
++          tErrno = errno;
++          rc = SQLITE_IOERR_UNLOCK;
++          if( IS_LOCK_ERROR(rc) ){
++            pFile->lastErrno = tErrno;
++          }
++          goto end_unlock;
++        }
++        lock.l_type = F_RDLCK;
++        lock.l_whence = SEEK_SET;
++        lock.l_start = SHARED_FIRST;
++        lock.l_len = divSize;
++        if( unixFileLock(pFile, &lock)==(-1) ){
++          tErrno = errno;
++          rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
++          if( IS_LOCK_ERROR(rc) ){
++            pFile->lastErrno = tErrno;
++          }
++          goto end_unlock;
++        }
++        lock.l_type = F_UNLCK;
++        lock.l_whence = SEEK_SET;
++        lock.l_start = SHARED_FIRST+divSize;
++        lock.l_len = SHARED_SIZE-divSize;
++        if( unixFileLock(pFile, &lock)==(-1) ){
++          tErrno = errno;
++          rc = SQLITE_IOERR_UNLOCK;
++          if( IS_LOCK_ERROR(rc) ){
++            pFile->lastErrno = tErrno;
++          }
++          goto end_unlock;
++        }
++      }else
++#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
++      {
++        lock.l_type = F_RDLCK;
++        lock.l_whence = SEEK_SET;
++        lock.l_start = SHARED_FIRST;
++        lock.l_len = SHARED_SIZE;
++        if( unixFileLock(pFile, &lock) ){
++          /* In theory, the call to unixFileLock() cannot fail because another
++          ** process is holding an incompatible lock. If it does, this 
++          ** indicates that the other process is not following the locking
++          ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
++          ** SQLITE_BUSY would confuse the upper layer (in practice it causes 
++          ** an assert to fail). */ 
++          rc = SQLITE_IOERR_RDLOCK;
++          pFile->lastErrno = errno;
++          goto end_unlock;
++        }
+       }
+-#endif
++    }
++    lock.l_type = F_UNLCK;
++    lock.l_whence = SEEK_SET;
++    lock.l_start = PENDING_BYTE;
++    lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
++    if( unixFileLock(pFile, &lock)==0 ){
++      pInode->eFileLock = SHARED_LOCK;
++    }else{
++      rc = SQLITE_IOERR_UNLOCK;
++      pFile->lastErrno = errno;
++      goto end_unlock;
+     }
+   }
+-
+-  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
+-    int rc;
+-    if( pFile->szChunk<=0 ){
+-      if( robust_ftruncate(pFile->h, nByte) ){
++  if( eFileLock==NO_LOCK ){
++    /* Decrement the shared lock counter.  Release the lock using an
++    ** OS call only when all threads in this same process have released
++    ** the lock.
++    */
++    pInode->nShared--;
++    if( pInode->nShared==0 ){
++      lock.l_type = F_UNLCK;
++      lock.l_whence = SEEK_SET;
++      lock.l_start = lock.l_len = 0L;
++      if( unixFileLock(pFile, &lock)==0 ){
++        pInode->eFileLock = NO_LOCK;
++      }else{
++        rc = SQLITE_IOERR_UNLOCK;
+         pFile->lastErrno = errno;
+-        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
++        pInode->eFileLock = NO_LOCK;
++        pFile->eFileLock = NO_LOCK;
+       }
+     }
+ 
+-    rc = unixMapfile(pFile, nByte);
+-    return rc;
++    /* Decrement the count of locks against this same file.  When the
++    ** count reaches zero, close any other file descriptors whose close
++    ** was deferred because of outstanding locks.
++    */
++    pInode->nLock--;
++    assert( pInode->nLock>=0 );
++    if( pInode->nLock==0 ){
++      closePendingFds(pFile);
++    }
+   }
+ 
+-  return SQLITE_OK;
++end_unlock:
++  unixLeaveMutex();
++  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
++  return rc;
+ }
+ 
+ /*
+-** If *pArg is inititially negative then this is a query.  Set *pArg to
+-** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
+ **
+-** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
+ */
+-static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
+-  if( *pArg<0 ){
+-    *pArg = (pFile->ctrlFlags & mask)!=0;
+-  }else if( (*pArg)==0 ){
+-    pFile->ctrlFlags &= ~mask;
+-  }else{
+-    pFile->ctrlFlags |= mask;
+-  }
++static int unixUnlock(sqlite3_file *id, int eFileLock){
++  assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
++  return posixUnlock(id, eFileLock, 0);
+ }
+ 
+-/* Forward declaration */
+-static int unixGetTempname(int nBuf, char *zBuf);
++static int unixMapfile(unixFile *pFd, i64 nByte);
++static void unixUnmapfile(unixFile *pFd);
+ 
+ /*
+-** Information and control of an open file handle.
++** This function performs the parts of the "close file" operation 
++** common to all locking schemes. It closes the directory and file
++** handles, if they are valid, and sets all fields of the unixFile
++** structure to 0.
++**
++** It is *not* necessary to hold the mutex when this routine is called,
++** even on VxWorks.  A mutex will be acquired on VxWorks by the
++** vxworksReleaseFileId() routine.
+ */
+-static int unixFileControl(sqlite3_file *id, int op, void *pArg){
++static int closeUnixFile(sqlite3_file *id){
+   unixFile *pFile = (unixFile*)id;
+-  switch( op ){
+-    case SQLITE_FCNTL_LOCKSTATE: {
+-      *(int*)pArg = pFile->eFileLock;
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_LAST_ERRNO: {
+-      *(int*)pArg = pFile->lastErrno;
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_CHUNK_SIZE: {
+-      pFile->szChunk = *(int *)pArg;
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_SIZE_HINT: {
+-      int rc;
+-      SimulateIOErrorBenign(1);
+-      rc = fcntlSizeHint(pFile, *(i64 *)pArg);
+-      SimulateIOErrorBenign(0);
+-      return rc;
+-    }
+-    case SQLITE_FCNTL_PERSIST_WAL: {
+-      unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
+-      unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_VFSNAME: {
+-      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_TEMPFILENAME: {
+-      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+-      if( zTFile ){
+-        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
+-        *(char**)pArg = zTFile;
+-      }
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_MMAP_SIZE: {
+-      i64 newLimit = *(i64*)pArg;
+-      if( newLimit>sqlite3GlobalConfig.mxMmap ){
+-        newLimit = sqlite3GlobalConfig.mxMmap;
+-      }
+-      *(i64*)pArg = pFile->mmapSizeMax;
+-      if( newLimit>=0 ){
+-        pFile->mmapSizeMax = newLimit;
+-        if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
+-      }
+-      return SQLITE_OK;
+-    }
+-#ifdef SQLITE_DEBUG
+-    /* The pager calls this method to signal that it has done
+-    ** a rollback and that the database is therefore unchanged and
+-    ** it hence it is OK for the transaction change counter to be
+-    ** unchanged.
+-    */
+-    case SQLITE_FCNTL_DB_UNCHANGED: {
+-      ((unixFile*)id)->dbUpdate = 0;
+-      return SQLITE_OK;
+-    }
+-#endif
+-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+-    case SQLITE_SET_LOCKPROXYFILE:
+-    case SQLITE_GET_LOCKPROXYFILE: {
+-      return proxyFileControl(id,op,pArg);
++  unixUnmapfile(pFile);
++  if( pFile->h>=0 ){
++    robust_close(pFile, pFile->h, __LINE__);
++    pFile->h = -1;
++  }
++#if OS_VXWORKS
++  if( pFile->pId ){
++    if( pFile->ctrlFlags & UNIXFILE_DELETE ){
++      osUnlink(pFile->pId->zCanonicalName);
+     }
+-#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
++    vxworksReleaseFileId(pFile->pId);
++    pFile->pId = 0;
+   }
+-  return SQLITE_NOTFOUND;
++#endif
++  OSTRACE(("CLOSE   %-3d\n", pFile->h));
++  OpenCounter(-1);
++  sqlite3_free(pFile->pUnused);
++  memset(pFile, 0, sizeof(unixFile));
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Return the sector size in bytes of the underlying block device for
+-** the specified file. This is almost always 512 bytes, but may be
+-** larger for some devices.
+-**
+-** SQLite code assumes this function cannot fail. It also assumes that
+-** if two files are created in the same file-system directory (i.e.
+-** a database and its journal file) that the sector size will be the
+-** same for both.
++** Close a file.
+ */
+-#ifndef __QNXNTO__ 
+-static int unixSectorSize(sqlite3_file *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  return SQLITE_DEFAULT_SECTOR_SIZE;
++static int unixClose(sqlite3_file *id){
++  int rc = SQLITE_OK;
++  unixFile *pFile = (unixFile *)id;
++  verifyDbFile(pFile);
++  unixUnlock(id, NO_LOCK);
++  unixEnterMutex();
++
++  /* unixFile.pInode is always valid here. Otherwise, a different close
++  ** routine (e.g. nolockClose()) would be called instead.
++  */
++  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
++  if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
++    /* If there are outstanding locks, do not actually close the file just
++    ** yet because that would clear those locks.  Instead, add the file
++    ** descriptor to pInode->pUnused list.  It will be automatically closed 
++    ** when the last lock is cleared.
++    */
++    setPendingFd(pFile);
++  }
++  releaseInodeInfo(pFile);
++  rc = closeUnixFile(id);
++  unixLeaveMutex();
++  return rc;
+ }
+-#endif
+ 
+-/*
+-** The following version of unixSectorSize() is optimized for QNX.
++/************** End of the posix advisory lock implementation *****************
++******************************************************************************/
++
++/******************************************************************************
++****************************** No-op Locking **********************************
++**
++** Of the various locking implementations available, this is by far the
++** simplest:  locking is ignored.  No attempt is made to lock the database
++** file for reading or writing.
++**
++** This locking mode is appropriate for use on read-only databases
++** (ex: databases that are burned into CD-ROM, for example.)  It can
++** also be used if the application employs some external mechanism to
++** prevent simultaneous access of the same database by two or more
++** database connections.  But there is a serious risk of database
++** corruption if this locking mode is used in situations where multiple
++** database connections are accessing the same database file at the same
++** time and one or more of those connections are writing.
+ */
+-#ifdef __QNXNTO__
+-#include <sys/dcmd_blk.h>
+-#include <sys/statvfs.h>
+-static int unixSectorSize(sqlite3_file *id){
+-  unixFile *pFile = (unixFile*)id;
+-  if( pFile->sectorSize == 0 ){
+-    struct statvfs fsInfo;
+-       
+-    /* Set defaults for non-supported filesystems */
+-    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+-    pFile->deviceCharacteristics = 0;
+-    if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
+-      return pFile->sectorSize;
+-    }
+ 
+-    if( !strcmp(fsInfo.f_basetype, "tmp") ) {
+-      pFile->sectorSize = fsInfo.f_bsize;
+-      pFile->deviceCharacteristics =
+-        SQLITE_IOCAP_ATOMIC4K |       /* All ram filesystem writes are atomic */
+-        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+-                                      ** the write succeeds */
+-        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+-                                      ** so it is ordered */
+-        0;
+-    }else if( strstr(fsInfo.f_basetype, "etfs") ){
+-      pFile->sectorSize = fsInfo.f_bsize;
+-      pFile->deviceCharacteristics =
+-        /* etfs cluster size writes are atomic */
+-        (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
+-        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+-                                      ** the write succeeds */
+-        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+-                                      ** so it is ordered */
+-        0;
+-    }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
+-      pFile->sectorSize = fsInfo.f_bsize;
+-      pFile->deviceCharacteristics =
+-        SQLITE_IOCAP_ATOMIC |         /* All filesystem writes are atomic */
+-        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+-                                      ** the write succeeds */
+-        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+-                                      ** so it is ordered */
+-        0;
+-    }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
+-      pFile->sectorSize = fsInfo.f_bsize;
+-      pFile->deviceCharacteristics =
+-        /* full bitset of atomics from max sector size and smaller */
+-        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+-        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+-                                      ** so it is ordered */
+-        0;
+-    }else if( strstr(fsInfo.f_basetype, "dos") ){
+-      pFile->sectorSize = fsInfo.f_bsize;
+-      pFile->deviceCharacteristics =
+-        /* full bitset of atomics from max sector size and smaller */
+-        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+-        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+-                                      ** so it is ordered */
+-        0;
+-    }else{
+-      pFile->deviceCharacteristics =
+-        SQLITE_IOCAP_ATOMIC512 |      /* blocks are atomic */
+-        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+-                                      ** the write succeeds */
+-        0;
+-    }
+-  }
+-  /* Last chance verification.  If the sector size isn't a multiple of 512
+-  ** then it isn't valid.*/
+-  if( pFile->sectorSize % 512 != 0 ){
+-    pFile->deviceCharacteristics = 0;
+-    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+-  }
+-  return pFile->sectorSize;
++static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
++  UNUSED_PARAMETER(NotUsed);
++  *pResOut = 0;
++  return SQLITE_OK;
++}
++static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
++  UNUSED_PARAMETER2(NotUsed, NotUsed2);
++  return SQLITE_OK;
++}
++static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
++  UNUSED_PARAMETER2(NotUsed, NotUsed2);
++  return SQLITE_OK;
+ }
+-#endif /* __QNXNTO__ */
+ 
+ /*
+-** Return the device characteristics for the file.
+-**
+-** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
+-** However, that choice is contraversial since technically the underlying
+-** file system does not always provide powersafe overwrites.  (In other
+-** words, after a power-loss event, parts of the file that were never
+-** written might end up being altered.)  However, non-PSOW behavior is very,
+-** very rare.  And asserting PSOW makes a large reduction in the amount
+-** of required I/O for journaling, since a lot of padding is eliminated.
+-**  Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
+-** available to turn it off and URI query parameter available to turn it off.
++** Close the file.
+ */
+-static int unixDeviceCharacteristics(sqlite3_file *id){
+-  unixFile *p = (unixFile*)id;
+-  int rc = 0;
+-#ifdef __QNXNTO__
+-  if( p->sectorSize==0 ) unixSectorSize(id);
+-  rc = p->deviceCharacteristics;
+-#endif
+-  if( p->ctrlFlags & UNIXFILE_PSOW ){
+-    rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
+-  }
+-  return rc;
++static int nolockClose(sqlite3_file *id) {
++  return closeUnixFile(id);
+ }
+ 
+-#ifndef SQLITE_OMIT_WAL
+-
++/******************* End of the no-op lock implementation *********************
++******************************************************************************/
+ 
+-/*
+-** Object used to represent an shared memory buffer.  
+-**
+-** When multiple threads all reference the same wal-index, each thread
+-** has its own unixShm object, but they all point to a single instance
+-** of this unixShmNode object.  In other words, each wal-index is opened
+-** only once per process.
+-**
+-** Each unixShmNode object is connected to a single unixInodeInfo object.
+-** We could coalesce this object into unixInodeInfo, but that would mean
+-** every open file that does not use shared memory (in other words, most
+-** open files) would have to carry around this extra information.  So
+-** the unixInodeInfo object contains a pointer to this unixShmNode object
+-** and the unixShmNode object is created only when needed.
+-**
+-** unixMutexHeld() must be true when creating or destroying
+-** this object or while reading or writing the following fields:
+-**
+-**      nRef
++/******************************************************************************
++************************* Begin dot-file Locking ******************************
+ **
+-** The following fields are read-only after the object is created:
+-** 
+-**      fid
+-**      zFilename
++** The dotfile locking implementation uses the existence of separate lock
++** files (really a directory) to control access to the database.  This works
++** on just about every filesystem imaginable.  But there are serious downsides:
+ **
+-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
+-** unixMutexHeld() is true when reading or writing any other field
+-** in this structure.
+-*/
+-struct unixShmNode {
+-  unixInodeInfo *pInode;     /* unixInodeInfo that owns this SHM node */
+-  sqlite3_mutex *mutex;      /* Mutex to access this object */
+-  char *zFilename;           /* Name of the mmapped file */
+-  int h;                     /* Open file descriptor */
+-  int szRegion;              /* Size of shared-memory regions */
+-  u16 nRegion;               /* Size of array apRegion */
+-  u8 isReadonly;             /* True if read-only */
+-  char **apRegion;           /* Array of mapped shared-memory regions */
+-  int nRef;                  /* Number of unixShm objects pointing to this */
+-  unixShm *pFirst;           /* All unixShm objects pointing to this */
+-#ifdef SQLITE_DEBUG
+-  u8 exclMask;               /* Mask of exclusive locks held */
+-  u8 sharedMask;             /* Mask of shared locks held */
+-  u8 nextShmId;              /* Next available unixShm.id value */
+-#endif
+-};
+-
+-/*
+-** Structure used internally by this VFS to record the state of an
+-** open shared memory connection.
++**    (1)  There is zero concurrency.  A single reader blocks all other
++**         connections from reading or writing the database.
+ **
+-** The following fields are initialized when this object is created and
+-** are read-only thereafter:
++**    (2)  An application crash or power loss can leave stale lock files
++**         sitting around that need to be cleared manually.
+ **
+-**    unixShm.pFile
+-**    unixShm.id
++** Nevertheless, a dotlock is an appropriate locking mode for use if no
++** other locking strategy is available.
+ **
+-** All other fields are read/write.  The unixShm.pFile->mutex must be held
+-** while accessing any read/write fields.
++** Dotfile locking works by creating a subdirectory in the same directory as
++** the database and with the same name but with a ".lock" extension added.
++** The existence of a lock directory implies an EXCLUSIVE lock.  All other
++** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
+ */
+-struct unixShm {
+-  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
+-  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
+-  u8 hasMutex;               /* True if holding the unixShmNode mutex */
+-  u8 id;                     /* Id of this connection within its unixShmNode */
+-  u16 sharedMask;            /* Mask of shared locks held */
+-  u16 exclMask;              /* Mask of exclusive locks held */
+-};
+ 
+ /*
+-** Constants used for locking
++** The file suffix added to the data base filename in order to create the
++** lock directory.
+ */
+-#define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
+-#define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
++#define DOTLOCK_SUFFIX ".lock"
+ 
+ /*
+-** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, set *pResOut
++** to a non-zero value otherwise *pResOut is set to zero.  The return value
++** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+ **
+-** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
+-** otherwise.
++** In dotfile locking, either a lock exists or it does not.  So in this
++** variation of CheckReservedLock(), *pResOut is set to true if any lock
++** is held on the file and false if the file is unlocked.
+ */
+-static int unixShmSystemLock(
+-  unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
+-  int lockType,          /* F_UNLCK, F_RDLCK, or F_WRLCK */
+-  int ofst,              /* First byte of the locking range */
+-  int n                  /* Number of bytes to lock */
+-){
+-  struct flock f;       /* The posix advisory locking structure */
+-  int rc = SQLITE_OK;   /* Result code form fcntl() */
+-
+-  /* Access to the unixShmNode object is serialized by the caller */
+-  assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
+-
+-  /* Shared locks never span more than one byte */
+-  assert( n==1 || lockType!=F_RDLCK );
+-
+-  /* Locks are within range */
+-  assert( n>=1 && n<SQLITE_SHM_NLOCK );
+-
+-  if( pShmNode->h>=0 ){
+-    /* Initialize the locking parameters */
+-    memset(&f, 0, sizeof(f));
+-    f.l_type = lockType;
+-    f.l_whence = SEEK_SET;
+-    f.l_start = ofst;
+-    f.l_len = n;
+-
+-    rc = osFcntl(pShmNode->h, F_SETLK, &f);
+-    rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
+-  }
+-
+-  /* Update the global lock state and do debug tracing */
+-#ifdef SQLITE_DEBUG
+-  { u16 mask;
+-  OSTRACE(("SHM-LOCK "));
+-  mask = (1<<(ofst+n)) - (1<<ofst);
+-  if( rc==SQLITE_OK ){
+-    if( lockType==F_UNLCK ){
+-      OSTRACE(("unlock %d ok", ofst));
+-      pShmNode->exclMask &= ~mask;
+-      pShmNode->sharedMask &= ~mask;
+-    }else if( lockType==F_RDLCK ){
+-      OSTRACE(("read-lock %d ok", ofst));
+-      pShmNode->exclMask &= ~mask;
+-      pShmNode->sharedMask |= mask;
+-    }else{
+-      assert( lockType==F_WRLCK );
+-      OSTRACE(("write-lock %d ok", ofst));
+-      pShmNode->exclMask |= mask;
+-      pShmNode->sharedMask &= ~mask;
+-    }
+-  }else{
+-    if( lockType==F_UNLCK ){
+-      OSTRACE(("unlock %d failed", ofst));
+-    }else if( lockType==F_RDLCK ){
+-      OSTRACE(("read-lock failed"));
+-    }else{
+-      assert( lockType==F_WRLCK );
+-      OSTRACE(("write-lock %d failed", ofst));
+-    }
+-  }
+-  OSTRACE((" - afterwards %03x,%03x\n",
+-           pShmNode->sharedMask, pShmNode->exclMask));
+-  }
+-#endif
+-
+-  return rc;        
+-}
++static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
++  int rc = SQLITE_OK;
++  int reserved = 0;
++  unixFile *pFile = (unixFile*)id;
+ 
++  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
++  
++  assert( pFile );
+ 
+-/*
+-** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
+-**
+-** This is not a VFS shared-memory method; it is a utility function called
+-** by VFS shared-memory methods.
+-*/
+-static void unixShmPurge(unixFile *pFd){
+-  unixShmNode *p = pFd->pInode->pShmNode;
+-  assert( unixMutexHeld() );
+-  if( p && p->nRef==0 ){
+-    int i;
+-    assert( p->pInode==pFd->pInode );
+-    sqlite3_mutex_free(p->mutex);
+-    for(i=0; i<p->nRegion; i++){
+-      if( p->h>=0 ){
+-        osMunmap(p->apRegion[i], p->szRegion);
+-      }else{
+-        sqlite3_free(p->apRegion[i]);
+-      }
+-    }
+-    sqlite3_free(p->apRegion);
+-    if( p->h>=0 ){
+-      robust_close(pFd, p->h, __LINE__);
+-      p->h = -1;
+-    }
+-    p->pInode->pShmNode = 0;
+-    sqlite3_free(p);
++  /* Check if a thread in this process holds such a lock */
++  if( pFile->eFileLock>SHARED_LOCK ){
++    /* Either this connection or some other connection in the same process
++    ** holds a lock on the file.  No need to check further. */
++    reserved = 1;
++  }else{
++    /* The lock is held if and only if the lockfile exists */
++    const char *zLockFile = (const char*)pFile->lockingContext;
++    reserved = osAccess(zLockFile, 0)==0;
+   }
++  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
++  *pResOut = reserved;
++  return rc;
+ }
+ 
+ /*
+-** Open a shared-memory area associated with open database file pDbFd.  
+-** This particular implementation uses mmapped files.
++** Lock the file with the lock specified by parameter eFileLock - one
++** of the following:
+ **
+-** The file used to implement shared-memory is in the same directory
+-** as the open database file and has the same name as the open database
+-** file with the "-shm" suffix added.  For example, if the database file
+-** is "/home/user1/config.db" then the file that is created and mmapped
+-** for shared memory will be called "/home/user1/config.db-shm".  
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
+ **
+-** Another approach to is to use files in /dev/shm or /dev/tmp or an
+-** some other tmpfs mount. But if a file in a different directory
+-** from the database file is used, then differing access permissions
+-** or a chroot() might cause two different processes on the same
+-** database to end up using different files for shared memory - 
+-** meaning that their memory would not really be shared - resulting
+-** in database corruption.  Nevertheless, this tmpfs file usage
+-** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
+-** or the equivalent.  The use of the SQLITE_SHM_DIRECTORY compile-time
+-** option results in an incompatible build of SQLite;  builds of SQLite
+-** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
+-** same database file at the same time, database corruption will likely
+-** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
+-** "unsupported" and may go away in a future SQLite release.
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
+ **
+-** When opening a new shared-memory file, if no other instances of that
+-** file are currently open, in this process or in other processes, then
+-** the file must be truncated to zero length or have its header cleared.
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
+ **
+-** If the original database file (pDbFd) is using the "unix-excl" VFS
+-** that means that an exclusive lock is held on the database file and
+-** that no other processes are able to read or write the database.  In
+-** that case, we do not really need shared memory.  No shared memory
+-** file is created.  The shared memory will be simulated with heap memory.
++** This routine will only increase a lock.  Use the sqlite3OsUnlock()
++** routine to lower a locking level.
++**
++** With dotfile locking, we really only support state (4): EXCLUSIVE.
++** But we track the other locking levels internally.
+ */
+-static int unixOpenSharedMemory(unixFile *pDbFd){
+-  struct unixShm *p = 0;          /* The connection to be opened */
+-  struct unixShmNode *pShmNode;   /* The underlying mmapped file */
+-  int rc;                         /* Result code */
+-  unixInodeInfo *pInode;          /* The inode of fd */
+-  char *zShmFilename;             /* Name of the file used for SHM */
+-  int nShmFilename;               /* Size of the SHM filename in bytes */
++static int dotlockLock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  char *zLockFile = (char *)pFile->lockingContext;
++  int rc = SQLITE_OK;
+ 
+-  /* Allocate space for the new unixShm object. */
+-  p = sqlite3_malloc( sizeof(*p) );
+-  if( p==0 ) return SQLITE_NOMEM;
+-  memset(p, 0, sizeof(*p));
+-  assert( pDbFd->pShm==0 );
+ 
+-  /* Check to see if a unixShmNode object already exists. Reuse an existing
+-  ** one if present. Create a new one if necessary.
++  /* If we have any lock, then the lock file already exists.  All we have
++  ** to do is adjust our internal record of the lock level.
+   */
+-  unixEnterMutex();
+-  pInode = pDbFd->pInode;
+-  pShmNode = pInode->pShmNode;
+-  if( pShmNode==0 ){
+-    struct stat sStat;                 /* fstat() info for database file */
+-
+-    /* Call fstat() to figure out the permissions on the database file. If
+-    ** a new *-shm file is created, an attempt will be made to create it
+-    ** with the same permissions.
+-    */
+-    if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
+-      rc = SQLITE_IOERR_FSTAT;
+-      goto shm_open_err;
+-    }
+-
+-#ifdef SQLITE_SHM_DIRECTORY
+-    nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
+-#else
+-    nShmFilename = 6 + (int)strlen(pDbFd->zPath);
+-#endif
+-    pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
+-    if( pShmNode==0 ){
+-      rc = SQLITE_NOMEM;
+-      goto shm_open_err;
+-    }
+-    memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
+-    zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
+-#ifdef SQLITE_SHM_DIRECTORY
+-    sqlite3_snprintf(nShmFilename, zShmFilename, 
+-                     SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
+-                     (u32)sStat.st_ino, (u32)sStat.st_dev);
++  if( pFile->eFileLock > NO_LOCK ){
++    pFile->eFileLock = eFileLock;
++    /* Always update the timestamp on the old file */
++#ifdef HAVE_UTIME
++    utime(zLockFile, NULL);
+ #else
+-    sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
+-    sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
++    utimes(zLockFile, NULL);
+ #endif
+-    pShmNode->h = -1;
+-    pDbFd->pInode->pShmNode = pShmNode;
+-    pShmNode->pInode = pDbFd->pInode;
+-    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+-    if( pShmNode->mutex==0 ){
+-      rc = SQLITE_NOMEM;
+-      goto shm_open_err;
+-    }
+-
+-    if( pInode->bProcessLock==0 ){
+-      int openFlags = O_RDWR | O_CREAT;
+-      if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
+-        openFlags = O_RDONLY;
+-        pShmNode->isReadonly = 1;
+-      }
+-      pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
+-      if( pShmNode->h<0 ){
+-        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
+-        goto shm_open_err;
+-      }
+-
+-      /* If this process is running as root, make sure that the SHM file
+-      ** is owned by the same user that owns the original database.  Otherwise,
+-      ** the original owner will not be able to connect.
+-      */
+-      osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
++    return SQLITE_OK;
++  }
+   
+-      /* Check to see if another process is holding the dead-man switch.
+-      ** If not, truncate the file to zero length. 
+-      */
+-      rc = SQLITE_OK;
+-      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
+-        if( robust_ftruncate(pShmNode->h, 0) ){
+-          rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
+-        }
+-      }
+-      if( rc==SQLITE_OK ){
+-        rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
++  /* grab an exclusive lock */
++  rc = osMkdir(zLockFile, 0777);
++  if( rc<0 ){
++    /* failed to open/create the lock directory */
++    int tErrno = errno;
++    if( EEXIST == tErrno ){
++      rc = SQLITE_BUSY;
++    } else {
++      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
++      if( IS_LOCK_ERROR(rc) ){
++        pFile->lastErrno = tErrno;
+       }
+-      if( rc ) goto shm_open_err;
+     }
+-  }
+-
+-  /* Make the new connection a child of the unixShmNode */
+-  p->pShmNode = pShmNode;
+-#ifdef SQLITE_DEBUG
+-  p->id = pShmNode->nextShmId++;
+-#endif
+-  pShmNode->nRef++;
+-  pDbFd->pShm = p;
+-  unixLeaveMutex();
+-
+-  /* The reference count on pShmNode has already been incremented under
+-  ** the cover of the unixEnterMutex() mutex and the pointer from the
+-  ** new (struct unixShm) object to the pShmNode has been set. All that is
+-  ** left to do is to link the new object into the linked list starting
+-  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex 
+-  ** mutex.
+-  */
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  p->pNext = pShmNode->pFirst;
+-  pShmNode->pFirst = p;
+-  sqlite3_mutex_leave(pShmNode->mutex);
+-  return SQLITE_OK;
+-
+-  /* Jump here on any error */
+-shm_open_err:
+-  unixShmPurge(pDbFd);       /* This call frees pShmNode if required */
+-  sqlite3_free(p);
+-  unixLeaveMutex();
++    return rc;
++  } 
++  
++  /* got it, set the type and return ok */
++  pFile->eFileLock = eFileLock;
+   return rc;
+ }
+ 
+ /*
+-** This function is called to obtain a pointer to region iRegion of the 
+-** shared-memory associated with the database file fd. Shared-memory regions 
+-** are numbered starting from zero. Each shared-memory region is szRegion 
+-** bytes in size.
+-**
+-** If an error occurs, an error code is returned and *pp is set to NULL.
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
+ **
+-** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
+-** region has not been allocated (by any client, including one running in a
+-** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
+-** bExtend is non-zero and the requested shared-memory region has not yet 
+-** been allocated, it is allocated by this function.
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
+ **
+-** If the shared-memory region has already been allocated or is allocated by
+-** this call as described above, then it is mapped into this processes 
+-** address space (if it is not already), *pp is set to point to the mapped 
+-** memory and SQLITE_OK returned.
++** When the locking level reaches NO_LOCK, delete the lock file.
+ */
+-static int unixShmMap(
+-  sqlite3_file *fd,               /* Handle open on database file */
+-  int iRegion,                    /* Region to retrieve */
+-  int szRegion,                   /* Size of regions */
+-  int bExtend,                    /* True to extend file if necessary */
+-  void volatile **pp              /* OUT: Mapped memory */
+-){
+-  unixFile *pDbFd = (unixFile*)fd;
+-  unixShm *p;
+-  unixShmNode *pShmNode;
+-  int rc = SQLITE_OK;
++static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  char *zLockFile = (char *)pFile->lockingContext;
++  int rc;
+ 
+-  /* If the shared-memory file has not yet been opened, open it now. */
+-  if( pDbFd->pShm==0 ){
+-    rc = unixOpenSharedMemory(pDbFd);
+-    if( rc!=SQLITE_OK ) return rc;
++  assert( pFile );
++  OSTRACE(("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
++           pFile->eFileLock, getpid()));
++  assert( eFileLock<=SHARED_LOCK );
++  
++  /* no-op if possible */
++  if( pFile->eFileLock==eFileLock ){
++    return SQLITE_OK;
+   }
+ 
+-  p = pDbFd->pShm;
+-  pShmNode = p->pShmNode;
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+-  assert( pShmNode->pInode==pDbFd->pInode );
+-  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
+-  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+-
+-  if( pShmNode->nRegion<=iRegion ){
+-    char **apNew;                      /* New apRegion[] array */
+-    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
+-    struct stat sStat;                 /* Used by fstat() */
+-
+-    pShmNode->szRegion = szRegion;
+-
+-    if( pShmNode->h>=0 ){
+-      /* The requested region is not mapped into this processes address space.
+-      ** Check to see if it has been allocated (i.e. if the wal-index file is
+-      ** large enough to contain the requested region).
+-      */
+-      if( osFstat(pShmNode->h, &sStat) ){
+-        rc = SQLITE_IOERR_SHMSIZE;
+-        goto shmpage_out;
+-      }
++  /* To downgrade to shared, simply update our internal notion of the
++  ** lock state.  No need to mess with the file on disk.
++  */
++  if( eFileLock==SHARED_LOCK ){
++    pFile->eFileLock = SHARED_LOCK;
++    return SQLITE_OK;
++  }
+   
+-      if( sStat.st_size<nByte ){
+-        /* The requested memory region does not exist. If bExtend is set to
+-        ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
+-        */
+-        if( !bExtend ){
+-          goto shmpage_out;
+-        }
+-
+-        /* Alternatively, if bExtend is true, extend the file. Do this by
+-        ** writing a single byte to the end of each (OS) page being
+-        ** allocated or extended. Technically, we need only write to the
+-        ** last page in order to extend the file. But writing to all new
+-        ** pages forces the OS to allocate them immediately, which reduces
+-        ** the chances of SIGBUS while accessing the mapped region later on.
+-        */
+-        else{
+-          static const int pgsz = 4096;
+-          int iPg;
+-
+-          /* Write to the last byte of each newly allocated or extended page */
+-          assert( (nByte % pgsz)==0 );
+-          for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
+-            if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
+-              const char *zFile = pShmNode->zFilename;
+-              rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
+-              goto shmpage_out;
+-            }
+-          }
+-        }
+-      }
+-    }
+-
+-    /* Map the requested memory region into this processes address space. */
+-    apNew = (char **)sqlite3_realloc(
+-        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
+-    );
+-    if( !apNew ){
+-      rc = SQLITE_IOERR_NOMEM;
+-      goto shmpage_out;
++  /* To fully unlock the database, delete the lock file */
++  assert( eFileLock==NO_LOCK );
++  rc = osRmdir(zLockFile);
++  if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
++  if( rc<0 ){
++    int tErrno = errno;
++    rc = 0;
++    if( ENOENT != tErrno ){
++      rc = SQLITE_IOERR_UNLOCK;
+     }
+-    pShmNode->apRegion = apNew;
+-    while(pShmNode->nRegion<=iRegion){
+-      void *pMem;
+-      if( pShmNode->h>=0 ){
+-        pMem = osMmap(0, szRegion,
+-            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
+-            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
+-        );
+-        if( pMem==MAP_FAILED ){
+-          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
+-          goto shmpage_out;
+-        }
+-      }else{
+-        pMem = sqlite3_malloc(szRegion);
+-        if( pMem==0 ){
+-          rc = SQLITE_NOMEM;
+-          goto shmpage_out;
+-        }
+-        memset(pMem, 0, szRegion);
+-      }
+-      pShmNode->apRegion[pShmNode->nRegion] = pMem;
+-      pShmNode->nRegion++;
++    if( IS_LOCK_ERROR(rc) ){
++      pFile->lastErrno = tErrno;
+     }
++    return rc; 
+   }
++  pFile->eFileLock = NO_LOCK;
++  return SQLITE_OK;
++}
+ 
+-shmpage_out:
+-  if( pShmNode->nRegion>iRegion ){
+-    *pp = pShmNode->apRegion[iRegion];
+-  }else{
+-    *pp = 0;
++/*
++** Close a file.  Make sure the lock has been released before closing.
++*/
++static int dotlockClose(sqlite3_file *id) {
++  int rc = SQLITE_OK;
++  if( id ){
++    unixFile *pFile = (unixFile*)id;
++    dotlockUnlock(id, NO_LOCK);
++    sqlite3_free(pFile->lockingContext);
++    rc = closeUnixFile(id);
+   }
+-  if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
+-  sqlite3_mutex_leave(pShmNode->mutex);
+   return rc;
+ }
++/****************** End of the dot-file lock implementation *******************
++******************************************************************************/
+ 
+-/*
+-** Change the lock state for a shared-memory segment.
++/******************************************************************************
++************************** Begin flock Locking ********************************
+ **
+-** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
+-** different here than in posix.  In xShmLock(), one can go from unlocked
+-** to shared and back or from unlocked to exclusive and back.  But one may
+-** not go from shared to exclusive or from exclusive to shared.
++** Use the flock() system call to do file locking.
++**
++** flock() locking is like dot-file locking in that the various
++** fine-grain locking levels supported by SQLite are collapsed into
++** a single exclusive lock.  In other words, SHARED, RESERVED, and
++** PENDING locks are the same thing as an EXCLUSIVE lock.  SQLite
++** still works when you do this, but concurrency is reduced since
++** only a single process can be reading the database at a time.
++**
++** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
++** compiling for VXWORKS.
+ */
+-static int unixShmLock(
+-  sqlite3_file *fd,          /* Database file holding the shared memory */
+-  int ofst,                  /* First lock to acquire or release */
+-  int n,                     /* Number of locks to acquire or release */
+-  int flags                  /* What to do with the lock */
+-){
+-  unixFile *pDbFd = (unixFile*)fd;      /* Connection holding shared memory */
+-  unixShm *p = pDbFd->pShm;             /* The shared memory being locked */
+-  unixShm *pX;                          /* For looping over all siblings */
+-  unixShmNode *pShmNode = p->pShmNode;  /* The underlying file iNode */
+-  int rc = SQLITE_OK;                   /* Result code */
+-  u16 mask;                             /* Mask of locks to take or release */
+-
+-  assert( pShmNode==pDbFd->pInode->pShmNode );
+-  assert( pShmNode->pInode==pDbFd->pInode );
+-  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
+-  assert( n>=1 );
+-  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
+-       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
+-       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
+-       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
+-  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
+-  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
+-  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+-
+-  mask = (1<<(ofst+n)) - (1<<ofst);
+-  assert( n>1 || mask==(1<<ofst) );
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  if( flags & SQLITE_SHM_UNLOCK ){
+-    u16 allMask = 0; /* Mask of locks held by siblings */
+-
+-    /* See if any siblings hold this same lock */
+-    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+-      if( pX==p ) continue;
+-      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
+-      allMask |= pX->sharedMask;
+-    }
+-
+-    /* Unlock the system-level locks */
+-    if( (mask & allMask)==0 ){
+-      rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+-    }else{
+-      rc = SQLITE_OK;
+-    }
+-
+-    /* Undo the local locks */
+-    if( rc==SQLITE_OK ){
+-      p->exclMask &= ~mask;
+-      p->sharedMask &= ~mask;
+-    } 
+-  }else if( flags & SQLITE_SHM_SHARED ){
+-    u16 allShared = 0;  /* Union of locks held by connections other than "p" */
+-
+-    /* Find out which shared locks are already held by sibling connections.
+-    ** If any sibling already holds an exclusive lock, go ahead and return
+-    ** SQLITE_BUSY.
+-    */
+-    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+-      if( (pX->exclMask & mask)!=0 ){
+-        rc = SQLITE_BUSY;
+-        break;
+-      }
+-      allShared |= pX->sharedMask;
+-    }
++#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+ 
+-    /* Get shared locks at the system level, if necessary */
+-    if( rc==SQLITE_OK ){
+-      if( (allShared & mask)==0 ){
+-        rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
+-      }else{
+-        rc = SQLITE_OK;
+-      }
+-    }
++/*
++** Retry flock() calls that fail with EINTR
++*/
++#ifdef EINTR
++static int robust_flock(int fd, int op){
++  int rc;
++  do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
++  return rc;
++}
++#else
++# define robust_flock(a,b) flock(a,b)
++#endif
++     
+ 
+-    /* Get the local shared locks */
+-    if( rc==SQLITE_OK ){
+-      p->sharedMask |= mask;
+-    }
+-  }else{
+-    /* Make sure no sibling connections hold locks that will block this
+-    ** lock.  If any do, return SQLITE_BUSY right away.
+-    */
+-    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+-      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+-        rc = SQLITE_BUSY;
+-        break;
+-      }
+-    }
++/*
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, set *pResOut
++** to a non-zero value otherwise *pResOut is set to zero.  The return value
++** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++*/
++static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
++  int rc = SQLITE_OK;
++  int reserved = 0;
++  unixFile *pFile = (unixFile*)id;
+   
+-    /* Get the exclusive locks at the system level.  Then if successful
+-    ** also mark the local connection as being locked.
+-    */
+-    if( rc==SQLITE_OK ){
+-      rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
+-      if( rc==SQLITE_OK ){
+-        assert( (p->sharedMask & mask)==0 );
+-        p->exclMask |= mask;
++  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
++  
++  assert( pFile );
++  
++  /* Check if a thread in this process holds such a lock */
++  if( pFile->eFileLock>SHARED_LOCK ){
++    reserved = 1;
++  }
++  
++  /* Otherwise see if some other process holds it. */
++  if( !reserved ){
++    /* attempt to get the lock */
++    int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
++    if( !lrc ){
++      /* got the lock, unlock it */
++      lrc = robust_flock(pFile->h, LOCK_UN);
++      if ( lrc ) {
++        int tErrno = errno;
++        /* unlock failed with an error */
++        lrc = SQLITE_IOERR_UNLOCK; 
++        if( IS_LOCK_ERROR(lrc) ){
++          pFile->lastErrno = tErrno;
++          rc = lrc;
++        }
++      }
++    } else {
++      int tErrno = errno;
++      reserved = 1;
++      /* someone else might have it reserved */
++      lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); 
++      if( IS_LOCK_ERROR(lrc) ){
++        pFile->lastErrno = tErrno;
++        rc = lrc;
+       }
+     }
+   }
+-  sqlite3_mutex_leave(pShmNode->mutex);
+-  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
+-           p->id, getpid(), p->sharedMask, p->exclMask));
++  OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
++
++#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
++  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
++    rc = SQLITE_OK;
++    reserved=1;
++  }
++#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
++  *pResOut = reserved;
+   return rc;
+ }
+ 
+ /*
+-** Implement a memory barrier or memory fence on shared memory.  
++** Lock the file with the lock specified by parameter eFileLock - one
++** of the following:
+ **
+-** All loads and stores begun before the barrier must complete before
+-** any load or store begun after the barrier.
+-*/
+-static void unixShmBarrier(
+-  sqlite3_file *fd                /* Database file holding the shared memory */
+-){
+-  UNUSED_PARAMETER(fd);
+-  unixEnterMutex();
+-  unixLeaveMutex();
+-}
+-
+-/*
+-** Close a connection to shared-memory.  Delete the underlying 
+-** storage if deleteFlag is true.
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
+ **
+-** If there is no shared memory associated with the connection then this
+-** routine is a harmless no-op.
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
++**
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
++**
++** flock() only really support EXCLUSIVE locks.  We track intermediate
++** lock states in the sqlite3_file structure, but all locks SHARED or
++** above are really EXCLUSIVE locks and exclude all other processes from
++** access the file.
++**
++** This routine will only increase a lock.  Use the sqlite3OsUnlock()
++** routine to lower a locking level.
+ */
+-static int unixShmUnmap(
+-  sqlite3_file *fd,               /* The underlying database file */
+-  int deleteFlag                  /* Delete shared-memory if true */
+-){
+-  unixShm *p;                     /* The connection to be closed */
+-  unixShmNode *pShmNode;          /* The underlying shared-memory file */
+-  unixShm **pp;                   /* For looping over sibling connections */
+-  unixFile *pDbFd;                /* The underlying database file */
+-
+-  pDbFd = (unixFile*)fd;
+-  p = pDbFd->pShm;
+-  if( p==0 ) return SQLITE_OK;
+-  pShmNode = p->pShmNode;
+-
+-  assert( pShmNode==pDbFd->pInode->pShmNode );
+-  assert( pShmNode->pInode==pDbFd->pInode );
+-
+-  /* Remove connection p from the set of connections associated
+-  ** with pShmNode */
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
+-  *pp = p->pNext;
++static int flockLock(sqlite3_file *id, int eFileLock) {
++  int rc = SQLITE_OK;
++  unixFile *pFile = (unixFile*)id;
+ 
+-  /* Free the connection p */
+-  sqlite3_free(p);
+-  pDbFd->pShm = 0;
+-  sqlite3_mutex_leave(pShmNode->mutex);
++  assert( pFile );
+ 
+-  /* If pShmNode->nRef has reached 0, then close the underlying
+-  ** shared-memory file, too */
+-  unixEnterMutex();
+-  assert( pShmNode->nRef>0 );
+-  pShmNode->nRef--;
+-  if( pShmNode->nRef==0 ){
+-    if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
+-    unixShmPurge(pDbFd);
++  /* if we already have a lock, it is exclusive.  
++  ** Just adjust level and punt on outta here. */
++  if (pFile->eFileLock > NO_LOCK) {
++    pFile->eFileLock = eFileLock;
++    return SQLITE_OK;
+   }
+-  unixLeaveMutex();
+-
+-  return SQLITE_OK;
++  
++  /* grab an exclusive lock */
++  
++  if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
++    int tErrno = errno;
++    /* didn't get, must be busy */
++    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
++    if( IS_LOCK_ERROR(rc) ){
++      pFile->lastErrno = tErrno;
++    }
++  } else {
++    /* got it, set the type and return ok */
++    pFile->eFileLock = eFileLock;
++  }
++  OSTRACE(("LOCK    %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), 
++           rc==SQLITE_OK ? "ok" : "failed"));
++#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
++  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
++    rc = SQLITE_BUSY;
++  }
++#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
++  return rc;
+ }
+ 
+ 
+-#else
+-# define unixShmMap     0
+-# define unixShmLock    0
+-# define unixShmBarrier 0
+-# define unixShmUnmap   0
+-#endif /* #ifndef SQLITE_OMIT_WAL */
+-
+ /*
+-** If it is currently memory mapped, unmap file pFd.
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
++**
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
+ */
+-static void unixUnmapfile(unixFile *pFd){
+-  assert( pFd->nFetchOut==0 );
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  if( pFd->pMapRegion ){
+-    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
+-    pFd->pMapRegion = 0;
+-    pFd->mmapSize = 0;
+-    pFd->mmapSizeActual = 0;
++static int flockUnlock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  
++  assert( pFile );
++  OSTRACE(("UNLOCK  %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
++           pFile->eFileLock, getpid()));
++  assert( eFileLock<=SHARED_LOCK );
++  
++  /* no-op if possible */
++  if( pFile->eFileLock==eFileLock ){
++    return SQLITE_OK;
++  }
++  
++  /* shared can just be set because we always have an exclusive */
++  if (eFileLock==SHARED_LOCK) {
++    pFile->eFileLock = eFileLock;
++    return SQLITE_OK;
++  }
++  
++  /* no, really, unlock. */
++  if( robust_flock(pFile->h, LOCK_UN) ){
++#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
++    return SQLITE_OK;
++#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
++    return SQLITE_IOERR_UNLOCK;
++  }else{
++    pFile->eFileLock = NO_LOCK;
++    return SQLITE_OK;
+   }
+-#endif
+ }
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+ /*
+-** Return the system page size.
++** Close a file.
+ */
+-static int unixGetPagesize(void){
+-#if HAVE_MREMAP
+-  return 512;
+-#elif defined(_BSD_SOURCE)
+-  return getpagesize();
+-#else
+-  return (int)sysconf(_SC_PAGESIZE);
+-#endif
++static int flockClose(sqlite3_file *id) {
++  int rc = SQLITE_OK;
++  if( id ){
++    flockUnlock(id, NO_LOCK);
++    rc = closeUnixFile(id);
++  }
++  return rc;
+ }
+-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-/*
+-** Attempt to set the size of the memory mapping maintained by file 
+-** descriptor pFd to nNew bytes. Any existing mapping is discarded.
+-**
+-** If successful, this function sets the following variables:
++#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
++
++/******************* End of the flock lock implementation *********************
++******************************************************************************/
++
++/******************************************************************************
++************************ Begin Named Semaphore Locking ************************
+ **
+-**       unixFile.pMapRegion
+-**       unixFile.mmapSize
+-**       unixFile.mmapSizeActual
++** Named semaphore locking is only supported on VxWorks.
+ **
+-** If unsuccessful, an error message is logged via sqlite3_log() and
+-** the three variables above are zeroed. In this case SQLite should
+-** continue accessing the database using the xRead() and xWrite()
+-** methods.
++** Semaphore locking is like dot-lock and flock in that it really only
++** supports EXCLUSIVE locking.  Only a single process can read or write
++** the database file at a time.  This reduces potential concurrency, but
++** makes the lock implementation much easier.
+ */
+-static void unixRemapfile(
+-  unixFile *pFd,                  /* File descriptor object */
+-  i64 nNew                        /* Required mapping size */
+-){
+-  const char *zErr = "mmap";
+-  int h = pFd->h;                      /* File descriptor open on db file */
+-  u8 *pOrig = (u8 *)pFd->pMapRegion;   /* Pointer to current file mapping */
+-  i64 nOrig = pFd->mmapSizeActual;     /* Size of pOrig region in bytes */
+-  u8 *pNew = 0;                        /* Location of new mapping */
+-  int flags = PROT_READ;               /* Flags to pass to mmap() */
+-
+-  assert( pFd->nFetchOut==0 );
+-  assert( nNew>pFd->mmapSize );
+-  assert( nNew<=pFd->mmapSizeMax );
+-  assert( nNew>0 );
+-  assert( pFd->mmapSizeActual>=pFd->mmapSize );
+-  assert( MAP_FAILED!=0 );
++#if OS_VXWORKS
+ 
+-  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
++/*
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, set *pResOut
++** to a non-zero value otherwise *pResOut is set to zero.  The return value
++** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++*/
++static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
++  int rc = SQLITE_OK;
++  int reserved = 0;
++  unixFile *pFile = (unixFile*)id;
+ 
+-  if( pOrig ){
+-    const int szSyspage = unixGetPagesize();
+-    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
+-    u8 *pReq = &pOrig[nReuse];
++  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
++  
++  assert( pFile );
+ 
+-    /* Unmap any pages of the existing mapping that cannot be reused. */
+-    if( nReuse!=nOrig ){
+-      osMunmap(pReq, nOrig-nReuse);
+-    }
++  /* Check if a thread in this process holds such a lock */
++  if( pFile->eFileLock>SHARED_LOCK ){
++    reserved = 1;
++  }
++  
++  /* Otherwise see if some other process holds it. */
++  if( !reserved ){
++    sem_t *pSem = pFile->pInode->pSem;
++    struct stat statBuf;
+ 
+-#if HAVE_MREMAP
+-    pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
+-    zErr = "mremap";
+-#else
+-    pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
+-    if( pNew!=MAP_FAILED ){
+-      if( pNew!=pReq ){
+-        osMunmap(pNew, nNew - nReuse);
+-        pNew = 0;
+-      }else{
+-        pNew = pOrig;
++    if( sem_trywait(pSem)==-1 ){
++      int tErrno = errno;
++      if( EAGAIN != tErrno ){
++        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
++        pFile->lastErrno = tErrno;
++      } else {
++        /* someone else has the lock when we are in NO_LOCK */
++        reserved = (pFile->eFileLock < SHARED_LOCK);
+       }
++    }else{
++      /* we could have it if we want it */
++      sem_post(pSem);
+     }
+-#endif
+-
+-    /* The attempt to extend the existing mapping failed. Free it. */
+-    if( pNew==MAP_FAILED || pNew==0 ){
+-      osMunmap(pOrig, nReuse);
+-    }
+-  }
+-
+-  /* If pNew is still NULL, try to create an entirely new mapping. */
+-  if( pNew==0 ){
+-    pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
+   }
++  OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
+ 
+-  if( pNew==MAP_FAILED ){
+-    pNew = 0;
+-    nNew = 0;
+-    unixLogError(SQLITE_OK, zErr, pFd->zPath);
+-
+-    /* If the mmap() above failed, assume that all subsequent mmap() calls
+-    ** will probably fail too. Fall back to using xRead/xWrite exclusively
+-    ** in this case.  */
+-    pFd->mmapSizeMax = 0;
+-  }
+-  pFd->pMapRegion = (void *)pNew;
+-  pFd->mmapSize = pFd->mmapSizeActual = nNew;
++  *pResOut = reserved;
++  return rc;
+ }
+-#endif
+ 
+ /*
+-** Memory map or remap the file opened by file-descriptor pFd (if the file
+-** is already mapped, the existing mapping is replaced by the new). Or, if 
+-** there already exists a mapping for this file, and there are still 
+-** outstanding xFetch() references to it, this function is a no-op.
++** Lock the file with the lock specified by parameter eFileLock - one
++** of the following:
+ **
+-** If parameter nByte is non-negative, then it is the requested size of 
+-** the mapping to create. Otherwise, if nByte is less than zero, then the 
+-** requested size is the size of the file on disk. The actual size of the
+-** created mapping is either the requested size or the value configured 
+-** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
+ **
+-** SQLITE_OK is returned if no error occurs (even if the mapping is not
+-** recreated as a result of outstanding references) or an SQLite error
+-** code otherwise.
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
++**
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
++**
++** Semaphore locks only really support EXCLUSIVE locks.  We track intermediate
++** lock states in the sqlite3_file structure, but all locks SHARED or
++** above are really EXCLUSIVE locks and exclude all other processes from
++** access the file.
++**
++** This routine will only increase a lock.  Use the sqlite3OsUnlock()
++** routine to lower a locking level.
+ */
+-static int unixMapfile(unixFile *pFd, i64 nByte){
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  i64 nMap = nByte;
+-  int rc;
+-
+-  assert( nMap>=0 || pFd->nFetchOut==0 );
+-  if( pFd->nFetchOut>0 ) return SQLITE_OK;
++static int semLock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  int fd;
++  sem_t *pSem = pFile->pInode->pSem;
++  int rc = SQLITE_OK;
+ 
+-  if( nMap<0 ){
+-    struct stat statbuf;          /* Low-level file information */
+-    rc = osFstat(pFd->h, &statbuf);
+-    if( rc!=SQLITE_OK ){
+-      return SQLITE_IOERR_FSTAT;
+-    }
+-    nMap = statbuf.st_size;
++  /* if we already have a lock, it is exclusive.  
++  ** Just adjust level and punt on outta here. */
++  if (pFile->eFileLock > NO_LOCK) {
++    pFile->eFileLock = eFileLock;
++    rc = SQLITE_OK;
++    goto sem_end_lock;
+   }
+-  if( nMap>pFd->mmapSizeMax ){
+-    nMap = pFd->mmapSizeMax;
++  
++  /* lock semaphore now but bail out when already locked. */
++  if( sem_trywait(pSem)==-1 ){
++    rc = SQLITE_BUSY;
++    goto sem_end_lock;
+   }
+ 
+-  if( nMap!=pFd->mmapSize ){
+-    if( nMap>0 ){
+-      unixRemapfile(pFd, nMap);
+-    }else{
+-      unixUnmapfile(pFd);
+-    }
+-  }
+-#endif
++  /* got it, set the type and return ok */
++  pFile->eFileLock = eFileLock;
+ 
+-  return SQLITE_OK;
++ sem_end_lock:
++  return rc;
+ }
+ 
+ /*
+-** If possible, return a pointer to a mapping of file fd starting at offset
+-** iOff. The mapping must be valid for at least nAmt bytes.
+-**
+-** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
+-** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
+-** Finally, if an error does occur, return an SQLite error code. The final
+-** value of *pp is undefined in this case.
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
+ **
+-** If this function does return a pointer, the caller must eventually 
+-** release the reference by calling unixUnfetch().
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
+ */
+-static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
+-#endif
+-  *pp = 0;
++static int semUnlock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  sem_t *pSem = pFile->pInode->pSem;
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  if( pFd->mmapSizeMax>0 ){
+-    if( pFd->pMapRegion==0 ){
+-      int rc = unixMapfile(pFd, -1);
+-      if( rc!=SQLITE_OK ) return rc;
+-    }
+-    if( pFd->mmapSize >= iOff+nAmt ){
+-      *pp = &((u8 *)pFd->pMapRegion)[iOff];
+-      pFd->nFetchOut++;
++  assert( pFile );
++  assert( pSem );
++  OSTRACE(("UNLOCK  %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
++           pFile->eFileLock, getpid()));
++  assert( eFileLock<=SHARED_LOCK );
++  
++  /* no-op if possible */
++  if( pFile->eFileLock==eFileLock ){
++    return SQLITE_OK;
++  }
++  
++  /* shared can just be set because we always have an exclusive */
++  if (eFileLock==SHARED_LOCK) {
++    pFile->eFileLock = eFileLock;
++    return SQLITE_OK;
++  }
++  
++  /* no, really unlock. */
++  if ( sem_post(pSem)==-1 ) {
++    int rc, tErrno = errno;
++    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
++    if( IS_LOCK_ERROR(rc) ){
++      pFile->lastErrno = tErrno;
+     }
++    return rc; 
+   }
+-#endif
++  pFile->eFileLock = NO_LOCK;
+   return SQLITE_OK;
+ }
+ 
+ /*
+-** If the third argument is non-NULL, then this function releases a 
+-** reference obtained by an earlier call to unixFetch(). The second
+-** argument passed to this function must be the same as the corresponding
+-** argument that was passed to the unixFetch() invocation. 
+-**
+-** Or, if the third argument is NULL, then this function is being called 
+-** to inform the VFS layer that, according to POSIX, any existing mapping 
+-** may now be invalid and should be unmapped.
+-*/
+-static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
+-  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
+-  UNUSED_PARAMETER(iOff);
+-
+-  /* If p==0 (unmap the entire file) then there must be no outstanding 
+-  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
+-  ** then there must be at least one outstanding.  */
+-  assert( (p==0)==(pFd->nFetchOut==0) );
+-
+-  /* If p!=0, it must match the iOff value. */
+-  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
+-
+-  if( p ){
+-    pFd->nFetchOut--;
+-  }else{
+-    unixUnmapfile(pFd);
++ ** Close a file.
++ */
++static int semClose(sqlite3_file *id) {
++  if( id ){
++    unixFile *pFile = (unixFile*)id;
++    semUnlock(id, NO_LOCK);
++    assert( pFile );
++    unixEnterMutex();
++    releaseInodeInfo(pFile);
++    unixLeaveMutex();
++    closeUnixFile(id);
+   }
+-
+-  assert( pFd->nFetchOut>=0 );
+   return SQLITE_OK;
+ }
+ 
++#endif /* OS_VXWORKS */
+ /*
+-** Here ends the implementation of all sqlite3_file methods.
++** Named semaphore locking is only available on VxWorks.
+ **
+-********************** End sqlite3_file Methods *******************************
++*************** End of the named semaphore lock implementation ****************
+ ******************************************************************************/
+ 
+-/*
+-** This division contains definitions of sqlite3_io_methods objects that
+-** implement various file locking strategies.  It also contains definitions
+-** of "finder" functions.  A finder-function is used to locate the appropriate
+-** sqlite3_io_methods object for a particular database file.  The pAppData
+-** field of the sqlite3_vfs VFS objects are initialized to be pointers to
+-** the correct finder-function for that VFS.
+-**
+-** Most finder functions return a pointer to a fixed sqlite3_io_methods
+-** object.  The only interesting finder-function is autolockIoFinder, which
+-** looks at the filesystem type and tries to guess the best locking
+-** strategy from that.
+-**
+-** For finder-funtion F, two objects are created:
+-**
+-**    (1) The real finder-function named "FImpt()".
+-**
+-**    (2) A constant pointer to this function named just "F".
+-**
+-**
+-** A pointer to the F pointer is used as the pAppData value for VFS
+-** objects.  We have to do this instead of letting pAppData point
+-** directly at the finder-function since C90 rules prevent a void*
+-** from be cast into a function pointer.
+-**
+-**
+-** Each instance of this macro generates two objects:
++
++/******************************************************************************
++*************************** Begin AFP Locking *********************************
+ **
+-**   *  A constant sqlite3_io_methods object call METHOD that has locking
+-**      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
++** AFP is the Apple Filing Protocol.  AFP is a network filesystem found
++** on Apple Macintosh computers - both OS9 and OSX.
+ **
+-**   *  An I/O method finder function called FINDER that returns a pointer
+-**      to the METHOD object in the previous bullet.
++** Third-party implementations of AFP are available.  But this code here
++** only works on OSX.
+ */
+-#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK)      \
+-static const sqlite3_io_methods METHOD = {                                   \
+-   VERSION,                    /* iVersion */                                \
+-   CLOSE,                      /* xClose */                                  \
+-   unixRead,                   /* xRead */                                   \
+-   unixWrite,                  /* xWrite */                                  \
+-   unixTruncate,               /* xTruncate */                               \
+-   unixSync,                   /* xSync */                                   \
+-   unixFileSize,               /* xFileSize */                               \
+-   LOCK,                       /* xLock */                                   \
+-   UNLOCK,                     /* xUnlock */                                 \
+-   CKLOCK,                     /* xCheckReservedLock */                      \
+-   unixFileControl,            /* xFileControl */                            \
+-   unixSectorSize,             /* xSectorSize */                             \
+-   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
+-   unixShmMap,                 /* xShmMap */                                 \
+-   unixShmLock,                /* xShmLock */                                \
+-   unixShmBarrier,             /* xShmBarrier */                             \
+-   unixShmUnmap,               /* xShmUnmap */                               \
+-   unixFetch,                  /* xFetch */                                  \
+-   unixUnfetch,                /* xUnfetch */                                \
+-};                                                                           \
+-static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
+-  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
+-  return &METHOD;                                                            \
+-}                                                                            \
+-static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
+-    = FINDER##Impl;
+ 
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ /*
+-** Here are all of the sqlite3_io_methods objects for each of the
+-** locking strategies.  Functions that return pointers to these methods
+-** are also created.
++** The afpLockingContext structure contains all afp lock specific state
+ */
+-IOMETHODS(
+-  posixIoFinder,            /* Finder function name */
+-  posixIoMethods,           /* sqlite3_io_methods object name */
+-  3,                        /* shared memory and mmap are enabled */
+-  unixClose,                /* xClose method */
+-  unixLock,                 /* xLock method */
+-  unixUnlock,               /* xUnlock method */
+-  unixCheckReservedLock     /* xCheckReservedLock method */
+-)
+-IOMETHODS(
+-  nolockIoFinder,           /* Finder function name */
+-  nolockIoMethods,          /* sqlite3_io_methods object name */
+-  1,                        /* shared memory is disabled */
+-  nolockClose,              /* xClose method */
+-  nolockLock,               /* xLock method */
+-  nolockUnlock,             /* xUnlock method */
+-  nolockCheckReservedLock   /* xCheckReservedLock method */
+-)
+-IOMETHODS(
+-  dotlockIoFinder,          /* Finder function name */
+-  dotlockIoMethods,         /* sqlite3_io_methods object name */
+-  1,                        /* shared memory is disabled */
+-  dotlockClose,             /* xClose method */
+-  dotlockLock,              /* xLock method */
+-  dotlockUnlock,            /* xUnlock method */
+-  dotlockCheckReservedLock  /* xCheckReservedLock method */
+-)
++typedef struct afpLockingContext afpLockingContext;
++struct afpLockingContext {
++  int reserved;
++  const char *dbPath;             /* Name of the open file */
++};
+ 
+-#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+-IOMETHODS(
+-  flockIoFinder,            /* Finder function name */
+-  flockIoMethods,           /* sqlite3_io_methods object name */
+-  1,                        /* shared memory is disabled */
+-  flockClose,               /* xClose method */
+-  flockLock,                /* xLock method */
+-  flockUnlock,              /* xUnlock method */
+-  flockCheckReservedLock    /* xCheckReservedLock method */
+-)
+-#endif
++struct ByteRangeLockPB2
++{
++  unsigned long long offset;        /* offset to first byte to lock */
++  unsigned long long length;        /* nbr of bytes to lock */
++  unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
++  unsigned char unLockFlag;         /* 1 = unlock, 0 = lock */
++  unsigned char startEndFlag;       /* 1=rel to end of fork, 0=rel to start */
++  int fd;                           /* file desc to assoc this lock with */
++};
+ 
+-#if OS_VXWORKS
+-IOMETHODS(
+-  semIoFinder,              /* Finder function name */
+-  semIoMethods,             /* sqlite3_io_methods object name */
+-  1,                        /* shared memory is disabled */
+-  semClose,                 /* xClose method */
+-  semLock,                  /* xLock method */
+-  semUnlock,                /* xUnlock method */
+-  semCheckReservedLock      /* xCheckReservedLock method */
+-)
+-#endif
++#define afpfsByteRangeLock2FSCTL        _IOWR('z', 23, struct ByteRangeLockPB2)
+ 
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-IOMETHODS(
+-  afpIoFinder,              /* Finder function name */
+-  afpIoMethods,             /* sqlite3_io_methods object name */
+-  1,                        /* shared memory is disabled */
+-  afpClose,                 /* xClose method */
+-  afpLock,                  /* xLock method */
+-  afpUnlock,                /* xUnlock method */
+-  afpCheckReservedLock      /* xCheckReservedLock method */
+-)
+-#endif
++/*
++** This is a utility for setting or clearing a bit-range lock on an
++** AFP filesystem.
++** 
++** Return SQLITE_OK on success, SQLITE_BUSY on failure.
++*/
++static int afpSetLock(
++  const char *path,              /* Name of the file to be locked or unlocked */
++  unixFile *pFile,               /* Open file descriptor on path */
++  unsigned long long offset,     /* First byte to be locked */
++  unsigned long long length,     /* Number of bytes to lock */
++  int setLockFlag                /* True to set lock.  False to clear lock */
++){
++  struct ByteRangeLockPB2 pb;
++  int err;
++  
++  pb.unLockFlag = setLockFlag ? 0 : 1;
++  pb.startEndFlag = 0;
++  pb.offset = offset;
++  pb.length = length; 
++  pb.fd = pFile->h;
++  
++  OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", 
++    (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
++    offset, length));
++  err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
++  if ( err==-1 ) {
++    int rc;
++    int tErrno = errno;
++    OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
++             path, tErrno, strerror(tErrno)));
++#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
++    rc = SQLITE_BUSY;
++#else
++    rc = sqliteErrorFromPosixError(tErrno,
++                    setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
++#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
++    if( IS_LOCK_ERROR(rc) ){
++      pFile->lastErrno = tErrno;
++    }
++    return rc;
++  } else {
++    return SQLITE_OK;
++  }
++}
+ 
+ /*
+-** The proxy locking method is a "super-method" in the sense that it
+-** opens secondary file descriptors for the conch and lock files and
+-** it uses proxy, dot-file, AFP, and flock() locking methods on those
+-** secondary files.  For this reason, the division that implements
+-** proxy locking is located much further down in the file.  But we need
+-** to go ahead and define the sqlite3_io_methods and finder function
+-** for proxy locking here.  So we forward declare the I/O methods.
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, set *pResOut
++** to a non-zero value otherwise *pResOut is set to zero.  The return value
++** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+ */
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-static int proxyClose(sqlite3_file*);
+-static int proxyLock(sqlite3_file*, int);
+-static int proxyUnlock(sqlite3_file*, int);
+-static int proxyCheckReservedLock(sqlite3_file*, int*);
+-IOMETHODS(
+-  proxyIoFinder,            /* Finder function name */
+-  proxyIoMethods,           /* sqlite3_io_methods object name */
+-  1,                        /* shared memory is disabled */
+-  proxyClose,               /* xClose method */
+-  proxyLock,                /* xLock method */
+-  proxyUnlock,              /* xUnlock method */
+-  proxyCheckReservedLock    /* xCheckReservedLock method */
+-)
+-#endif
++static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
++  int rc = SQLITE_OK;
++  int reserved = 0;
++  unixFile *pFile = (unixFile*)id;
++  afpLockingContext *context;
++  
++  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
++  
++  assert( pFile );
++  context = (afpLockingContext *) pFile->lockingContext;
++  if( context->reserved ){
++    *pResOut = 1;
++    return SQLITE_OK;
++  }
++  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
++  
++  /* Check if a thread in this process holds such a lock */
++  if( pFile->pInode->eFileLock>SHARED_LOCK ){
++    reserved = 1;
++  }
++  
++  /* Otherwise see if some other process holds it.
++   */
++  if( !reserved ){
++    /* lock the RESERVED byte */
++    int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);  
++    if( SQLITE_OK==lrc ){
++      /* if we succeeded in taking the reserved lock, unlock it to restore
++      ** the original state */
++      lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
++    } else {
++      /* if we failed to get the lock then someone else must have it */
++      reserved = 1;
++    }
++    if( IS_LOCK_ERROR(lrc) ){
++      rc=lrc;
++    }
++  }
++  
++  unixLeaveMutex();
++  OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
++  
++  *pResOut = reserved;
++  return rc;
++}
+ 
+-/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-IOMETHODS(
+-  nfsIoFinder,               /* Finder function name */
+-  nfsIoMethods,              /* sqlite3_io_methods object name */
+-  1,                         /* shared memory is disabled */
+-  unixClose,                 /* xClose method */
+-  unixLock,                  /* xLock method */
+-  nfsUnlock,                 /* xUnlock method */
+-  unixCheckReservedLock      /* xCheckReservedLock method */
+-)
+-#endif
++/*
++** Lock the file with the lock specified by parameter eFileLock - one
++** of the following:
++**
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
++**
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
++**
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
++**
++** This routine will only increase a lock.  Use the sqlite3OsUnlock()
++** routine to lower a locking level.
++*/
++static int afpLock(sqlite3_file *id, int eFileLock){
++  int rc = SQLITE_OK;
++  unixFile *pFile = (unixFile*)id;
++  unixInodeInfo *pInode = pFile->pInode;
++  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
++  
++  assert( pFile );
++  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
++           azFileLock(eFileLock), azFileLock(pFile->eFileLock),
++           azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
++
++  /* If there is already a lock of this type or more restrictive on the
++  ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
++  ** unixEnterMutex() hasn't been called yet.
++  */
++  if( pFile->eFileLock>=eFileLock ){
++    OSTRACE(("LOCK    %d %s ok (already held) (afp)\n", pFile->h,
++           azFileLock(eFileLock)));
++    return SQLITE_OK;
++  }
++
++  /* Make sure the locking sequence is correct
++  **  (1) We never move from unlocked to anything higher than shared lock.
++  **  (2) SQLite never explicitly requests a pendig lock.
++  **  (3) A shared lock is always held when a reserve lock is requested.
++  */
++  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
++  assert( eFileLock!=PENDING_LOCK );
++  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
++  
++  /* This mutex is needed because pFile->pInode is shared across threads
++  */
++  unixEnterMutex();
++  pInode = pFile->pInode;
++
++  /* If some thread using this PID has a lock via a different unixFile*
++  ** handle that precludes the requested lock, return BUSY.
++  */
++  if( (pFile->eFileLock!=pInode->eFileLock && 
++       (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
++     ){
++    rc = SQLITE_BUSY;
++    goto afp_end_lock;
++  }
++  
++  /* If a SHARED lock is requested, and some thread using this PID already
++  ** has a SHARED or RESERVED lock, then increment reference counts and
++  ** return SQLITE_OK.
++  */
++  if( eFileLock==SHARED_LOCK && 
++     (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
++    assert( eFileLock==SHARED_LOCK );
++    assert( pFile->eFileLock==0 );
++    assert( pInode->nShared>0 );
++    pFile->eFileLock = SHARED_LOCK;
++    pInode->nShared++;
++    pInode->nLock++;
++    goto afp_end_lock;
++  }
++    
++  /* A PENDING lock is needed before acquiring a SHARED lock and before
++  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
++  ** be released.
++  */
++  if( eFileLock==SHARED_LOCK 
++      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
++  ){
++    int failed;
++    failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
++    if (failed) {
++      rc = failed;
++      goto afp_end_lock;
++    }
++  }
++  
++  /* If control gets to this point, then actually go ahead and make
++  ** operating system calls for the specified lock.
++  */
++  if( eFileLock==SHARED_LOCK ){
++    int lrc1, lrc2, lrc1Errno = 0;
++    long lk, mask;
++    
++    assert( pInode->nShared==0 );
++    assert( pInode->eFileLock==0 );
++        
++    mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
++    /* Now get the read-lock SHARED_LOCK */
++    /* note that the quality of the randomness doesn't matter that much */
++    lk = random(); 
++    pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
++    lrc1 = afpSetLock(context->dbPath, pFile, 
++          SHARED_FIRST+pInode->sharedByte, 1, 1);
++    if( IS_LOCK_ERROR(lrc1) ){
++      lrc1Errno = pFile->lastErrno;
++    }
++    /* Drop the temporary PENDING lock */
++    lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
++    
++    if( IS_LOCK_ERROR(lrc1) ) {
++      pFile->lastErrno = lrc1Errno;
++      rc = lrc1;
++      goto afp_end_lock;
++    } else if( IS_LOCK_ERROR(lrc2) ){
++      rc = lrc2;
++      goto afp_end_lock;
++    } else if( lrc1 != SQLITE_OK ) {
++      rc = lrc1;
++    } else {
++      pFile->eFileLock = SHARED_LOCK;
++      pInode->nLock++;
++      pInode->nShared = 1;
++    }
++  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
++    /* We are trying for an exclusive lock but another thread in this
++     ** same process is still holding a shared lock. */
++    rc = SQLITE_BUSY;
++  }else{
++    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
++    ** assumed that there is a SHARED or greater lock on the file
++    ** already.
++    */
++    int failed = 0;
++    assert( 0!=pFile->eFileLock );
++    if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
++        /* Acquire a RESERVED lock */
++        failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
++      if( !failed ){
++        context->reserved = 1;
++      }
++    }
++    if (!failed && eFileLock == EXCLUSIVE_LOCK) {
++      /* Acquire an EXCLUSIVE lock */
++        
++      /* Remove the shared lock before trying the range.  we'll need to 
++      ** reestablish the shared lock if we can't get the  afpUnlock
++      */
++      if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
++                         pInode->sharedByte, 1, 0)) ){
++        int failed2 = SQLITE_OK;
++        /* now attemmpt to get the exclusive lock range */
++        failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, 
++                               SHARED_SIZE, 1);
++        if( failed && (failed2 = afpSetLock(context->dbPath, pFile, 
++                       SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
++          /* Can't reestablish the shared lock.  Sqlite can't deal, this is
++          ** a critical I/O error
++          */
++          rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : 
++               SQLITE_IOERR_LOCK;
++          goto afp_end_lock;
++        } 
++      }else{
++        rc = failed; 
++      }
++    }
++    if( failed ){
++      rc = failed;
++    }
++  }
++  
++  if( rc==SQLITE_OK ){
++    pFile->eFileLock = eFileLock;
++    pInode->eFileLock = eFileLock;
++  }else if( eFileLock==EXCLUSIVE_LOCK ){
++    pFile->eFileLock = PENDING_LOCK;
++    pInode->eFileLock = PENDING_LOCK;
++  }
++  
++afp_end_lock:
++  unixLeaveMutex();
++  OSTRACE(("LOCK    %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), 
++         rc==SQLITE_OK ? "ok" : "failed"));
++  return rc;
++}
+ 
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-/* 
+-** This "finder" function attempts to determine the best locking strategy 
+-** for the database file "filePath".  It then returns the sqlite3_io_methods
+-** object that implements that strategy.
++/*
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
+ **
+-** This is for MacOSX only.
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
+ */
+-static const sqlite3_io_methods *autolockIoFinderImpl(
+-  const char *filePath,    /* name of the database file */
+-  unixFile *pNew           /* open file object for the database file */
+-){
+-  static const struct Mapping {
+-    const char *zFilesystem;              /* Filesystem type name */
+-    const sqlite3_io_methods *pMethods;   /* Appropriate locking method */
+-  } aMap[] = {
+-    { "hfs",    &posixIoMethods },
+-    { "ufs",    &posixIoMethods },
+-    { "afpfs",  &afpIoMethods },
+-    { "smbfs",  &afpIoMethods },
+-    { "webdav", &nolockIoMethods },
+-    { 0, 0 }
+-  };
+-  int i;
+-  struct statfs fsInfo;
+-  struct flock lockInfo;
++static int afpUnlock(sqlite3_file *id, int eFileLock) {
++  int rc = SQLITE_OK;
++  unixFile *pFile = (unixFile*)id;
++  unixInodeInfo *pInode;
++  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
++  int skipShared = 0;
++#ifdef SQLITE_TEST
++  int h = pFile->h;
++#endif
+ 
+-  if( !filePath ){
+-    /* If filePath==NULL that means we are dealing with a transient file
+-    ** that does not need to be locked. */
+-    return &nolockIoMethods;
++  assert( pFile );
++  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
++           pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
++           getpid()));
++
++  assert( eFileLock<=SHARED_LOCK );
++  if( pFile->eFileLock<=eFileLock ){
++    return SQLITE_OK;
+   }
+-  if( statfs(filePath, &fsInfo) != -1 ){
+-    if( fsInfo.f_flags & MNT_RDONLY ){
+-      return &nolockIoMethods;
++  unixEnterMutex();
++  pInode = pFile->pInode;
++  assert( pInode->nShared!=0 );
++  if( pFile->eFileLock>SHARED_LOCK ){
++    assert( pInode->eFileLock==pFile->eFileLock );
++    SimulateIOErrorBenign(1);
++    SimulateIOError( h=(-1) )
++    SimulateIOErrorBenign(0);
++    
++#ifdef SQLITE_DEBUG
++    /* When reducing a lock such that other processes can start
++    ** reading the database file again, make sure that the
++    ** transaction counter was updated if any part of the database
++    ** file changed.  If the transaction counter is not updated,
++    ** other connections to the same file might not realize that
++    ** the file has changed and hence might not know to flush their
++    ** cache.  The use of a stale cache can lead to database corruption.
++    */
++    assert( pFile->inNormalWrite==0
++           || pFile->dbUpdate==0
++           || pFile->transCntrChng==1 );
++    pFile->inNormalWrite = 0;
++#endif
++    
++    if( pFile->eFileLock==EXCLUSIVE_LOCK ){
++      rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
++      if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
++        /* only re-establish the shared lock if necessary */
++        int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
++        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
++      } else {
++        skipShared = 1;
++      }
+     }
+-    for(i=0; aMap[i].zFilesystem; i++){
+-      if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
+-        return aMap[i].pMethods;
++    if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
++      rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
++    } 
++    if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
++      rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
++      if( !rc ){ 
++        context->reserved = 0; 
+       }
+     }
++    if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
++      pInode->eFileLock = SHARED_LOCK;
++    }
+   }
++  if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
+ 
+-  /* Default case. Handles, amongst others, "nfs".
+-  ** Test byte-range lock using fcntl(). If the call succeeds, 
+-  ** assume that the file-system supports POSIX style locks. 
+-  */
+-  lockInfo.l_len = 1;
+-  lockInfo.l_start = 0;
+-  lockInfo.l_whence = SEEK_SET;
+-  lockInfo.l_type = F_RDLCK;
+-  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
+-    if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
+-      return &nfsIoMethods;
+-    } else {
+-      return &posixIoMethods;
++    /* Decrement the shared lock counter.  Release the lock using an
++    ** OS call only when all threads in this same process have released
++    ** the lock.
++    */
++    unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
++    pInode->nShared--;
++    if( pInode->nShared==0 ){
++      SimulateIOErrorBenign(1);
++      SimulateIOError( h=(-1) )
++      SimulateIOErrorBenign(0);
++      if( !skipShared ){
++        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
++      }
++      if( !rc ){
++        pInode->eFileLock = NO_LOCK;
++        pFile->eFileLock = NO_LOCK;
++      }
++    }
++    if( rc==SQLITE_OK ){
++      pInode->nLock--;
++      assert( pInode->nLock>=0 );
++      if( pInode->nLock==0 ){
++        closePendingFds(pFile);
++      }
+     }
+-  }else{
+-    return &dotlockIoMethods;
+   }
++  
++  unixLeaveMutex();
++  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
++  return rc;
+ }
+-static const sqlite3_io_methods 
+-  *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
+-
+-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+ 
+-#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
+-/* 
+-** This "finder" function attempts to determine the best locking strategy 
+-** for the database file "filePath".  It then returns the sqlite3_io_methods
+-** object that implements that strategy.
+-**
+-** This is for VXWorks only.
++/*
++** Close a file & cleanup AFP specific locking context 
+ */
+-static const sqlite3_io_methods *autolockIoFinderImpl(
+-  const char *filePath,    /* name of the database file */
+-  unixFile *pNew           /* the open file object */
+-){
+-  struct flock lockInfo;
+-
+-  if( !filePath ){
+-    /* If filePath==NULL that means we are dealing with a transient file
+-    ** that does not need to be locked. */
+-    return &nolockIoMethods;
+-  }
+-
+-  /* Test if fcntl() is supported and use POSIX style locks.
+-  ** Otherwise fall back to the named semaphore method.
+-  */
+-  lockInfo.l_len = 1;
+-  lockInfo.l_start = 0;
+-  lockInfo.l_whence = SEEK_SET;
+-  lockInfo.l_type = F_RDLCK;
+-  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
+-    return &posixIoMethods;
+-  }else{
+-    return &semIoMethods;
++static int afpClose(sqlite3_file *id) {
++  int rc = SQLITE_OK;
++  if( id ){
++    unixFile *pFile = (unixFile*)id;
++    afpUnlock(id, NO_LOCK);
++    unixEnterMutex();
++    if( pFile->pInode && pFile->pInode->nLock ){
++      /* If there are outstanding locks, do not actually close the file just
++      ** yet because that would clear those locks.  Instead, add the file
++      ** descriptor to pInode->aPending.  It will be automatically closed when
++      ** the last lock is cleared.
++      */
++      setPendingFd(pFile);
++    }
++    releaseInodeInfo(pFile);
++    sqlite3_free(pFile->lockingContext);
++    rc = closeUnixFile(id);
++    unixLeaveMutex();
+   }
++  return rc;
+ }
+-static const sqlite3_io_methods 
+-  *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
+ 
+-#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
++#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
++/*
++** The code above is the AFP lock implementation.  The code is specific
++** to MacOSX and does not work on other unix platforms.  No alternative
++** is available.  If you don't compile for a mac, then the "unix-afp"
++** VFS is not available.
++**
++********************* End of the AFP lock implementation **********************
++******************************************************************************/
++
++/******************************************************************************
++*************************** Begin NFS Locking ********************************/
+ 
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ /*
+-** An abstract type for a pointer to a IO method finder function:
+-*/
+-typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
++ ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++ ** must be either NO_LOCK or SHARED_LOCK.
++ **
++ ** If the locking level of the file descriptor is already at or below
++ ** the requested locking level, this routine is a no-op.
++ */
++static int nfsUnlock(sqlite3_file *id, int eFileLock){
++  return posixUnlock(id, eFileLock, 1);
++}
+ 
++#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
++/*
++** The code above is the NFS lock implementation.  The code is specific
++** to MacOSX and does not work on other unix platforms.  No alternative
++** is available.  
++**
++********************* End of the NFS lock implementation **********************
++******************************************************************************/
+ 
+-/****************************************************************************
+-**************************** sqlite3_vfs methods ****************************
++/******************************************************************************
++**************** Non-locking sqlite3_file methods *****************************
+ **
+-** This division contains the implementation of methods on the
+-** sqlite3_vfs object.
++** The next division contains implementations for all methods of the 
++** sqlite3_file object other than the locking methods.  The locking
++** methods were defined in divisions above (one locking method per
++** division).  Those methods that are common to all locking modes
++** are gather together into this division.
+ */
+ 
+ /*
+-** Initialize the contents of the unixFile structure pointed to by pId.
++** Seek to the offset passed as the second argument, then read cnt 
++** bytes into pBuf. Return the number of bytes actually read.
++**
++** NB:  If you define USE_PREAD or USE_PREAD64, then it might also
++** be necessary to define _XOPEN_SOURCE to be 500.  This varies from
++** one system to another.  Since SQLite does not define USE_PREAD
++** any any form by default, we will not attempt to define _XOPEN_SOURCE.
++** See tickets #2741 and #2681.
++**
++** To avoid stomping the errno value on a failed read the lastErrno value
++** is set before returning.
+ */
+-static int fillInUnixFile(
+-  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
+-  int h,                  /* Open file descriptor of file being opened */
+-  sqlite3_file *pId,      /* Write to the unixFile structure here */
+-  const char *zFilename,  /* Name of the file being opened */
+-  int ctrlFlags           /* Zero or more UNIXFILE_* values */
+-){
+-  const sqlite3_io_methods *pLockingStyle;
+-  unixFile *pNew = (unixFile *)pId;
+-  int rc = SQLITE_OK;
+-
+-  assert( pNew->pInode==NULL );
+-
+-  /* Usually the path zFilename should not be a relative pathname. The
+-  ** exception is when opening the proxy "conch" file in builds that
+-  ** include the special Apple locking styles.
+-  */
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-  assert( zFilename==0 || zFilename[0]=='/' 
+-    || pVfs->pAppData==(void*)&autolockIoFinder );
++static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
++  int got;
++  int prior = 0;
++#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
++  i64 newOffset;
++#endif
++  TIMER_START;
++  assert( cnt==(cnt&0x1ffff) );
++  cnt &= 0x1ffff;
++  do{
++#if defined(USE_PREAD)
++    got = osPread(id->h, pBuf, cnt, offset);
++    SimulateIOError( got = -1 );
++#elif defined(USE_PREAD64)
++    got = osPread64(id->h, pBuf, cnt, offset);
++    SimulateIOError( got = -1 );
+ #else
+-  assert( zFilename==0 || zFilename[0]=='/' );
++    newOffset = lseek(id->h, offset, SEEK_SET);
++    SimulateIOError( newOffset-- );
++    if( newOffset!=offset ){
++      if( newOffset == -1 ){
++        ((unixFile*)id)->lastErrno = errno;
++      }else{
++        ((unixFile*)id)->lastErrno = 0;
++      }
++      return -1;
++    }
++    got = osRead(id->h, pBuf, cnt);
+ #endif
++    if( got==cnt ) break;
++    if( got<0 ){
++      if( errno==EINTR ){ got = 1; continue; }
++      prior = 0;
++      ((unixFile*)id)->lastErrno = errno;
++      break;
++    }else if( got>0 ){
++      cnt -= got;
++      offset += got;
++      prior += got;
++      pBuf = (void*)(got + (char*)pBuf);
++    }
++  }while( got>0 );
++  TIMER_END;
++  OSTRACE(("READ    %-3d %5d %7lld %llu\n",
++            id->h, got+prior, offset-prior, TIMER_ELAPSED));
++  return got+prior;
++}
+ 
+-  /* No locking occurs in temporary files */
+-  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
++/*
++** Read data from a file into a buffer.  Return SQLITE_OK if all
++** bytes were read successfully and SQLITE_IOERR if anything goes
++** wrong.
++*/
++static int unixRead(
++  sqlite3_file *id, 
++  void *pBuf, 
++  int amt,
++  sqlite3_int64 offset
++){
++  unixFile *pFile = (unixFile *)id;
++  int got;
++  assert( id );
++  assert( offset>=0 );
++  assert( amt>0 );
+ 
+-  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
+-  pNew->h = h;
+-  pNew->pVfs = pVfs;
+-  pNew->zPath = zFilename;
+-  pNew->ctrlFlags = (u8)ctrlFlags;
+-  pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
+-  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
+-                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+-    pNew->ctrlFlags |= UNIXFILE_PSOW;
+-  }
+-  if( strcmp(pVfs->zName,"unix-excl")==0 ){
+-    pNew->ctrlFlags |= UNIXFILE_EXCL;
+-  }
++  /* If this is a database file (not a journal, master-journal or temp
++  ** file), the bytes in the locking range should never be read or written. */
++#if 0
++  assert( pFile->pUnused==0
++       || offset>=PENDING_BYTE+512
++       || offset+amt<=PENDING_BYTE 
++  );
++#endif
+ 
+-#if OS_VXWORKS
+-  pNew->pId = vxworksFindFileId(zFilename);
+-  if( pNew->pId==0 ){
+-    ctrlFlags |= UNIXFILE_NOLOCK;
+-    rc = SQLITE_NOMEM;
++#if SQLITE_MAX_MMAP_SIZE>0
++  /* Deal with as much of this read request as possible by transfering
++  ** data from the memory mapping using memcpy().  */
++  if( offset<pFile->mmapSize ){
++    if( offset+amt <= pFile->mmapSize ){
++      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
++      return SQLITE_OK;
++    }else{
++      int nCopy = pFile->mmapSize - offset;
++      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
++      pBuf = &((u8 *)pBuf)[nCopy];
++      amt -= nCopy;
++      offset += nCopy;
++    }
+   }
+ #endif
+ 
+-  if( ctrlFlags & UNIXFILE_NOLOCK ){
+-    pLockingStyle = &nolockIoMethods;
++  got = seekAndRead(pFile, offset, pBuf, amt);
++  if( got==amt ){
++    return SQLITE_OK;
++  }else if( got<0 ){
++    /* lastErrno set by seekAndRead */
++    return SQLITE_IOERR_READ;
+   }else{
+-    pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-    /* Cache zFilename in the locking context (AFP and dotlock override) for
+-    ** proxyLock activation is possible (remote proxy is based on db name)
+-    ** zFilename remains valid until file is closed, to support */
+-    pNew->lockingContext = (void*)zFilename;
+-#endif
++    pFile->lastErrno = 0; /* not a system error */
++    /* Unread parts of the buffer must be zero-filled */
++    memset(&((char*)pBuf)[got], 0, amt-got);
++    return SQLITE_IOERR_SHORT_READ;
+   }
++}
+ 
+-  if( pLockingStyle == &posixIoMethods
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+-    || pLockingStyle == &nfsIoMethods
+-#endif
+-  ){
+-    unixEnterMutex();
+-    rc = findInodeInfo(pNew, &pNew->pInode);
+-    if( rc!=SQLITE_OK ){
+-      /* If an error occurred in findInodeInfo(), close the file descriptor
+-      ** immediately, before releasing the mutex. findInodeInfo() may fail
+-      ** in two scenarios:
+-      **
+-      **   (a) A call to fstat() failed.
+-      **   (b) A malloc failed.
+-      **
+-      ** Scenario (b) may only occur if the process is holding no other
+-      ** file descriptors open on the same file. If there were other file
+-      ** descriptors on this file, then no malloc would be required by
+-      ** findInodeInfo(). If this is the case, it is quite safe to close
+-      ** handle h - as it is guaranteed that no posix locks will be released
+-      ** by doing so.
+-      **
+-      ** If scenario (a) caused the error then things are not so safe. The
+-      ** implicit assumption here is that if fstat() fails, things are in
+-      ** such bad shape that dropping a lock or two doesn't matter much.
+-      */
+-      robust_close(pNew, h, __LINE__);
+-      h = -1;
++/*
++** Attempt to seek the file-descriptor passed as the first argument to
++** absolute offset iOff, then attempt to write nBuf bytes of data from
++** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, 
++** return the actual number of bytes written (which may be less than
++** nBuf).
++*/
++static int seekAndWriteFd(
++  int fd,                         /* File descriptor to write to */
++  i64 iOff,                       /* File offset to begin writing at */
++  const void *pBuf,               /* Copy data from this buffer to the file */
++  int nBuf,                       /* Size of buffer pBuf in bytes */
++  int *piErrno                    /* OUT: Error number if error occurs */
++){
++  int rc = 0;                     /* Value returned by system call */
++
++  assert( nBuf==(nBuf&0x1ffff) );
++  nBuf &= 0x1ffff;
++  TIMER_START;
++
++#if defined(USE_PREAD)
++  do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
++#elif defined(USE_PREAD64)
++  do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
++#else
++  do{
++    i64 iSeek = lseek(fd, iOff, SEEK_SET);
++    SimulateIOError( iSeek-- );
++
++    if( iSeek!=iOff ){
++      if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
++      return -1;
+     }
+-    unixLeaveMutex();
+-  }
++    rc = osWrite(fd, pBuf, nBuf);
++  }while( rc<0 && errno==EINTR );
++#endif
++
++  TIMER_END;
++  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
++
++  if( rc<0 && piErrno ) *piErrno = errno;
++  return rc;
++}
++
++
++/*
++** Seek to the offset in id->offset then read cnt bytes into pBuf.
++** Return the number of bytes actually read.  Update the offset.
++**
++** To avoid stomping the errno value on a failed write the lastErrno value
++** is set before returning.
++*/
++static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
++  return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
++}
++
++
++/*
++** Write data from a buffer into a file.  Return SQLITE_OK on success
++** or some other error code on failure.
++*/
++static int unixWrite(
++  sqlite3_file *id, 
++  const void *pBuf, 
++  int amt,
++  sqlite3_int64 offset 
++){
++  unixFile *pFile = (unixFile*)id;
++  int wrote = 0;
++  assert( id );
++  assert( amt>0 );
++
++  /* If this is a database file (not a journal, master-journal or temp
++  ** file), the bytes in the locking range should never be read or written. */
++#if 0
++  assert( pFile->pUnused==0
++       || offset>=PENDING_BYTE+512
++       || offset+amt<=PENDING_BYTE 
++  );
++#endif
+ 
+-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+-  else if( pLockingStyle == &afpIoMethods ){
+-    /* AFP locking uses the file path so it needs to be included in
+-    ** the afpLockingContext.
+-    */
+-    afpLockingContext *pCtx;
+-    pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
+-    if( pCtx==0 ){
+-      rc = SQLITE_NOMEM;
+-    }else{
+-      /* NB: zFilename exists and remains valid until the file is closed
+-      ** according to requirement F11141.  So we do not need to make a
+-      ** copy of the filename. */
+-      pCtx->dbPath = zFilename;
+-      pCtx->reserved = 0;
+-      srandomdev();
+-      unixEnterMutex();
+-      rc = findInodeInfo(pNew, &pNew->pInode);
+-      if( rc!=SQLITE_OK ){
+-        sqlite3_free(pNew->lockingContext);
+-        robust_close(pNew, h, __LINE__);
+-        h = -1;
++#ifdef SQLITE_DEBUG
++  /* If we are doing a normal write to a database file (as opposed to
++  ** doing a hot-journal rollback or a write to some file other than a
++  ** normal database file) then record the fact that the database
++  ** has changed.  If the transaction counter is modified, record that
++  ** fact too.
++  */
++  if( pFile->inNormalWrite ){
++    pFile->dbUpdate = 1;  /* The database has been modified */
++    if( offset<=24 && offset+amt>=27 ){
++      int rc;
++      char oldCntr[4];
++      SimulateIOErrorBenign(1);
++      rc = seekAndRead(pFile, 24, oldCntr, 4);
++      SimulateIOErrorBenign(0);
++      if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
++        pFile->transCntrChng = 1;  /* The transaction counter has changed */
+       }
+-      unixLeaveMutex();        
+     }
+   }
+ #endif
+ 
+-  else if( pLockingStyle == &dotlockIoMethods ){
+-    /* Dotfile locking uses the file path so it needs to be included in
+-    ** the dotlockLockingContext 
+-    */
+-    char *zLockFile;
+-    int nFilename;
+-    assert( zFilename!=0 );
+-    nFilename = (int)strlen(zFilename) + 6;
+-    zLockFile = (char *)sqlite3_malloc(nFilename);
+-    if( zLockFile==0 ){
+-      rc = SQLITE_NOMEM;
++#if SQLITE_MAX_MMAP_SIZE>0
++  /* Deal with as much of this write request as possible by transfering
++  ** data from the memory mapping using memcpy().  */
++  if( offset<pFile->mmapSize ){
++    if( offset+amt <= pFile->mmapSize ){
++      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
++      return SQLITE_OK;
+     }else{
+-      sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
++      int nCopy = pFile->mmapSize - offset;
++      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
++      pBuf = &((u8 *)pBuf)[nCopy];
++      amt -= nCopy;
++      offset += nCopy;
+     }
+-    pNew->lockingContext = zLockFile;
+   }
++#endif
+ 
+-#if OS_VXWORKS
+-  else if( pLockingStyle == &semIoMethods ){
+-    /* Named semaphore locking uses the file path so it needs to be
+-    ** included in the semLockingContext
+-    */
+-    unixEnterMutex();
+-    rc = findInodeInfo(pNew, &pNew->pInode);
+-    if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
+-      char *zSemName = pNew->pInode->aSemName;
+-      int n;
+-      sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
+-                       pNew->pId->zCanonicalName);
+-      for( n=1; zSemName[n]; n++ )
+-        if( zSemName[n]=='/' ) zSemName[n] = '_';
+-      pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
+-      if( pNew->pInode->pSem == SEM_FAILED ){
+-        rc = SQLITE_NOMEM;
+-        pNew->pInode->aSemName[0] = '\0';
+-      }
++  while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
++    amt -= wrote;
++    offset += wrote;
++    pBuf = &((char*)pBuf)[wrote];
++  }
++  SimulateIOError(( wrote=(-1), amt=1 ));
++  SimulateDiskfullError(( wrote=0, amt=1 ));
++
++  if( amt>0 ){
++    if( wrote<0 && pFile->lastErrno!=ENOSPC ){
++      /* lastErrno set by seekAndWrite */
++      return SQLITE_IOERR_WRITE;
++    }else{
++      pFile->lastErrno = 0; /* not a system error */
++      return SQLITE_FULL;
+     }
+-    unixLeaveMutex();
+   }
++
++  return SQLITE_OK;
++}
++
++#ifdef SQLITE_TEST
++/*
++** Count the number of fullsyncs and normal syncs.  This is used to test
++** that syncs and fullsyncs are occurring at the right times.
++*/
++SQLITE_API int sqlite3_sync_count = 0;
++SQLITE_API int sqlite3_fullsync_count = 0;
+ #endif
+-  
+-  pNew->lastErrno = 0;
+-#if OS_VXWORKS
+-  if( rc!=SQLITE_OK ){
+-    if( h>=0 ) robust_close(pNew, h, __LINE__);
+-    h = -1;
+-    osUnlink(zFilename);
+-    pNew->ctrlFlags |= UNIXFILE_DELETE;
+-  }
++
++/*
++** We do not trust systems to provide a working fdatasync().  Some do.
++** Others do no.  To be safe, we will stick with the (slightly slower)
++** fsync(). If you know that your system does support fdatasync() correctly,
++** then simply compile with -Dfdatasync=fdatasync
++*/
++#if !defined(fdatasync)
++# define fdatasync fsync
+ #endif
+-  if( rc!=SQLITE_OK ){
+-    if( h>=0 ) robust_close(pNew, h, __LINE__);
+-  }else{
+-    pNew->pMethod = pLockingStyle;
+-    OpenCounter(+1);
+-    verifyDbFile(pNew);
+-  }
+-  return rc;
+-}
+ 
+ /*
+-** Return the name of a directory in which to put temporary files.
+-** If no suitable temporary file directory can be found, return NULL.
++** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
++** the F_FULLFSYNC macro is defined.  F_FULLFSYNC is currently
++** only available on Mac OS X.  But that could change.
+ */
+-static const char *unixTempFileDir(void){
+-  static const char *azDirs[] = {
+-     0,
+-     0,
+-     "/var/tmp",
+-     "/usr/tmp",
+-     "/tmp",
+-     0        /* List terminator */
+-  };
+-  unsigned int i;
+-  struct stat buf;
+-  const char *zDir = 0;
++#ifdef F_FULLFSYNC
++# define HAVE_FULLFSYNC 1
++#else
++# define HAVE_FULLFSYNC 0
++#endif
+ 
+-  azDirs[0] = sqlite3_temp_directory;
+-  if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
+-  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
+-    if( zDir==0 ) continue;
+-    if( osStat(zDir, &buf) ) continue;
+-    if( !S_ISDIR(buf.st_mode) ) continue;
+-    if( osAccess(zDir, 07) ) continue;
+-    break;
+-  }
+-  return zDir;
+-}
+ 
+ /*
+-** Create a temporary file name in zBuf.  zBuf must be allocated
+-** by the calling process and must be big enough to hold at least
+-** pVfs->mxPathname bytes.
++** The fsync() system call does not work as advertised on many
++** unix systems.  The following procedure is an attempt to make
++** it work better.
++**
++** The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful
++** for testing when we want to run through the test suite quickly.
++** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
++** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
++** or power failure will likely corrupt the database file.
++**
++** SQLite sets the dataOnly flag if the size of the file is unchanged.
++** The idea behind dataOnly is that it should only write the file content
++** to disk, not the inode.  We only set dataOnly if the file size is 
++** unchanged since the file size is part of the inode.  However, 
++** Ted Ts'o tells us that fdatasync() will also write the inode if the
++** file size has changed.  The only real difference between fdatasync()
++** and fsync(), Ted tells us, is that fdatasync() will not flush the
++** inode if the mtime or owner or other inode attributes have changed.
++** We only care about the file size, not the other file attributes, so
++** as far as SQLite is concerned, an fdatasync() is always adequate.
++** So, we always use fdatasync() if it is available, regardless of
++** the value of the dataOnly flag.
+ */
+-static int unixGetTempname(int nBuf, char *zBuf){
+-  static const unsigned char zChars[] =
+-    "abcdefghijklmnopqrstuvwxyz"
+-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+-    "0123456789";
+-  unsigned int i, j;
+-  const char *zDir;
++static int full_fsync(int fd, int fullSync, int dataOnly){
++  int rc;
+ 
+-  /* It's odd to simulate an io-error here, but really this is just
+-  ** using the io-error infrastructure to test that SQLite handles this
+-  ** function failing. 
++  /* The following "ifdef/elif/else/" block has the same structure as
++  ** the one below. It is replicated here solely to avoid cluttering 
++  ** up the real code with the UNUSED_PARAMETER() macros.
+   */
+-  SimulateIOError( return SQLITE_IOERR );
++#ifdef SQLITE_NO_SYNC
++  UNUSED_PARAMETER(fd);
++  UNUSED_PARAMETER(fullSync);
++  UNUSED_PARAMETER(dataOnly);
++#elif HAVE_FULLFSYNC
++  UNUSED_PARAMETER(dataOnly);
++#else
++  UNUSED_PARAMETER(fullSync);
++  UNUSED_PARAMETER(dataOnly);
++#endif
+ 
+-  zDir = unixTempFileDir();
+-  if( zDir==0 ) zDir = ".";
++  /* Record the number of times that we do a normal fsync() and 
++  ** FULLSYNC.  This is used during testing to verify that this procedure
++  ** gets called with the correct arguments.
++  */
++#ifdef SQLITE_TEST
++  if( fullSync ) sqlite3_fullsync_count++;
++  sqlite3_sync_count++;
++#endif
+ 
+-  /* Check that the output buffer is large enough for the temporary file 
+-  ** name. If it is not, return SQLITE_ERROR.
++  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
++  ** no-op
+   */
+-  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
+-    return SQLITE_ERROR;
++#ifdef SQLITE_NO_SYNC
++  rc = SQLITE_OK;
++#elif HAVE_FULLFSYNC
++  if( fullSync ){
++    rc = osFcntl(fd, F_FULLFSYNC, 0);
++  }else{
++    rc = 1;
++  }
++  /* If the FULLFSYNC failed, fall back to attempting an fsync().
++  ** It shouldn't be possible for fullfsync to fail on the local 
++  ** file system (on OSX), so failure indicates that FULLFSYNC
++  ** isn't supported for this file system. So, attempt an fsync 
++  ** and (for now) ignore the overhead of a superfluous fcntl call.  
++  ** It'd be better to detect fullfsync support once and avoid 
++  ** the fcntl call every time sync is called.
++  */
++  if( rc ) rc = fsync(fd);
++
++#elif defined(__APPLE__)
++  /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
++  ** so currently we default to the macro that redefines fdatasync to fsync
++  */
++  rc = fsync(fd);
++#else 
++  rc = fdatasync(fd);
++#if OS_VXWORKS
++  if( rc==-1 && errno==ENOTSUP ){
++    rc = fsync(fd);
+   }
++#endif /* OS_VXWORKS */
++#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
+ 
+-  do{
+-    sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
+-    j = (int)strlen(zBuf);
+-    sqlite3_randomness(15, &zBuf[j]);
+-    for(i=0; i<15; i++, j++){
+-      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
+-    }
+-    zBuf[j] = 0;
+-    zBuf[j+1] = 0;
+-  }while( osAccess(zBuf,0)==0 );
+-  return SQLITE_OK;
++  if( OS_VXWORKS && rc!= -1 ){
++    rc = 0;
++  }
++  return rc;
+ }
+ 
+-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+ /*
+-** Routine to transform a unixFile into a proxy-locking unixFile.
+-** Implementation in the proxy-lock division, but used by unixOpen()
+-** if SQLITE_PREFER_PROXY_LOCKING is defined.
++** Open a file descriptor to the directory containing file zFilename.
++** If successful, *pFd is set to the opened file descriptor and
++** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
++** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
++** value.
++**
++** The directory file descriptor is used for only one thing - to
++** fsync() a directory to make sure file creation and deletion events
++** are flushed to disk.  Such fsyncs are not needed on newer
++** journaling filesystems, but are required on older filesystems.
++**
++** This routine can be overridden using the xSetSysCall interface.
++** The ability to override this routine was added in support of the
++** chromium sandbox.  Opening a directory is a security risk (we are
++** told) so making it overrideable allows the chromium sandbox to
++** replace this routine with a harmless no-op.  To make this routine
++** a no-op, replace it with a stub that returns SQLITE_OK but leaves
++** *pFd set to a negative number.
++**
++** If SQLITE_OK is returned, the caller is responsible for closing
++** the file descriptor *pFd using close().
+ */
+-static int proxyTransformUnixFile(unixFile*, const char*);
+-#endif
++static int openDirectory(const char *zFilename, int *pFd){
++  int ii;
++  int fd = -1;
++  char zDirname[MAX_PATHNAME+1];
++
++  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
++  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
++  if( ii>0 ){
++    zDirname[ii] = '\0';
++    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
++    if( fd>=0 ){
++      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
++    }
++  }
++  *pFd = fd;
++  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
++}
+ 
+ /*
+-** Search for an unused file descriptor that was opened on the database 
+-** file (not a journal or master-journal file) identified by pathname
+-** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
+-** argument to this function.
++** Make sure all writes to a particular file are committed to disk.
+ **
+-** Such a file descriptor may exist if a database connection was closed
+-** but the associated file descriptor could not be closed because some
+-** other file descriptor open on the same file is holding a file-lock.
+-** Refer to comments in the unixClose() function and the lengthy comment
+-** describing "Posix Advisory Locking" at the start of this file for 
+-** further details. Also, ticket #4018.
++** If dataOnly==0 then both the file itself and its metadata (file
++** size, access time, etc) are synced.  If dataOnly!=0 then only the
++** file data is synced.
+ **
+-** If a suitable file descriptor is found, then it is returned. If no
+-** such file descriptor is located, -1 is returned.
++** Under Unix, also make sure that the directory entry for the file
++** has been created by fsync-ing the directory that contains the file.
++** If we do not do this and we encounter a power failure, the directory
++** entry for the journal might not exist after we reboot.  The next
++** SQLite to access the file will not know that the journal exists (because
++** the directory entry for the journal was never created) and the transaction
++** will not roll back - possibly leading to database corruption.
+ */
+-static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
+-  UnixUnusedFd *pUnused = 0;
++static int unixSync(sqlite3_file *id, int flags){
++  int rc;
++  unixFile *pFile = (unixFile*)id;
+ 
+-  /* Do not search for an unused file descriptor on vxworks. Not because
+-  ** vxworks would not benefit from the change (it might, we're not sure),
+-  ** but because no way to test it is currently available. It is better 
+-  ** not to risk breaking vxworks support for the sake of such an obscure 
+-  ** feature.  */
+-#if !OS_VXWORKS
+-  struct stat sStat;                   /* Results of stat() call */
++  int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
++  int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
+ 
+-  /* A stat() call may fail for various reasons. If this happens, it is
+-  ** almost certain that an open() call on the same path will also fail.
+-  ** For this reason, if an error occurs in the stat() call here, it is
+-  ** ignored and -1 is returned. The caller will try to open a new file
+-  ** descriptor on the same path, fail, and return an error to SQLite.
+-  **
+-  ** Even if a subsequent open() call does succeed, the consequences of
+-  ** not searching for a resusable file descriptor are not dire.  */
+-  if( 0==osStat(zPath, &sStat) ){
+-    unixInodeInfo *pInode;
++  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
++  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
++      || (flags&0x0F)==SQLITE_SYNC_FULL
++  );
+ 
+-    unixEnterMutex();
+-    pInode = inodeList;
+-    while( pInode && (pInode->fileId.dev!=sStat.st_dev
+-                     || pInode->fileId.ino!=sStat.st_ino) ){
+-       pInode = pInode->pNext;
+-    }
+-    if( pInode ){
+-      UnixUnusedFd **pp;
+-      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
+-      pUnused = *pp;
+-      if( pUnused ){
+-        *pp = pUnused->pNext;
+-      }
++  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
++  ** line is to test that doing so does not cause any problems.
++  */
++  SimulateDiskfullError( return SQLITE_FULL );
++
++  assert( pFile );
++  OSTRACE(("SYNC    %-3d\n", pFile->h));
++  rc = full_fsync(pFile->h, isFullsync, isDataOnly);
++  SimulateIOError( rc=1 );
++  if( rc ){
++    pFile->lastErrno = errno;
++    return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
++  }
++
++  /* Also fsync the directory containing the file if the DIRSYNC flag
++  ** is set.  This is a one-time occurrence.  Many systems (examples: AIX)
++  ** are unable to fsync a directory, so ignore errors on the fsync.
++  */
++  if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
++    int dirfd;
++    OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
++            HAVE_FULLFSYNC, isFullsync));
++    rc = osOpenDirectory(pFile->zPath, &dirfd);
++    if( rc==SQLITE_OK && dirfd>=0 ){
++      full_fsync(dirfd, 0, 0);
++      robust_close(pFile, dirfd, __LINE__);
++    }else if( rc==SQLITE_CANTOPEN ){
++      rc = SQLITE_OK;
+     }
+-    unixLeaveMutex();
++    pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
+   }
+-#endif    /* if !OS_VXWORKS */
+-  return pUnused;
++  return rc;
+ }
+ 
+ /*
+-** This function is called by unixOpen() to determine the unix permissions
+-** to create new files with. If no error occurs, then SQLITE_OK is returned
+-** and a value suitable for passing as the third argument to open(2) is
+-** written to *pMode. If an IO error occurs, an SQLite error code is 
+-** returned and the value of *pMode is not modified.
+-**
+-** In most cases cases, this routine sets *pMode to 0, which will become
+-** an indication to robust_open() to create the file using
+-** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
+-** But if the file being opened is a WAL or regular journal file, then 
+-** this function queries the file-system for the permissions on the 
+-** corresponding database file and sets *pMode to this value. Whenever 
+-** possible, WAL and journal files are created using the same permissions 
+-** as the associated database file.
+-**
+-** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
+-** original filename is unavailable.  But 8_3_NAMES is only used for
+-** FAT filesystems and permissions do not matter there, so just use
+-** the default permissions.
++** Truncate an open file to a specified size
+ */
+-static int findCreateFileMode(
+-  const char *zPath,              /* Path of file (possibly) being created */
+-  int flags,                      /* Flags passed as 4th argument to xOpen() */
+-  mode_t *pMode,                  /* OUT: Permissions to open file with */
+-  uid_t *pUid,                    /* OUT: uid to set on the file */
+-  gid_t *pGid                     /* OUT: gid to set on the file */
+-){
+-  int rc = SQLITE_OK;             /* Return Code */
+-  *pMode = 0;
+-  *pUid = 0;
+-  *pGid = 0;
+-  if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
+-    char zDb[MAX_PATHNAME+1];     /* Database file path */
+-    int nDb;                      /* Number of valid bytes in zDb */
+-    struct stat sStat;            /* Output of stat() on database file */
++static int unixTruncate(sqlite3_file *id, i64 nByte){
++  unixFile *pFile = (unixFile *)id;
++  int rc;
++  assert( pFile );
++  SimulateIOError( return SQLITE_IOERR_TRUNCATE );
+ 
+-    /* zPath is a path to a WAL or journal file. The following block derives
+-    ** the path to the associated database file from zPath. This block handles
+-    ** the following naming conventions:
+-    **
+-    **   "<path to db>-journal"
+-    **   "<path to db>-wal"
+-    **   "<path to db>-journalNN"
+-    **   "<path to db>-walNN"
+-    **
+-    ** where NN is a decimal number. The NN naming schemes are 
+-    ** used by the test_multiplex.c module.
+-    */
+-    nDb = sqlite3Strlen30(zPath) - 1; 
+-#ifdef SQLITE_ENABLE_8_3_NAMES
+-    while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
+-    if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
+-#else
+-    while( zPath[nDb]!='-' ){
+-      assert( nDb>0 );
+-      assert( zPath[nDb]!='\n' );
+-      nDb--;
++  /* If the user has configured a chunk-size for this file, truncate the
++  ** file so that it consists of an integer number of chunks (i.e. the
++  ** actual file size after the operation may be larger than the requested
++  ** size).
++  */
++  if( pFile->szChunk>0 ){
++    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
++  }
++
++  rc = robust_ftruncate(pFile->h, (off_t)nByte);
++  if( rc ){
++    pFile->lastErrno = errno;
++    return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
++  }else{
++#ifdef SQLITE_DEBUG
++    /* If we are doing a normal write to a database file (as opposed to
++    ** doing a hot-journal rollback or a write to some file other than a
++    ** normal database file) and we truncate the file to zero length,
++    ** that effectively updates the change counter.  This might happen
++    ** when restoring a database using the backup API from a zero-length
++    ** source.
++    */
++    if( pFile->inNormalWrite && nByte==0 ){
++      pFile->transCntrChng = 1;
+     }
+ #endif
+-    memcpy(zDb, zPath, nDb);
+-    zDb[nDb] = '\0';
+ 
+-    if( 0==osStat(zDb, &sStat) ){
+-      *pMode = sStat.st_mode & 0777;
+-      *pUid = sStat.st_uid;
+-      *pGid = sStat.st_gid;
+-    }else{
+-      rc = SQLITE_IOERR_FSTAT;
++    /* If the file was just truncated to a size smaller than the currently
++    ** mapped region, reduce the effective mapping size as well. SQLite will
++    ** use read() and write() to access data beyond this point from now on.  
++    */
++    if( nByte<pFile->mmapSize ){
++      pFile->mmapSize = nByte;
+     }
+-  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
+-    *pMode = 0600;
++
++    return SQLITE_OK;
+   }
+-  return rc;
+ }
+ 
+ /*
+-** Open the file zPath.
+-** 
+-** Previously, the SQLite OS layer used three functions in place of this
+-** one:
+-**
+-**     sqlite3OsOpenReadWrite();
+-**     sqlite3OsOpenReadOnly();
+-**     sqlite3OsOpenExclusive();
+-**
+-** These calls correspond to the following combinations of flags:
+-**
+-**     ReadWrite() ->     (READWRITE | CREATE)
+-**     ReadOnly()  ->     (READONLY) 
+-**     OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
+-**
+-** The old OpenExclusive() accepted a boolean argument - "delFlag". If
+-** true, the file was configured to be automatically deleted when the
+-** file handle closed. To achieve the same effect using this new 
+-** interface, add the DELETEONCLOSE flag to those specified above for 
+-** OpenExclusive().
++** Determine the current size of a file in bytes
+ */
+-static int unixOpen(
+-  sqlite3_vfs *pVfs,           /* The VFS for which this is the xOpen method */
+-  const char *zPath,           /* Pathname of file to be opened */
+-  sqlite3_file *pFile,         /* The file descriptor to be filled in */
+-  int flags,                   /* Input flags to control the opening */
+-  int *pOutFlags               /* Output flags returned to SQLite core */
+-){
+-  unixFile *p = (unixFile *)pFile;
+-  int fd = -1;                   /* File descriptor returned by open() */
+-  int openFlags = 0;             /* Flags to pass to open() */
+-  int eType = flags&0xFFFFFF00;  /* Type of file to open */
+-  int noLock;                    /* True to omit locking primitives */
+-  int rc = SQLITE_OK;            /* Function Return Code */
+-  int ctrlFlags = 0;             /* UNIXFILE_* flags */
+-
+-  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
+-  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
+-  int isCreate     = (flags & SQLITE_OPEN_CREATE);
+-  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
+-  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
+-#endif
+-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
+-  struct statfs fsInfo;
+-#endif
++static int unixFileSize(sqlite3_file *id, i64 *pSize){
++  int rc;
++  struct stat buf;
++  assert( id );
++  rc = osFstat(((unixFile*)id)->h, &buf);
++  SimulateIOError( rc=1 );
++  if( rc!=0 ){
++    ((unixFile*)id)->lastErrno = errno;
++    return SQLITE_IOERR_FSTAT;
++  }
++  *pSize = buf.st_size;
+ 
+-  /* If creating a master or main-file journal, this function will open
+-  ** a file-descriptor on the directory too. The first time unixSync()
+-  ** is called the directory file descriptor will be fsync()ed and close()d.
++  /* When opening a zero-size database, the findInodeInfo() procedure
++  ** writes a single byte into that file in order to work around a bug
++  ** in the OS-X msdos filesystem.  In order to avoid problems with upper
++  ** layers, we need to report this file size as zero even though it is
++  ** really 1.   Ticket #3260.
+   */
+-  int syncDir = (isCreate && (
+-        eType==SQLITE_OPEN_MASTER_JOURNAL 
+-     || eType==SQLITE_OPEN_MAIN_JOURNAL 
+-     || eType==SQLITE_OPEN_WAL
+-  ));
++  if( *pSize==1 ) *pSize = 0;
+ 
+-  /* If argument zPath is a NULL pointer, this function is required to open
+-  ** a temporary file. Use this buffer to store the file name in.
+-  */
+-  char zTmpname[MAX_PATHNAME+2];
+-  const char *zName = zPath;
+ 
+-  /* Check the following statements are true: 
+-  **
+-  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
+-  **   (b) if CREATE is set, then READWRITE must also be set, and
+-  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
+-  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
+-  */
+-  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
+-  assert(isCreate==0 || isReadWrite);
+-  assert(isExclusive==0 || isCreate);
+-  assert(isDelete==0 || isCreate);
++  return SQLITE_OK;
++}
+ 
+-  /* The main DB, main journal, WAL file and master journal are never 
+-  ** automatically deleted. Nor are they ever temporary files.  */
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
++#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
++/*
++** Handler for proxy-locking file-control verbs.  Defined below in the
++** proxying locking division.
++*/
++static int proxyFileControl(sqlite3_file*,int,void*);
++#endif
+ 
+-  /* Assert that the upper layer has set one of the "file-type" flags. */
+-  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
+-       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
+-       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
+-       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
+-  );
++/* 
++** This function is called to handle the SQLITE_FCNTL_SIZE_HINT 
++** file-control operation.  Enlarge the database to nBytes in size
++** (rounded up to the next chunk-size).  If the database is already
++** nBytes or larger, this routine is a no-op.
++*/
++static int fcntlSizeHint(unixFile *pFile, i64 nByte){
++  if( pFile->szChunk>0 ){
++    i64 nSize;                    /* Required file size */
++    struct stat buf;              /* Used to hold return values of fstat() */
++   
++    if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
+ 
+-  memset(p, 0, sizeof(unixFile));
++    nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
++    if( nSize>(i64)buf.st_size ){
+ 
+-  if( eType==SQLITE_OPEN_MAIN_DB ){
+-    UnixUnusedFd *pUnused;
+-    pUnused = findReusableFd(zName, flags);
+-    if( pUnused ){
+-      fd = pUnused->fd;
+-    }else{
+-      pUnused = sqlite3_malloc(sizeof(*pUnused));
+-      if( !pUnused ){
+-        return SQLITE_NOMEM;
++#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
++      /* The code below is handling the return value of osFallocate() 
++      ** correctly. posix_fallocate() is defined to "returns zero on success, 
++      ** or an error number on  failure". See the manpage for details. */
++      int err;
++      do{
++        err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
++      }while( err==EINTR );
++      if( err ) return SQLITE_IOERR_WRITE;
++#else
++      /* If the OS does not have posix_fallocate(), fake it. First use
++      ** ftruncate() to set the file size, then write a single byte to
++      ** the last byte in each block within the extended region. This
++      ** is the same technique used by glibc to implement posix_fallocate()
++      ** on systems that do not have a real fallocate() system call.
++      */
++      int nBlk = buf.st_blksize;  /* File-system block size */
++      i64 iWrite;                 /* Next offset to write to */
++
++      if( robust_ftruncate(pFile->h, nSize) ){
++        pFile->lastErrno = errno;
++        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
++      }
++      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
++      while( iWrite<nSize ){
++        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
++        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
++        iWrite += nBlk;
+       }
++#endif
+     }
+-    p->pUnused = pUnused;
+-
+-    /* Database filenames are double-zero terminated if they are not
+-    ** URIs with parameters.  Hence, they can always be passed into
+-    ** sqlite3_uri_parameter(). */
+-    assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
++  }
+ 
+-  }else if( !zName ){
+-    /* If zName is NULL, the upper layer is requesting a temp file. */
+-    assert(isDelete && !syncDir);
+-    rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
+-    if( rc!=SQLITE_OK ){
+-      return rc;
++  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
++    int rc;
++    if( pFile->szChunk<=0 ){
++      if( robust_ftruncate(pFile->h, nByte) ){
++        pFile->lastErrno = errno;
++        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
++      }
+     }
+-    zName = zTmpname;
+ 
+-    /* Generated temporary filenames are always double-zero terminated
+-    ** for use by sqlite3_uri_parameter(). */
+-    assert( zName[strlen(zName)+1]==0 );
++    rc = unixMapfile(pFile, nByte);
++    return rc;
+   }
+ 
+-  /* Determine the value of the flags parameter passed to POSIX function
+-  ** open(). These must be calculated even if open() is not called, as
+-  ** they may be stored as part of the file handle and used by the 
+-  ** 'conch file' locking functions later on.  */
+-  if( isReadonly )  openFlags |= O_RDONLY;
+-  if( isReadWrite ) openFlags |= O_RDWR;
+-  if( isCreate )    openFlags |= O_CREAT;
+-  if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
+-  openFlags |= (O_LARGEFILE|O_BINARY);
++  return SQLITE_OK;
++}
+ 
+-  if( fd<0 ){
+-    mode_t openMode;              /* Permissions to create file with */
+-    uid_t uid;                    /* Userid for the file */
+-    gid_t gid;                    /* Groupid for the file */
+-    rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
+-    if( rc!=SQLITE_OK ){
+-      assert( !p->pUnused );
+-      assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
++/*
++** If *pArg is inititially negative then this is a query.  Set *pArg to
++** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
++**
++** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
++*/
++static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
++  if( *pArg<0 ){
++    *pArg = (pFile->ctrlFlags & mask)!=0;
++  }else if( (*pArg)==0 ){
++    pFile->ctrlFlags &= ~mask;
++  }else{
++    pFile->ctrlFlags |= mask;
++  }
++}
++
++/* Forward declaration */
++static int unixGetTempname(int nBuf, char *zBuf);
++
++/*
++** Information and control of an open file handle.
++*/
++static int unixFileControl(sqlite3_file *id, int op, void *pArg){
++  unixFile *pFile = (unixFile*)id;
++  switch( op ){
++    case SQLITE_FCNTL_LOCKSTATE: {
++      *(int*)pArg = pFile->eFileLock;
++      return SQLITE_OK;
++    }
++    case SQLITE_LAST_ERRNO: {
++      *(int*)pArg = pFile->lastErrno;
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_CHUNK_SIZE: {
++      pFile->szChunk = *(int *)pArg;
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_SIZE_HINT: {
++      int rc;
++      SimulateIOErrorBenign(1);
++      rc = fcntlSizeHint(pFile, *(i64 *)pArg);
++      SimulateIOErrorBenign(0);
+       return rc;
+     }
+-    fd = robust_open(zName, openFlags, openMode);
+-    OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
+-    if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
+-      /* Failed to open the file for read/write access. Try read-only. */
+-      flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
+-      openFlags &= ~(O_RDWR|O_CREAT);
+-      flags |= SQLITE_OPEN_READONLY;
+-      openFlags |= O_RDONLY;
+-      isReadonly = 1;
+-      fd = robust_open(zName, openFlags, openMode);
++    case SQLITE_FCNTL_PERSIST_WAL: {
++      unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
++      return SQLITE_OK;
+     }
+-    if( fd<0 ){
+-      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
+-      goto open_finished;
++    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
++      unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
++      return SQLITE_OK;
+     }
+-
+-    /* If this process is running as root and if creating a new rollback
+-    ** journal or WAL file, set the ownership of the journal or WAL to be
+-    ** the same as the original database.
++    case SQLITE_FCNTL_VFSNAME: {
++      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_TEMPFILENAME: {
++      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
++      if( zTFile ){
++        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
++        *(char**)pArg = zTFile;
++      }
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_MMAP_SIZE: {
++      i64 newLimit = *(i64*)pArg;
++      if( newLimit>sqlite3GlobalConfig.mxMmap ){
++        newLimit = sqlite3GlobalConfig.mxMmap;
++      }
++      *(i64*)pArg = pFile->mmapSizeMax;
++      if( newLimit>=0 ){
++        pFile->mmapSizeMax = newLimit;
++        if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
++      }
++      return SQLITE_OK;
++    }
++#ifdef SQLITE_DEBUG
++    /* The pager calls this method to signal that it has done
++    ** a rollback and that the database is therefore unchanged and
++    ** it hence it is OK for the transaction change counter to be
++    ** unchanged.
+     */
+-    if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
+-      osFchown(fd, uid, gid);
++    case SQLITE_FCNTL_DB_UNCHANGED: {
++      ((unixFile*)id)->dbUpdate = 0;
++      return SQLITE_OK;
+     }
+-  }
+-  assert( fd>=0 );
+-  if( pOutFlags ){
+-    *pOutFlags = flags;
+-  }
+-
+-  if( p->pUnused ){
+-    p->pUnused->fd = fd;
+-    p->pUnused->flags = flags;
+-  }
+-
+-  if( isDelete ){
+-#if OS_VXWORKS
+-    zPath = zName;
+-#else
+-    osUnlink(zName);
+ #endif
++#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
++    case SQLITE_SET_LOCKPROXYFILE:
++    case SQLITE_GET_LOCKPROXYFILE: {
++      return proxyFileControl(id,op,pArg);
++    }
++#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+   }
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-  else{
+-    p->openFlags = openFlags;
+-  }
+-#endif
+-
+-  noLock = eType!=SQLITE_OPEN_MAIN_DB;
++  return SQLITE_NOTFOUND;
++}
+ 
+-  
+-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
+-  if( fstatfs(fd, &fsInfo) == -1 ){
+-    ((unixFile*)pFile)->lastErrno = errno;
+-    robust_close(p, fd, __LINE__);
+-    return SQLITE_IOERR_ACCESS;
+-  }
+-  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
+-    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
+-  }
++/*
++** Return the sector size in bytes of the underlying block device for
++** the specified file. This is almost always 512 bytes, but may be
++** larger for some devices.
++**
++** SQLite code assumes this function cannot fail. It also assumes that
++** if two files are created in the same file-system directory (i.e.
++** a database and its journal file) that the sector size will be the
++** same for both.
++*/
++#ifndef __QNXNTO__ 
++static int unixSectorSize(sqlite3_file *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  return SQLITE_DEFAULT_SECTOR_SIZE;
++}
+ #endif
+ 
+-  /* Set up appropriate ctrlFlags */
+-  if( isDelete )                ctrlFlags |= UNIXFILE_DELETE;
+-  if( isReadonly )              ctrlFlags |= UNIXFILE_RDONLY;
+-  if( noLock )                  ctrlFlags |= UNIXFILE_NOLOCK;
+-  if( syncDir )                 ctrlFlags |= UNIXFILE_DIRSYNC;
+-  if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
+-
+-#if SQLITE_ENABLE_LOCKING_STYLE
+-#if SQLITE_PREFER_PROXY_LOCKING
+-  isAutoProxy = 1;
+-#endif
+-  if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
+-    char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
+-    int useProxy = 0;
++/*
++** The following version of unixSectorSize() is optimized for QNX.
++*/
++#ifdef __QNXNTO__
++#include <sys/dcmd_blk.h>
++#include <sys/statvfs.h>
++static int unixSectorSize(sqlite3_file *id){
++  unixFile *pFile = (unixFile*)id;
++  if( pFile->sectorSize == 0 ){
++    struct statvfs fsInfo;
++       
++    /* Set defaults for non-supported filesystems */
++    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
++    pFile->deviceCharacteristics = 0;
++    if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
++      return pFile->sectorSize;
++    }
+ 
+-    /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means 
+-    ** never use proxy, NULL means use proxy for non-local files only.  */
+-    if( envforce!=NULL ){
+-      useProxy = atoi(envforce)>0;
++    if( !strcmp(fsInfo.f_basetype, "tmp") ) {
++      pFile->sectorSize = fsInfo.f_bsize;
++      pFile->deviceCharacteristics =
++        SQLITE_IOCAP_ATOMIC4K |       /* All ram filesystem writes are atomic */
++        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
++                                      ** the write succeeds */
++        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
++                                      ** so it is ordered */
++        0;
++    }else if( strstr(fsInfo.f_basetype, "etfs") ){
++      pFile->sectorSize = fsInfo.f_bsize;
++      pFile->deviceCharacteristics =
++        /* etfs cluster size writes are atomic */
++        (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
++        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
++                                      ** the write succeeds */
++        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
++                                      ** so it is ordered */
++        0;
++    }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
++      pFile->sectorSize = fsInfo.f_bsize;
++      pFile->deviceCharacteristics =
++        SQLITE_IOCAP_ATOMIC |         /* All filesystem writes are atomic */
++        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
++                                      ** the write succeeds */
++        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
++                                      ** so it is ordered */
++        0;
++    }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
++      pFile->sectorSize = fsInfo.f_bsize;
++      pFile->deviceCharacteristics =
++        /* full bitset of atomics from max sector size and smaller */
++        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
++        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
++                                      ** so it is ordered */
++        0;
++    }else if( strstr(fsInfo.f_basetype, "dos") ){
++      pFile->sectorSize = fsInfo.f_bsize;
++      pFile->deviceCharacteristics =
++        /* full bitset of atomics from max sector size and smaller */
++        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
++        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
++                                      ** so it is ordered */
++        0;
+     }else{
+-      if( statfs(zPath, &fsInfo) == -1 ){
+-        /* In theory, the close(fd) call is sub-optimal. If the file opened
+-        ** with fd is a database file, and there are other connections open
+-        ** on that file that are currently holding advisory locks on it,
+-        ** then the call to close() will cancel those locks. In practice,
+-        ** we're assuming that statfs() doesn't fail very often. At least
+-        ** not while other file descriptors opened by the same process on
+-        ** the same file are working.  */
+-        p->lastErrno = errno;
+-        robust_close(p, fd, __LINE__);
+-        rc = SQLITE_IOERR_ACCESS;
+-        goto open_finished;
+-      }
+-      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
+-    }
+-    if( useProxy ){
+-      rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+-      if( rc==SQLITE_OK ){
+-        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
+-        if( rc!=SQLITE_OK ){
+-          /* Use unixClose to clean up the resources added in fillInUnixFile 
+-          ** and clear all the structure's references.  Specifically, 
+-          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
+-          */
+-          unixClose(pFile);
+-          return rc;
+-        }
+-      }
+-      goto open_finished;
++      pFile->deviceCharacteristics =
++        SQLITE_IOCAP_ATOMIC512 |      /* blocks are atomic */
++        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
++                                      ** the write succeeds */
++        0;
+     }
+   }
+-#endif
+-  
+-  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+-
+-open_finished:
+-  if( rc!=SQLITE_OK ){
+-    sqlite3_free(p->pUnused);
++  /* Last chance verification.  If the sector size isn't a multiple of 512
++  ** then it isn't valid.*/
++  if( pFile->sectorSize % 512 != 0 ){
++    pFile->deviceCharacteristics = 0;
++    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+   }
+-  return rc;
++  return pFile->sectorSize;
+ }
+-
++#endif /* __QNXNTO__ */
+ 
+ /*
+-** Delete the file at zPath. If the dirSync argument is true, fsync()
+-** the directory after deleting the file.
++** Return the device characteristics for the file.
++**
++** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
++** However, that choice is contraversial since technically the underlying
++** file system does not always provide powersafe overwrites.  (In other
++** words, after a power-loss event, parts of the file that were never
++** written might end up being altered.)  However, non-PSOW behavior is very,
++** very rare.  And asserting PSOW makes a large reduction in the amount
++** of required I/O for journaling, since a lot of padding is eliminated.
++**  Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
++** available to turn it off and URI query parameter available to turn it off.
+ */
+-static int unixDelete(
+-  sqlite3_vfs *NotUsed,     /* VFS containing this as the xDelete method */
+-  const char *zPath,        /* Name of file to be deleted */
+-  int dirSync               /* If true, fsync() directory after deleting file */
+-){
+-  int rc = SQLITE_OK;
+-  UNUSED_PARAMETER(NotUsed);
+-  SimulateIOError(return SQLITE_IOERR_DELETE);
+-  if( osUnlink(zPath)==(-1) ){
+-    if( errno==ENOENT ){
+-      rc = SQLITE_IOERR_DELETE_NOENT;
+-    }else{
+-      rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+-    }
+-    return rc;
+-  }
+-#ifndef SQLITE_DISABLE_DIRSYNC
+-  if( (dirSync & 1)!=0 ){
+-    int fd;
+-    rc = osOpenDirectory(zPath, &fd);
+-    if( rc==SQLITE_OK ){
+-#if OS_VXWORKS
+-      if( fsync(fd)==-1 )
+-#else
+-      if( fsync(fd) )
++static int unixDeviceCharacteristics(sqlite3_file *id){
++  unixFile *p = (unixFile*)id;
++  int rc = 0;
++#ifdef __QNXNTO__
++  if( p->sectorSize==0 ) unixSectorSize(id);
++  rc = p->deviceCharacteristics;
+ #endif
+-      {
+-        rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
+-      }
+-      robust_close(0, fd, __LINE__);
+-    }else if( rc==SQLITE_CANTOPEN ){
+-      rc = SQLITE_OK;
+-    }
++  if( p->ctrlFlags & UNIXFILE_PSOW ){
++    rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
+   }
+-#endif
+   return rc;
+ }
+ 
++#ifndef SQLITE_OMIT_WAL
++
++
+ /*
+-** Test the existence of or access permissions of file zPath. The
+-** test performed depends on the value of flags:
++** Object used to represent an shared memory buffer.  
+ **
+-**     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
+-**     SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
+-**     SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
++** When multiple threads all reference the same wal-index, each thread
++** has its own unixShm object, but they all point to a single instance
++** of this unixShmNode object.  In other words, each wal-index is opened
++** only once per process.
+ **
+-** Otherwise return 0.
++** Each unixShmNode object is connected to a single unixInodeInfo object.
++** We could coalesce this object into unixInodeInfo, but that would mean
++** every open file that does not use shared memory (in other words, most
++** open files) would have to carry around this extra information.  So
++** the unixInodeInfo object contains a pointer to this unixShmNode object
++** and the unixShmNode object is created only when needed.
++**
++** unixMutexHeld() must be true when creating or destroying
++** this object or while reading or writing the following fields:
++**
++**      nRef
++**
++** The following fields are read-only after the object is created:
++** 
++**      fid
++**      zFilename
++**
++** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
++** unixMutexHeld() is true when reading or writing any other field
++** in this structure.
+ */
+-static int unixAccess(
+-  sqlite3_vfs *NotUsed,   /* The VFS containing this xAccess method */
+-  const char *zPath,      /* Path of the file to examine */
+-  int flags,              /* What do we want to learn about the zPath file? */
+-  int *pResOut            /* Write result boolean here */
+-){
+-  int amode = 0;
+-  UNUSED_PARAMETER(NotUsed);
+-  SimulateIOError( return SQLITE_IOERR_ACCESS; );
+-  switch( flags ){
+-    case SQLITE_ACCESS_EXISTS:
+-      amode = F_OK;
+-      break;
+-    case SQLITE_ACCESS_READWRITE:
+-      amode = W_OK|R_OK;
+-      break;
+-    case SQLITE_ACCESS_READ:
+-      amode = R_OK;
+-      break;
++struct unixShmNode {
++  unixInodeInfo *pInode;     /* unixInodeInfo that owns this SHM node */
++  sqlite3_mutex *mutex;      /* Mutex to access this object */
++  char *zFilename;           /* Name of the mmapped file */
++  int h;                     /* Open file descriptor */
++  int szRegion;              /* Size of shared-memory regions */
++  u16 nRegion;               /* Size of array apRegion */
++  u8 isReadonly;             /* True if read-only */
++  char **apRegion;           /* Array of mapped shared-memory regions */
++  int nRef;                  /* Number of unixShm objects pointing to this */
++  unixShm *pFirst;           /* All unixShm objects pointing to this */
++#ifdef SQLITE_DEBUG
++  u8 exclMask;               /* Mask of exclusive locks held */
++  u8 sharedMask;             /* Mask of shared locks held */
++  u8 nextShmId;              /* Next available unixShm.id value */
++#endif
++};
+ 
+-    default:
+-      assert(!"Invalid flags argument");
+-  }
+-  *pResOut = (osAccess(zPath, amode)==0);
+-  if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
+-    struct stat buf;
+-    if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
+-      *pResOut = 0;
+-    }
+-  }
+-  return SQLITE_OK;
+-}
++/*
++** Structure used internally by this VFS to record the state of an
++** open shared memory connection.
++**
++** The following fields are initialized when this object is created and
++** are read-only thereafter:
++**
++**    unixShm.pFile
++**    unixShm.id
++**
++** All other fields are read/write.  The unixShm.pFile->mutex must be held
++** while accessing any read/write fields.
++*/
++struct unixShm {
++  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
++  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
++  u8 hasMutex;               /* True if holding the unixShmNode mutex */
++  u8 id;                     /* Id of this connection within its unixShmNode */
++  u16 sharedMask;            /* Mask of shared locks held */
++  u16 exclMask;              /* Mask of exclusive locks held */
++};
+ 
++/*
++** Constants used for locking
++*/
++#define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
++#define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
+ 
+ /*
+-** Turn a relative pathname into a full pathname. The relative path
+-** is stored as a nul-terminated string in the buffer pointed to by
+-** zPath. 
++** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
+ **
+-** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes 
+-** (in this case, MAX_PATHNAME bytes). The full-path is written to
+-** this buffer before returning.
++** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
++** otherwise.
+ */
+-static int unixFullPathname(
+-  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
+-  const char *zPath,            /* Possibly relative input path */
+-  int nOut,                     /* Size of output buffer in bytes */
+-  char *zOut                    /* Output buffer */
++static int unixShmSystemLock(
++  unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
++  int lockType,          /* F_UNLCK, F_RDLCK, or F_WRLCK */
++  int ofst,              /* First byte of the locking range */
++  int n                  /* Number of bytes to lock */
+ ){
++  struct flock f;       /* The posix advisory locking structure */
++  int rc = SQLITE_OK;   /* Result code form fcntl() */
+ 
+-  /* It's odd to simulate an io-error here, but really this is just
+-  ** using the io-error infrastructure to test that SQLite handles this
+-  ** function failing. This function could fail if, for example, the
+-  ** current working directory has been unlinked.
+-  */
+-  SimulateIOError( return SQLITE_ERROR );
++  /* Access to the unixShmNode object is serialized by the caller */
++  assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
+ 
+-  assert( pVfs->mxPathname==MAX_PATHNAME );
+-  UNUSED_PARAMETER(pVfs);
++  /* Shared locks never span more than one byte */
++  assert( n==1 || lockType!=F_RDLCK );
+ 
+-  zOut[nOut-1] = '\0';
+-  if( zPath[0]=='/' ){
+-    sqlite3_snprintf(nOut, zOut, "%s", zPath);
++  /* Locks are within range */
++  assert( n>=1 && n<SQLITE_SHM_NLOCK );
++
++  if( pShmNode->h>=0 ){
++    /* Initialize the locking parameters */
++    memset(&f, 0, sizeof(f));
++    f.l_type = lockType;
++    f.l_whence = SEEK_SET;
++    f.l_start = ofst;
++    f.l_len = n;
++
++    rc = osFcntl(pShmNode->h, F_SETLK, &f);
++    rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
++  }
++
++  /* Update the global lock state and do debug tracing */
++#ifdef SQLITE_DEBUG
++  { u16 mask;
++  OSTRACE(("SHM-LOCK "));
++  mask = (1<<(ofst+n)) - (1<<ofst);
++  if( rc==SQLITE_OK ){
++    if( lockType==F_UNLCK ){
++      OSTRACE(("unlock %d ok", ofst));
++      pShmNode->exclMask &= ~mask;
++      pShmNode->sharedMask &= ~mask;
++    }else if( lockType==F_RDLCK ){
++      OSTRACE(("read-lock %d ok", ofst));
++      pShmNode->exclMask &= ~mask;
++      pShmNode->sharedMask |= mask;
++    }else{
++      assert( lockType==F_WRLCK );
++      OSTRACE(("write-lock %d ok", ofst));
++      pShmNode->exclMask |= mask;
++      pShmNode->sharedMask &= ~mask;
++    }
+   }else{
+-    int nCwd;
+-    if( osGetcwd(zOut, nOut-1)==0 ){
+-      return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
++    if( lockType==F_UNLCK ){
++      OSTRACE(("unlock %d failed", ofst));
++    }else if( lockType==F_RDLCK ){
++      OSTRACE(("read-lock failed"));
++    }else{
++      assert( lockType==F_WRLCK );
++      OSTRACE(("write-lock %d failed", ofst));
+     }
+-    nCwd = (int)strlen(zOut);
+-    sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
+   }
+-  return SQLITE_OK;
+-}
+-
++  OSTRACE((" - afterwards %03x,%03x\n",
++           pShmNode->sharedMask, pShmNode->exclMask));
++  }
++#endif
+ 
+-#ifndef SQLITE_OMIT_LOAD_EXTENSION
+-/*
+-** Interfaces for opening a shared library, finding entry points
+-** within the shared library, and closing the shared library.
+-*/
+-#include <dlfcn.h>
+-static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
+-  UNUSED_PARAMETER(NotUsed);
+-  return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
++  return rc;        
+ }
+ 
++
+ /*
+-** SQLite calls this function immediately after a call to unixDlSym() or
+-** unixDlOpen() fails (returns a null pointer). If a more detailed error
+-** message is available, it is written to zBufOut. If no error message
+-** is available, zBufOut is left unmodified and SQLite uses a default
+-** error message.
++** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
++**
++** This is not a VFS shared-memory method; it is a utility function called
++** by VFS shared-memory methods.
+ */
+-static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
+-  const char *zErr;
+-  UNUSED_PARAMETER(NotUsed);
+-  unixEnterMutex();
+-  zErr = dlerror();
+-  if( zErr ){
+-    sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
++static void unixShmPurge(unixFile *pFd){
++  unixShmNode *p = pFd->pInode->pShmNode;
++  assert( unixMutexHeld() );
++  if( p && p->nRef==0 ){
++    int i;
++    assert( p->pInode==pFd->pInode );
++    sqlite3_mutex_free(p->mutex);
++    for(i=0; i<p->nRegion; i++){
++      if( p->h>=0 ){
++        osMunmap(p->apRegion[i], p->szRegion);
++      }else{
++        sqlite3_free(p->apRegion[i]);
++      }
++    }
++    sqlite3_free(p->apRegion);
++    if( p->h>=0 ){
++      robust_close(pFd, p->h, __LINE__);
++      p->h = -1;
++    }
++    p->pInode->pShmNode = 0;
++    sqlite3_free(p);
+   }
+-  unixLeaveMutex();
+-}
+-static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
+-  /* 
+-  ** GCC with -pedantic-errors says that C90 does not allow a void* to be
+-  ** cast into a pointer to a function.  And yet the library dlsym() routine
+-  ** returns a void* which is really a pointer to a function.  So how do we
+-  ** use dlsym() with -pedantic-errors?
+-  **
+-  ** Variable x below is defined to be a pointer to a function taking
+-  ** parameters void* and const char* and returning a pointer to a function.
+-  ** We initialize x by assigning it a pointer to the dlsym() function.
+-  ** (That assignment requires a cast.)  Then we call the function that
+-  ** x points to.  
+-  **
+-  ** This work-around is unlikely to work correctly on any system where
+-  ** you really cannot cast a function pointer into void*.  But then, on the
+-  ** other hand, dlsym() will not work on such a system either, so we have
+-  ** not really lost anything.
+-  */
+-  void (*(*x)(void*,const char*))(void);
+-  UNUSED_PARAMETER(NotUsed);
+-  x = (void(*(*)(void*,const char*))(void))dlsym;
+-  return (*x)(p, zSym);
+-}
+-static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
+-  UNUSED_PARAMETER(NotUsed);
+-  dlclose(pHandle);
+ }
+-#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
+-  #define unixDlOpen  0
+-  #define unixDlError 0
+-  #define unixDlSym   0
+-  #define unixDlClose 0
+-#endif
+ 
+ /*
+-** Write nBuf bytes of random data to the supplied buffer zBuf.
++** Open a shared-memory area associated with open database file pDbFd.  
++** This particular implementation uses mmapped files.
++**
++** The file used to implement shared-memory is in the same directory
++** as the open database file and has the same name as the open database
++** file with the "-shm" suffix added.  For example, if the database file
++** is "/home/user1/config.db" then the file that is created and mmapped
++** for shared memory will be called "/home/user1/config.db-shm".  
++**
++** Another approach to is to use files in /dev/shm or /dev/tmp or an
++** some other tmpfs mount. But if a file in a different directory
++** from the database file is used, then differing access permissions
++** or a chroot() might cause two different processes on the same
++** database to end up using different files for shared memory - 
++** meaning that their memory would not really be shared - resulting
++** in database corruption.  Nevertheless, this tmpfs file usage
++** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
++** or the equivalent.  The use of the SQLITE_SHM_DIRECTORY compile-time
++** option results in an incompatible build of SQLite;  builds of SQLite
++** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
++** same database file at the same time, database corruption will likely
++** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
++** "unsupported" and may go away in a future SQLite release.
++**
++** When opening a new shared-memory file, if no other instances of that
++** file are currently open, in this process or in other processes, then
++** the file must be truncated to zero length or have its header cleared.
++**
++** If the original database file (pDbFd) is using the "unix-excl" VFS
++** that means that an exclusive lock is held on the database file and
++** that no other processes are able to read or write the database.  In
++** that case, we do not really need shared memory.  No shared memory
++** file is created.  The shared memory will be simulated with heap memory.
+ */
+-static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
+-  UNUSED_PARAMETER(NotUsed);
+-  assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
++static int unixOpenSharedMemory(unixFile *pDbFd){
++  struct unixShm *p = 0;          /* The connection to be opened */
++  struct unixShmNode *pShmNode;   /* The underlying mmapped file */
++  int rc;                         /* Result code */
++  unixInodeInfo *pInode;          /* The inode of fd */
++  char *zShmFilename;             /* Name of the file used for SHM */
++  int nShmFilename;               /* Size of the SHM filename in bytes */
+ 
+-  /* We have to initialize zBuf to prevent valgrind from reporting
+-  ** errors.  The reports issued by valgrind are incorrect - we would
+-  ** prefer that the randomness be increased by making use of the
+-  ** uninitialized space in zBuf - but valgrind errors tend to worry
+-  ** some users.  Rather than argue, it seems easier just to initialize
+-  ** the whole array and silence valgrind, even if that means less randomness
+-  ** in the random seed.
+-  **
+-  ** When testing, initializing zBuf[] to zero is all we do.  That means
+-  ** that we always use the same random number sequence.  This makes the
+-  ** tests repeatable.
+-  */
+-  memset(zBuf, 0, nBuf);
+-#if !defined(SQLITE_TEST)
+-  {
+-    int pid, fd, got;
+-    fd = robust_open("/dev/urandom", O_RDONLY, 0);
+-    if( fd<0 ){
+-      time_t t;
+-      time(&t);
+-      memcpy(zBuf, &t, sizeof(t));
+-      pid = getpid();
+-      memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
+-      assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
+-      nBuf = sizeof(t) + sizeof(pid);
+-    }else{
+-      do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
+-      robust_close(0, fd, __LINE__);
+-    }
+-  }
+-#endif
+-  return nBuf;
+-}
++  /* Allocate space for the new unixShm object. */
++  p = sqlite3_malloc( sizeof(*p) );
++  if( p==0 ) return SQLITE_NOMEM;
++  memset(p, 0, sizeof(*p));
++  assert( pDbFd->pShm==0 );
+ 
++  /* Check to see if a unixShmNode object already exists. Reuse an existing
++  ** one if present. Create a new one if necessary.
++  */
++  unixEnterMutex();
++  pInode = pDbFd->pInode;
++  pShmNode = pInode->pShmNode;
++  if( pShmNode==0 ){
++    struct stat sStat;                 /* fstat() info for database file */
+ 
+-/*
+-** Sleep for a little while.  Return the amount of time slept.
+-** The argument is the number of microseconds we want to sleep.
+-** The return value is the number of microseconds of sleep actually
+-** requested from the underlying operating system, a number which
+-** might be greater than or equal to the argument, but not less
+-** than the argument.
+-*/
+-static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
+-#if OS_VXWORKS
+-  struct timespec sp;
++    /* Call fstat() to figure out the permissions on the database file. If
++    ** a new *-shm file is created, an attempt will be made to create it
++    ** with the same permissions.
++    */
++    if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
++      rc = SQLITE_IOERR_FSTAT;
++      goto shm_open_err;
++    }
+ 
+-  sp.tv_sec = microseconds / 1000000;
+-  sp.tv_nsec = (microseconds % 1000000) * 1000;
+-  nanosleep(&sp, NULL);
+-  UNUSED_PARAMETER(NotUsed);
+-  return microseconds;
+-#elif defined(HAVE_USLEEP) && HAVE_USLEEP
+-  usleep(microseconds);
+-  UNUSED_PARAMETER(NotUsed);
+-  return microseconds;
++#ifdef SQLITE_SHM_DIRECTORY
++    nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
+ #else
+-  int seconds = (microseconds+999999)/1000000;
+-  sleep(seconds);
+-  UNUSED_PARAMETER(NotUsed);
+-  return seconds*1000000;
++    nShmFilename = 6 + (int)strlen(pDbFd->zPath);
+ #endif
+-}
++    pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
++    if( pShmNode==0 ){
++      rc = SQLITE_NOMEM;
++      goto shm_open_err;
++    }
++    memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
++    zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
++#ifdef SQLITE_SHM_DIRECTORY
++    sqlite3_snprintf(nShmFilename, zShmFilename, 
++                     SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
++                     (u32)sStat.st_ino, (u32)sStat.st_dev);
++#else
++    sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
++    sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
++#endif
++    pShmNode->h = -1;
++    pDbFd->pInode->pShmNode = pShmNode;
++    pShmNode->pInode = pDbFd->pInode;
++    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
++    if( pShmNode->mutex==0 ){
++      rc = SQLITE_NOMEM;
++      goto shm_open_err;
++    }
++
++    if( pInode->bProcessLock==0 ){
++      int openFlags = O_RDWR | O_CREAT;
++      if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
++        openFlags = O_RDONLY;
++        pShmNode->isReadonly = 1;
++      }
++      pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
++      if( pShmNode->h<0 ){
++        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
++        goto shm_open_err;
++      }
++
++      /* If this process is running as root, make sure that the SHM file
++      ** is owned by the same user that owns the original database.  Otherwise,
++      ** the original owner will not be able to connect.
++      */
++      osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
++  
++      /* Check to see if another process is holding the dead-man switch.
++      ** If not, truncate the file to zero length. 
++      */
++      rc = SQLITE_OK;
++      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
++        if( robust_ftruncate(pShmNode->h, 0) ){
++          rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
++        }
++      }
++      if( rc==SQLITE_OK ){
++        rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
++      }
++      if( rc ) goto shm_open_err;
++    }
++  }
+ 
+-/*
+-** The following variable, if set to a non-zero value, is interpreted as
+-** the number of seconds since 1970 and is used to set the result of
+-** sqlite3OsCurrentTime() during testing.
+-*/
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_current_time = 0;  /* Fake system time in seconds since 1970. */
++  /* Make the new connection a child of the unixShmNode */
++  p->pShmNode = pShmNode;
++#ifdef SQLITE_DEBUG
++  p->id = pShmNode->nextShmId++;
+ #endif
++  pShmNode->nRef++;
++  pDbFd->pShm = p;
++  unixLeaveMutex();
++
++  /* The reference count on pShmNode has already been incremented under
++  ** the cover of the unixEnterMutex() mutex and the pointer from the
++  ** new (struct unixShm) object to the pShmNode has been set. All that is
++  ** left to do is to link the new object into the linked list starting
++  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex 
++  ** mutex.
++  */
++  sqlite3_mutex_enter(pShmNode->mutex);
++  p->pNext = pShmNode->pFirst;
++  pShmNode->pFirst = p;
++  sqlite3_mutex_leave(pShmNode->mutex);
++  return SQLITE_OK;
++
++  /* Jump here on any error */
++shm_open_err:
++  unixShmPurge(pDbFd);       /* This call frees pShmNode if required */
++  sqlite3_free(p);
++  unixLeaveMutex();
++  return rc;
++}
+ 
+ /*
+-** Find the current time (in Universal Coordinated Time).  Write into *piNow
+-** the current time and date as a Julian Day number times 86_400_000.  In
+-** other words, write into *piNow the number of milliseconds since the Julian
+-** epoch of noon in Greenwich on November 24, 4714 B.C according to the
+-** proleptic Gregorian calendar.
++** This function is called to obtain a pointer to region iRegion of the 
++** shared-memory associated with the database file fd. Shared-memory regions 
++** are numbered starting from zero. Each shared-memory region is szRegion 
++** bytes in size.
+ **
+-** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date 
+-** cannot be found.
++** If an error occurs, an error code is returned and *pp is set to NULL.
++**
++** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
++** region has not been allocated (by any client, including one running in a
++** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
++** bExtend is non-zero and the requested shared-memory region has not yet 
++** been allocated, it is allocated by this function.
++**
++** If the shared-memory region has already been allocated or is allocated by
++** this call as described above, then it is mapped into this processes 
++** address space (if it is not already), *pp is set to point to the mapped 
++** memory and SQLITE_OK returned.
+ */
+-static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
+-  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
++static int unixShmMap(
++  sqlite3_file *fd,               /* Handle open on database file */
++  int iRegion,                    /* Region to retrieve */
++  int szRegion,                   /* Size of regions */
++  int bExtend,                    /* True to extend file if necessary */
++  void volatile **pp              /* OUT: Mapped memory */
++){
++  unixFile *pDbFd = (unixFile*)fd;
++  unixShm *p;
++  unixShmNode *pShmNode;
+   int rc = SQLITE_OK;
+-#if defined(NO_GETTOD)
+-  time_t t;
+-  time(&t);
+-  *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
+-#elif OS_VXWORKS
+-  struct timespec sNow;
+-  clock_gettime(CLOCK_REALTIME, &sNow);
+-  *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
+-#else
+-  struct timeval sNow;
+-  if( gettimeofday(&sNow, 0)==0 ){
+-    *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+-  }else{
+-    rc = SQLITE_ERROR;
++
++  /* If the shared-memory file has not yet been opened, open it now. */
++  if( pDbFd->pShm==0 ){
++    rc = unixOpenSharedMemory(pDbFd);
++    if( rc!=SQLITE_OK ) return rc;
+   }
+-#endif
+ 
+-#ifdef SQLITE_TEST
+-  if( sqlite3_current_time ){
+-    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
++  p = pDbFd->pShm;
++  pShmNode = p->pShmNode;
++  sqlite3_mutex_enter(pShmNode->mutex);
++  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
++  assert( pShmNode->pInode==pDbFd->pInode );
++  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
++  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
++
++  if( pShmNode->nRegion<=iRegion ){
++    char **apNew;                      /* New apRegion[] array */
++    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
++    struct stat sStat;                 /* Used by fstat() */
++
++    pShmNode->szRegion = szRegion;
++
++    if( pShmNode->h>=0 ){
++      /* The requested region is not mapped into this processes address space.
++      ** Check to see if it has been allocated (i.e. if the wal-index file is
++      ** large enough to contain the requested region).
++      */
++      if( osFstat(pShmNode->h, &sStat) ){
++        rc = SQLITE_IOERR_SHMSIZE;
++        goto shmpage_out;
++      }
++  
++      if( sStat.st_size<nByte ){
++        /* The requested memory region does not exist. If bExtend is set to
++        ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
++        */
++        if( !bExtend ){
++          goto shmpage_out;
++        }
++
++        /* Alternatively, if bExtend is true, extend the file. Do this by
++        ** writing a single byte to the end of each (OS) page being
++        ** allocated or extended. Technically, we need only write to the
++        ** last page in order to extend the file. But writing to all new
++        ** pages forces the OS to allocate them immediately, which reduces
++        ** the chances of SIGBUS while accessing the mapped region later on.
++        */
++        else{
++          static const int pgsz = 4096;
++          int iPg;
++
++          /* Write to the last byte of each newly allocated or extended page */
++          assert( (nByte % pgsz)==0 );
++          for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
++            if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
++              const char *zFile = pShmNode->zFilename;
++              rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
++              goto shmpage_out;
++            }
++          }
++        }
++      }
++    }
++
++    /* Map the requested memory region into this processes address space. */
++    apNew = (char **)sqlite3_realloc(
++        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
++    );
++    if( !apNew ){
++      rc = SQLITE_IOERR_NOMEM;
++      goto shmpage_out;
++    }
++    pShmNode->apRegion = apNew;
++    while(pShmNode->nRegion<=iRegion){
++      void *pMem;
++      if( pShmNode->h>=0 ){
++        pMem = osMmap(0, szRegion,
++            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
++            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
++        );
++        if( pMem==MAP_FAILED ){
++          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
++          goto shmpage_out;
++        }
++      }else{
++        pMem = sqlite3_malloc(szRegion);
++        if( pMem==0 ){
++          rc = SQLITE_NOMEM;
++          goto shmpage_out;
++        }
++        memset(pMem, 0, szRegion);
++      }
++      pShmNode->apRegion[pShmNode->nRegion] = pMem;
++      pShmNode->nRegion++;
++    }
+   }
+-#endif
+-  UNUSED_PARAMETER(NotUsed);
+-  return rc;
+-}
+ 
+-/*
+-** Find the current time (in Universal Coordinated Time).  Write the
+-** current time and date as a Julian Day number into *prNow and
+-** return 0.  Return 1 if the time and date cannot be found.
+-*/
+-static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
+-  sqlite3_int64 i = 0;
+-  int rc;
+-  UNUSED_PARAMETER(NotUsed);
+-  rc = unixCurrentTimeInt64(0, &i);
+-  *prNow = i/86400000.0;
++shmpage_out:
++  if( pShmNode->nRegion>iRegion ){
++    *pp = pShmNode->apRegion[iRegion];
++  }else{
++    *pp = 0;
++  }
++  if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
++  sqlite3_mutex_leave(pShmNode->mutex);
+   return rc;
+ }
+ 
+ /*
+-** We added the xGetLastError() method with the intention of providing
+-** better low-level error messages when operating-system problems come up
+-** during SQLite operation.  But so far, none of that has been implemented
+-** in the core.  So this routine is never called.  For now, it is merely
+-** a place-holder.
+-*/
+-static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
+-  UNUSED_PARAMETER(NotUsed);
+-  UNUSED_PARAMETER(NotUsed2);
+-  UNUSED_PARAMETER(NotUsed3);
+-  return 0;
+-}
+-
+-
+-/*
+-************************ End of sqlite3_vfs methods ***************************
+-******************************************************************************/
+-
+-/******************************************************************************
+-************************** Begin Proxy Locking ********************************
+-**
+-** Proxy locking is a "uber-locking-method" in this sense:  It uses the
+-** other locking methods on secondary lock files.  Proxy locking is a
+-** meta-layer over top of the primitive locking implemented above.  For
+-** this reason, the division that implements of proxy locking is deferred
+-** until late in the file (here) after all of the other I/O methods have
+-** been defined - so that the primitive locking methods are available
+-** as services to help with the implementation of proxy locking.
+-**
+-****
+-**
+-** The default locking schemes in SQLite use byte-range locks on the
+-** database file to coordinate safe, concurrent access by multiple readers
+-** and writers [http://sqlite.org/lockingv3.html].  The five file locking
+-** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
+-** as POSIX read & write locks over fixed set of locations (via fsctl),
+-** on AFP and SMB only exclusive byte-range locks are available via fsctl
+-** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
+-** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
+-** address in the shared range is taken for a SHARED lock, the entire
+-** shared range is taken for an EXCLUSIVE lock):
+-**
+-**      PENDING_BYTE        0x40000000
+-**      RESERVED_BYTE       0x40000001
+-**      SHARED_RANGE        0x40000002 -> 0x40000200
+-**
+-** This works well on the local file system, but shows a nearly 100x
+-** slowdown in read performance on AFP because the AFP client disables
+-** the read cache when byte-range locks are present.  Enabling the read
+-** cache exposes a cache coherency problem that is present on all OS X
+-** supported network file systems.  NFS and AFP both observe the
+-** close-to-open semantics for ensuring cache coherency
+-** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
+-** address the requirements for concurrent database access by multiple
+-** readers and writers
+-** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
+-**
+-** To address the performance and cache coherency issues, proxy file locking
+-** changes the way database access is controlled by limiting access to a
+-** single host at a time and moving file locks off of the database file
+-** and onto a proxy file on the local file system.  
+-**
+-**
+-** Using proxy locks
+-** -----------------
+-**
+-** C APIs
+-**
+-**  sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
+-**                       <proxy_path> | ":auto:");
+-**  sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
+-**
+-**
+-** SQL pragmas
+-**
+-**  PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
+-**  PRAGMA [database.]lock_proxy_file
+-**
+-** Specifying ":auto:" means that if there is a conch file with a matching
+-** host ID in it, the proxy path in the conch file will be used, otherwise
+-** a proxy path based on the user's temp dir
+-** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
+-** actual proxy file name is generated from the name and path of the
+-** database file.  For example:
+-**
+-**       For database path "/Users/me/foo.db" 
+-**       The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
+-**
+-** Once a lock proxy is configured for a database connection, it can not
+-** be removed, however it may be switched to a different proxy path via
+-** the above APIs (assuming the conch file is not being held by another
+-** connection or process). 
+-**
+-**
+-** How proxy locking works
+-** -----------------------
+-**
+-** Proxy file locking relies primarily on two new supporting files: 
+-**
+-**   *  conch file to limit access to the database file to a single host
+-**      at a time
+-**
+-**   *  proxy file to act as a proxy for the advisory locks normally
+-**      taken on the database
+-**
+-** The conch file - to use a proxy file, sqlite must first "hold the conch"
+-** by taking an sqlite-style shared lock on the conch file, reading the
+-** contents and comparing the host's unique host ID (see below) and lock
+-** proxy path against the values stored in the conch.  The conch file is
+-** stored in the same directory as the database file and the file name
+-** is patterned after the database file name as ".<databasename>-conch".
+-** If the conch file does not exist, or it's contents do not match the
+-** host ID and/or proxy path, then the lock is escalated to an exclusive
+-** lock and the conch file contents is updated with the host ID and proxy
+-** path and the lock is downgraded to a shared lock again.  If the conch
+-** is held by another process (with a shared lock), the exclusive lock
+-** will fail and SQLITE_BUSY is returned.
+-**
+-** The proxy file - a single-byte file used for all advisory file locks
+-** normally taken on the database file.   This allows for safe sharing
+-** of the database file for multiple readers and writers on the same
+-** host (the conch ensures that they all use the same local lock file).
+-**
+-** Requesting the lock proxy does not immediately take the conch, it is
+-** only taken when the first request to lock database file is made.  
+-** This matches the semantics of the traditional locking behavior, where
+-** opening a connection to a database file does not take a lock on it.
+-** The shared lock and an open file descriptor are maintained until 
+-** the connection to the database is closed. 
+-**
+-** The proxy file and the lock file are never deleted so they only need
+-** to be created the first time they are used.
+-**
+-** Configuration options
+-** ---------------------
+-**
+-**  SQLITE_PREFER_PROXY_LOCKING
+-**
+-**       Database files accessed on non-local file systems are
+-**       automatically configured for proxy locking, lock files are
+-**       named automatically using the same logic as
+-**       PRAGMA lock_proxy_file=":auto:"
+-**    
+-**  SQLITE_PROXY_DEBUG
+-**
+-**       Enables the logging of error messages during host id file
+-**       retrieval and creation
+-**
+-**  LOCKPROXYDIR
+-**
+-**       Overrides the default directory used for lock proxy files that
+-**       are named automatically via the ":auto:" setting
+-**
+-**  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
++** Change the lock state for a shared-memory segment.
+ **
+-**       Permissions to use when creating a directory for storing the
+-**       lock proxy files, only used when LOCKPROXYDIR is not set.
+-**    
+-**    
+-** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
+-** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
+-** force proxy locking to be used for every database file opened, and 0
+-** will force automatic proxy locking to be disabled for all database
+-** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
+-** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
++** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
++** different here than in posix.  In xShmLock(), one can go from unlocked
++** to shared and back or from unlocked to exclusive and back.  But one may
++** not go from shared to exclusive or from exclusive to shared.
+ */
++static int unixShmLock(
++  sqlite3_file *fd,          /* Database file holding the shared memory */
++  int ofst,                  /* First lock to acquire or release */
++  int n,                     /* Number of locks to acquire or release */
++  int flags                  /* What to do with the lock */
++){
++  unixFile *pDbFd = (unixFile*)fd;      /* Connection holding shared memory */
++  unixShm *p = pDbFd->pShm;             /* The shared memory being locked */
++  unixShm *pX;                          /* For looping over all siblings */
++  unixShmNode *pShmNode = p->pShmNode;  /* The underlying file iNode */
++  int rc = SQLITE_OK;                   /* Result code */
++  u16 mask;                             /* Mask of locks to take or release */
+ 
+-/*
+-** Proxy locking is only available on MacOSX 
+-*/
+-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++  assert( pShmNode==pDbFd->pInode->pShmNode );
++  assert( pShmNode->pInode==pDbFd->pInode );
++  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
++  assert( n>=1 );
++  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
++       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
++       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
++       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
++  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
++  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
++  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ 
+-/*
+-** The proxyLockingContext has the path and file structures for the remote 
+-** and local proxy files in it
+-*/
+-typedef struct proxyLockingContext proxyLockingContext;
+-struct proxyLockingContext {
+-  unixFile *conchFile;         /* Open conch file */
+-  char *conchFilePath;         /* Name of the conch file */
+-  unixFile *lockProxy;         /* Open proxy lock file */
+-  char *lockProxyPath;         /* Name of the proxy lock file */
+-  char *dbPath;                /* Name of the open file */
+-  int conchHeld;               /* 1 if the conch is held, -1 if lockless */
+-  void *oldLockingContext;     /* Original lockingcontext to restore on close */
+-  sqlite3_io_methods const *pOldMethod;     /* Original I/O methods for close */
+-};
++  mask = (1<<(ofst+n)) - (1<<ofst);
++  assert( n>1 || mask==(1<<ofst) );
++  sqlite3_mutex_enter(pShmNode->mutex);
++  if( flags & SQLITE_SHM_UNLOCK ){
++    u16 allMask = 0; /* Mask of locks held by siblings */
+ 
+-/* 
+-** The proxy lock file path for the database at dbPath is written into lPath, 
+-** which must point to valid, writable memory large enough for a maxLen length
+-** file path. 
+-*/
+-static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
+-  int len;
+-  int dbLen;
+-  int i;
++    /* See if any siblings hold this same lock */
++    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
++      if( pX==p ) continue;
++      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
++      allMask |= pX->sharedMask;
++    }
+ 
+-#ifdef LOCKPROXYDIR
+-  len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
+-#else
+-# ifdef _CS_DARWIN_USER_TEMP_DIR
+-  {
+-    if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
+-      OSTRACE(("GETLOCKPATH  failed %s errno=%d pid=%d\n",
+-               lPath, errno, getpid()));
+-      return SQLITE_IOERR_LOCK;
++    /* Unlock the system-level locks */
++    if( (mask & allMask)==0 ){
++      rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
++    }else{
++      rc = SQLITE_OK;
+     }
+-    len = strlcat(lPath, "sqliteplocks", maxLen);    
+-  }
+-# else
+-  len = strlcpy(lPath, "/tmp/", maxLen);
+-# endif
+-#endif
+ 
+-  if( lPath[len-1]!='/' ){
+-    len = strlcat(lPath, "/", maxLen);
+-  }
+-  
+-  /* transform the db path to a unique cache name */
+-  dbLen = (int)strlen(dbPath);
+-  for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
+-    char c = dbPath[i];
+-    lPath[i+len] = (c=='/')?'_':c;
+-  }
+-  lPath[i+len]='\0';
+-  strlcat(lPath, ":auto:", maxLen);
+-  OSTRACE(("GETLOCKPATH  proxy lock path=%s pid=%d\n", lPath, getpid()));
+-  return SQLITE_OK;
+-}
++    /* Undo the local locks */
++    if( rc==SQLITE_OK ){
++      p->exclMask &= ~mask;
++      p->sharedMask &= ~mask;
++    } 
++  }else if( flags & SQLITE_SHM_SHARED ){
++    u16 allShared = 0;  /* Union of locks held by connections other than "p" */
+ 
+-/* 
+- ** Creates the lock file and any missing directories in lockPath
+- */
+-static int proxyCreateLockPath(const char *lockPath){
+-  int i, len;
+-  char buf[MAXPATHLEN];
+-  int start = 0;
+-  
+-  assert(lockPath!=NULL);
+-  /* try to create all the intermediate directories */
+-  len = (int)strlen(lockPath);
+-  buf[0] = lockPath[0];
+-  for( i=1; i<len; i++ ){
+-    if( lockPath[i] == '/' && (i - start > 0) ){
+-      /* only mkdir if leaf dir != "." or "/" or ".." */
+-      if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') 
+-         || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
+-        buf[i]='\0';
+-        if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
+-          int err=errno;
+-          if( err!=EEXIST ) {
+-            OSTRACE(("CREATELOCKPATH  FAILED creating %s, "
+-                     "'%s' proxy lock path=%s pid=%d\n",
+-                     buf, strerror(err), lockPath, getpid()));
+-            return err;
+-          }
+-        }
++    /* Find out which shared locks are already held by sibling connections.
++    ** If any sibling already holds an exclusive lock, go ahead and return
++    ** SQLITE_BUSY.
++    */
++    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
++      if( (pX->exclMask & mask)!=0 ){
++        rc = SQLITE_BUSY;
++        break;
+       }
+-      start=i+1;
++      allShared |= pX->sharedMask;
+     }
+-    buf[i] = lockPath[i];
+-  }
+-  OSTRACE(("CREATELOCKPATH  proxy lock path=%s pid=%d\n", lockPath, getpid()));
+-  return 0;
+-}
+-
+-/*
+-** Create a new VFS file descriptor (stored in memory obtained from
+-** sqlite3_malloc) and open the file named "path" in the file descriptor.
+-**
+-** The caller is responsible not only for closing the file descriptor
+-** but also for freeing the memory associated with the file descriptor.
+-*/
+-static int proxyCreateUnixFile(
+-    const char *path,        /* path for the new unixFile */
+-    unixFile **ppFile,       /* unixFile created and returned by ref */
+-    int islockfile           /* if non zero missing dirs will be created */
+-) {
+-  int fd = -1;
+-  unixFile *pNew;
+-  int rc = SQLITE_OK;
+-  int openFlags = O_RDWR | O_CREAT;
+-  sqlite3_vfs dummyVfs;
+-  int terrno = 0;
+-  UnixUnusedFd *pUnused = NULL;
+ 
+-  /* 1. first try to open/create the file
+-  ** 2. if that fails, and this is a lock file (not-conch), try creating
+-  ** the parent directories and then try again.
+-  ** 3. if that fails, try to open the file read-only
+-  ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
+-  */
+-  pUnused = findReusableFd(path, openFlags);
+-  if( pUnused ){
+-    fd = pUnused->fd;
+-  }else{
+-    pUnused = sqlite3_malloc(sizeof(*pUnused));
+-    if( !pUnused ){
+-      return SQLITE_NOMEM;
+-    }
+-  }
+-  if( fd<0 ){
+-    fd = robust_open(path, openFlags, 0);
+-    terrno = errno;
+-    if( fd<0 && errno==ENOENT && islockfile ){
+-      if( proxyCreateLockPath(path) == SQLITE_OK ){
+-        fd = robust_open(path, openFlags, 0);
++    /* Get shared locks at the system level, if necessary */
++    if( rc==SQLITE_OK ){
++      if( (allShared & mask)==0 ){
++        rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
++      }else{
++        rc = SQLITE_OK;
+       }
+     }
+-  }
+-  if( fd<0 ){
+-    openFlags = O_RDONLY;
+-    fd = robust_open(path, openFlags, 0);
+-    terrno = errno;
+-  }
+-  if( fd<0 ){
+-    if( islockfile ){
+-      return SQLITE_BUSY;
++
++    /* Get the local shared locks */
++    if( rc==SQLITE_OK ){
++      p->sharedMask |= mask;
+     }
+-    switch (terrno) {
+-      case EACCES:
+-        return SQLITE_PERM;
+-      case EIO: 
+-        return SQLITE_IOERR_LOCK; /* even though it is the conch */
+-      default:
+-        return SQLITE_CANTOPEN_BKPT;
++  }else{
++    /* Make sure no sibling connections hold locks that will block this
++    ** lock.  If any do, return SQLITE_BUSY right away.
++    */
++    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
++      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
++        rc = SQLITE_BUSY;
++        break;
++      }
+     }
+-  }
+-  
+-  pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
+-  if( pNew==NULL ){
+-    rc = SQLITE_NOMEM;
+-    goto end_create_proxy;
+-  }
+-  memset(pNew, 0, sizeof(unixFile));
+-  pNew->openFlags = openFlags;
+-  memset(&dummyVfs, 0, sizeof(dummyVfs));
+-  dummyVfs.pAppData = (void*)&autolockIoFinder;
+-  dummyVfs.zName = "dummy";
+-  pUnused->fd = fd;
+-  pUnused->flags = openFlags;
+-  pNew->pUnused = pUnused;
+   
+-  rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
+-  if( rc==SQLITE_OK ){
+-    *ppFile = pNew;
+-    return SQLITE_OK;
++    /* Get the exclusive locks at the system level.  Then if successful
++    ** also mark the local connection as being locked.
++    */
++    if( rc==SQLITE_OK ){
++      rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
++      if( rc==SQLITE_OK ){
++        assert( (p->sharedMask & mask)==0 );
++        p->exclMask |= mask;
++      }
++    }
+   }
+-end_create_proxy:    
+-  robust_close(pNew, fd, __LINE__);
+-  sqlite3_free(pNew);
+-  sqlite3_free(pUnused);
++  sqlite3_mutex_leave(pShmNode->mutex);
++  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
++           p->id, getpid(), p->sharedMask, p->exclMask));
+   return rc;
+ }
+ 
+-#ifdef SQLITE_TEST
+-/* simulate multiple hosts by creating unique hostid file paths */
+-SQLITE_API int sqlite3_hostid_num = 0;
+-#endif
++/*
++** Implement a memory barrier or memory fence on shared memory.  
++**
++** All loads and stores begun before the barrier must complete before
++** any load or store begun after the barrier.
++*/
++static void unixShmBarrier(
++  sqlite3_file *fd                /* Database file holding the shared memory */
++){
++  UNUSED_PARAMETER(fd);
++  unixEnterMutex();
++  unixLeaveMutex();
++}
+ 
+-#define PROXY_HOSTIDLEN    16  /* conch file host id length */
++/*
++** Close a connection to shared-memory.  Delete the underlying 
++** storage if deleteFlag is true.
++**
++** If there is no shared memory associated with the connection then this
++** routine is a harmless no-op.
++*/
++static int unixShmUnmap(
++  sqlite3_file *fd,               /* The underlying database file */
++  int deleteFlag                  /* Delete shared-memory if true */
++){
++  unixShm *p;                     /* The connection to be closed */
++  unixShmNode *pShmNode;          /* The underlying shared-memory file */
++  unixShm **pp;                   /* For looping over sibling connections */
++  unixFile *pDbFd;                /* The underlying database file */
+ 
+-/* Not always defined in the headers as it ought to be */
+-extern int gethostuuid(uuid_t id, const struct timespec *wait);
++  pDbFd = (unixFile*)fd;
++  p = pDbFd->pShm;
++  if( p==0 ) return SQLITE_OK;
++  pShmNode = p->pShmNode;
+ 
+-/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN 
+-** bytes of writable memory.
+-*/
+-static int proxyGetHostID(unsigned char *pHostID, int *pError){
+-  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
+-  {
+-    static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
+-    if( gethostuuid(pHostID, &timeout) ){
+-      int err = errno;
+-      if( pError ){
+-        *pError = err;
+-      }
+-      return SQLITE_IOERR;
+-    }
++  assert( pShmNode==pDbFd->pInode->pShmNode );
++  assert( pShmNode->pInode==pDbFd->pInode );
++
++  /* Remove connection p from the set of connections associated
++  ** with pShmNode */
++  sqlite3_mutex_enter(pShmNode->mutex);
++  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
++  *pp = p->pNext;
++
++  /* Free the connection p */
++  sqlite3_free(p);
++  pDbFd->pShm = 0;
++  sqlite3_mutex_leave(pShmNode->mutex);
++
++  /* If pShmNode->nRef has reached 0, then close the underlying
++  ** shared-memory file, too */
++  unixEnterMutex();
++  assert( pShmNode->nRef>0 );
++  pShmNode->nRef--;
++  if( pShmNode->nRef==0 ){
++    if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
++    unixShmPurge(pDbFd);
+   }
++  unixLeaveMutex();
++
++  return SQLITE_OK;
++}
++
++
+ #else
+-  UNUSED_PARAMETER(pError);
+-#endif
+-#ifdef SQLITE_TEST
+-  /* simulate multiple hosts by creating unique hostid file paths */
+-  if( sqlite3_hostid_num != 0){
+-    pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
++# define unixShmMap     0
++# define unixShmLock    0
++# define unixShmBarrier 0
++# define unixShmUnmap   0
++#endif /* #ifndef SQLITE_OMIT_WAL */
++
++/*
++** If it is currently memory mapped, unmap file pFd.
++*/
++static void unixUnmapfile(unixFile *pFd){
++  assert( pFd->nFetchOut==0 );
++#if SQLITE_MAX_MMAP_SIZE>0
++  if( pFd->pMapRegion ){
++    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
++    pFd->pMapRegion = 0;
++    pFd->mmapSize = 0;
++    pFd->mmapSizeActual = 0;
+   }
+ #endif
+-  
+-  return SQLITE_OK;
+ }
+ 
+-/* The conch file contains the header, host id and lock file path
+- */
+-#define PROXY_CONCHVERSION 2   /* 1-byte header, 16-byte host id, path */
+-#define PROXY_HEADERLEN    1   /* conch file header length */
+-#define PROXY_PATHINDEX    (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
+-#define PROXY_MAXCONCHLEN  (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
++#if SQLITE_MAX_MMAP_SIZE>0
++/*
++** Return the system page size.
++*/
++static int unixGetPagesize(void){
++#if HAVE_MREMAP
++  return 512;
++#elif defined(_BSD_SOURCE)
++  return getpagesize();
++#else
++  return (int)sysconf(_SC_PAGESIZE);
++#endif
++}
++#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+ 
+-/* 
+-** Takes an open conch file, copies the contents to a new path and then moves 
+-** it back.  The newly created file's file descriptor is assigned to the
+-** conch file structure and finally the original conch file descriptor is 
+-** closed.  Returns zero if successful.
++#if SQLITE_MAX_MMAP_SIZE>0
++/*
++** Attempt to set the size of the memory mapping maintained by file 
++** descriptor pFd to nNew bytes. Any existing mapping is discarded.
++**
++** If successful, this function sets the following variables:
++**
++**       unixFile.pMapRegion
++**       unixFile.mmapSize
++**       unixFile.mmapSizeActual
++**
++** If unsuccessful, an error message is logged via sqlite3_log() and
++** the three variables above are zeroed. In this case SQLite should
++** continue accessing the database using the xRead() and xWrite()
++** methods.
+ */
+-static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
+-  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
+-  unixFile *conchFile = pCtx->conchFile;
+-  char tPath[MAXPATHLEN];
+-  char buf[PROXY_MAXCONCHLEN];
+-  char *cPath = pCtx->conchFilePath;
+-  size_t readLen = 0;
+-  size_t pathLen = 0;
+-  char errmsg[64] = "";
+-  int fd = -1;
+-  int rc = -1;
+-  UNUSED_PARAMETER(myHostID);
++static void unixRemapfile(
++  unixFile *pFd,                  /* File descriptor object */
++  i64 nNew                        /* Required mapping size */
++){
++  const char *zErr = "mmap";
++  int h = pFd->h;                      /* File descriptor open on db file */
++  u8 *pOrig = (u8 *)pFd->pMapRegion;   /* Pointer to current file mapping */
++  i64 nOrig = pFd->mmapSizeActual;     /* Size of pOrig region in bytes */
++  u8 *pNew = 0;                        /* Location of new mapping */
++  int flags = PROT_READ;               /* Flags to pass to mmap() */
+ 
+-  /* create a new path by replace the trailing '-conch' with '-break' */
+-  pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
+-  if( pathLen>MAXPATHLEN || pathLen<6 || 
+-     (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
+-    sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
+-    goto end_breaklock;
+-  }
+-  /* read the conch content */
+-  readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
+-  if( readLen<PROXY_PATHINDEX ){
+-    sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
+-    goto end_breaklock;
+-  }
+-  /* write it out to the temporary break file */
+-  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
+-  if( fd<0 ){
+-    sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
+-    goto end_breaklock;
+-  }
+-  if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
+-    sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
+-    goto end_breaklock;
+-  }
+-  if( rename(tPath, cPath) ){
+-    sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
+-    goto end_breaklock;
+-  }
+-  rc = 0;
+-  fprintf(stderr, "broke stale lock on %s\n", cPath);
+-  robust_close(pFile, conchFile->h, __LINE__);
+-  conchFile->h = fd;
+-  conchFile->openFlags = O_RDWR | O_CREAT;
++  assert( pFd->nFetchOut==0 );
++  assert( nNew>pFd->mmapSize );
++  assert( nNew<=pFd->mmapSizeMax );
++  assert( nNew>0 );
++  assert( pFd->mmapSizeActual>=pFd->mmapSize );
++  assert( MAP_FAILED!=0 );
+ 
+-end_breaklock:
+-  if( rc ){
+-    if( fd>=0 ){
+-      osUnlink(tPath);
+-      robust_close(pFile, fd, __LINE__);
++  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
++
++  if( pOrig ){
++    const int szSyspage = unixGetPagesize();
++    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
++    u8 *pReq = &pOrig[nReuse];
++
++    /* Unmap any pages of the existing mapping that cannot be reused. */
++    if( nReuse!=nOrig ){
++      osMunmap(pReq, nOrig-nReuse);
+     }
+-    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
+-  }
+-  return rc;
+-}
+ 
+-/* Take the requested lock on the conch file and break a stale lock if the 
+-** host id matches.
+-*/
+-static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
+-  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
+-  unixFile *conchFile = pCtx->conchFile;
+-  int rc = SQLITE_OK;
+-  int nTries = 0;
+-  struct timespec conchModTime;
+-  
+-  memset(&conchModTime, 0, sizeof(conchModTime));
+-  do {
+-    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
+-    nTries ++;
+-    if( rc==SQLITE_BUSY ){
+-      /* If the lock failed (busy):
+-       * 1st try: get the mod time of the conch, wait 0.5s and try again. 
+-       * 2nd try: fail if the mod time changed or host id is different, wait 
+-       *           10 sec and try again
+-       * 3rd try: break the lock unless the mod time has changed.
+-       */
+-      struct stat buf;
+-      if( osFstat(conchFile->h, &buf) ){
+-        pFile->lastErrno = errno;
+-        return SQLITE_IOERR_LOCK;
+-      }
+-      
+-      if( nTries==1 ){
+-        conchModTime = buf.st_mtimespec;
+-        usleep(500000); /* wait 0.5 sec and try the lock again*/
+-        continue;  
++#if HAVE_MREMAP
++    pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
++    zErr = "mremap";
++#else
++    pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
++    if( pNew!=MAP_FAILED ){
++      if( pNew!=pReq ){
++        osMunmap(pNew, nNew - nReuse);
++        pNew = 0;
++      }else{
++        pNew = pOrig;
+       }
++    }
++#endif
+ 
+-      assert( nTries>1 );
+-      if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || 
+-         conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
+-        return SQLITE_BUSY;
+-      }
+-      
+-      if( nTries==2 ){  
+-        char tBuf[PROXY_MAXCONCHLEN];
+-        int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
+-        if( len<0 ){
+-          pFile->lastErrno = errno;
+-          return SQLITE_IOERR_LOCK;
+-        }
+-        if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
+-          /* don't break the lock if the host id doesn't match */
+-          if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
+-            return SQLITE_BUSY;
+-          }
+-        }else{
+-          /* don't break the lock on short read or a version mismatch */
+-          return SQLITE_BUSY;
+-        }
+-        usleep(10000000); /* wait 10 sec and try the lock again */
+-        continue; 
+-      }
+-      
+-      assert( nTries==3 );
+-      if( 0==proxyBreakConchLock(pFile, myHostID) ){
+-        rc = SQLITE_OK;
+-        if( lockType==EXCLUSIVE_LOCK ){
+-          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);          
+-        }
+-        if( !rc ){
+-          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
+-        }
+-      }
++    /* The attempt to extend the existing mapping failed. Free it. */
++    if( pNew==MAP_FAILED || pNew==0 ){
++      osMunmap(pOrig, nReuse);
+     }
+-  } while( rc==SQLITE_BUSY && nTries<3 );
+-  
+-  return rc;
++  }
++
++  /* If pNew is still NULL, try to create an entirely new mapping. */
++  if( pNew==0 ){
++    pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
++  }
++
++  if( pNew==MAP_FAILED ){
++    pNew = 0;
++    nNew = 0;
++    unixLogError(SQLITE_OK, zErr, pFd->zPath);
++
++    /* If the mmap() above failed, assume that all subsequent mmap() calls
++    ** will probably fail too. Fall back to using xRead/xWrite exclusively
++    ** in this case.  */
++    pFd->mmapSizeMax = 0;
++  }
++  pFd->pMapRegion = (void *)pNew;
++  pFd->mmapSize = pFd->mmapSizeActual = nNew;
+ }
++#endif
+ 
+-/* Takes the conch by taking a shared lock and read the contents conch, if 
+-** lockPath is non-NULL, the host ID and lock file path must match.  A NULL 
+-** lockPath means that the lockPath in the conch file will be used if the 
+-** host IDs match, or a new lock path will be generated automatically 
+-** and written to the conch file.
++/*
++** Memory map or remap the file opened by file-descriptor pFd (if the file
++** is already mapped, the existing mapping is replaced by the new). Or, if 
++** there already exists a mapping for this file, and there are still 
++** outstanding xFetch() references to it, this function is a no-op.
++**
++** If parameter nByte is non-negative, then it is the requested size of 
++** the mapping to create. Otherwise, if nByte is less than zero, then the 
++** requested size is the size of the file on disk. The actual size of the
++** created mapping is either the requested size or the value configured 
++** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
++**
++** SQLITE_OK is returned if no error occurs (even if the mapping is not
++** recreated as a result of outstanding references) or an SQLite error
++** code otherwise.
+ */
+-static int proxyTakeConch(unixFile *pFile){
+-  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
+-  
+-  if( pCtx->conchHeld!=0 ){
+-    return SQLITE_OK;
+-  }else{
+-    unixFile *conchFile = pCtx->conchFile;
+-    uuid_t myHostID;
+-    int pError = 0;
+-    char readBuf[PROXY_MAXCONCHLEN];
+-    char lockPath[MAXPATHLEN];
+-    char *tempLockPath = NULL;
+-    int rc = SQLITE_OK;
+-    int createConch = 0;
+-    int hostIdMatch = 0;
+-    int readLen = 0;
+-    int tryOldLockPath = 0;
+-    int forceNewLockPath = 0;
+-    
+-    OSTRACE(("TAKECONCH  %d for %s pid=%d\n", conchFile->h,
+-             (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
+-
+-    rc = proxyGetHostID(myHostID, &pError);
+-    if( (rc&0xff)==SQLITE_IOERR ){
+-      pFile->lastErrno = pError;
+-      goto end_takeconch;
+-    }
+-    rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
++static int unixMapfile(unixFile *pFd, i64 nByte){
++#if SQLITE_MAX_MMAP_SIZE>0
++  i64 nMap = nByte;
++  int rc;
++
++  assert( nMap>=0 || pFd->nFetchOut==0 );
++  if( pFd->nFetchOut>0 ) return SQLITE_OK;
++
++  if( nMap<0 ){
++    struct stat statbuf;          /* Low-level file information */
++    rc = osFstat(pFd->h, &statbuf);
+     if( rc!=SQLITE_OK ){
+-      goto end_takeconch;
++      return SQLITE_IOERR_FSTAT;
+     }
+-    /* read the existing conch file */
+-    readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
+-    if( readLen<0 ){
+-      /* I/O error: lastErrno set by seekAndRead */
+-      pFile->lastErrno = conchFile->lastErrno;
+-      rc = SQLITE_IOERR_READ;
+-      goto end_takeconch;
+-    }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || 
+-             readBuf[0]!=(char)PROXY_CONCHVERSION ){
+-      /* a short read or version format mismatch means we need to create a new 
+-      ** conch file. 
+-      */
+-      createConch = 1;
++    nMap = statbuf.st_size;
++  }
++  if( nMap>pFd->mmapSizeMax ){
++    nMap = pFd->mmapSizeMax;
++  }
++
++  if( nMap!=pFd->mmapSize ){
++    if( nMap>0 ){
++      unixRemapfile(pFd, nMap);
++    }else{
++      unixUnmapfile(pFd);
+     }
+-    /* if the host id matches and the lock path already exists in the conch
+-    ** we'll try to use the path there, if we can't open that path, we'll 
+-    ** retry with a new auto-generated path 
+-    */
+-    do { /* in case we need to try again for an :auto: named lock file */
++  }
++#endif
+ 
+-      if( !createConch && !forceNewLockPath ){
+-        hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, 
+-                                  PROXY_HOSTIDLEN);
+-        /* if the conch has data compare the contents */
+-        if( !pCtx->lockProxyPath ){
+-          /* for auto-named local lock file, just check the host ID and we'll
+-           ** use the local lock file path that's already in there
+-           */
+-          if( hostIdMatch ){
+-            size_t pathLen = (readLen - PROXY_PATHINDEX);
+-            
+-            if( pathLen>=MAXPATHLEN ){
+-              pathLen=MAXPATHLEN-1;
+-            }
+-            memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
+-            lockPath[pathLen] = 0;
+-            tempLockPath = lockPath;
+-            tryOldLockPath = 1;
+-            /* create a copy of the lock path if the conch is taken */
+-            goto end_takeconch;
+-          }
+-        }else if( hostIdMatch
+-               && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
+-                           readLen-PROXY_PATHINDEX)
+-        ){
+-          /* conch host and lock path match */
+-          goto end_takeconch; 
+-        }
+-      }
+-      
+-      /* if the conch isn't writable and doesn't match, we can't take it */
+-      if( (conchFile->openFlags&O_RDWR) == 0 ){
+-        rc = SQLITE_BUSY;
+-        goto end_takeconch;
+-      }
+-      
+-      /* either the conch didn't match or we need to create a new one */
+-      if( !pCtx->lockProxyPath ){
+-        proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
+-        tempLockPath = lockPath;
+-        /* create a copy of the lock path _only_ if the conch is taken */
+-      }
+-      
+-      /* update conch with host and path (this will fail if other process
+-      ** has a shared lock already), if the host id matches, use the big
+-      ** stick.
+-      */
+-      futimes(conchFile->h, NULL);
+-      if( hostIdMatch && !createConch ){
+-        if( conchFile->pInode && conchFile->pInode->nShared>1 ){
+-          /* We are trying for an exclusive lock but another thread in this
+-           ** same process is still holding a shared lock. */
+-          rc = SQLITE_BUSY;
+-        } else {          
+-          rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
+-        }
+-      }else{
+-        rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
+-      }
+-      if( rc==SQLITE_OK ){
+-        char writeBuffer[PROXY_MAXCONCHLEN];
+-        int writeSize = 0;
+-        
+-        writeBuffer[0] = (char)PROXY_CONCHVERSION;
+-        memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
+-        if( pCtx->lockProxyPath!=NULL ){
+-          strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
+-        }else{
+-          strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
+-        }
+-        writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
+-        robust_ftruncate(conchFile->h, writeSize);
+-        rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
+-        fsync(conchFile->h);
+-        /* If we created a new conch file (not just updated the contents of a 
+-         ** valid conch file), try to match the permissions of the database 
+-         */
+-        if( rc==SQLITE_OK && createConch ){
+-          struct stat buf;
+-          int err = osFstat(pFile->h, &buf);
+-          if( err==0 ){
+-            mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
+-                                        S_IROTH|S_IWOTH);
+-            /* try to match the database file R/W permissions, ignore failure */
+-#ifndef SQLITE_PROXY_DEBUG
+-            osFchmod(conchFile->h, cmode);
+-#else
+-            do{
+-              rc = osFchmod(conchFile->h, cmode);
+-            }while( rc==(-1) && errno==EINTR );
+-            if( rc!=0 ){
+-              int code = errno;
+-              fprintf(stderr, "fchmod %o FAILED with %d %s\n",
+-                      cmode, code, strerror(code));
+-            } else {
+-              fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
+-            }
+-          }else{
+-            int code = errno;
+-            fprintf(stderr, "STAT FAILED[%d] with %d %s\n", 
+-                    err, code, strerror(code));
++  return SQLITE_OK;
++}
++
++/*
++** If possible, return a pointer to a mapping of file fd starting at offset
++** iOff. The mapping must be valid for at least nAmt bytes.
++**
++** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
++** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
++** Finally, if an error does occur, return an SQLite error code. The final
++** value of *pp is undefined in this case.
++**
++** If this function does return a pointer, the caller must eventually 
++** release the reference by calling unixUnfetch().
++*/
++static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
++#if SQLITE_MAX_MMAP_SIZE>0
++  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
  #endif
+-          }
+-        }
+-      }
+-      conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
+-      
+-    end_takeconch:
+-      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
+-      if( rc==SQLITE_OK && pFile->openFlags ){
+-        int fd;
+-        if( pFile->h>=0 ){
+-          robust_close(pFile, pFile->h, __LINE__);
+-        }
+-        pFile->h = -1;
+-        fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
+-        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
+-        if( fd>=0 ){
+-          pFile->h = fd;
+-        }else{
+-          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
+-           during locking */
+-        }
+-      }
+-      if( rc==SQLITE_OK && !pCtx->lockProxy ){
+-        char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
+-        rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
+-        if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
+-          /* we couldn't create the proxy lock file with the old lock file path
+-           ** so try again via auto-naming 
+-           */
+-          forceNewLockPath = 1;
+-          tryOldLockPath = 0;
+-          continue; /* go back to the do {} while start point, try again */
+-        }
+-      }
+-      if( rc==SQLITE_OK ){
+-        /* Need to make a copy of path if we extracted the value
+-         ** from the conch file or the path was allocated on the stack
+-         */
+-        if( tempLockPath ){
+-          pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
+-          if( !pCtx->lockProxyPath ){
+-            rc = SQLITE_NOMEM;
+-          }
+-        }
+-      }
+-      if( rc==SQLITE_OK ){
+-        pCtx->conchHeld = 1;
+-        
+-        if( pCtx->lockProxy->pMethod == &afpIoMethods ){
+-          afpLockingContext *afpCtx;
+-          afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
+-          afpCtx->dbPath = pCtx->lockProxyPath;
+-        }
+-      } else {
+-        conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+-      }
+-      OSTRACE(("TAKECONCH  %d %s\n", conchFile->h,
+-               rc==SQLITE_OK?"ok":"failed"));
+-      return rc;
+-    } while (1); /* in case we need to retry the :auto: lock file - 
+-                 ** we should never get here except via the 'continue' call. */
++  *pp = 0;
++
++#if SQLITE_MAX_MMAP_SIZE>0
++  if( pFd->mmapSizeMax>0 ){
++    if( pFd->pMapRegion==0 ){
++      int rc = unixMapfile(pFd, -1);
++      if( rc!=SQLITE_OK ) return rc;
++    }
++    if( pFd->mmapSize >= iOff+nAmt ){
++      *pp = &((u8 *)pFd->pMapRegion)[iOff];
++      pFd->nFetchOut++;
++    }
+   }
++#endif
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** If pFile holds a lock on a conch file, then release that lock.
++** If the third argument is non-NULL, then this function releases a 
++** reference obtained by an earlier call to unixFetch(). The second
++** argument passed to this function must be the same as the corresponding
++** argument that was passed to the unixFetch() invocation. 
++**
++** Or, if the third argument is NULL, then this function is being called 
++** to inform the VFS layer that, according to POSIX, any existing mapping 
++** may now be invalid and should be unmapped.
+ */
+-static int proxyReleaseConch(unixFile *pFile){
+-  int rc = SQLITE_OK;         /* Subroutine return code */
+-  proxyLockingContext *pCtx;  /* The locking context for the proxy lock */
+-  unixFile *conchFile;        /* Name of the conch file */
++static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
++  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
++  UNUSED_PARAMETER(iOff);
+ 
+-  pCtx = (proxyLockingContext *)pFile->lockingContext;
+-  conchFile = pCtx->conchFile;
+-  OSTRACE(("RELEASECONCH  %d for %s pid=%d\n", conchFile->h,
+-           (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), 
+-           getpid()));
+-  if( pCtx->conchHeld>0 ){
+-    rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
++  /* If p==0 (unmap the entire file) then there must be no outstanding 
++  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
++  ** then there must be at least one outstanding.  */
++  assert( (p==0)==(pFd->nFetchOut==0) );
++
++  /* If p!=0, it must match the iOff value. */
++  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
++
++  if( p ){
++    pFd->nFetchOut--;
++  }else{
++    unixUnmapfile(pFd);
+   }
+-  pCtx->conchHeld = 0;
+-  OSTRACE(("RELEASECONCH  %d %s\n", conchFile->h,
+-           (rc==SQLITE_OK ? "ok" : "failed")));
+-  return rc;
++
++  assert( pFd->nFetchOut>=0 );
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Given the name of a database file, compute the name of its conch file.
+-** Store the conch filename in memory obtained from sqlite3_malloc().
+-** Make *pConchPath point to the new name.  Return SQLITE_OK on success
+-** or SQLITE_NOMEM if unable to obtain memory.
++** Here ends the implementation of all sqlite3_file methods.
+ **
+-** The caller is responsible for ensuring that the allocated memory
+-** space is eventually freed.
++********************** End sqlite3_file Methods *******************************
++******************************************************************************/
++
++/*
++** This division contains definitions of sqlite3_io_methods objects that
++** implement various file locking strategies.  It also contains definitions
++** of "finder" functions.  A finder-function is used to locate the appropriate
++** sqlite3_io_methods object for a particular database file.  The pAppData
++** field of the sqlite3_vfs VFS objects are initialized to be pointers to
++** the correct finder-function for that VFS.
+ **
+-** *pConchPath is set to NULL if a memory allocation error occurs.
++** Most finder functions return a pointer to a fixed sqlite3_io_methods
++** object.  The only interesting finder-function is autolockIoFinder, which
++** looks at the filesystem type and tries to guess the best locking
++** strategy from that.
++**
++** For finder-funtion F, two objects are created:
++**
++**    (1) The real finder-function named "FImpt()".
++**
++**    (2) A constant pointer to this function named just "F".
++**
++**
++** A pointer to the F pointer is used as the pAppData value for VFS
++** objects.  We have to do this instead of letting pAppData point
++** directly at the finder-function since C90 rules prevent a void*
++** from be cast into a function pointer.
++**
++**
++** Each instance of this macro generates two objects:
++**
++**   *  A constant sqlite3_io_methods object call METHOD that has locking
++**      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
++**
++**   *  An I/O method finder function called FINDER that returns a pointer
++**      to the METHOD object in the previous bullet.
+ */
+-static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
+-  int i;                        /* Loop counter */
+-  int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
+-  char *conchPath;              /* buffer in which to construct conch name */
++#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK)      \
++static const sqlite3_io_methods METHOD = {                                   \
++   VERSION,                    /* iVersion */                                \
++   CLOSE,                      /* xClose */                                  \
++   unixRead,                   /* xRead */                                   \
++   unixWrite,                  /* xWrite */                                  \
++   unixTruncate,               /* xTruncate */                               \
++   unixSync,                   /* xSync */                                   \
++   unixFileSize,               /* xFileSize */                               \
++   LOCK,                       /* xLock */                                   \
++   UNLOCK,                     /* xUnlock */                                 \
++   CKLOCK,                     /* xCheckReservedLock */                      \
++   unixFileControl,            /* xFileControl */                            \
++   unixSectorSize,             /* xSectorSize */                             \
++   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
++   unixShmMap,                 /* xShmMap */                                 \
++   unixShmLock,                /* xShmLock */                                \
++   unixShmBarrier,             /* xShmBarrier */                             \
++   unixShmUnmap,               /* xShmUnmap */                               \
++   unixFetch,                  /* xFetch */                                  \
++   unixUnfetch,                /* xUnfetch */                                \
++};                                                                           \
++static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
++  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
++  return &METHOD;                                                            \
++}                                                                            \
++static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
++    = FINDER##Impl;
+ 
+-  /* Allocate space for the conch filename and initialize the name to
+-  ** the name of the original database file. */  
+-  *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
+-  if( conchPath==0 ){
+-    return SQLITE_NOMEM;
++/*
++** Here are all of the sqlite3_io_methods objects for each of the
++** locking strategies.  Functions that return pointers to these methods
++** are also created.
++*/
++IOMETHODS(
++  posixIoFinder,            /* Finder function name */
++  posixIoMethods,           /* sqlite3_io_methods object name */
++  3,                        /* shared memory and mmap are enabled */
++  unixClose,                /* xClose method */
++  unixLock,                 /* xLock method */
++  unixUnlock,               /* xUnlock method */
++  unixCheckReservedLock     /* xCheckReservedLock method */
++)
++IOMETHODS(
++  nolockIoFinder,           /* Finder function name */
++  nolockIoMethods,          /* sqlite3_io_methods object name */
++  1,                        /* shared memory is disabled */
++  nolockClose,              /* xClose method */
++  nolockLock,               /* xLock method */
++  nolockUnlock,             /* xUnlock method */
++  nolockCheckReservedLock   /* xCheckReservedLock method */
++)
++IOMETHODS(
++  dotlockIoFinder,          /* Finder function name */
++  dotlockIoMethods,         /* sqlite3_io_methods object name */
++  1,                        /* shared memory is disabled */
++  dotlockClose,             /* xClose method */
++  dotlockLock,              /* xLock method */
++  dotlockUnlock,            /* xUnlock method */
++  dotlockCheckReservedLock  /* xCheckReservedLock method */
++)
++
++#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
++IOMETHODS(
++  flockIoFinder,            /* Finder function name */
++  flockIoMethods,           /* sqlite3_io_methods object name */
++  1,                        /* shared memory is disabled */
++  flockClose,               /* xClose method */
++  flockLock,                /* xLock method */
++  flockUnlock,              /* xUnlock method */
++  flockCheckReservedLock    /* xCheckReservedLock method */
++)
++#endif
++
++#if OS_VXWORKS
++IOMETHODS(
++  semIoFinder,              /* Finder function name */
++  semIoMethods,             /* sqlite3_io_methods object name */
++  1,                        /* shared memory is disabled */
++  semClose,                 /* xClose method */
++  semLock,                  /* xLock method */
++  semUnlock,                /* xUnlock method */
++  semCheckReservedLock      /* xCheckReservedLock method */
++)
++#endif
++
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++IOMETHODS(
++  afpIoFinder,              /* Finder function name */
++  afpIoMethods,             /* sqlite3_io_methods object name */
++  1,                        /* shared memory is disabled */
++  afpClose,                 /* xClose method */
++  afpLock,                  /* xLock method */
++  afpUnlock,                /* xUnlock method */
++  afpCheckReservedLock      /* xCheckReservedLock method */
++)
++#endif
++
++/*
++** The proxy locking method is a "super-method" in the sense that it
++** opens secondary file descriptors for the conch and lock files and
++** it uses proxy, dot-file, AFP, and flock() locking methods on those
++** secondary files.  For this reason, the division that implements
++** proxy locking is located much further down in the file.  But we need
++** to go ahead and define the sqlite3_io_methods and finder function
++** for proxy locking here.  So we forward declare the I/O methods.
++*/
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++static int proxyClose(sqlite3_file*);
++static int proxyLock(sqlite3_file*, int);
++static int proxyUnlock(sqlite3_file*, int);
++static int proxyCheckReservedLock(sqlite3_file*, int*);
++IOMETHODS(
++  proxyIoFinder,            /* Finder function name */
++  proxyIoMethods,           /* sqlite3_io_methods object name */
++  1,                        /* shared memory is disabled */
++  proxyClose,               /* xClose method */
++  proxyLock,                /* xLock method */
++  proxyUnlock,              /* xUnlock method */
++  proxyCheckReservedLock    /* xCheckReservedLock method */
++)
++#endif
++
++/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++IOMETHODS(
++  nfsIoFinder,               /* Finder function name */
++  nfsIoMethods,              /* sqlite3_io_methods object name */
++  1,                         /* shared memory is disabled */
++  unixClose,                 /* xClose method */
++  unixLock,                  /* xLock method */
++  nfsUnlock,                 /* xUnlock method */
++  unixCheckReservedLock      /* xCheckReservedLock method */
++)
++#endif
++
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++/* 
++** This "finder" function attempts to determine the best locking strategy 
++** for the database file "filePath".  It then returns the sqlite3_io_methods
++** object that implements that strategy.
++**
++** This is for MacOSX only.
++*/
++static const sqlite3_io_methods *autolockIoFinderImpl(
++  const char *filePath,    /* name of the database file */
++  unixFile *pNew           /* open file object for the database file */
++){
++  static const struct Mapping {
++    const char *zFilesystem;              /* Filesystem type name */
++    const sqlite3_io_methods *pMethods;   /* Appropriate locking method */
++  } aMap[] = {
++    { "hfs",    &posixIoMethods },
++    { "ufs",    &posixIoMethods },
++    { "afpfs",  &afpIoMethods },
++    { "smbfs",  &afpIoMethods },
++    { "webdav", &nolockIoMethods },
++    { 0, 0 }
++  };
++  int i;
++  struct statfs fsInfo;
++  struct flock lockInfo;
++
++  if( !filePath ){
++    /* If filePath==NULL that means we are dealing with a transient file
++    ** that does not need to be locked. */
++    return &nolockIoMethods;
+   }
+-  memcpy(conchPath, dbPath, len+1);
+-  
+-  /* now insert a "." before the last / character */
+-  for( i=(len-1); i>=0; i-- ){
+-    if( conchPath[i]=='/' ){
+-      i++;
+-      break;
++  if( statfs(filePath, &fsInfo) != -1 ){
++    if( fsInfo.f_flags & MNT_RDONLY ){
++      return &nolockIoMethods;
++    }
++    for(i=0; aMap[i].zFilesystem; i++){
++      if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
++        return aMap[i].pMethods;
++      }
+     }
+   }
+-  conchPath[i]='.';
+-  while ( i<len ){
+-    conchPath[i+1]=dbPath[i];
+-    i++;
+-  }
+-
+-  /* append the "-conch" suffix to the file */
+-  memcpy(&conchPath[i+1], "-conch", 7);
+-  assert( (int)strlen(conchPath) == len+7 );
+ 
+-  return SQLITE_OK;
++  /* Default case. Handles, amongst others, "nfs".
++  ** Test byte-range lock using fcntl(). If the call succeeds, 
++  ** assume that the file-system supports POSIX style locks. 
++  */
++  lockInfo.l_len = 1;
++  lockInfo.l_start = 0;
++  lockInfo.l_whence = SEEK_SET;
++  lockInfo.l_type = F_RDLCK;
++  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
++    if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
++      return &nfsIoMethods;
++    } else {
++      return &posixIoMethods;
++    }
++  }else{
++    return &dotlockIoMethods;
++  }
+ }
++static const sqlite3_io_methods 
++  *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
+ 
++#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+ 
+-/* Takes a fully configured proxy locking-style unix file and switches
+-** the local lock file path 
++#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
++/* 
++** This "finder" function attempts to determine the best locking strategy 
++** for the database file "filePath".  It then returns the sqlite3_io_methods
++** object that implements that strategy.
++**
++** This is for VXWorks only.
+ */
+-static int switchLockProxyPath(unixFile *pFile, const char *path) {
+-  proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
+-  char *oldPath = pCtx->lockProxyPath;
+-  int rc = SQLITE_OK;
++static const sqlite3_io_methods *autolockIoFinderImpl(
++  const char *filePath,    /* name of the database file */
++  unixFile *pNew           /* the open file object */
++){
++  struct flock lockInfo;
+ 
+-  if( pFile->eFileLock!=NO_LOCK ){
+-    return SQLITE_BUSY;
+-  }  
++  if( !filePath ){
++    /* If filePath==NULL that means we are dealing with a transient file
++    ** that does not need to be locked. */
++    return &nolockIoMethods;
++  }
+ 
+-  /* nothing to do if the path is NULL, :auto: or matches the existing path */
+-  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
+-    (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
+-    return SQLITE_OK;
++  /* Test if fcntl() is supported and use POSIX style locks.
++  ** Otherwise fall back to the named semaphore method.
++  */
++  lockInfo.l_len = 1;
++  lockInfo.l_start = 0;
++  lockInfo.l_whence = SEEK_SET;
++  lockInfo.l_type = F_RDLCK;
++  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
++    return &posixIoMethods;
+   }else{
+-    unixFile *lockProxy = pCtx->lockProxy;
+-    pCtx->lockProxy=NULL;
+-    pCtx->conchHeld = 0;
+-    if( lockProxy!=NULL ){
+-      rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
+-      if( rc ) return rc;
+-      sqlite3_free(lockProxy);
+-    }
+-    sqlite3_free(oldPath);
+-    pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
++    return &semIoMethods;
+   }
+-  
+-  return rc;
+ }
++static const sqlite3_io_methods 
++  *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
++
++#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
+ 
+ /*
+-** pFile is a file that has been opened by a prior xOpen call.  dbPath
+-** is a string buffer at least MAXPATHLEN+1 characters in size.
++** An abstract type for a pointer to a IO method finder function:
++*/
++typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
++
++
++/****************************************************************************
++**************************** sqlite3_vfs methods ****************************
+ **
+-** This routine find the filename associated with pFile and writes it
+-** int dbPath.
++** This division contains the implementation of methods on the
++** sqlite3_vfs object.
+ */
+-static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
+-#if defined(__APPLE__)
+-  if( pFile->pMethod == &afpIoMethods ){
+-    /* afp style keeps a reference to the db path in the filePath field 
+-    ** of the struct */
+-    assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+-    strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
+-  } else
+-#endif
+-  if( pFile->pMethod == &dotlockIoMethods ){
+-    /* dot lock style uses the locking context to store the dot lock
+-    ** file path */
+-    int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
+-    memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
+-  }else{
+-    /* all other styles use the locking context to store the db file path */
+-    assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+-    strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
+-  }
+-  return SQLITE_OK;
+-}
+ 
+ /*
+-** Takes an already filled in unix file and alters it so all file locking 
+-** will be performed on the local proxy lock file.  The following fields
+-** are preserved in the locking context so that they can be restored and 
+-** the unix structure properly cleaned up at close time:
+-**  ->lockingContext
+-**  ->pMethod
++** Initialize the contents of the unixFile structure pointed to by pId.
+ */
+-static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
+-  proxyLockingContext *pCtx;
+-  char dbPath[MAXPATHLEN+1];       /* Name of the database file */
+-  char *lockPath=NULL;
++static int fillInUnixFile(
++  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
++  int h,                  /* Open file descriptor of file being opened */
++  sqlite3_file *pId,      /* Write to the unixFile structure here */
++  const char *zFilename,  /* Name of the file being opened */
++  int ctrlFlags           /* Zero or more UNIXFILE_* values */
++){
++  const sqlite3_io_methods *pLockingStyle;
++  unixFile *pNew = (unixFile *)pId;
+   int rc = SQLITE_OK;
+-  
+-  if( pFile->eFileLock!=NO_LOCK ){
+-    return SQLITE_BUSY;
++
++  assert( pNew->pInode==NULL );
++
++  /* Usually the path zFilename should not be a relative pathname. The
++  ** exception is when opening the proxy "conch" file in builds that
++  ** include the special Apple locking styles.
++  */
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++  assert( zFilename==0 || zFilename[0]=='/' 
++    || pVfs->pAppData==(void*)&autolockIoFinder );
++#else
++  assert( zFilename==0 || zFilename[0]=='/' );
++#endif
++
++  /* No locking occurs in temporary files */
++  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
++
++  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
++  pNew->h = h;
++  pNew->pVfs = pVfs;
++  pNew->zPath = zFilename;
++  pNew->ctrlFlags = (u8)ctrlFlags;
++  pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
++  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
++                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
++    pNew->ctrlFlags |= UNIXFILE_PSOW;
+   }
+-  proxyGetDbPathForUnixFile(pFile, dbPath);
+-  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
+-    lockPath=NULL;
+-  }else{
+-    lockPath=(char *)path;
++  if( strcmp(pVfs->zName,"unix-excl")==0 ){
++    pNew->ctrlFlags |= UNIXFILE_EXCL;
+   }
+-  
+-  OSTRACE(("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
+-           (lockPath ? lockPath : ":auto:"), getpid()));
+ 
+-  pCtx = sqlite3_malloc( sizeof(*pCtx) );
+-  if( pCtx==0 ){
+-    return SQLITE_NOMEM;
++#if OS_VXWORKS
++  pNew->pId = vxworksFindFileId(zFilename);
++  if( pNew->pId==0 ){
++    ctrlFlags |= UNIXFILE_NOLOCK;
++    rc = SQLITE_NOMEM;
+   }
+-  memset(pCtx, 0, sizeof(*pCtx));
++#endif
+ 
+-  rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
+-  if( rc==SQLITE_OK ){
+-    rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
+-    if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
+-      /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
+-      ** (c) the file system is read-only, then enable no-locking access.
+-      ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
+-      ** that openFlags will have only one of O_RDONLY or O_RDWR.
++  if( ctrlFlags & UNIXFILE_NOLOCK ){
++    pLockingStyle = &nolockIoMethods;
++  }else{
++    pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
++#if SQLITE_ENABLE_LOCKING_STYLE
++    /* Cache zFilename in the locking context (AFP and dotlock override) for
++    ** proxyLock activation is possible (remote proxy is based on db name)
++    ** zFilename remains valid until file is closed, to support */
++    pNew->lockingContext = (void*)zFilename;
++#endif
++  }
++
++  if( pLockingStyle == &posixIoMethods
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
++    || pLockingStyle == &nfsIoMethods
++#endif
++  ){
++    unixEnterMutex();
++    rc = findInodeInfo(pNew, &pNew->pInode);
++    if( rc!=SQLITE_OK ){
++      /* If an error occurred in findInodeInfo(), close the file descriptor
++      ** immediately, before releasing the mutex. findInodeInfo() may fail
++      ** in two scenarios:
++      **
++      **   (a) A call to fstat() failed.
++      **   (b) A malloc failed.
++      **
++      ** Scenario (b) may only occur if the process is holding no other
++      ** file descriptors open on the same file. If there were other file
++      ** descriptors on this file, then no malloc would be required by
++      ** findInodeInfo(). If this is the case, it is quite safe to close
++      ** handle h - as it is guaranteed that no posix locks will be released
++      ** by doing so.
++      **
++      ** If scenario (a) caused the error then things are not so safe. The
++      ** implicit assumption here is that if fstat() fails, things are in
++      ** such bad shape that dropping a lock or two doesn't matter much.
+       */
+-      struct statfs fsInfo;
+-      struct stat conchInfo;
+-      int goLockless = 0;
++      robust_close(pNew, h, __LINE__);
++      h = -1;
++    }
++    unixLeaveMutex();
++  }
+ 
+-      if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
+-        int err = errno;
+-        if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
+-          goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
+-        }
+-      }
+-      if( goLockless ){
+-        pCtx->conchHeld = -1; /* read only FS/ lockless */
+-        rc = SQLITE_OK;
++#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
++  else if( pLockingStyle == &afpIoMethods ){
++    /* AFP locking uses the file path so it needs to be included in
++    ** the afpLockingContext.
++    */
++    afpLockingContext *pCtx;
++    pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
++    if( pCtx==0 ){
++      rc = SQLITE_NOMEM;
++    }else{
++      /* NB: zFilename exists and remains valid until the file is closed
++      ** according to requirement F11141.  So we do not need to make a
++      ** copy of the filename. */
++      pCtx->dbPath = zFilename;
++      pCtx->reserved = 0;
++      srandomdev();
++      unixEnterMutex();
++      rc = findInodeInfo(pNew, &pNew->pInode);
++      if( rc!=SQLITE_OK ){
++        sqlite3_free(pNew->lockingContext);
++        robust_close(pNew, h, __LINE__);
++        h = -1;
+       }
++      unixLeaveMutex();        
+     }
+-  }  
+-  if( rc==SQLITE_OK && lockPath ){
+-    pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
+   }
++#endif
+ 
+-  if( rc==SQLITE_OK ){
+-    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
+-    if( pCtx->dbPath==NULL ){
++  else if( pLockingStyle == &dotlockIoMethods ){
++    /* Dotfile locking uses the file path so it needs to be included in
++    ** the dotlockLockingContext 
++    */
++    char *zLockFile;
++    int nFilename;
++    assert( zFilename!=0 );
++    nFilename = (int)strlen(zFilename) + 6;
++    zLockFile = (char *)sqlite3_malloc(nFilename);
++    if( zLockFile==0 ){
+       rc = SQLITE_NOMEM;
++    }else{
++      sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
+     }
++    pNew->lockingContext = zLockFile;
+   }
+-  if( rc==SQLITE_OK ){
+-    /* all memory is allocated, proxys are created and assigned, 
+-    ** switch the locking context and pMethod then return.
++
++#if OS_VXWORKS
++  else if( pLockingStyle == &semIoMethods ){
++    /* Named semaphore locking uses the file path so it needs to be
++    ** included in the semLockingContext
+     */
+-    pCtx->oldLockingContext = pFile->lockingContext;
+-    pFile->lockingContext = pCtx;
+-    pCtx->pOldMethod = pFile->pMethod;
+-    pFile->pMethod = &proxyIoMethods;
+-  }else{
+-    if( pCtx->conchFile ){ 
+-      pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
+-      sqlite3_free(pCtx->conchFile);
++    unixEnterMutex();
++    rc = findInodeInfo(pNew, &pNew->pInode);
++    if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
++      char *zSemName = pNew->pInode->aSemName;
++      int n;
++      sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
++                       pNew->pId->zCanonicalName);
++      for( n=1; zSemName[n]; n++ )
++        if( zSemName[n]=='/' ) zSemName[n] = '_';
++      pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
++      if( pNew->pInode->pSem == SEM_FAILED ){
++        rc = SQLITE_NOMEM;
++        pNew->pInode->aSemName[0] = '\0';
++      }
+     }
+-    sqlite3DbFree(0, pCtx->lockProxyPath);
+-    sqlite3_free(pCtx->conchFilePath); 
+-    sqlite3_free(pCtx);
++    unixLeaveMutex();
++  }
++#endif
++  
++  pNew->lastErrno = 0;
++#if OS_VXWORKS
++  if( rc!=SQLITE_OK ){
++    if( h>=0 ) robust_close(pNew, h, __LINE__);
++    h = -1;
++    osUnlink(zFilename);
++    pNew->ctrlFlags |= UNIXFILE_DELETE;
++  }
++#endif
++  if( rc!=SQLITE_OK ){
++    if( h>=0 ) robust_close(pNew, h, __LINE__);
++  }else{
++    pNew->pMethod = pLockingStyle;
++    OpenCounter(+1);
++    verifyDbFile(pNew);
+   }
+-  OSTRACE(("TRANSPROXY  %d %s\n", pFile->h,
+-           (rc==SQLITE_OK ? "ok" : "failed")));
+   return rc;
+ }
+ 
++/*
++** Return the name of a directory in which to put temporary files.
++** If no suitable temporary file directory can be found, return NULL.
++*/
++static const char *unixTempFileDir(void){
++  static const char *azDirs[] = {
++     0,
++     0,
++     "/var/tmp",
++     "/usr/tmp",
++     "/tmp",
++     0        /* List terminator */
++  };
++  unsigned int i;
++  struct stat buf;
++  const char *zDir = 0;
++
++  azDirs[0] = sqlite3_temp_directory;
++  if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
++  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
++    if( zDir==0 ) continue;
++    if( osStat(zDir, &buf) ) continue;
++    if( !S_ISDIR(buf.st_mode) ) continue;
++    if( osAccess(zDir, 07) ) continue;
++    break;
++  }
++  return zDir;
++}
+ 
+ /*
+-** This routine handles sqlite3_file_control() calls that are specific
+-** to proxy locking.
++** Create a temporary file name in zBuf.  zBuf must be allocated
++** by the calling process and must be big enough to hold at least
++** pVfs->mxPathname bytes.
+ */
+-static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
+-  switch( op ){
+-    case SQLITE_GET_LOCKPROXYFILE: {
+-      unixFile *pFile = (unixFile*)id;
+-      if( pFile->pMethod == &proxyIoMethods ){
+-        proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
+-        proxyTakeConch(pFile);
+-        if( pCtx->lockProxyPath ){
+-          *(const char **)pArg = pCtx->lockProxyPath;
+-        }else{
+-          *(const char **)pArg = ":auto: (not held)";
+-        }
+-      } else {
+-        *(const char **)pArg = NULL;
+-      }
+-      return SQLITE_OK;
++static int unixGetTempname(int nBuf, char *zBuf){
++  static const unsigned char zChars[] =
++    "abcdefghijklmnopqrstuvwxyz"
++    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
++    "0123456789";
++  unsigned int i, j;
++  const char *zDir;
++
++  /* It's odd to simulate an io-error here, but really this is just
++  ** using the io-error infrastructure to test that SQLite handles this
++  ** function failing. 
++  */
++  SimulateIOError( return SQLITE_IOERR );
++
++  zDir = unixTempFileDir();
++  if( zDir==0 ) zDir = ".";
++
++  /* Check that the output buffer is large enough for the temporary file 
++  ** name. If it is not, return SQLITE_ERROR.
++  */
++  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
++    return SQLITE_ERROR;
++  }
++
++  do{
++    sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
++    j = (int)strlen(zBuf);
++    sqlite3_randomness(15, &zBuf[j]);
++    for(i=0; i<15; i++, j++){
++      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
+     }
+-    case SQLITE_SET_LOCKPROXYFILE: {
+-      unixFile *pFile = (unixFile*)id;
+-      int rc = SQLITE_OK;
+-      int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
+-      if( pArg==NULL || (const char *)pArg==0 ){
+-        if( isProxyStyle ){
+-          /* turn off proxy locking - not supported */
+-          rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
+-        }else{
+-          /* turn off proxy locking - already off - NOOP */
+-          rc = SQLITE_OK;
+-        }
+-      }else{
+-        const char *proxyPath = (const char *)pArg;
+-        if( isProxyStyle ){
+-          proxyLockingContext *pCtx = 
+-            (proxyLockingContext*)pFile->lockingContext;
+-          if( !strcmp(pArg, ":auto:") 
+-           || (pCtx->lockProxyPath &&
+-               !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
+-          ){
+-            rc = SQLITE_OK;
+-          }else{
+-            rc = switchLockProxyPath(pFile, proxyPath);
+-          }
+-        }else{
+-          /* turn on proxy file locking */
+-          rc = proxyTransformUnixFile(pFile, proxyPath);
+-        }
+-      }
+-      return rc;
++    zBuf[j] = 0;
++    zBuf[j+1] = 0;
++  }while( osAccess(zBuf,0)==0 );
++  return SQLITE_OK;
++}
++
++#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
++/*
++** Routine to transform a unixFile into a proxy-locking unixFile.
++** Implementation in the proxy-lock division, but used by unixOpen()
++** if SQLITE_PREFER_PROXY_LOCKING is defined.
++*/
++static int proxyTransformUnixFile(unixFile*, const char*);
++#endif
++
++/*
++** Search for an unused file descriptor that was opened on the database 
++** file (not a journal or master-journal file) identified by pathname
++** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
++** argument to this function.
++**
++** Such a file descriptor may exist if a database connection was closed
++** but the associated file descriptor could not be closed because some
++** other file descriptor open on the same file is holding a file-lock.
++** Refer to comments in the unixClose() function and the lengthy comment
++** describing "Posix Advisory Locking" at the start of this file for 
++** further details. Also, ticket #4018.
++**
++** If a suitable file descriptor is found, then it is returned. If no
++** such file descriptor is located, -1 is returned.
++*/
++static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
++  UnixUnusedFd *pUnused = 0;
++
++  /* Do not search for an unused file descriptor on vxworks. Not because
++  ** vxworks would not benefit from the change (it might, we're not sure),
++  ** but because no way to test it is currently available. It is better 
++  ** not to risk breaking vxworks support for the sake of such an obscure 
++  ** feature.  */
++#if !OS_VXWORKS
++  struct stat sStat;                   /* Results of stat() call */
++
++  /* A stat() call may fail for various reasons. If this happens, it is
++  ** almost certain that an open() call on the same path will also fail.
++  ** For this reason, if an error occurs in the stat() call here, it is
++  ** ignored and -1 is returned. The caller will try to open a new file
++  ** descriptor on the same path, fail, and return an error to SQLite.
++  **
++  ** Even if a subsequent open() call does succeed, the consequences of
++  ** not searching for a resusable file descriptor are not dire.  */
++  if( 0==osStat(zPath, &sStat) ){
++    unixInodeInfo *pInode;
++
++    unixEnterMutex();
++    pInode = inodeList;
++    while( pInode && (pInode->fileId.dev!=sStat.st_dev
++                     || pInode->fileId.ino!=sStat.st_ino) ){
++       pInode = pInode->pNext;
+     }
+-    default: {
+-      assert( 0 );  /* The call assures that only valid opcodes are sent */
++    if( pInode ){
++      UnixUnusedFd **pp;
++      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
++      pUnused = *pp;
++      if( pUnused ){
++        *pp = pUnused->pNext;
++      }
+     }
++    unixLeaveMutex();
+   }
+-  /*NOTREACHED*/
+-  return SQLITE_ERROR;
++#endif    /* if !OS_VXWORKS */
++  return pUnused;
+ }
  
+ /*
+-** Within this division (the proxying locking implementation) the procedures
+-** above this point are all utilities.  The lock-related methods of the
+-** proxy-locking sqlite3_io_method object follow.
++** This function is called by unixOpen() to determine the unix permissions
++** to create new files with. If no error occurs, then SQLITE_OK is returned
++** and a value suitable for passing as the third argument to open(2) is
++** written to *pMode. If an IO error occurs, an SQLite error code is 
++** returned and the value of *pMode is not modified.
++**
++** In most cases cases, this routine sets *pMode to 0, which will become
++** an indication to robust_open() to create the file using
++** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
++** But if the file being opened is a WAL or regular journal file, then 
++** this function queries the file-system for the permissions on the 
++** corresponding database file and sets *pMode to this value. Whenever 
++** possible, WAL and journal files are created using the same permissions 
++** as the associated database file.
++**
++** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
++** original filename is unavailable.  But 8_3_NAMES is only used for
++** FAT filesystems and permissions do not matter there, so just use
++** the default permissions.
+ */
++static int findCreateFileMode(
++  const char *zPath,              /* Path of file (possibly) being created */
++  int flags,                      /* Flags passed as 4th argument to xOpen() */
++  mode_t *pMode,                  /* OUT: Permissions to open file with */
++  uid_t *pUid,                    /* OUT: uid to set on the file */
++  gid_t *pGid                     /* OUT: gid to set on the file */
++){
++  int rc = SQLITE_OK;             /* Return Code */
++  *pMode = 0;
++  *pUid = 0;
++  *pGid = 0;
++  if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
++    char zDb[MAX_PATHNAME+1];     /* Database file path */
++    int nDb;                      /* Number of valid bytes in zDb */
++    struct stat sStat;            /* Output of stat() on database file */
  
-@@ -43883,6 +46197,38 @@
++    /* zPath is a path to a WAL or journal file. The following block derives
++    ** the path to the associated database file from zPath. This block handles
++    ** the following naming conventions:
++    **
++    **   "<path to db>-journal"
++    **   "<path to db>-wal"
++    **   "<path to db>-journalNN"
++    **   "<path to db>-walNN"
++    **
++    ** where NN is a decimal number. The NN naming schemes are 
++    ** used by the test_multiplex.c module.
++    */
++    nDb = sqlite3Strlen30(zPath) - 1; 
++#ifdef SQLITE_ENABLE_8_3_NAMES
++    while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
++    if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
++#else
++    while( zPath[nDb]!='-' ){
++      assert( nDb>0 );
++      assert( zPath[nDb]!='\n' );
++      nDb--;
++    }
++#endif
++    memcpy(zDb, zPath, nDb);
++    zDb[nDb] = '\0';
  
- #endif /* SQLITE_OMIT_DISKIO */
+-/*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, set *pResOut
+-** to a non-zero value otherwise *pResOut is set to zero.  The return value
+-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+-*/
+-static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
+-  unixFile *pFile = (unixFile*)id;
+-  int rc = proxyTakeConch(pFile);
+-  if( rc==SQLITE_OK ){
+-    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+-    if( pCtx->conchHeld>0 ){
+-      unixFile *proxy = pCtx->lockProxy;
+-      return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
+-    }else{ /* conchHeld < 0 is lockless */
+-      pResOut=0;
++    if( 0==osStat(zDb, &sStat) ){
++      *pMode = sStat.st_mode & 0777;
++      *pUid = sStat.st_uid;
++      *pGid = sStat.st_gid;
++    }else{
++      rc = SQLITE_IOERR_FSTAT;
+     }
++  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
++    *pMode = 0600;
+   }
+   return rc;
+ }
+ 
+ /*
+-** Lock the file with the lock specified by parameter eFileLock - one
+-** of the following:
++** Open the file zPath.
++** 
++** Previously, the SQLite OS layer used three functions in place of this
++** one:
+ **
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
++**     sqlite3OsOpenReadWrite();
++**     sqlite3OsOpenReadOnly();
++**     sqlite3OsOpenExclusive();
+ **
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
++** These calls correspond to the following combinations of flags:
+ **
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
++**     ReadWrite() ->     (READWRITE | CREATE)
++**     ReadOnly()  ->     (READONLY) 
++**     OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
+ **
+-** This routine will only increase a lock.  Use the sqlite3OsUnlock()
+-** routine to lower a locking level.
++** The old OpenExclusive() accepted a boolean argument - "delFlag". If
++** true, the file was configured to be automatically deleted when the
++** file handle closed. To achieve the same effect using this new 
++** interface, add the DELETEONCLOSE flag to those specified above for 
++** OpenExclusive().
+ */
+-static int proxyLock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  int rc = proxyTakeConch(pFile);
+-  if( rc==SQLITE_OK ){
+-    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+-    if( pCtx->conchHeld>0 ){
+-      unixFile *proxy = pCtx->lockProxy;
+-      rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
+-      pFile->eFileLock = proxy->eFileLock;
+-    }else{
+-      /* conchHeld < 0 is lockless */
+-    }
+-  }
+-  return rc;
+-}
++static int unixOpen(
++  sqlite3_vfs *pVfs,           /* The VFS for which this is the xOpen method */
++  const char *zPath,           /* Pathname of file to be opened */
++  sqlite3_file *pFile,         /* The file descriptor to be filled in */
++  int flags,                   /* Input flags to control the opening */
++  int *pOutFlags               /* Output flags returned to SQLite core */
++){
++  unixFile *p = (unixFile *)pFile;
++  int fd = -1;                   /* File descriptor returned by open() */
++  int openFlags = 0;             /* Flags to pass to open() */
++  int eType = flags&0xFFFFFF00;  /* Type of file to open */
++  int noLock;                    /* True to omit locking primitives */
++  int rc = SQLITE_OK;            /* Function Return Code */
++  int ctrlFlags = 0;             /* UNIXFILE_* flags */
  
-+/* BEGIN CRYPTO */
++  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
++  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
++  int isCreate     = (flags & SQLITE_OPEN_CREATE);
++  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
++  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
++#if SQLITE_ENABLE_LOCKING_STYLE
++  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
++#endif
++#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
++  struct statfs fsInfo;
++#endif
+ 
+-/*
+-** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
+-*/
+-static int proxyUnlock(sqlite3_file *id, int eFileLock) {
+-  unixFile *pFile = (unixFile*)id;
+-  int rc = proxyTakeConch(pFile);
+-  if( rc==SQLITE_OK ){
+-    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+-    if( pCtx->conchHeld>0 ){
+-      unixFile *proxy = pCtx->lockProxy;
+-      rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
+-      pFile->eFileLock = proxy->eFileLock;
++  /* If creating a master or main-file journal, this function will open
++  ** a file-descriptor on the directory too. The first time unixSync()
++  ** is called the directory file descriptor will be fsync()ed and close()d.
++  */
++  int syncDir = (isCreate && (
++        eType==SQLITE_OPEN_MASTER_JOURNAL 
++     || eType==SQLITE_OPEN_MAIN_JOURNAL 
++     || eType==SQLITE_OPEN_WAL
++  ));
++
++  /* If argument zPath is a NULL pointer, this function is required to open
++  ** a temporary file. Use this buffer to store the file name in.
++  */
++  char zTmpname[MAX_PATHNAME+2];
++  const char *zName = zPath;
++
++  /* Check the following statements are true: 
++  **
++  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
++  **   (b) if CREATE is set, then READWRITE must also be set, and
++  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
++  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
++  */
++  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
++  assert(isCreate==0 || isReadWrite);
++  assert(isExclusive==0 || isCreate);
++  assert(isDelete==0 || isCreate);
++
++  /* The main DB, main journal, WAL file and master journal are never 
++  ** automatically deleted. Nor are they ever temporary files.  */
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
++
++  /* Assert that the upper layer has set one of the "file-type" flags. */
++  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
++       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
++       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
++       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
++  );
++
++  memset(p, 0, sizeof(unixFile));
++
++  if( eType==SQLITE_OPEN_MAIN_DB ){
++    UnixUnusedFd *pUnused;
++    pUnused = findReusableFd(zName, flags);
++    if( pUnused ){
++      fd = pUnused->fd;
+     }else{
+-      /* conchHeld < 0 is lockless */
++      pUnused = sqlite3_malloc(sizeof(*pUnused));
++      if( !pUnused ){
++        return SQLITE_NOMEM;
++      }
+     }
+-  }
+-  return rc;
+-}
++    p->pUnused = pUnused;
+ 
+-/*
+-** Close a file that uses proxy locks.
+-*/
+-static int proxyClose(sqlite3_file *id) {
+-  if( id ){
+-    unixFile *pFile = (unixFile*)id;
+-    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+-    unixFile *lockProxy = pCtx->lockProxy;
+-    unixFile *conchFile = pCtx->conchFile;
+-    int rc = SQLITE_OK;
+-    
+-    if( lockProxy ){
+-      rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
+-      if( rc ) return rc;
+-      rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
+-      if( rc ) return rc;
+-      sqlite3_free(lockProxy);
+-      pCtx->lockProxy = 0;
+-    }
+-    if( conchFile ){
+-      if( pCtx->conchHeld ){
+-        rc = proxyReleaseConch(pFile);
+-        if( rc ) return rc;
+-      }
+-      rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
+-      if( rc ) return rc;
+-      sqlite3_free(conchFile);
++    /* Database filenames are double-zero terminated if they are not
++    ** URIs with parameters.  Hence, they can always be passed into
++    ** sqlite3_uri_parameter(). */
++    assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
++
++  }else if( !zName ){
++    /* If zName is NULL, the upper layer is requesting a temp file. */
++    assert(isDelete && !syncDir);
++    rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
++    if( rc!=SQLITE_OK ){
++      return rc;
+     }
+-    sqlite3DbFree(0, pCtx->lockProxyPath);
+-    sqlite3_free(pCtx->conchFilePath);
+-    sqlite3DbFree(0, pCtx->dbPath);
+-    /* restore the original locking context and pMethod then close it */
+-    pFile->lockingContext = pCtx->oldLockingContext;
+-    pFile->pMethod = pCtx->pOldMethod;
+-    sqlite3_free(pCtx);
+-    return pFile->pMethod->xClose(id);
++    zName = zTmpname;
++
++    /* Generated temporary filenames are always double-zero terminated
++    ** for use by sqlite3_uri_parameter(). */
++    assert( zName[strlen(zName)+1]==0 );
+   }
+-  return SQLITE_OK;
+-}
+ 
++  /* Determine the value of the flags parameter passed to POSIX function
++  ** open(). These must be calculated even if open() is not called, as
++  ** they may be stored as part of the file handle and used by the 
++  ** 'conch file' locking functions later on.  */
++  if( isReadonly )  openFlags |= O_RDONLY;
++  if( isReadWrite ) openFlags |= O_RDWR;
++  if( isCreate )    openFlags |= O_CREAT;
++  if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
++  openFlags |= (O_LARGEFILE|O_BINARY);
+ 
++  if( fd<0 ){
++    mode_t openMode;              /* Permissions to create file with */
++    uid_t uid;                    /* Userid for the file */
++    gid_t gid;                    /* Groupid for the file */
++    rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
++    if( rc!=SQLITE_OK ){
++      assert( !p->pUnused );
++      assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
++      return rc;
++    }
++    fd = robust_open(zName, openFlags, openMode);
++    OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
++    if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
++      /* Failed to open the file for read/write access. Try read-only. */
++      flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
++      openFlags &= ~(O_RDWR|O_CREAT);
++      flags |= SQLITE_OPEN_READONLY;
++      openFlags |= O_RDONLY;
++      isReadonly = 1;
++      fd = robust_open(zName, openFlags, openMode);
++    }
++    if( fd<0 ){
++      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
++      goto open_finished;
++    }
+ 
+-#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+-/*
+-** The proxy locking style is intended for use with AFP filesystems.
+-** And since AFP is only supported on MacOSX, the proxy locking is also
+-** restricted to MacOSX.
+-** 
+-**
+-******************* End of the proxy lock implementation **********************
+-******************************************************************************/
++    /* If this process is running as root and if creating a new rollback
++    ** journal or WAL file, set the ownership of the journal or WAL to be
++    ** the same as the original database.
++    */
++    if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
++      osFchown(fd, uid, gid);
++    }
++  }
++  assert( fd>=0 );
++  if( pOutFlags ){
++    *pOutFlags = flags;
++  }
+ 
+-/*
+-** Initialize the operating system interface.
+-**
+-** This routine registers all VFS implementations for unix-like operating
+-** systems.  This routine, and the sqlite3_os_end() routine that follows,
+-** should be the only routines in this file that are visible from other
+-** files.
+-**
+-** This routine is called once during SQLite initialization and by a
+-** single thread.  The memory allocation and mutex subsystems have not
+-** necessarily been initialized when this routine is called, and so they
+-** should not be used.
+-*/
+-SQLITE_API int sqlite3_os_init(void){ 
+-  /* 
+-  ** The following macro defines an initializer for an sqlite3_vfs object.
+-  ** The name of the VFS is NAME.  The pAppData is a pointer to a pointer
+-  ** to the "finder" function.  (pAppData is a pointer to a pointer because
+-  ** silly C90 rules prohibit a void* from being cast to a function pointer
+-  ** and so we have to go through the intermediate pointer to avoid problems
+-  ** when compiling with -pedantic-errors on GCC.)
+-  **
+-  ** The FINDER parameter to this macro is the name of the pointer to the
+-  ** finder-function.  The finder-function returns a pointer to the
+-  ** sqlite_io_methods object that implements the desired locking
+-  ** behaviors.  See the division above that contains the IOMETHODS
+-  ** macro for addition information on finder-functions.
+-  **
+-  ** Most finders simply return a pointer to a fixed sqlite3_io_methods
+-  ** object.  But the "autolockIoFinder" available on MacOSX does a little
+-  ** more than that; it looks at the filesystem type that hosts the 
+-  ** database file and tries to choose an locking method appropriate for
+-  ** that filesystem time.
+-  */
+-  #define UNIXVFS(VFSNAME, FINDER) {                        \
+-    3,                    /* iVersion */                    \
+-    sizeof(unixFile),     /* szOsFile */                    \
+-    MAX_PATHNAME,         /* mxPathname */                  \
+-    0,                    /* pNext */                       \
+-    VFSNAME,              /* zName */                       \
+-    (void*)&FINDER,       /* pAppData */                    \
+-    unixOpen,             /* xOpen */                       \
+-    unixDelete,           /* xDelete */                     \
+-    unixAccess,           /* xAccess */                     \
+-    unixFullPathname,     /* xFullPathname */               \
+-    unixDlOpen,           /* xDlOpen */                     \
+-    unixDlError,          /* xDlError */                    \
+-    unixDlSym,            /* xDlSym */                      \
+-    unixDlClose,          /* xDlClose */                    \
+-    unixRandomness,       /* xRandomness */                 \
+-    unixSleep,            /* xSleep */                      \
+-    unixCurrentTime,      /* xCurrentTime */                \
+-    unixGetLastError,     /* xGetLastError */               \
+-    unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
+-    unixSetSystemCall,    /* xSetSystemCall */              \
+-    unixGetSystemCall,    /* xGetSystemCall */              \
+-    unixNextSystemCall,   /* xNextSystemCall */             \
++  if( p->pUnused ){
++    p->pUnused->fd = fd;
++    p->pUnused->flags = flags;
+   }
+ 
+-  /*
+-  ** All default VFSes for unix are contained in the following array.
+-  **
+-  ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
+-  ** by the SQLite core when the VFS is registered.  So the following
+-  ** array cannot be const.
+-  */
+-  static sqlite3_vfs aVfs[] = {
+-#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
+-    UNIXVFS("unix",          autolockIoFinder ),
+-#else
+-    UNIXVFS("unix",          posixIoFinder ),
+-#endif
+-    UNIXVFS("unix-none",     nolockIoFinder ),
+-    UNIXVFS("unix-dotfile",  dotlockIoFinder ),
+-    UNIXVFS("unix-excl",     posixIoFinder ),
++  if( isDelete ){
+ #if OS_VXWORKS
+-    UNIXVFS("unix-namedsem", semIoFinder ),
++    zPath = zName;
++#else
++    osUnlink(zName);
+ #endif
++  }
+ #if SQLITE_ENABLE_LOCKING_STYLE
+-    UNIXVFS("unix-posix",    posixIoFinder ),
+-#if !OS_VXWORKS
+-    UNIXVFS("unix-flock",    flockIoFinder ),
++  else{
++    p->openFlags = openFlags;
++  }
++#endif
++
++  noLock = eType!=SQLITE_OPEN_MAIN_DB;
++
++  
++#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
++  if( fstatfs(fd, &fsInfo) == -1 ){
++    ((unixFile*)pFile)->lastErrno = errno;
++    robust_close(p, fd, __LINE__);
++    return SQLITE_IOERR_ACCESS;
++  }
++  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
++    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
++  }
+ #endif
++
++  /* Set up appropriate ctrlFlags */
++  if( isDelete )                ctrlFlags |= UNIXFILE_DELETE;
++  if( isReadonly )              ctrlFlags |= UNIXFILE_RDONLY;
++  if( noLock )                  ctrlFlags |= UNIXFILE_NOLOCK;
++  if( syncDir )                 ctrlFlags |= UNIXFILE_DIRSYNC;
++  if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
++
++#if SQLITE_ENABLE_LOCKING_STYLE
++#if SQLITE_PREFER_PROXY_LOCKING
++  isAutoProxy = 1;
+ #endif
+-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+-    UNIXVFS("unix-afp",      afpIoFinder ),
+-    UNIXVFS("unix-nfs",      nfsIoFinder ),
+-    UNIXVFS("unix-proxy",    proxyIoFinder ),
++  if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
++    char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
++    int useProxy = 0;
++
++    /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means 
++    ** never use proxy, NULL means use proxy for non-local files only.  */
++    if( envforce!=NULL ){
++      useProxy = atoi(envforce)>0;
++    }else{
++      if( statfs(zPath, &fsInfo) == -1 ){
++        /* In theory, the close(fd) call is sub-optimal. If the file opened
++        ** with fd is a database file, and there are other connections open
++        ** on that file that are currently holding advisory locks on it,
++        ** then the call to close() will cancel those locks. In practice,
++        ** we're assuming that statfs() doesn't fail very often. At least
++        ** not while other file descriptors opened by the same process on
++        ** the same file are working.  */
++        p->lastErrno = errno;
++        robust_close(p, fd, __LINE__);
++        rc = SQLITE_IOERR_ACCESS;
++        goto open_finished;
++      }
++      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
++    }
++    if( useProxy ){
++      rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
++      if( rc==SQLITE_OK ){
++        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
++        if( rc!=SQLITE_OK ){
++          /* Use unixClose to clean up the resources added in fillInUnixFile 
++          ** and clear all the structure's references.  Specifically, 
++          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
++          */
++          unixClose(pFile);
++          return rc;
++        }
++      }
++      goto open_finished;
++    }
++  }
+ #endif
+-  };
+-  unsigned int i;          /* Loop counter */
+-
+-  /* Double-check that the aSyscall[] array has been constructed
+-  ** correctly.  See ticket [bb3a86e890c8e96ab] */
+-  assert( ArraySize(aSyscall)==24 );
++  
++  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+ 
+-  /* Register all VFSes defined in the aVfs[] array */
+-  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
+-    sqlite3_vfs_register(&aVfs[i], i==0);
++open_finished:
++  if( rc!=SQLITE_OK ){
++    sqlite3_free(p->pUnused);
+   }
+-  return SQLITE_OK; 
+-}
+-
+-/*
+-** Shutdown the operating system interface.
+-**
+-** Some operating systems might need to do some cleanup in this routine,
+-** to release dynamically allocated objects.  But not on unix.
+-** This routine is a no-op for unix.
+-*/
+-SQLITE_API int sqlite3_os_end(void){ 
+-  return SQLITE_OK; 
++  return rc;
+ }
+- 
+-#endif /* SQLITE_OS_UNIX */
+ 
+-/************** End of os_unix.c *********************************************/
+-/************** Begin file os_win.c ******************************************/
+-/*
+-** 2004 May 22
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-******************************************************************************
+-**
+-** This file contains code that is specific to Windows.
+-*/
+-#if SQLITE_OS_WIN               /* This file is used for Windows only */
+-
+-#ifdef __CYGWIN__
+-# include <sys/cygwin.h>
+-#endif
+-
+-/*
+-** Include code that is common to all os_*.c files
+-*/
+-/************** Include os_common.h in the middle of os_win.c ****************/
+-/************** Begin file os_common.h ***************************************/
+-/*
+-** 2004 May 22
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-******************************************************************************
+-**
+-** This file contains macros and a little bit of code that is common to
+-** all of the platform-specific files (os_*.c) and is #included into those
+-** files.
+-**
+-** This file should be #included by the os_*.c files only.  It is not a
+-** general purpose header file.
+-*/
+-#ifndef _OS_COMMON_H_
+-#define _OS_COMMON_H_
+ 
+ /*
+-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
+-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
+-** switch.  The following code should catch this problem at compile-time.
++** Delete the file at zPath. If the dirSync argument is true, fsync()
++** the directory after deleting the file.
+ */
+-#ifdef MEMORY_DEBUG
+-# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
+-#endif
+-
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+-# ifndef SQLITE_DEBUG_OS_TRACE
+-#   define SQLITE_DEBUG_OS_TRACE 0
+-# endif
+-  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+-# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
++static int unixDelete(
++  sqlite3_vfs *NotUsed,     /* VFS containing this as the xDelete method */
++  const char *zPath,        /* Name of file to be deleted */
++  int dirSync               /* If true, fsync() directory after deleting file */
++){
++  int rc = SQLITE_OK;
++  UNUSED_PARAMETER(NotUsed);
++  SimulateIOError(return SQLITE_IOERR_DELETE);
++  if( osUnlink(zPath)==(-1) ){
++    if( errno==ENOENT ){
++      rc = SQLITE_IOERR_DELETE_NOENT;
++    }else{
++      rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
++    }
++    return rc;
++  }
++#ifndef SQLITE_DISABLE_DIRSYNC
++  if( (dirSync & 1)!=0 ){
++    int fd;
++    rc = osOpenDirectory(zPath, &fd);
++    if( rc==SQLITE_OK ){
++#if OS_VXWORKS
++      if( fsync(fd)==-1 )
+ #else
+-# define OSTRACE(X)
++      if( fsync(fd) )
+ #endif
++      {
++        rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
++      }
++      robust_close(0, fd, __LINE__);
++    }else if( rc==SQLITE_CANTOPEN ){
++      rc = SQLITE_OK;
++    }
++  }
++#endif
++  return rc;
++}
+ 
+ /*
+-** Macros for performance tracing.  Normally turned off.  Only works
+-** on i486 hardware.
+-*/
+-#ifdef SQLITE_PERFORMANCE_TRACE
+-
+-/* 
+-** hwtime.h contains inline assembler code for implementing 
+-** high-performance timing routines.
+-*/
+-/************** Include hwtime.h in the middle of os_common.h ****************/
+-/************** Begin file hwtime.h ******************************************/
+-/*
+-** 2008 May 27
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
++** Test the existence of or access permissions of file zPath. The
++** test performed depends on the value of flags:
+ **
+-******************************************************************************
++**     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
++**     SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
++**     SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
+ **
+-** This file contains inline asm code for retrieving "high-performance"
+-** counters for x86 class CPUs.
+-*/
+-#ifndef _HWTIME_H_
+-#define _HWTIME_H_
+-
+-/*
+-** The following routine only works on pentium-class (or newer) processors.
+-** It uses the RDTSC opcode to read the cycle count value out of the
+-** processor and returns that value.  This can be used for high-res
+-** profiling.
++** Otherwise return 0.
+ */
+-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
+-      (defined(i386) || defined(__i386__) || defined(_M_IX86))
+-
+-  #if defined(__GNUC__)
+-
+-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+-     unsigned int lo, hi;
+-     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+-     return (sqlite_uint64)hi << 32 | lo;
+-  }
+-
+-  #elif defined(_MSC_VER)
+-
+-  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+-     __asm {
+-        rdtsc
+-        ret       ; return value at EDX:EAX
+-     }
+-  }
+-
+-  #endif
+-
+-#elif (defined(__GNUC__) && defined(__x86_64__))
++static int unixAccess(
++  sqlite3_vfs *NotUsed,   /* The VFS containing this xAccess method */
++  const char *zPath,      /* Path of the file to examine */
++  int flags,              /* What do we want to learn about the zPath file? */
++  int *pResOut            /* Write result boolean here */
++){
++  int amode = 0;
++  UNUSED_PARAMETER(NotUsed);
++  SimulateIOError( return SQLITE_IOERR_ACCESS; );
++  switch( flags ){
++    case SQLITE_ACCESS_EXISTS:
++      amode = F_OK;
++      break;
++    case SQLITE_ACCESS_READWRITE:
++      amode = W_OK|R_OK;
++      break;
++    case SQLITE_ACCESS_READ:
++      amode = R_OK;
++      break;
+ 
+-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+-      unsigned long val;
+-      __asm__ __volatile__ ("rdtsc" : "=A" (val));
+-      return val;
++    default:
++      assert(!"Invalid flags argument");
+   }
+- 
+-#elif (defined(__GNUC__) && defined(__ppc__))
+-
+-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+-      unsigned long long retval;
+-      unsigned long junk;
+-      __asm__ __volatile__ ("\n\
+-          1:      mftbu   %1\n\
+-                  mftb    %L0\n\
+-                  mftbu   %0\n\
+-                  cmpw    %0,%1\n\
+-                  bne     1b"
+-                  : "=r" (retval), "=r" (junk));
+-      return retval;
++  *pResOut = (osAccess(zPath, amode)==0);
++  if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
++    struct stat buf;
++    if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
++      *pResOut = 0;
++    }
+   }
++  return SQLITE_OK;
++}
+ 
+-#else
+ 
+-  #error Need implementation of sqlite3Hwtime() for your platform.
++/*
++** Turn a relative pathname into a full pathname. The relative path
++** is stored as a nul-terminated string in the buffer pointed to by
++** zPath. 
++**
++** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes 
++** (in this case, MAX_PATHNAME bytes). The full-path is written to
++** this buffer before returning.
++*/
++static int unixFullPathname(
++  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
++  const char *zPath,            /* Possibly relative input path */
++  int nOut,                     /* Size of output buffer in bytes */
++  char *zOut                    /* Output buffer */
++){
+ 
+-  /*
+-  ** To compile without implementing sqlite3Hwtime() for your platform,
+-  ** you can remove the above #error and use the following
+-  ** stub function.  You will lose timing support for many
+-  ** of the debugging and testing utilities, but it should at
+-  ** least compile and run.
++  /* It's odd to simulate an io-error here, but really this is just
++  ** using the io-error infrastructure to test that SQLite handles this
++  ** function failing. This function could fail if, for example, the
++  ** current working directory has been unlinked.
+   */
+-SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+-
+-#endif
++  SimulateIOError( return SQLITE_ERROR );
+ 
+-#endif /* !defined(_HWTIME_H_) */
++  assert( pVfs->mxPathname==MAX_PATHNAME );
++  UNUSED_PARAMETER(pVfs);
+ 
+-/************** End of hwtime.h **********************************************/
+-/************** Continuing where we left off in os_common.h ******************/
++  zOut[nOut-1] = '\0';
++  if( zPath[0]=='/' ){
++    sqlite3_snprintf(nOut, zOut, "%s", zPath);
++  }else{
++    int nCwd;
++    if( osGetcwd(zOut, nOut-1)==0 ){
++      return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
++    }
++    nCwd = (int)strlen(zOut);
++    sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
++  }
++  return SQLITE_OK;
++}
+ 
+-static sqlite_uint64 g_start;
+-static sqlite_uint64 g_elapsed;
+-#define TIMER_START       g_start=sqlite3Hwtime()
+-#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
+-#define TIMER_ELAPSED     g_elapsed
+-#else
+-#define TIMER_START
+-#define TIMER_END
+-#define TIMER_ELAPSED     ((sqlite_uint64)0)
+-#endif
+ 
++#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ /*
+-** If we compile with the SQLITE_TEST macro set, then the following block
+-** of code will give us the ability to simulate a disk I/O error.  This
+-** is used for testing the I/O recovery logic.
++** Interfaces for opening a shared library, finding entry points
++** within the shared library, and closing the shared library.
+ */
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
+-SQLITE_API int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
+-SQLITE_API int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
+-SQLITE_API int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
+-SQLITE_API int sqlite3_io_error_benign = 0;         /* True if errors are benign */
+-SQLITE_API int sqlite3_diskfull_pending = 0;
+-SQLITE_API int sqlite3_diskfull = 0;
+-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
+-#define SimulateIOError(CODE)  \
+-  if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+-       || sqlite3_io_error_pending-- == 1 )  \
+-              { local_ioerr(); CODE; }
+-static void local_ioerr(){
+-  IOTRACE(("IOERR\n"));
+-  sqlite3_io_error_hit++;
+-  if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
++#include <dlfcn.h>
++static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
++  UNUSED_PARAMETER(NotUsed);
++  return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
+ }
+-#define SimulateDiskfullError(CODE) \
+-   if( sqlite3_diskfull_pending ){ \
+-     if( sqlite3_diskfull_pending == 1 ){ \
+-       local_ioerr(); \
+-       sqlite3_diskfull = 1; \
+-       sqlite3_io_error_hit = 1; \
+-       CODE; \
+-     }else{ \
+-       sqlite3_diskfull_pending--; \
+-     } \
+-   }
+-#else
+-#define SimulateIOErrorBenign(X)
+-#define SimulateIOError(A)
+-#define SimulateDiskfullError(A)
+-#endif
+ 
+ /*
+-** When testing, keep a count of the number of open files.
++** SQLite calls this function immediately after a call to unixDlSym() or
++** unixDlOpen() fails (returns a null pointer). If a more detailed error
++** message is available, it is written to zBufOut. If no error message
++** is available, zBufOut is left unmodified and SQLite uses a default
++** error message.
+ */
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_open_file_count = 0;
+-#define OpenCounter(X)  sqlite3_open_file_count+=(X)
+-#else
+-#define OpenCounter(X)
++static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
++  const char *zErr;
++  UNUSED_PARAMETER(NotUsed);
++  unixEnterMutex();
++  zErr = dlerror();
++  if( zErr ){
++    sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
++  }
++  unixLeaveMutex();
++}
++static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
++  /* 
++  ** GCC with -pedantic-errors says that C90 does not allow a void* to be
++  ** cast into a pointer to a function.  And yet the library dlsym() routine
++  ** returns a void* which is really a pointer to a function.  So how do we
++  ** use dlsym() with -pedantic-errors?
++  **
++  ** Variable x below is defined to be a pointer to a function taking
++  ** parameters void* and const char* and returning a pointer to a function.
++  ** We initialize x by assigning it a pointer to the dlsym() function.
++  ** (That assignment requires a cast.)  Then we call the function that
++  ** x points to.  
++  **
++  ** This work-around is unlikely to work correctly on any system where
++  ** you really cannot cast a function pointer into void*.  But then, on the
++  ** other hand, dlsym() will not work on such a system either, so we have
++  ** not really lost anything.
++  */
++  void (*(*x)(void*,const char*))(void);
++  UNUSED_PARAMETER(NotUsed);
++  x = (void(*(*)(void*,const char*))(void))dlsym;
++  return (*x)(p, zSym);
++}
++static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
++  UNUSED_PARAMETER(NotUsed);
++  dlclose(pHandle);
++}
++#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
++  #define unixDlOpen  0
++  #define unixDlError 0
++  #define unixDlSym   0
++  #define unixDlClose 0
+ #endif
+ 
+-#endif /* !defined(_OS_COMMON_H_) */
+-
+-/************** End of os_common.h *******************************************/
+-/************** Continuing where we left off in os_win.c *********************/
+-
+ /*
+-** Compiling and using WAL mode requires several APIs that are only
+-** available in Windows platforms based on the NT kernel.
++** Write nBuf bytes of random data to the supplied buffer zBuf.
+ */
+-#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
+-# error "WAL mode requires support from the Windows NT kernel, compile\
+- with SQLITE_OMIT_WAL."
++static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
++  UNUSED_PARAMETER(NotUsed);
++  assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
++
++  /* We have to initialize zBuf to prevent valgrind from reporting
++  ** errors.  The reports issued by valgrind are incorrect - we would
++  ** prefer that the randomness be increased by making use of the
++  ** uninitialized space in zBuf - but valgrind errors tend to worry
++  ** some users.  Rather than argue, it seems easier just to initialize
++  ** the whole array and silence valgrind, even if that means less randomness
++  ** in the random seed.
++  **
++  ** When testing, initializing zBuf[] to zero is all we do.  That means
++  ** that we always use the same random number sequence.  This makes the
++  ** tests repeatable.
++  */
++  memset(zBuf, 0, nBuf);
++#if !defined(SQLITE_TEST)
++  {
++    int pid, fd, got;
++    fd = robust_open("/dev/urandom", O_RDONLY, 0);
++    if( fd<0 ){
++      time_t t;
++      time(&t);
++      memcpy(zBuf, &t, sizeof(t));
++      pid = getpid();
++      memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
++      assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
++      nBuf = sizeof(t) + sizeof(pid);
++    }else{
++      do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
++      robust_close(0, fd, __LINE__);
++    }
++  }
+ #endif
++  return nBuf;
++}
++
+ 
+ /*
+-** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
+-** based on the sub-platform)?
++** Sleep for a little while.  Return the amount of time slept.
++** The argument is the number of microseconds we want to sleep.
++** The return value is the number of microseconds of sleep actually
++** requested from the underlying operating system, a number which
++** might be greater than or equal to the argument, but not less
++** than the argument.
+ */
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+-#  define SQLITE_WIN32_HAS_ANSI
++static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
++#if OS_VXWORKS
++  struct timespec sp;
++
++  sp.tv_sec = microseconds / 1000000;
++  sp.tv_nsec = (microseconds % 1000000) * 1000;
++  nanosleep(&sp, NULL);
++  UNUSED_PARAMETER(NotUsed);
++  return microseconds;
++#elif defined(HAVE_USLEEP) && HAVE_USLEEP
++  usleep(microseconds);
++  UNUSED_PARAMETER(NotUsed);
++  return microseconds;
++#else
++  int seconds = (microseconds+999999)/1000000;
++  sleep(seconds);
++  UNUSED_PARAMETER(NotUsed);
++  return seconds*1000000;
+ #endif
++}
+ 
+ /*
+-** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
+-** based on the sub-platform)?
++** The following variable, if set to a non-zero value, is interpreted as
++** the number of seconds since 1970 and is used to set the result of
++** sqlite3OsCurrentTime() during testing.
+ */
+-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+-#  define SQLITE_WIN32_HAS_WIDE
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_current_time = 0;  /* Fake system time in seconds since 1970. */
+ #endif
+ 
+ /*
+-** Do we need to manually define the Win32 file mapping APIs for use with WAL
+-** mode (e.g. these APIs are available in the Windows CE SDK; however, they
+-** are not present in the header file)?
+-*/
+-#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
+-/*
+-** Two of the file mapping APIs are different under WinRT.  Figure out which
+-** set we need.
++** Find the current time (in Universal Coordinated Time).  Write into *piNow
++** the current time and date as a Julian Day number times 86_400_000.  In
++** other words, write into *piNow the number of milliseconds since the Julian
++** epoch of noon in Greenwich on November 24, 4714 B.C according to the
++** proleptic Gregorian calendar.
++**
++** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date 
++** cannot be found.
+ */
+-#if SQLITE_OS_WINRT
+-WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
+-        LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
+-
+-WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
++static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
++  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
++  int rc = SQLITE_OK;
++#if defined(NO_GETTOD)
++  time_t t;
++  time(&t);
++  *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
++#elif OS_VXWORKS
++  struct timespec sNow;
++  clock_gettime(CLOCK_REALTIME, &sNow);
++  *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
+ #else
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
+-        DWORD, DWORD, DWORD, LPCSTR);
+-#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
+-
+-#if defined(SQLITE_WIN32_HAS_WIDE)
+-WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
+-        DWORD, DWORD, DWORD, LPCWSTR);
+-#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
+-
+-WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
+-#endif /* SQLITE_OS_WINRT */
++  struct timeval sNow;
++  if( gettimeofday(&sNow, 0)==0 ){
++    *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
++  }else{
++    rc = SQLITE_ERROR;
++  }
++#endif
+ 
+-/*
+-** This file mapping API is common to both Win32 and WinRT.
+-*/
+-WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
+-#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
++#ifdef SQLITE_TEST
++  if( sqlite3_current_time ){
++    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
++  }
++#endif
++  UNUSED_PARAMETER(NotUsed);
++  return rc;
++}
+ 
+ /*
+-** Macro to find the minimum of two numeric values.
++** Find the current time (in Universal Coordinated Time).  Write the
++** current time and date as a Julian Day number into *prNow and
++** return 0.  Return 1 if the time and date cannot be found.
+ */
+-#ifndef MIN
+-# define MIN(x,y) ((x)<(y)?(x):(y))
+-#endif
++static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
++  sqlite3_int64 i = 0;
++  int rc;
++  UNUSED_PARAMETER(NotUsed);
++  rc = unixCurrentTimeInt64(0, &i);
++  *prNow = i/86400000.0;
++  return rc;
++}
+ 
+ /*
+-** Some Microsoft compilers lack this definition.
++** We added the xGetLastError() method with the intention of providing
++** better low-level error messages when operating-system problems come up
++** during SQLite operation.  But so far, none of that has been implemented
++** in the core.  So this routine is never called.  For now, it is merely
++** a place-holder.
+ */
+-#ifndef INVALID_FILE_ATTRIBUTES
+-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 
+-#endif
++static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
++  UNUSED_PARAMETER(NotUsed);
++  UNUSED_PARAMETER(NotUsed2);
++  UNUSED_PARAMETER(NotUsed3);
++  return 0;
++}
+ 
+-#ifndef FILE_FLAG_MASK
+-# define FILE_FLAG_MASK          (0xFF3C0000)
+-#endif
+ 
+-#ifndef FILE_ATTRIBUTE_MASK
+-# define FILE_ATTRIBUTE_MASK     (0x0003FFF7)
+-#endif
++/*
++************************ End of sqlite3_vfs methods ***************************
++******************************************************************************/
+ 
+-#ifndef SQLITE_OMIT_WAL
+-/* Forward references */
+-typedef struct winShm winShm;           /* A connection to shared-memory */
+-typedef struct winShmNode winShmNode;   /* A region of shared-memory */
+-#endif
++/******************************************************************************
++************************** Begin Proxy Locking ********************************
++**
++** Proxy locking is a "uber-locking-method" in this sense:  It uses the
++** other locking methods on secondary lock files.  Proxy locking is a
++** meta-layer over top of the primitive locking implemented above.  For
++** this reason, the division that implements of proxy locking is deferred
++** until late in the file (here) after all of the other I/O methods have
++** been defined - so that the primitive locking methods are available
++** as services to help with the implementation of proxy locking.
++**
++****
++**
++** The default locking schemes in SQLite use byte-range locks on the
++** database file to coordinate safe, concurrent access by multiple readers
++** and writers [http://sqlite.org/lockingv3.html].  The five file locking
++** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
++** as POSIX read & write locks over fixed set of locations (via fsctl),
++** on AFP and SMB only exclusive byte-range locks are available via fsctl
++** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
++** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
++** address in the shared range is taken for a SHARED lock, the entire
++** shared range is taken for an EXCLUSIVE lock):
++**
++**      PENDING_BYTE        0x40000000
++**      RESERVED_BYTE       0x40000001
++**      SHARED_RANGE        0x40000002 -> 0x40000200
++**
++** This works well on the local file system, but shows a nearly 100x
++** slowdown in read performance on AFP because the AFP client disables
++** the read cache when byte-range locks are present.  Enabling the read
++** cache exposes a cache coherency problem that is present on all OS X
++** supported network file systems.  NFS and AFP both observe the
++** close-to-open semantics for ensuring cache coherency
++** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
++** address the requirements for concurrent database access by multiple
++** readers and writers
++** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
++**
++** To address the performance and cache coherency issues, proxy file locking
++** changes the way database access is controlled by limiting access to a
++** single host at a time and moving file locks off of the database file
++** and onto a proxy file on the local file system.  
++**
++**
++** Using proxy locks
++** -----------------
++**
++** C APIs
++**
++**  sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
++**                       <proxy_path> | ":auto:");
++**  sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
++**
++**
++** SQL pragmas
++**
++**  PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
++**  PRAGMA [database.]lock_proxy_file
++**
++** Specifying ":auto:" means that if there is a conch file with a matching
++** host ID in it, the proxy path in the conch file will be used, otherwise
++** a proxy path based on the user's temp dir
++** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
++** actual proxy file name is generated from the name and path of the
++** database file.  For example:
++**
++**       For database path "/Users/me/foo.db" 
++**       The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
++**
++** Once a lock proxy is configured for a database connection, it can not
++** be removed, however it may be switched to a different proxy path via
++** the above APIs (assuming the conch file is not being held by another
++** connection or process). 
++**
++**
++** How proxy locking works
++** -----------------------
++**
++** Proxy file locking relies primarily on two new supporting files: 
++**
++**   *  conch file to limit access to the database file to a single host
++**      at a time
++**
++**   *  proxy file to act as a proxy for the advisory locks normally
++**      taken on the database
++**
++** The conch file - to use a proxy file, sqlite must first "hold the conch"
++** by taking an sqlite-style shared lock on the conch file, reading the
++** contents and comparing the host's unique host ID (see below) and lock
++** proxy path against the values stored in the conch.  The conch file is
++** stored in the same directory as the database file and the file name
++** is patterned after the database file name as ".<databasename>-conch".
++** If the conch file does not exist, or it's contents do not match the
++** host ID and/or proxy path, then the lock is escalated to an exclusive
++** lock and the conch file contents is updated with the host ID and proxy
++** path and the lock is downgraded to a shared lock again.  If the conch
++** is held by another process (with a shared lock), the exclusive lock
++** will fail and SQLITE_BUSY is returned.
++**
++** The proxy file - a single-byte file used for all advisory file locks
++** normally taken on the database file.   This allows for safe sharing
++** of the database file for multiple readers and writers on the same
++** host (the conch ensures that they all use the same local lock file).
++**
++** Requesting the lock proxy does not immediately take the conch, it is
++** only taken when the first request to lock database file is made.  
++** This matches the semantics of the traditional locking behavior, where
++** opening a connection to a database file does not take a lock on it.
++** The shared lock and an open file descriptor are maintained until 
++** the connection to the database is closed. 
++**
++** The proxy file and the lock file are never deleted so they only need
++** to be created the first time they are used.
++**
++** Configuration options
++** ---------------------
++**
++**  SQLITE_PREFER_PROXY_LOCKING
++**
++**       Database files accessed on non-local file systems are
++**       automatically configured for proxy locking, lock files are
++**       named automatically using the same logic as
++**       PRAGMA lock_proxy_file=":auto:"
++**    
++**  SQLITE_PROXY_DEBUG
++**
++**       Enables the logging of error messages during host id file
++**       retrieval and creation
++**
++**  LOCKPROXYDIR
++**
++**       Overrides the default directory used for lock proxy files that
++**       are named automatically via the ":auto:" setting
++**
++**  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
++**
++**       Permissions to use when creating a directory for storing the
++**       lock proxy files, only used when LOCKPROXYDIR is not set.
++**    
++**    
++** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
++** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
++** force proxy locking to be used for every database file opened, and 0
++** will force automatic proxy locking to be disabled for all database
++** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
++** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
++*/
+ 
+ /*
+-** WinCE lacks native support for file locking so we have to fake it
+-** with some code of our own.
++** Proxy locking is only available on MacOSX 
+ */
+-#if SQLITE_OS_WINCE
+-typedef struct winceLock {
+-  int nReaders;       /* Number of reader locks obtained */
+-  BOOL bPending;      /* Indicates a pending lock has been obtained */
+-  BOOL bReserved;     /* Indicates a reserved lock has been obtained */
+-  BOOL bExclusive;    /* Indicates an exclusive lock has been obtained */
+-} winceLock;
+-#endif
++#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ 
+ /*
+-** The winFile structure is a subclass of sqlite3_file* specific to the win32
+-** portability layer.
++** The proxyLockingContext has the path and file structures for the remote 
++** and local proxy files in it
+ */
+-typedef struct winFile winFile;
+-struct winFile {
+-  const sqlite3_io_methods *pMethod; /*** Must be first ***/
+-  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
+-  HANDLE h;               /* Handle for accessing the file */
+-  u8 locktype;            /* Type of lock currently held on this file */
+-  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
+-  u8 ctrlFlags;           /* Flags.  See WINFILE_* below */
+-  DWORD lastErrno;        /* The Windows errno from the last I/O error */
+-#ifndef SQLITE_OMIT_WAL
+-  winShm *pShm;           /* Instance of shared memory on this file */
+-#endif
+-  const char *zPath;      /* Full pathname of this file */
+-  int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
+-#if SQLITE_OS_WINCE
+-  LPWSTR zDeleteOnClose;  /* Name of file to delete when closing */
+-  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
+-  HANDLE hShared;         /* Shared memory segment used for locking */
+-  winceLock local;        /* Locks obtained by this instance of winFile */
+-  winceLock *shared;      /* Global shared lock memory for the file  */
+-#endif
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  int nFetchOut;                /* Number of outstanding xFetch references */
+-  HANDLE hMap;                  /* Handle for accessing memory mapping */
+-  void *pMapRegion;             /* Area memory mapped */
+-  sqlite3_int64 mmapSize;       /* Usable size of mapped region */
+-  sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
+-  sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
+-#endif
++typedef struct proxyLockingContext proxyLockingContext;
++struct proxyLockingContext {
++  unixFile *conchFile;         /* Open conch file */
++  char *conchFilePath;         /* Name of the conch file */
++  unixFile *lockProxy;         /* Open proxy lock file */
++  char *lockProxyPath;         /* Name of the proxy lock file */
++  char *dbPath;                /* Name of the open file */
++  int conchHeld;               /* 1 if the conch is held, -1 if lockless */
++  void *oldLockingContext;     /* Original lockingcontext to restore on close */
++  sqlite3_io_methods const *pOldMethod;     /* Original I/O methods for close */
+ };
+ 
+-/*
+-** Allowed values for winFile.ctrlFlags
++/* 
++** The proxy lock file path for the database at dbPath is written into lPath, 
++** which must point to valid, writable memory large enough for a maxLen length
++** file path. 
+ */
+-#define WINFILE_RDONLY          0x02   /* Connection is read only */
+-#define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
+-#define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
++static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
++  int len;
++  int dbLen;
++  int i;
+ 
+-/*
+- * The size of the buffer used by sqlite3_win32_write_debug().
+- */
+-#ifndef SQLITE_WIN32_DBG_BUF_SIZE
+-#  define SQLITE_WIN32_DBG_BUF_SIZE   ((int)(4096-sizeof(DWORD)))
++#ifdef LOCKPROXYDIR
++  len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
++#else
++# ifdef _CS_DARWIN_USER_TEMP_DIR
++  {
++    if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
++      OSTRACE(("GETLOCKPATH  failed %s errno=%d pid=%d\n",
++               lPath, errno, getpid()));
++      return SQLITE_IOERR_LOCK;
++    }
++    len = strlcat(lPath, "sqliteplocks", maxLen);    
++  }
++# else
++  len = strlcpy(lPath, "/tmp/", maxLen);
++# endif
+ #endif
+ 
+-/*
+- * The value used with sqlite3_win32_set_directory() to specify that
+- * the data directory should be changed.
+- */
+-#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
+-#  define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
+-#endif
++  if( lPath[len-1]!='/' ){
++    len = strlcat(lPath, "/", maxLen);
++  }
++  
++  /* transform the db path to a unique cache name */
++  dbLen = (int)strlen(dbPath);
++  for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
++    char c = dbPath[i];
++    lPath[i+len] = (c=='/')?'_':c;
++  }
++  lPath[i+len]='\0';
++  strlcat(lPath, ":auto:", maxLen);
++  OSTRACE(("GETLOCKPATH  proxy lock path=%s pid=%d\n", lPath, getpid()));
++  return SQLITE_OK;
++}
+ 
+-/*
+- * The value used with sqlite3_win32_set_directory() to specify that
+- * the temporary directory should be changed.
++/* 
++ ** Creates the lock file and any missing directories in lockPath
+  */
+-#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
+-#  define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
+-#endif
++static int proxyCreateLockPath(const char *lockPath){
++  int i, len;
++  char buf[MAXPATHLEN];
++  int start = 0;
++  
++  assert(lockPath!=NULL);
++  /* try to create all the intermediate directories */
++  len = (int)strlen(lockPath);
++  buf[0] = lockPath[0];
++  for( i=1; i<len; i++ ){
++    if( lockPath[i] == '/' && (i - start > 0) ){
++      /* only mkdir if leaf dir != "." or "/" or ".." */
++      if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') 
++         || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
++        buf[i]='\0';
++        if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
++          int err=errno;
++          if( err!=EEXIST ) {
++            OSTRACE(("CREATELOCKPATH  FAILED creating %s, "
++                     "'%s' proxy lock path=%s pid=%d\n",
++                     buf, strerror(err), lockPath, getpid()));
++            return err;
++          }
++        }
++      }
++      start=i+1;
++    }
++    buf[i] = lockPath[i];
++  }
++  OSTRACE(("CREATELOCKPATH  proxy lock path=%s pid=%d\n", lockPath, getpid()));
++  return 0;
++}
+ 
+ /*
+- * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
+- * various Win32 API heap functions instead of our own.
+- */
+-#ifdef SQLITE_WIN32_MALLOC
++** Create a new VFS file descriptor (stored in memory obtained from
++** sqlite3_malloc) and open the file named "path" in the file descriptor.
++**
++** The caller is responsible not only for closing the file descriptor
++** but also for freeing the memory associated with the file descriptor.
++*/
++static int proxyCreateUnixFile(
++    const char *path,        /* path for the new unixFile */
++    unixFile **ppFile,       /* unixFile created and returned by ref */
++    int islockfile           /* if non zero missing dirs will be created */
++) {
++  int fd = -1;
++  unixFile *pNew;
++  int rc = SQLITE_OK;
++  int openFlags = O_RDWR | O_CREAT;
++  sqlite3_vfs dummyVfs;
++  int terrno = 0;
++  UnixUnusedFd *pUnused = NULL;
+ 
+-/*
+- * If this is non-zero, an isolated heap will be created by the native Win32
+- * allocator subsystem; otherwise, the default process heap will be used.  This
+- * setting has no effect when compiling for WinRT.  By default, this is enabled
+- * and an isolated heap will be created to store all allocated data.
+- *
+- ******************************************************************************
+- * WARNING: It is important to note that when this setting is non-zero and the
+- *          winMemShutdown function is called (e.g. by the sqlite3_shutdown
+- *          function), all data that was allocated using the isolated heap will
+- *          be freed immediately and any attempt to access any of that freed
+- *          data will almost certainly result in an immediate access violation.
+- ******************************************************************************
+- */
+-#ifndef SQLITE_WIN32_HEAP_CREATE
+-#  define SQLITE_WIN32_HEAP_CREATE    (TRUE)
++  /* 1. first try to open/create the file
++  ** 2. if that fails, and this is a lock file (not-conch), try creating
++  ** the parent directories and then try again.
++  ** 3. if that fails, try to open the file read-only
++  ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
++  */
++  pUnused = findReusableFd(path, openFlags);
++  if( pUnused ){
++    fd = pUnused->fd;
++  }else{
++    pUnused = sqlite3_malloc(sizeof(*pUnused));
++    if( !pUnused ){
++      return SQLITE_NOMEM;
++    }
++  }
++  if( fd<0 ){
++    fd = robust_open(path, openFlags, 0);
++    terrno = errno;
++    if( fd<0 && errno==ENOENT && islockfile ){
++      if( proxyCreateLockPath(path) == SQLITE_OK ){
++        fd = robust_open(path, openFlags, 0);
++      }
++    }
++  }
++  if( fd<0 ){
++    openFlags = O_RDONLY;
++    fd = robust_open(path, openFlags, 0);
++    terrno = errno;
++  }
++  if( fd<0 ){
++    if( islockfile ){
++      return SQLITE_BUSY;
++    }
++    switch (terrno) {
++      case EACCES:
++        return SQLITE_PERM;
++      case EIO: 
++        return SQLITE_IOERR_LOCK; /* even though it is the conch */
++      default:
++        return SQLITE_CANTOPEN_BKPT;
++    }
++  }
++  
++  pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
++  if( pNew==NULL ){
++    rc = SQLITE_NOMEM;
++    goto end_create_proxy;
++  }
++  memset(pNew, 0, sizeof(unixFile));
++  pNew->openFlags = openFlags;
++  memset(&dummyVfs, 0, sizeof(dummyVfs));
++  dummyVfs.pAppData = (void*)&autolockIoFinder;
++  dummyVfs.zName = "dummy";
++  pUnused->fd = fd;
++  pUnused->flags = openFlags;
++  pNew->pUnused = pUnused;
++  
++  rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
++  if( rc==SQLITE_OK ){
++    *ppFile = pNew;
++    return SQLITE_OK;
++  }
++end_create_proxy:    
++  robust_close(pNew, fd, __LINE__);
++  sqlite3_free(pNew);
++  sqlite3_free(pUnused);
++  return rc;
++}
++
++#ifdef SQLITE_TEST
++/* simulate multiple hosts by creating unique hostid file paths */
++SQLITE_API int sqlite3_hostid_num = 0;
+ #endif
+ 
+-/*
+- * The initial size of the Win32-specific heap.  This value may be zero.
+- */
+-#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
+-#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
+-                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
++#define PROXY_HOSTIDLEN    16  /* conch file host id length */
++
++/* Not always defined in the headers as it ought to be */
++extern int gethostuuid(uuid_t id, const struct timespec *wait);
++
++/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN 
++** bytes of writable memory.
++*/
++static int proxyGetHostID(unsigned char *pHostID, int *pError){
++  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
++  {
++    static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
++    if( gethostuuid(pHostID, &timeout) ){
++      int err = errno;
++      if( pError ){
++        *pError = err;
++      }
++      return SQLITE_IOERR;
++    }
++  }
++#else
++  UNUSED_PARAMETER(pError);
+ #endif
+-
+-/*
+- * The maximum size of the Win32-specific heap.  This value may be zero.
+- */
+-#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
+-#  define SQLITE_WIN32_HEAP_MAX_SIZE  (0)
++#ifdef SQLITE_TEST
++  /* simulate multiple hosts by creating unique hostid file paths */
++  if( sqlite3_hostid_num != 0){
++    pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
++  }
+ #endif
++  
++  return SQLITE_OK;
++}
+ 
+-/*
+- * The extra flags to use in calls to the Win32 heap APIs.  This value may be
+- * zero for the default behavior.
++/* The conch file contains the header, host id and lock file path
+  */
+-#ifndef SQLITE_WIN32_HEAP_FLAGS
+-#  define SQLITE_WIN32_HEAP_FLAGS     (0)
+-#endif
++#define PROXY_CONCHVERSION 2   /* 1-byte header, 16-byte host id, path */
++#define PROXY_HEADERLEN    1   /* conch file header length */
++#define PROXY_PATHINDEX    (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
++#define PROXY_MAXCONCHLEN  (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
+ 
+-/*
+-** The winMemData structure stores information required by the Win32-specific
+-** sqlite3_mem_methods implementation.
++/* 
++** Takes an open conch file, copies the contents to a new path and then moves 
++** it back.  The newly created file's file descriptor is assigned to the
++** conch file structure and finally the original conch file descriptor is 
++** closed.  Returns zero if successful.
+ */
+-typedef struct winMemData winMemData;
+-struct winMemData {
+-#ifndef NDEBUG
+-  u32 magic;    /* Magic number to detect structure corruption. */
+-#endif
+-  HANDLE hHeap; /* The handle to our heap. */
+-  BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
+-};
++static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
++  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
++  unixFile *conchFile = pCtx->conchFile;
++  char tPath[MAXPATHLEN];
++  char buf[PROXY_MAXCONCHLEN];
++  char *cPath = pCtx->conchFilePath;
++  size_t readLen = 0;
++  size_t pathLen = 0;
++  char errmsg[64] = "";
++  int fd = -1;
++  int rc = -1;
++  UNUSED_PARAMETER(myHostID);
+ 
+-#ifndef NDEBUG
+-#define WINMEM_MAGIC     0x42b2830b
+-#endif
++  /* create a new path by replace the trailing '-conch' with '-break' */
++  pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
++  if( pathLen>MAXPATHLEN || pathLen<6 || 
++     (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
++    sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
++    goto end_breaklock;
++  }
++  /* read the conch content */
++  readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
++  if( readLen<PROXY_PATHINDEX ){
++    sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
++    goto end_breaklock;
++  }
++  /* write it out to the temporary break file */
++  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
++  if( fd<0 ){
++    sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
++    goto end_breaklock;
++  }
++  if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
++    sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
++    goto end_breaklock;
++  }
++  if( rename(tPath, cPath) ){
++    sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
++    goto end_breaklock;
++  }
++  rc = 0;
++  fprintf(stderr, "broke stale lock on %s\n", cPath);
++  robust_close(pFile, conchFile->h, __LINE__);
++  conchFile->h = fd;
++  conchFile->openFlags = O_RDWR | O_CREAT;
+ 
+-static struct winMemData win_mem_data = {
+-#ifndef NDEBUG
+-  WINMEM_MAGIC,
+-#endif
+-  NULL, FALSE
+-};
++end_breaklock:
++  if( rc ){
++    if( fd>=0 ){
++      osUnlink(tPath);
++      robust_close(pFile, fd, __LINE__);
++    }
++    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
++  }
++  return rc;
++}
+ 
+-#ifndef NDEBUG
+-#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+-#else
+-#define winMemAssertMagic()
+-#endif
++/* Take the requested lock on the conch file and break a stale lock if the 
++** host id matches.
++*/
++static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
++  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
++  unixFile *conchFile = pCtx->conchFile;
++  int rc = SQLITE_OK;
++  int nTries = 0;
++  struct timespec conchModTime;
++  
++  memset(&conchModTime, 0, sizeof(conchModTime));
++  do {
++    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
++    nTries ++;
++    if( rc==SQLITE_BUSY ){
++      /* If the lock failed (busy):
++       * 1st try: get the mod time of the conch, wait 0.5s and try again. 
++       * 2nd try: fail if the mod time changed or host id is different, wait 
++       *           10 sec and try again
++       * 3rd try: break the lock unless the mod time has changed.
++       */
++      struct stat buf;
++      if( osFstat(conchFile->h, &buf) ){
++        pFile->lastErrno = errno;
++        return SQLITE_IOERR_LOCK;
++      }
++      
++      if( nTries==1 ){
++        conchModTime = buf.st_mtimespec;
++        usleep(500000); /* wait 0.5 sec and try the lock again*/
++        continue;  
++      }
+ 
+-#define winMemGetHeap() win_mem_data.hHeap
++      assert( nTries>1 );
++      if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || 
++         conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
++        return SQLITE_BUSY;
++      }
++      
++      if( nTries==2 ){  
++        char tBuf[PROXY_MAXCONCHLEN];
++        int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
++        if( len<0 ){
++          pFile->lastErrno = errno;
++          return SQLITE_IOERR_LOCK;
++        }
++        if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
++          /* don't break the lock if the host id doesn't match */
++          if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
++            return SQLITE_BUSY;
++          }
++        }else{
++          /* don't break the lock on short read or a version mismatch */
++          return SQLITE_BUSY;
++        }
++        usleep(10000000); /* wait 10 sec and try the lock again */
++        continue; 
++      }
++      
++      assert( nTries==3 );
++      if( 0==proxyBreakConchLock(pFile, myHostID) ){
++        rc = SQLITE_OK;
++        if( lockType==EXCLUSIVE_LOCK ){
++          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);          
++        }
++        if( !rc ){
++          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
++        }
++      }
++    }
++  } while( rc==SQLITE_BUSY && nTries<3 );
++  
++  return rc;
++}
+ 
+-static void *winMemMalloc(int nBytes);
+-static void winMemFree(void *pPrior);
+-static void *winMemRealloc(void *pPrior, int nBytes);
+-static int winMemSize(void *p);
+-static int winMemRoundup(int n);
+-static int winMemInit(void *pAppData);
+-static void winMemShutdown(void *pAppData);
++/* Takes the conch by taking a shared lock and read the contents conch, if 
++** lockPath is non-NULL, the host ID and lock file path must match.  A NULL 
++** lockPath means that the lockPath in the conch file will be used if the 
++** host IDs match, or a new lock path will be generated automatically 
++** and written to the conch file.
++*/
++static int proxyTakeConch(unixFile *pFile){
++  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
++  
++  if( pCtx->conchHeld!=0 ){
++    return SQLITE_OK;
++  }else{
++    unixFile *conchFile = pCtx->conchFile;
++    uuid_t myHostID;
++    int pError = 0;
++    char readBuf[PROXY_MAXCONCHLEN];
++    char lockPath[MAXPATHLEN];
++    char *tempLockPath = NULL;
++    int rc = SQLITE_OK;
++    int createConch = 0;
++    int hostIdMatch = 0;
++    int readLen = 0;
++    int tryOldLockPath = 0;
++    int forceNewLockPath = 0;
++    
++    OSTRACE(("TAKECONCH  %d for %s pid=%d\n", conchFile->h,
++             (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
+ 
+-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
+-#endif /* SQLITE_WIN32_MALLOC */
++    rc = proxyGetHostID(myHostID, &pError);
++    if( (rc&0xff)==SQLITE_IOERR ){
++      pFile->lastErrno = pError;
++      goto end_takeconch;
++    }
++    rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
++    if( rc!=SQLITE_OK ){
++      goto end_takeconch;
++    }
++    /* read the existing conch file */
++    readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
++    if( readLen<0 ){
++      /* I/O error: lastErrno set by seekAndRead */
++      pFile->lastErrno = conchFile->lastErrno;
++      rc = SQLITE_IOERR_READ;
++      goto end_takeconch;
++    }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || 
++             readBuf[0]!=(char)PROXY_CONCHVERSION ){
++      /* a short read or version format mismatch means we need to create a new 
++      ** conch file. 
++      */
++      createConch = 1;
++    }
++    /* if the host id matches and the lock path already exists in the conch
++    ** we'll try to use the path there, if we can't open that path, we'll 
++    ** retry with a new auto-generated path 
++    */
++    do { /* in case we need to try again for an :auto: named lock file */
+ 
+-/*
+-** The following variable is (normally) set once and never changes
+-** thereafter.  It records whether the operating system is Win9x
+-** or WinNT.
+-**
+-** 0:   Operating system unknown.
+-** 1:   Operating system is Win9x.
+-** 2:   Operating system is WinNT.
+-**
+-** In order to facilitate testing on a WinNT system, the test fixture
+-** can manually set this value to 1 to emulate Win98 behavior.
+-*/
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_os_type = 0;
++      if( !createConch && !forceNewLockPath ){
++        hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, 
++                                  PROXY_HOSTIDLEN);
++        /* if the conch has data compare the contents */
++        if( !pCtx->lockProxyPath ){
++          /* for auto-named local lock file, just check the host ID and we'll
++           ** use the local lock file path that's already in there
++           */
++          if( hostIdMatch ){
++            size_t pathLen = (readLen - PROXY_PATHINDEX);
++            
++            if( pathLen>=MAXPATHLEN ){
++              pathLen=MAXPATHLEN-1;
++            }
++            memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
++            lockPath[pathLen] = 0;
++            tempLockPath = lockPath;
++            tryOldLockPath = 1;
++            /* create a copy of the lock path if the conch is taken */
++            goto end_takeconch;
++          }
++        }else if( hostIdMatch
++               && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
++                           readLen-PROXY_PATHINDEX)
++        ){
++          /* conch host and lock path match */
++          goto end_takeconch; 
++        }
++      }
++      
++      /* if the conch isn't writable and doesn't match, we can't take it */
++      if( (conchFile->openFlags&O_RDWR) == 0 ){
++        rc = SQLITE_BUSY;
++        goto end_takeconch;
++      }
++      
++      /* either the conch didn't match or we need to create a new one */
++      if( !pCtx->lockProxyPath ){
++        proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
++        tempLockPath = lockPath;
++        /* create a copy of the lock path _only_ if the conch is taken */
++      }
++      
++      /* update conch with host and path (this will fail if other process
++      ** has a shared lock already), if the host id matches, use the big
++      ** stick.
++      */
++      futimes(conchFile->h, NULL);
++      if( hostIdMatch && !createConch ){
++        if( conchFile->pInode && conchFile->pInode->nShared>1 ){
++          /* We are trying for an exclusive lock but another thread in this
++           ** same process is still holding a shared lock. */
++          rc = SQLITE_BUSY;
++        } else {          
++          rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
++        }
++      }else{
++        rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
++      }
++      if( rc==SQLITE_OK ){
++        char writeBuffer[PROXY_MAXCONCHLEN];
++        int writeSize = 0;
++        
++        writeBuffer[0] = (char)PROXY_CONCHVERSION;
++        memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
++        if( pCtx->lockProxyPath!=NULL ){
++          strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
++        }else{
++          strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
++        }
++        writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
++        robust_ftruncate(conchFile->h, writeSize);
++        rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
++        fsync(conchFile->h);
++        /* If we created a new conch file (not just updated the contents of a 
++         ** valid conch file), try to match the permissions of the database 
++         */
++        if( rc==SQLITE_OK && createConch ){
++          struct stat buf;
++          int err = osFstat(pFile->h, &buf);
++          if( err==0 ){
++            mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
++                                        S_IROTH|S_IWOTH);
++            /* try to match the database file R/W permissions, ignore failure */
++#ifndef SQLITE_PROXY_DEBUG
++            osFchmod(conchFile->h, cmode);
+ #else
+-static int sqlite3_os_type = 0;
+-#endif
+-
+-#ifndef SYSCALL
+-#  define SYSCALL sqlite3_syscall_ptr
++            do{
++              rc = osFchmod(conchFile->h, cmode);
++            }while( rc==(-1) && errno==EINTR );
++            if( rc!=0 ){
++              int code = errno;
++              fprintf(stderr, "fchmod %o FAILED with %d %s\n",
++                      cmode, code, strerror(code));
++            } else {
++              fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
++            }
++          }else{
++            int code = errno;
++            fprintf(stderr, "STAT FAILED[%d] with %d %s\n", 
++                    err, code, strerror(code));
+ #endif
++          }
++        }
++      }
++      conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
++      
++    end_takeconch:
++      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
++      if( rc==SQLITE_OK && pFile->openFlags ){
++        int fd;
++        if( pFile->h>=0 ){
++          robust_close(pFile, pFile->h, __LINE__);
++        }
++        pFile->h = -1;
++        fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
++        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
++        if( fd>=0 ){
++          pFile->h = fd;
++        }else{
++          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
++           during locking */
++        }
++      }
++      if( rc==SQLITE_OK && !pCtx->lockProxy ){
++        char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
++        rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
++        if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
++          /* we couldn't create the proxy lock file with the old lock file path
++           ** so try again via auto-naming 
++           */
++          forceNewLockPath = 1;
++          tryOldLockPath = 0;
++          continue; /* go back to the do {} while start point, try again */
++        }
++      }
++      if( rc==SQLITE_OK ){
++        /* Need to make a copy of path if we extracted the value
++         ** from the conch file or the path was allocated on the stack
++         */
++        if( tempLockPath ){
++          pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
++          if( !pCtx->lockProxyPath ){
++            rc = SQLITE_NOMEM;
++          }
++        }
++      }
++      if( rc==SQLITE_OK ){
++        pCtx->conchHeld = 1;
++        
++        if( pCtx->lockProxy->pMethod == &afpIoMethods ){
++          afpLockingContext *afpCtx;
++          afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
++          afpCtx->dbPath = pCtx->lockProxyPath;
++        }
++      } else {
++        conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
++      }
++      OSTRACE(("TAKECONCH  %d %s\n", conchFile->h,
++               rc==SQLITE_OK?"ok":"failed"));
++      return rc;
++    } while (1); /* in case we need to retry the :auto: lock file - 
++                 ** we should never get here except via the 'continue' call. */
++  }
++}
+ 
+ /*
+-** This function is not available on Windows CE or WinRT.
+- */
++** If pFile holds a lock on a conch file, then release that lock.
++*/
++static int proxyReleaseConch(unixFile *pFile){
++  int rc = SQLITE_OK;         /* Subroutine return code */
++  proxyLockingContext *pCtx;  /* The locking context for the proxy lock */
++  unixFile *conchFile;        /* Name of the conch file */
+ 
+-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+-#  define osAreFileApisANSI()       1
+-#endif
++  pCtx = (proxyLockingContext *)pFile->lockingContext;
++  conchFile = pCtx->conchFile;
++  OSTRACE(("RELEASECONCH  %d for %s pid=%d\n", conchFile->h,
++           (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), 
++           getpid()));
++  if( pCtx->conchHeld>0 ){
++    rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
++  }
++  pCtx->conchHeld = 0;
++  OSTRACE(("RELEASECONCH  %d %s\n", conchFile->h,
++           (rc==SQLITE_OK ? "ok" : "failed")));
++  return rc;
++}
+ 
+ /*
+-** Many system calls are accessed through pointer-to-functions so that
+-** they may be overridden at runtime to facilitate fault injection during
+-** testing and sandboxing.  The following array holds the names and pointers
+-** to all overrideable system calls.
++** Given the name of a database file, compute the name of its conch file.
++** Store the conch filename in memory obtained from sqlite3_malloc().
++** Make *pConchPath point to the new name.  Return SQLITE_OK on success
++** or SQLITE_NOMEM if unable to obtain memory.
++**
++** The caller is responsible for ensuring that the allocated memory
++** space is eventually freed.
++**
++** *pConchPath is set to NULL if a memory allocation error occurs.
+ */
+-static struct win_syscall {
+-  const char *zName;            /* Name of the system call */
+-  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
+-  sqlite3_syscall_ptr pDefault; /* Default value */
+-} aSyscall[] = {
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+-  { "AreFileApisANSI",         (SYSCALL)AreFileApisANSI,         0 },
+-#else
+-  { "AreFileApisANSI",         (SYSCALL)0,                       0 },
+-#endif
+-
+-#ifndef osAreFileApisANSI
+-#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
+-#endif
+-
+-#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "CharLowerW",              (SYSCALL)CharLowerW,              0 },
+-#else
+-  { "CharLowerW",              (SYSCALL)0,                       0 },
+-#endif
++static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
++  int i;                        /* Loop counter */
++  int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
++  char *conchPath;              /* buffer in which to construct conch name */
+ 
+-#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
++  /* Allocate space for the conch filename and initialize the name to
++  ** the name of the original database file. */  
++  *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
++  if( conchPath==0 ){
++    return SQLITE_NOMEM;
++  }
++  memcpy(conchPath, dbPath, len+1);
++  
++  /* now insert a "." before the last / character */
++  for( i=(len-1); i>=0; i-- ){
++    if( conchPath[i]=='/' ){
++      i++;
++      break;
++    }
++  }
++  conchPath[i]='.';
++  while ( i<len ){
++    conchPath[i+1]=dbPath[i];
++    i++;
++  }
+ 
+-#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "CharUpperW",              (SYSCALL)CharUpperW,              0 },
+-#else
+-  { "CharUpperW",              (SYSCALL)0,                       0 },
+-#endif
++  /* append the "-conch" suffix to the file */
++  memcpy(&conchPath[i+1], "-conch", 7);
++  assert( (int)strlen(conchPath) == len+7 );
+ 
+-#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
++  return SQLITE_OK;
++}
+ 
+-  { "CloseHandle",             (SYSCALL)CloseHandle,             0 },
+ 
+-#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
++/* Takes a fully configured proxy locking-style unix file and switches
++** the local lock file path 
++*/
++static int switchLockProxyPath(unixFile *pFile, const char *path) {
++  proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
++  char *oldPath = pCtx->lockProxyPath;
++  int rc = SQLITE_OK;
+ 
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "CreateFileA",             (SYSCALL)CreateFileA,             0 },
+-#else
+-  { "CreateFileA",             (SYSCALL)0,                       0 },
+-#endif
++  if( pFile->eFileLock!=NO_LOCK ){
++    return SQLITE_BUSY;
++  }  
+ 
+-#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
+-        LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
++  /* nothing to do if the path is NULL, :auto: or matches the existing path */
++  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
++    (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
++    return SQLITE_OK;
++  }else{
++    unixFile *lockProxy = pCtx->lockProxy;
++    pCtx->lockProxy=NULL;
++    pCtx->conchHeld = 0;
++    if( lockProxy!=NULL ){
++      rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
++      if( rc ) return rc;
++      sqlite3_free(lockProxy);
++    }
++    sqlite3_free(oldPath);
++    pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
++  }
++  
++  return rc;
++}
+ 
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "CreateFileW",             (SYSCALL)CreateFileW,             0 },
+-#else
+-  { "CreateFileW",             (SYSCALL)0,                       0 },
++/*
++** pFile is a file that has been opened by a prior xOpen call.  dbPath
++** is a string buffer at least MAXPATHLEN+1 characters in size.
++**
++** This routine find the filename associated with pFile and writes it
++** int dbPath.
++*/
++static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
++#if defined(__APPLE__)
++  if( pFile->pMethod == &afpIoMethods ){
++    /* afp style keeps a reference to the db path in the filePath field 
++    ** of the struct */
++    assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
++    strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
++  } else
+ #endif
++  if( pFile->pMethod == &dotlockIoMethods ){
++    /* dot lock style uses the locking context to store the dot lock
++    ** file path */
++    int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
++    memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
++  }else{
++    /* all other styles use the locking context to store the db file path */
++    assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
++    strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
++  }
++  return SQLITE_OK;
++}
+ 
+-#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
+-        LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
+-
+-#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
+-        !defined(SQLITE_OMIT_WAL))
+-  { "CreateFileMappingA",      (SYSCALL)CreateFileMappingA,      0 },
+-#else
+-  { "CreateFileMappingA",      (SYSCALL)0,                       0 },
+-#endif
++/*
++** Takes an already filled in unix file and alters it so all file locking 
++** will be performed on the local proxy lock file.  The following fields
++** are preserved in the locking context so that they can be restored and 
++** the unix structure properly cleaned up at close time:
++**  ->lockingContext
++**  ->pMethod
++*/
++static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
++  proxyLockingContext *pCtx;
++  char dbPath[MAXPATHLEN+1];       /* Name of the database file */
++  char *lockPath=NULL;
++  int rc = SQLITE_OK;
++  
++  if( pFile->eFileLock!=NO_LOCK ){
++    return SQLITE_BUSY;
++  }
++  proxyGetDbPathForUnixFile(pFile, dbPath);
++  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
++    lockPath=NULL;
++  }else{
++    lockPath=(char *)path;
++  }
++  
++  OSTRACE(("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
++           (lockPath ? lockPath : ":auto:"), getpid()));
+ 
+-#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+-        DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
++  pCtx = sqlite3_malloc( sizeof(*pCtx) );
++  if( pCtx==0 ){
++    return SQLITE_NOMEM;
++  }
++  memset(pCtx, 0, sizeof(*pCtx));
+ 
+-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+-        !defined(SQLITE_OMIT_WAL))
+-  { "CreateFileMappingW",      (SYSCALL)CreateFileMappingW,      0 },
+-#else
+-  { "CreateFileMappingW",      (SYSCALL)0,                       0 },
+-#endif
++  rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
++  if( rc==SQLITE_OK ){
++    rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
++    if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
++      /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
++      ** (c) the file system is read-only, then enable no-locking access.
++      ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
++      ** that openFlags will have only one of O_RDONLY or O_RDWR.
++      */
++      struct statfs fsInfo;
++      struct stat conchInfo;
++      int goLockless = 0;
+ 
+-#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+-        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
++      if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
++        int err = errno;
++        if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
++          goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
++        }
++      }
++      if( goLockless ){
++        pCtx->conchHeld = -1; /* read only FS/ lockless */
++        rc = SQLITE_OK;
++      }
++    }
++  }  
++  if( rc==SQLITE_OK && lockPath ){
++    pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
++  }
+ 
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "CreateMutexW",            (SYSCALL)CreateMutexW,            0 },
+-#else
+-  { "CreateMutexW",            (SYSCALL)0,                       0 },
+-#endif
++  if( rc==SQLITE_OK ){
++    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
++    if( pCtx->dbPath==NULL ){
++      rc = SQLITE_NOMEM;
++    }
++  }
++  if( rc==SQLITE_OK ){
++    /* all memory is allocated, proxys are created and assigned, 
++    ** switch the locking context and pMethod then return.
++    */
++    pCtx->oldLockingContext = pFile->lockingContext;
++    pFile->lockingContext = pCtx;
++    pCtx->pOldMethod = pFile->pMethod;
++    pFile->pMethod = &proxyIoMethods;
++  }else{
++    if( pCtx->conchFile ){ 
++      pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
++      sqlite3_free(pCtx->conchFile);
++    }
++    sqlite3DbFree(0, pCtx->lockProxyPath);
++    sqlite3_free(pCtx->conchFilePath); 
++    sqlite3_free(pCtx);
++  }
++  OSTRACE(("TRANSPROXY  %d %s\n", pFile->h,
++           (rc==SQLITE_OK ? "ok" : "failed")));
++  return rc;
++}
+ 
+-#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
+-        LPCWSTR))aSyscall[8].pCurrent)
+ 
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "DeleteFileA",             (SYSCALL)DeleteFileA,             0 },
+-#else
+-  { "DeleteFileA",             (SYSCALL)0,                       0 },
+-#endif
++/*
++** This routine handles sqlite3_file_control() calls that are specific
++** to proxy locking.
++*/
++static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
++  switch( op ){
++    case SQLITE_GET_LOCKPROXYFILE: {
++      unixFile *pFile = (unixFile*)id;
++      if( pFile->pMethod == &proxyIoMethods ){
++        proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
++        proxyTakeConch(pFile);
++        if( pCtx->lockProxyPath ){
++          *(const char **)pArg = pCtx->lockProxyPath;
++        }else{
++          *(const char **)pArg = ":auto: (not held)";
++        }
++      } else {
++        *(const char **)pArg = NULL;
++      }
++      return SQLITE_OK;
++    }
++    case SQLITE_SET_LOCKPROXYFILE: {
++      unixFile *pFile = (unixFile*)id;
++      int rc = SQLITE_OK;
++      int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
++      if( pArg==NULL || (const char *)pArg==0 ){
++        if( isProxyStyle ){
++          /* turn off proxy locking - not supported */
++          rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
++        }else{
++          /* turn off proxy locking - already off - NOOP */
++          rc = SQLITE_OK;
++        }
++      }else{
++        const char *proxyPath = (const char *)pArg;
++        if( isProxyStyle ){
++          proxyLockingContext *pCtx = 
++            (proxyLockingContext*)pFile->lockingContext;
++          if( !strcmp(pArg, ":auto:") 
++           || (pCtx->lockProxyPath &&
++               !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
++          ){
++            rc = SQLITE_OK;
++          }else{
++            rc = switchLockProxyPath(pFile, proxyPath);
++          }
++        }else{
++          /* turn on proxy file locking */
++          rc = proxyTransformUnixFile(pFile, proxyPath);
++        }
++      }
++      return rc;
++    }
++    default: {
++      assert( 0 );  /* The call assures that only valid opcodes are sent */
++    }
++  }
++  /*NOTREACHED*/
++  return SQLITE_ERROR;
++}
+ 
+-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
++/*
++** Within this division (the proxying locking implementation) the procedures
++** above this point are all utilities.  The lock-related methods of the
++** proxy-locking sqlite3_io_method object follow.
++*/
+ 
+-#if defined(SQLITE_WIN32_HAS_WIDE)
+-  { "DeleteFileW",             (SYSCALL)DeleteFileW,             0 },
+-#else
+-  { "DeleteFileW",             (SYSCALL)0,                       0 },
+-#endif
+ 
+-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
++/*
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, set *pResOut
++** to a non-zero value otherwise *pResOut is set to zero.  The return value
++** is set to SQLITE_OK unless an I/O error occurs during lock checking.
++*/
++static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
++  unixFile *pFile = (unixFile*)id;
++  int rc = proxyTakeConch(pFile);
++  if( rc==SQLITE_OK ){
++    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
++    if( pCtx->conchHeld>0 ){
++      unixFile *proxy = pCtx->lockProxy;
++      return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
++    }else{ /* conchHeld < 0 is lockless */
++      pResOut=0;
++    }
++  }
++  return rc;
++}
+ 
+-#if SQLITE_OS_WINCE
+-  { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
+-#else
+-  { "FileTimeToLocalFileTime", (SYSCALL)0,                       0 },
+-#endif
++/*
++** Lock the file with the lock specified by parameter eFileLock - one
++** of the following:
++**
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
++**
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
++**
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
++**
++** This routine will only increase a lock.  Use the sqlite3OsUnlock()
++** routine to lower a locking level.
++*/
++static int proxyLock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  int rc = proxyTakeConch(pFile);
++  if( rc==SQLITE_OK ){
++    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
++    if( pCtx->conchHeld>0 ){
++      unixFile *proxy = pCtx->lockProxy;
++      rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
++      pFile->eFileLock = proxy->eFileLock;
++    }else{
++      /* conchHeld < 0 is lockless */
++    }
++  }
++  return rc;
++}
+ 
+-#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+-        LPFILETIME))aSyscall[11].pCurrent)
+ 
+-#if SQLITE_OS_WINCE
+-  { "FileTimeToSystemTime",    (SYSCALL)FileTimeToSystemTime,    0 },
+-#else
+-  { "FileTimeToSystemTime",    (SYSCALL)0,                       0 },
+-#endif
++/*
++** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
++** must be either NO_LOCK or SHARED_LOCK.
++**
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
++*/
++static int proxyUnlock(sqlite3_file *id, int eFileLock) {
++  unixFile *pFile = (unixFile*)id;
++  int rc = proxyTakeConch(pFile);
++  if( rc==SQLITE_OK ){
++    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
++    if( pCtx->conchHeld>0 ){
++      unixFile *proxy = pCtx->lockProxy;
++      rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
++      pFile->eFileLock = proxy->eFileLock;
++    }else{
++      /* conchHeld < 0 is lockless */
++    }
++  }
++  return rc;
++}
+ 
+-#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+-        LPSYSTEMTIME))aSyscall[12].pCurrent)
++/*
++** Close a file that uses proxy locks.
++*/
++static int proxyClose(sqlite3_file *id) {
++  if( id ){
++    unixFile *pFile = (unixFile*)id;
++    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
++    unixFile *lockProxy = pCtx->lockProxy;
++    unixFile *conchFile = pCtx->conchFile;
++    int rc = SQLITE_OK;
++    
++    if( lockProxy ){
++      rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
++      if( rc ) return rc;
++      rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
++      if( rc ) return rc;
++      sqlite3_free(lockProxy);
++      pCtx->lockProxy = 0;
++    }
++    if( conchFile ){
++      if( pCtx->conchHeld ){
++        rc = proxyReleaseConch(pFile);
++        if( rc ) return rc;
++      }
++      rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
++      if( rc ) return rc;
++      sqlite3_free(conchFile);
++    }
++    sqlite3DbFree(0, pCtx->lockProxyPath);
++    sqlite3_free(pCtx->conchFilePath);
++    sqlite3DbFree(0, pCtx->dbPath);
++    /* restore the original locking context and pMethod then close it */
++    pFile->lockingContext = pCtx->oldLockingContext;
++    pFile->pMethod = pCtx->pOldMethod;
++    sqlite3_free(pCtx);
++    return pFile->pMethod->xClose(id);
++  }
++  return SQLITE_OK;
++}
+ 
+-  { "FlushFileBuffers",        (SYSCALL)FlushFileBuffers,        0 },
+ 
+-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
+ 
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "FormatMessageA",          (SYSCALL)FormatMessageA,          0 },
+-#else
+-  { "FormatMessageA",          (SYSCALL)0,                       0 },
+-#endif
++#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
++/*
++** The proxy locking style is intended for use with AFP filesystems.
++** And since AFP is only supported on MacOSX, the proxy locking is also
++** restricted to MacOSX.
++** 
++**
++******************* End of the proxy lock implementation **********************
++******************************************************************************/
+ 
+-#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
+-        DWORD,va_list*))aSyscall[14].pCurrent)
++/*
++** Initialize the operating system interface.
++**
++** This routine registers all VFS implementations for unix-like operating
++** systems.  This routine, and the sqlite3_os_end() routine that follows,
++** should be the only routines in this file that are visible from other
++** files.
++**
++** This routine is called once during SQLite initialization and by a
++** single thread.  The memory allocation and mutex subsystems have not
++** necessarily been initialized when this routine is called, and so they
++** should not be used.
++*/
++SQLITE_API int sqlite3_os_init(void){ 
++  /* 
++  ** The following macro defines an initializer for an sqlite3_vfs object.
++  ** The name of the VFS is NAME.  The pAppData is a pointer to a pointer
++  ** to the "finder" function.  (pAppData is a pointer to a pointer because
++  ** silly C90 rules prohibit a void* from being cast to a function pointer
++  ** and so we have to go through the intermediate pointer to avoid problems
++  ** when compiling with -pedantic-errors on GCC.)
++  **
++  ** The FINDER parameter to this macro is the name of the pointer to the
++  ** finder-function.  The finder-function returns a pointer to the
++  ** sqlite_io_methods object that implements the desired locking
++  ** behaviors.  See the division above that contains the IOMETHODS
++  ** macro for addition information on finder-functions.
++  **
++  ** Most finders simply return a pointer to a fixed sqlite3_io_methods
++  ** object.  But the "autolockIoFinder" available on MacOSX does a little
++  ** more than that; it looks at the filesystem type that hosts the 
++  ** database file and tries to choose an locking method appropriate for
++  ** that filesystem time.
++  */
++  #define UNIXVFS(VFSNAME, FINDER) {                        \
++    3,                    /* iVersion */                    \
++    sizeof(unixFile),     /* szOsFile */                    \
++    MAX_PATHNAME,         /* mxPathname */                  \
++    0,                    /* pNext */                       \
++    VFSNAME,              /* zName */                       \
++    (void*)&FINDER,       /* pAppData */                    \
++    unixOpen,             /* xOpen */                       \
++    unixDelete,           /* xDelete */                     \
++    unixAccess,           /* xAccess */                     \
++    unixFullPathname,     /* xFullPathname */               \
++    unixDlOpen,           /* xDlOpen */                     \
++    unixDlError,          /* xDlError */                    \
++    unixDlSym,            /* xDlSym */                      \
++    unixDlClose,          /* xDlClose */                    \
++    unixRandomness,       /* xRandomness */                 \
++    unixSleep,            /* xSleep */                      \
++    unixCurrentTime,      /* xCurrentTime */                \
++    unixGetLastError,     /* xGetLastError */               \
++    unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
++    unixSetSystemCall,    /* xSetSystemCall */              \
++    unixGetSystemCall,    /* xGetSystemCall */              \
++    unixNextSystemCall,   /* xNextSystemCall */             \
++  }
+ 
+-#if defined(SQLITE_WIN32_HAS_WIDE)
+-  { "FormatMessageW",          (SYSCALL)FormatMessageW,          0 },
++  /*
++  ** All default VFSes for unix are contained in the following array.
++  **
++  ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
++  ** by the SQLite core when the VFS is registered.  So the following
++  ** array cannot be const.
++  */
++  static sqlite3_vfs aVfs[] = {
++#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
++    UNIXVFS("unix",          autolockIoFinder ),
+ #else
+-  { "FormatMessageW",          (SYSCALL)0,                       0 },
++    UNIXVFS("unix",          posixIoFinder ),
+ #endif
+-
+-#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
+-        DWORD,va_list*))aSyscall[15].pCurrent)
+-
+-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
+-  { "FreeLibrary",             (SYSCALL)FreeLibrary,             0 },
+-#else
+-  { "FreeLibrary",             (SYSCALL)0,                       0 },
++    UNIXVFS("unix-none",     nolockIoFinder ),
++    UNIXVFS("unix-dotfile",  dotlockIoFinder ),
++    UNIXVFS("unix-excl",     posixIoFinder ),
++#if OS_VXWORKS
++    UNIXVFS("unix-namedsem", semIoFinder ),
++#endif
++#if SQLITE_ENABLE_LOCKING_STYLE
++    UNIXVFS("unix-posix",    posixIoFinder ),
++#if !OS_VXWORKS
++    UNIXVFS("unix-flock",    flockIoFinder ),
+ #endif
+-
+-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
+-
+-  { "GetCurrentProcessId",     (SYSCALL)GetCurrentProcessId,     0 },
+-
+-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
+-
+-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
+-  { "GetDiskFreeSpaceA",       (SYSCALL)GetDiskFreeSpaceA,       0 },
+-#else
+-  { "GetDiskFreeSpaceA",       (SYSCALL)0,                       0 },
+ #endif
+-
+-#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
+-        LPDWORD))aSyscall[18].pCurrent)
+-
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "GetDiskFreeSpaceW",       (SYSCALL)GetDiskFreeSpaceW,       0 },
+-#else
+-  { "GetDiskFreeSpaceW",       (SYSCALL)0,                       0 },
++#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
++    UNIXVFS("unix-afp",      afpIoFinder ),
++    UNIXVFS("unix-nfs",      nfsIoFinder ),
++    UNIXVFS("unix-proxy",    proxyIoFinder ),
+ #endif
++  };
++  unsigned int i;          /* Loop counter */
+ 
+-#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
+-        LPDWORD))aSyscall[19].pCurrent)
+-
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "GetFileAttributesA",      (SYSCALL)GetFileAttributesA,      0 },
+-#else
+-  { "GetFileAttributesA",      (SYSCALL)0,                       0 },
+-#endif
++  /* Double-check that the aSyscall[] array has been constructed
++  ** correctly.  See ticket [bb3a86e890c8e96ab] */
++  assert( ArraySize(aSyscall)==24 );
+ 
+-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
++  /* Register all VFSes defined in the aVfs[] array */
++  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
++    sqlite3_vfs_register(&aVfs[i], i==0);
++  }
++  return SQLITE_OK; 
++}
+ 
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "GetFileAttributesW",      (SYSCALL)GetFileAttributesW,      0 },
+-#else
+-  { "GetFileAttributesW",      (SYSCALL)0,                       0 },
+-#endif
++/*
++** Shutdown the operating system interface.
++**
++** Some operating systems might need to do some cleanup in this routine,
++** to release dynamically allocated objects.  But not on unix.
++** This routine is a no-op for unix.
++*/
++SQLITE_API int sqlite3_os_end(void){ 
++  return SQLITE_OK; 
++}
++ 
++#endif /* SQLITE_OS_UNIX */
+ 
+-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
++/************** End of os_unix.c *********************************************/
++/************** Begin file os_win.c ******************************************/
++/*
++** 2004 May 22
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++******************************************************************************
++**
++** This file contains code that is specific to Windows.
++*/
++#if SQLITE_OS_WIN               /* This file is used for Windows only */
+ 
+-#if defined(SQLITE_WIN32_HAS_WIDE)
+-  { "GetFileAttributesExW",    (SYSCALL)GetFileAttributesExW,    0 },
+-#else
+-  { "GetFileAttributesExW",    (SYSCALL)0,                       0 },
++#ifdef __CYGWIN__
++# include <sys/cygwin.h>
+ #endif
+ 
+-#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
+-        LPVOID))aSyscall[22].pCurrent)
++/*
++** Include code that is common to all os_*.c files
++*/
++/************** Include os_common.h in the middle of os_win.c ****************/
++/************** Begin file os_common.h ***************************************/
++/*
++** 2004 May 22
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++******************************************************************************
++**
++** This file contains macros and a little bit of code that is common to
++** all of the platform-specific files (os_*.c) and is #included into those
++** files.
++**
++** This file should be #included by the os_*.c files only.  It is not a
++** general purpose header file.
++*/
++#ifndef _OS_COMMON_H_
++#define _OS_COMMON_H_
+ 
+-#if !SQLITE_OS_WINRT
+-  { "GetFileSize",             (SYSCALL)GetFileSize,             0 },
+-#else
+-  { "GetFileSize",             (SYSCALL)0,                       0 },
++/*
++** At least two bugs have slipped in because we changed the MEMORY_DEBUG
++** macro to SQLITE_DEBUG and some older makefiles have not yet made the
++** switch.  The following code should catch this problem at compile-time.
++*/
++#ifdef MEMORY_DEBUG
++# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
+ #endif
+ 
+-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
+-
+-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
+-  { "GetFullPathNameA",        (SYSCALL)GetFullPathNameA,        0 },
++#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
++# ifndef SQLITE_DEBUG_OS_TRACE
++#   define SQLITE_DEBUG_OS_TRACE 0
++# endif
++  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
++# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
+ #else
+-  { "GetFullPathNameA",        (SYSCALL)0,                       0 },
++# define OSTRACE(X)
+ #endif
+ 
+-#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
+-        LPSTR*))aSyscall[24].pCurrent)
++/*
++** Macros for performance tracing.  Normally turned off.  Only works
++** on i486 hardware.
++*/
++#ifdef SQLITE_PERFORMANCE_TRACE
+ 
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "GetFullPathNameW",        (SYSCALL)GetFullPathNameW,        0 },
+-#else
+-  { "GetFullPathNameW",        (SYSCALL)0,                       0 },
+-#endif
++/* 
++** hwtime.h contains inline assembler code for implementing 
++** high-performance timing routines.
++*/
++/************** Include hwtime.h in the middle of os_common.h ****************/
++/************** Begin file hwtime.h ******************************************/
++/*
++** 2008 May 27
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++******************************************************************************
++**
++** This file contains inline asm code for retrieving "high-performance"
++** counters for x86 class CPUs.
++*/
++#ifndef _HWTIME_H_
++#define _HWTIME_H_
+ 
+-#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
+-        LPWSTR*))aSyscall[25].pCurrent)
++/*
++** The following routine only works on pentium-class (or newer) processors.
++** It uses the RDTSC opcode to read the cycle count value out of the
++** processor and returns that value.  This can be used for high-res
++** profiling.
++*/
++#if (defined(__GNUC__) || defined(_MSC_VER)) && \
++      (defined(i386) || defined(__i386__) || defined(_M_IX86))
+ 
+-  { "GetLastError",            (SYSCALL)GetLastError,            0 },
++  #if defined(__GNUC__)
+ 
+-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
++  __inline__ sqlite_uint64 sqlite3Hwtime(void){
++     unsigned int lo, hi;
++     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++     return (sqlite_uint64)hi << 32 | lo;
++  }
+ 
+-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
+-#if SQLITE_OS_WINCE
+-  /* The GetProcAddressA() routine is only available on Windows CE. */
+-  { "GetProcAddressA",         (SYSCALL)GetProcAddressA,         0 },
+-#else
+-  /* All other Windows platforms expect GetProcAddress() to take
+-  ** an ANSI string regardless of the _UNICODE setting */
+-  { "GetProcAddressA",         (SYSCALL)GetProcAddress,          0 },
+-#endif
+-#else
+-  { "GetProcAddressA",         (SYSCALL)0,                       0 },
+-#endif
++  #elif defined(_MSC_VER)
+ 
+-#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
+-        LPCSTR))aSyscall[27].pCurrent)
++  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
++     __asm {
++        rdtsc
++        ret       ; return value at EDX:EAX
++     }
++  }
+ 
+-#if !SQLITE_OS_WINRT
+-  { "GetSystemInfo",           (SYSCALL)GetSystemInfo,           0 },
+-#else
+-  { "GetSystemInfo",           (SYSCALL)0,                       0 },
+-#endif
++  #endif
+ 
+-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
++#elif (defined(__GNUC__) && defined(__x86_64__))
+ 
+-  { "GetSystemTime",           (SYSCALL)GetSystemTime,           0 },
++  __inline__ sqlite_uint64 sqlite3Hwtime(void){
++      unsigned long val;
++      __asm__ __volatile__ ("rdtsc" : "=A" (val));
++      return val;
++  }
++ 
++#elif (defined(__GNUC__) && defined(__ppc__))
+ 
+-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
++  __inline__ sqlite_uint64 sqlite3Hwtime(void){
++      unsigned long long retval;
++      unsigned long junk;
++      __asm__ __volatile__ ("\n\
++          1:      mftbu   %1\n\
++                  mftb    %L0\n\
++                  mftbu   %0\n\
++                  cmpw    %0,%1\n\
++                  bne     1b"
++                  : "=r" (retval), "=r" (junk));
++      return retval;
++  }
+ 
+-#if !SQLITE_OS_WINCE
+-  { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
+ #else
+-  { "GetSystemTimeAsFileTime", (SYSCALL)0,                       0 },
+-#endif
+ 
+-#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
+-        LPFILETIME))aSyscall[30].pCurrent)
++  #error Need implementation of sqlite3Hwtime() for your platform.
++
++  /*
++  ** To compile without implementing sqlite3Hwtime() for your platform,
++  ** you can remove the above #error and use the following
++  ** stub function.  You will lose timing support for many
++  ** of the debugging and testing utilities, but it should at
++  ** least compile and run.
++  */
++SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+ 
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "GetTempPathA",            (SYSCALL)GetTempPathA,            0 },
+-#else
+-  { "GetTempPathA",            (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
++#endif /* !defined(_HWTIME_H_) */
+ 
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+-  { "GetTempPathW",            (SYSCALL)GetTempPathW,            0 },
++/************** End of hwtime.h **********************************************/
++/************** Continuing where we left off in os_common.h ******************/
++
++static sqlite_uint64 g_start;
++static sqlite_uint64 g_elapsed;
++#define TIMER_START       g_start=sqlite3Hwtime()
++#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
++#define TIMER_ELAPSED     g_elapsed
+ #else
+-  { "GetTempPathW",            (SYSCALL)0,                       0 },
++#define TIMER_START
++#define TIMER_END
++#define TIMER_ELAPSED     ((sqlite_uint64)0)
+ #endif
+ 
+-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
+-
+-#if !SQLITE_OS_WINRT
+-  { "GetTickCount",            (SYSCALL)GetTickCount,            0 },
++/*
++** If we compile with the SQLITE_TEST macro set, then the following block
++** of code will give us the ability to simulate a disk I/O error.  This
++** is used for testing the I/O recovery logic.
++*/
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
++SQLITE_API int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
++SQLITE_API int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
++SQLITE_API int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
++SQLITE_API int sqlite3_io_error_benign = 0;         /* True if errors are benign */
++SQLITE_API int sqlite3_diskfull_pending = 0;
++SQLITE_API int sqlite3_diskfull = 0;
++#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
++#define SimulateIOError(CODE)  \
++  if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
++       || sqlite3_io_error_pending-- == 1 )  \
++              { local_ioerr(); CODE; }
++static void local_ioerr(){
++  IOTRACE(("IOERR\n"));
++  sqlite3_io_error_hit++;
++  if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
++}
++#define SimulateDiskfullError(CODE) \
++   if( sqlite3_diskfull_pending ){ \
++     if( sqlite3_diskfull_pending == 1 ){ \
++       local_ioerr(); \
++       sqlite3_diskfull = 1; \
++       sqlite3_io_error_hit = 1; \
++       CODE; \
++     }else{ \
++       sqlite3_diskfull_pending--; \
++     } \
++   }
+ #else
+-  { "GetTickCount",            (SYSCALL)0,                       0 },
++#define SimulateIOErrorBenign(X)
++#define SimulateIOError(A)
++#define SimulateDiskfullError(A)
+ #endif
+ 
+-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
+-
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
++/*
++** When testing, keep a count of the number of open files.
++*/
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_open_file_count = 0;
++#define OpenCounter(X)  sqlite3_open_file_count+=(X)
+ #else
+-  { "GetVersionExA",           (SYSCALL)0,                       0 },
++#define OpenCounter(X)
+ #endif
+ 
+-#define osGetVersionExA ((BOOL(WINAPI*)( \
+-        LPOSVERSIONINFOA))aSyscall[34].pCurrent)
+-
+-  { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },
++#endif /* !defined(_OS_COMMON_H_) */
+ 
+-#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
+-        SIZE_T))aSyscall[35].pCurrent)
++/************** End of os_common.h *******************************************/
++/************** Continuing where we left off in os_win.c *********************/
+ 
+-#if !SQLITE_OS_WINRT
+-  { "HeapCreate",              (SYSCALL)HeapCreate,              0 },
+-#else
+-  { "HeapCreate",              (SYSCALL)0,                       0 },
++/*
++** Compiling and using WAL mode requires several APIs that are only
++** available in Windows platforms based on the NT kernel.
++*/
++#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
++# error "WAL mode requires support from the Windows NT kernel, compile\
++ with SQLITE_OMIT_WAL."
+ #endif
+ 
+-#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
+-        SIZE_T))aSyscall[36].pCurrent)
+-
+-#if !SQLITE_OS_WINRT
+-  { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },
+-#else
+-  { "HeapDestroy",             (SYSCALL)0,                       0 },
++/*
++** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
++** based on the sub-platform)?
++*/
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
++#  define SQLITE_WIN32_HAS_ANSI
+ #endif
+ 
+-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
+-
+-  { "HeapFree",                (SYSCALL)HeapFree,                0 },
++/*
++** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
++** based on the sub-platform)?
++*/
++#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
++#  define SQLITE_WIN32_HAS_WIDE
++#endif
+ 
+-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
++/*
++** Do we need to manually define the Win32 file mapping APIs for use with WAL
++** mode (e.g. these APIs are available in the Windows CE SDK; however, they
++** are not present in the header file)?
++*/
++#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
++/*
++** Two of the file mapping APIs are different under WinRT.  Figure out which
++** set we need.
++*/
++#if SQLITE_OS_WINRT
++WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
++        LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
+ 
+-  { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },
++WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
++#else
++#if defined(SQLITE_WIN32_HAS_ANSI)
++WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
++        DWORD, DWORD, DWORD, LPCSTR);
++#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
+ 
+-#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
+-        SIZE_T))aSyscall[39].pCurrent)
++#if defined(SQLITE_WIN32_HAS_WIDE)
++WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
++        DWORD, DWORD, DWORD, LPCWSTR);
++#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
+ 
+-  { "HeapSize",                (SYSCALL)HeapSize,                0 },
++WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
++#endif /* SQLITE_OS_WINRT */
+ 
+-#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
+-        LPCVOID))aSyscall[40].pCurrent)
++/*
++** This file mapping API is common to both Win32 and WinRT.
++*/
++WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
++#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
+ 
+-#if !SQLITE_OS_WINRT
+-  { "HeapValidate",            (SYSCALL)HeapValidate,            0 },
+-#else
+-  { "HeapValidate",            (SYSCALL)0,                       0 },
++/*
++** Macro to find the minimum of two numeric values.
++*/
++#ifndef MIN
++# define MIN(x,y) ((x)<(y)?(x):(y))
+ #endif
+ 
+-#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
+-        LPCVOID))aSyscall[41].pCurrent)
+-
+-#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+-  { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
+-#else
+-  { "LoadLibraryA",            (SYSCALL)0,                       0 },
++/*
++** Some Microsoft compilers lack this definition.
++*/
++#ifndef INVALID_FILE_ATTRIBUTES
++# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 
+ #endif
+ 
+-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
+-
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+-        !defined(SQLITE_OMIT_LOAD_EXTENSION)
+-  { "LoadLibraryW",            (SYSCALL)LoadLibraryW,            0 },
+-#else
+-  { "LoadLibraryW",            (SYSCALL)0,                       0 },
++#ifndef FILE_FLAG_MASK
++# define FILE_FLAG_MASK          (0xFF3C0000)
+ #endif
+ 
+-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
+-
+-#if !SQLITE_OS_WINRT
+-  { "LocalFree",               (SYSCALL)LocalFree,               0 },
+-#else
+-  { "LocalFree",               (SYSCALL)0,                       0 },
++#ifndef FILE_ATTRIBUTE_MASK
++# define FILE_ATTRIBUTE_MASK     (0x0003FFF7)
+ #endif
+ 
+-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
+-
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+-  { "LockFile",                (SYSCALL)LockFile,                0 },
+-#else
+-  { "LockFile",                (SYSCALL)0,                       0 },
++#ifndef SQLITE_OMIT_WAL
++/* Forward references */
++typedef struct winShm winShm;           /* A connection to shared-memory */
++typedef struct winShmNode winShmNode;   /* A region of shared-memory */
+ #endif
+ 
+-#ifndef osLockFile
+-#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+-        DWORD))aSyscall[45].pCurrent)
++/*
++** WinCE lacks native support for file locking so we have to fake it
++** with some code of our own.
++*/
++#if SQLITE_OS_WINCE
++typedef struct winceLock {
++  int nReaders;       /* Number of reader locks obtained */
++  BOOL bPending;      /* Indicates a pending lock has been obtained */
++  BOOL bReserved;     /* Indicates a reserved lock has been obtained */
++  BOOL bExclusive;    /* Indicates an exclusive lock has been obtained */
++} winceLock;
+ #endif
+ 
+-#if !SQLITE_OS_WINCE
+-  { "LockFileEx",              (SYSCALL)LockFileEx,              0 },
+-#else
+-  { "LockFileEx",              (SYSCALL)0,                       0 },
++/*
++** The winFile structure is a subclass of sqlite3_file* specific to the win32
++** portability layer.
++*/
++typedef struct winFile winFile;
++struct winFile {
++  const sqlite3_io_methods *pMethod; /*** Must be first ***/
++  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
++  HANDLE h;               /* Handle for accessing the file */
++  u8 locktype;            /* Type of lock currently held on this file */
++  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
++  u8 ctrlFlags;           /* Flags.  See WINFILE_* below */
++  DWORD lastErrno;        /* The Windows errno from the last I/O error */
++#ifndef SQLITE_OMIT_WAL
++  winShm *pShm;           /* Instance of shared memory on this file */
+ #endif
+-
+-#ifndef osLockFileEx
+-#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
+-        LPOVERLAPPED))aSyscall[46].pCurrent)
++  const char *zPath;      /* Full pathname of this file */
++  int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
++#if SQLITE_OS_WINCE
++  LPWSTR zDeleteOnClose;  /* Name of file to delete when closing */
++  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
++  HANDLE hShared;         /* Shared memory segment used for locking */
++  winceLock local;        /* Locks obtained by this instance of winFile */
++  winceLock *shared;      /* Global shared lock memory for the file  */
+ #endif
+-
+-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
+-  { "MapViewOfFile",           (SYSCALL)MapViewOfFile,           0 },
+-#else
+-  { "MapViewOfFile",           (SYSCALL)0,                       0 },
++#if SQLITE_MAX_MMAP_SIZE>0
++  int nFetchOut;                /* Number of outstanding xFetch references */
++  HANDLE hMap;                  /* Handle for accessing memory mapping */
++  void *pMapRegion;             /* Area memory mapped */
++  sqlite3_int64 mmapSize;       /* Usable size of mapped region */
++  sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
++  sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
+ #endif
++};
+ 
+-#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+-        SIZE_T))aSyscall[47].pCurrent)
+-
+-  { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },
+-
+-#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
+-        int))aSyscall[48].pCurrent)
+-
+-  { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
+-
+-#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
+-        LARGE_INTEGER*))aSyscall[49].pCurrent)
+-
+-  { "ReadFile",                (SYSCALL)ReadFile,                0 },
+-
+-#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
+-        LPOVERLAPPED))aSyscall[50].pCurrent)
+-
+-  { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },
+-
+-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
++/*
++** Allowed values for winFile.ctrlFlags
++*/
++#define WINFILE_RDONLY          0x02   /* Connection is read only */
++#define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
++#define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
+ 
+-#if !SQLITE_OS_WINRT
+-  { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },
+-#else
+-  { "SetFilePointer",          (SYSCALL)0,                       0 },
++/*
++ * The size of the buffer used by sqlite3_win32_write_debug().
++ */
++#ifndef SQLITE_WIN32_DBG_BUF_SIZE
++#  define SQLITE_WIN32_DBG_BUF_SIZE   ((int)(4096-sizeof(DWORD)))
+ #endif
+ 
+-#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
+-        DWORD))aSyscall[52].pCurrent)
+-
+-#if !SQLITE_OS_WINRT
+-  { "Sleep",                   (SYSCALL)Sleep,                   0 },
+-#else
+-  { "Sleep",                   (SYSCALL)0,                       0 },
++/*
++ * The value used with sqlite3_win32_set_directory() to specify that
++ * the data directory should be changed.
++ */
++#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
++#  define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
+ #endif
+ 
+-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
+-
+-  { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },
++/*
++ * The value used with sqlite3_win32_set_directory() to specify that
++ * the temporary directory should be changed.
++ */
++#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
++#  define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
++#endif
+ 
+-#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
+-        LPFILETIME))aSyscall[54].pCurrent)
++/*
++ * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
++ * various Win32 API heap functions instead of our own.
++ */
++#ifdef SQLITE_WIN32_MALLOC
+ 
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+-  { "UnlockFile",              (SYSCALL)UnlockFile,              0 },
+-#else
+-  { "UnlockFile",              (SYSCALL)0,                       0 },
++/*
++ * If this is non-zero, an isolated heap will be created by the native Win32
++ * allocator subsystem; otherwise, the default process heap will be used.  This
++ * setting has no effect when compiling for WinRT.  By default, this is enabled
++ * and an isolated heap will be created to store all allocated data.
++ *
++ ******************************************************************************
++ * WARNING: It is important to note that when this setting is non-zero and the
++ *          winMemShutdown function is called (e.g. by the sqlite3_shutdown
++ *          function), all data that was allocated using the isolated heap will
++ *          be freed immediately and any attempt to access any of that freed
++ *          data will almost certainly result in an immediate access violation.
++ ******************************************************************************
++ */
++#ifndef SQLITE_WIN32_HEAP_CREATE
++#  define SQLITE_WIN32_HEAP_CREATE    (TRUE)
+ #endif
+ 
+-#ifndef osUnlockFile
+-#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+-        DWORD))aSyscall[55].pCurrent)
++/*
++ * The initial size of the Win32-specific heap.  This value may be zero.
++ */
++#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
++#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
++                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
+ #endif
+ 
+-#if !SQLITE_OS_WINCE
+-  { "UnlockFileEx",            (SYSCALL)UnlockFileEx,            0 },
+-#else
+-  { "UnlockFileEx",            (SYSCALL)0,                       0 },
++/*
++ * The maximum size of the Win32-specific heap.  This value may be zero.
++ */
++#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
++#  define SQLITE_WIN32_HEAP_MAX_SIZE  (0)
+ #endif
+ 
+-#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+-        LPOVERLAPPED))aSyscall[56].pCurrent)
+-
+-#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
+-  { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },
+-#else
+-  { "UnmapViewOfFile",         (SYSCALL)0,                       0 },
++/*
++ * The extra flags to use in calls to the Win32 heap APIs.  This value may be
++ * zero for the default behavior.
++ */
++#ifndef SQLITE_WIN32_HEAP_FLAGS
++#  define SQLITE_WIN32_HEAP_FLAGS     (0)
+ #endif
+ 
+-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
+-
+-  { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },
+-
+-#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
+-        LPCSTR,LPBOOL))aSyscall[58].pCurrent)
+-
+-  { "WriteFile",               (SYSCALL)WriteFile,               0 },
+-
+-#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
+-        LPOVERLAPPED))aSyscall[59].pCurrent)
++/*
++** The winMemData structure stores information required by the Win32-specific
++** sqlite3_mem_methods implementation.
++*/
++typedef struct winMemData winMemData;
++struct winMemData {
++#ifndef NDEBUG
++  u32 magic;    /* Magic number to detect structure corruption. */
++#endif
++  HANDLE hHeap; /* The handle to our heap. */
++  BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
++};
+ 
+-#if SQLITE_OS_WINRT
+-  { "CreateEventExW",          (SYSCALL)CreateEventExW,          0 },
+-#else
+-  { "CreateEventExW",          (SYSCALL)0,                       0 },
++#ifndef NDEBUG
++#define WINMEM_MAGIC     0x42b2830b
+ #endif
+ 
+-#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
+-        DWORD,DWORD))aSyscall[60].pCurrent)
++static struct winMemData win_mem_data = {
++#ifndef NDEBUG
++  WINMEM_MAGIC,
++#endif
++  NULL, FALSE
++};
+ 
+-#if !SQLITE_OS_WINRT
+-  { "WaitForSingleObject",     (SYSCALL)WaitForSingleObject,     0 },
++#ifndef NDEBUG
++#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+ #else
+-  { "WaitForSingleObject",     (SYSCALL)0,                       0 },
++#define winMemAssertMagic()
+ #endif
+ 
+-#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
+-        DWORD))aSyscall[61].pCurrent)
++#define winMemGetHeap() win_mem_data.hHeap
+ 
+-#if SQLITE_OS_WINRT
+-  { "WaitForSingleObjectEx",   (SYSCALL)WaitForSingleObjectEx,   0 },
+-#else
+-  { "WaitForSingleObjectEx",   (SYSCALL)0,                       0 },
+-#endif
++static void *winMemMalloc(int nBytes);
++static void winMemFree(void *pPrior);
++static void *winMemRealloc(void *pPrior, int nBytes);
++static int winMemSize(void *p);
++static int winMemRoundup(int n);
++static int winMemInit(void *pAppData);
++static void winMemShutdown(void *pAppData);
+ 
+-#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
+-        BOOL))aSyscall[62].pCurrent)
++SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
++#endif /* SQLITE_WIN32_MALLOC */
+ 
+-#if SQLITE_OS_WINRT
+-  { "SetFilePointerEx",        (SYSCALL)SetFilePointerEx,        0 },
++/*
++** The following variable is (normally) set once and never changes
++** thereafter.  It records whether the operating system is Win9x
++** or WinNT.
++**
++** 0:   Operating system unknown.
++** 1:   Operating system is Win9x.
++** 2:   Operating system is WinNT.
++**
++** In order to facilitate testing on a WinNT system, the test fixture
++** can manually set this value to 1 to emulate Win98 behavior.
++*/
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_os_type = 0;
+ #else
+-  { "SetFilePointerEx",        (SYSCALL)0,                       0 },
++static int sqlite3_os_type = 0;
+ #endif
+ 
+-#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
+-        PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
+-
+-#if SQLITE_OS_WINRT
+-  { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
+-#else
+-  { "GetFileInformationByHandleEx", (SYSCALL)0,                  0 },
++#ifndef SYSCALL
++#  define SYSCALL sqlite3_syscall_ptr
+ #endif
+ 
+-#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
+-        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
++/*
++** This function is not available on Windows CE or WinRT.
++ */
+ 
+-#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
+-  { "MapViewOfFileFromApp",    (SYSCALL)MapViewOfFileFromApp,    0 },
+-#else
+-  { "MapViewOfFileFromApp",    (SYSCALL)0,                       0 },
++#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
++#  define osAreFileApisANSI()       1
+ #endif
+ 
+-#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
+-        SIZE_T))aSyscall[65].pCurrent)
+-
+-#if SQLITE_OS_WINRT
+-  { "CreateFile2",             (SYSCALL)CreateFile2,             0 },
++/*
++** Many system calls are accessed through pointer-to-functions so that
++** they may be overridden at runtime to facilitate fault injection during
++** testing and sandboxing.  The following array holds the names and pointers
++** to all overrideable system calls.
++*/
++static struct win_syscall {
++  const char *zName;            /* Name of the system call */
++  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
++  sqlite3_syscall_ptr pDefault; /* Default value */
++} aSyscall[] = {
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
++  { "AreFileApisANSI",         (SYSCALL)AreFileApisANSI,         0 },
+ #else
+-  { "CreateFile2",             (SYSCALL)0,                       0 },
++  { "AreFileApisANSI",         (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
+-        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
++#ifndef osAreFileApisANSI
++#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
++#endif
+ 
+-#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+-  { "LoadPackagedLibrary",     (SYSCALL)LoadPackagedLibrary,     0 },
++#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
++  { "CharLowerW",              (SYSCALL)CharLowerW,              0 },
+ #else
+-  { "LoadPackagedLibrary",     (SYSCALL)0,                       0 },
++  { "CharLowerW",              (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
+-        DWORD))aSyscall[67].pCurrent)
++#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
+ 
+-#if SQLITE_OS_WINRT
+-  { "GetTickCount64",          (SYSCALL)GetTickCount64,          0 },
++#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
++  { "CharUpperW",              (SYSCALL)CharUpperW,              0 },
+ #else
+-  { "GetTickCount64",          (SYSCALL)0,                       0 },
++  { "CharUpperW",              (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
++#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
+ 
+-#if SQLITE_OS_WINRT
+-  { "GetNativeSystemInfo",     (SYSCALL)GetNativeSystemInfo,     0 },
+-#else
+-  { "GetNativeSystemInfo",     (SYSCALL)0,                       0 },
+-#endif
++  { "CloseHandle",             (SYSCALL)CloseHandle,             0 },
+ 
+-#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
+-        LPSYSTEM_INFO))aSyscall[69].pCurrent)
++#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
+ 
+ #if defined(SQLITE_WIN32_HAS_ANSI)
+-  { "OutputDebugStringA",      (SYSCALL)OutputDebugStringA,      0 },
++  { "CreateFileA",             (SYSCALL)CreateFileA,             0 },
+ #else
+-  { "OutputDebugStringA",      (SYSCALL)0,                       0 },
++  { "CreateFileA",             (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
++#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
++        LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
+ 
+-#if defined(SQLITE_WIN32_HAS_WIDE)
+-  { "OutputDebugStringW",      (SYSCALL)OutputDebugStringW,      0 },
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
++  { "CreateFileW",             (SYSCALL)CreateFileW,             0 },
+ #else
+-  { "OutputDebugStringW",      (SYSCALL)0,                       0 },
++  { "CreateFileW",             (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
+-
+-  { "GetProcessHeap",          (SYSCALL)GetProcessHeap,          0 },
+-
+-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
++#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
++        LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
+ 
+-#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
+-  { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
++#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
++        !defined(SQLITE_OMIT_WAL))
++  { "CreateFileMappingA",      (SYSCALL)CreateFileMappingA,      0 },
+ #else
+-  { "CreateFileMappingFromApp", (SYSCALL)0,                      0 },
++  { "CreateFileMappingA",      (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
+-        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
+-
+-}; /* End of the overrideable system calls */
+-
+-/*
+-** This is the xSetSystemCall() method of sqlite3_vfs for all of the
+-** "win32" VFSes.  Return SQLITE_OK opon successfully updating the
+-** system call pointer, or SQLITE_NOTFOUND if there is no configurable
+-** system call named zName.
+-*/
+-static int winSetSystemCall(
+-  sqlite3_vfs *pNotUsed,        /* The VFS pointer.  Not used */
+-  const char *zName,            /* Name of system call to override */
+-  sqlite3_syscall_ptr pNewFunc  /* Pointer to new system call value */
+-){
+-  unsigned int i;
+-  int rc = SQLITE_NOTFOUND;
+-
+-  UNUSED_PARAMETER(pNotUsed);
+-  if( zName==0 ){
+-    /* If no zName is given, restore all system calls to their default
+-    ** settings and return NULL
+-    */
+-    rc = SQLITE_OK;
+-    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+-      if( aSyscall[i].pDefault ){
+-        aSyscall[i].pCurrent = aSyscall[i].pDefault;
+-      }
+-    }
+-  }else{
+-    /* If zName is specified, operate on only the one system call
+-    ** specified.
+-    */
+-    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+-      if( strcmp(zName, aSyscall[i].zName)==0 ){
+-        if( aSyscall[i].pDefault==0 ){
+-          aSyscall[i].pDefault = aSyscall[i].pCurrent;
+-        }
+-        rc = SQLITE_OK;
+-        if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
+-        aSyscall[i].pCurrent = pNewFunc;
+-        break;
+-      }
+-    }
+-  }
+-  return rc;
+-}
+-
+-/*
+-** Return the value of a system call.  Return NULL if zName is not a
+-** recognized system call name.  NULL is also returned if the system call
+-** is currently undefined.
+-*/
+-static sqlite3_syscall_ptr winGetSystemCall(
+-  sqlite3_vfs *pNotUsed,
+-  const char *zName
+-){
+-  unsigned int i;
+-
+-  UNUSED_PARAMETER(pNotUsed);
+-  for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+-    if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
+-  }
+-  return 0;
+-}
+-
+-/*
+-** Return the name of the first system call after zName.  If zName==NULL
+-** then return the name of the first system call.  Return NULL if zName
+-** is the last system call or if zName is not the name of a valid
+-** system call.
+-*/
+-static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
+-  int i = -1;
+-
+-  UNUSED_PARAMETER(p);
+-  if( zName ){
+-    for(i=0; i<ArraySize(aSyscall)-1; i++){
+-      if( strcmp(zName, aSyscall[i].zName)==0 ) break;
+-    }
+-  }
+-  for(i++; i<ArraySize(aSyscall); i++){
+-    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
+-  }
+-  return 0;
+-}
+-
+-/*
+-** This function outputs the specified (ANSI) string to the Win32 debugger
+-** (if available).
+-*/
++#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
++        DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
+ 
+-SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
+-  char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
+-  int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
+-  if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
+-  assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
+-#if defined(SQLITE_WIN32_HAS_ANSI)
+-  if( nMin>0 ){
+-    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
+-    memcpy(zDbgBuf, zBuf, nMin);
+-    osOutputDebugStringA(zDbgBuf);
+-  }else{
+-    osOutputDebugStringA(zBuf);
+-  }
+-#elif defined(SQLITE_WIN32_HAS_WIDE)
+-  memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
+-  if ( osMultiByteToWideChar(
+-          osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
+-          nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
+-    return;
+-  }
+-  osOutputDebugStringW((LPCWSTR)zDbgBuf);
++#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
++        !defined(SQLITE_OMIT_WAL))
++  { "CreateFileMappingW",      (SYSCALL)CreateFileMappingW,      0 },
+ #else
+-  if( nMin>0 ){
+-    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
+-    memcpy(zDbgBuf, zBuf, nMin);
+-    fprintf(stderr, "%s", zDbgBuf);
+-  }else{
+-    fprintf(stderr, "%s", zBuf);
+-  }
+-#endif
+-}
+-
+-/*
+-** The following routine suspends the current thread for at least ms
+-** milliseconds.  This is equivalent to the Win32 Sleep() interface.
+-*/
+-#if SQLITE_OS_WINRT
+-static HANDLE sleepObj = NULL;
++  { "CreateFileMappingW",      (SYSCALL)0,                       0 },
+ #endif
+ 
+-SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
+-#if SQLITE_OS_WINRT
+-  if ( sleepObj==NULL ){
+-    sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
+-                                SYNCHRONIZE);
+-  }
+-  assert( sleepObj!=NULL );
+-  osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
+-#else
+-  osSleep(milliseconds);
+-#endif
+-}
++#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
++        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
+ 
+-/*
+-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
+-** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
+-**
+-** Here is an interesting observation:  Win95, Win98, and WinME lack
+-** the LockFileEx() API.  But we can still statically link against that
+-** API as long as we don't call it when running Win95/98/ME.  A call to
+-** this routine is used to determine if the host is Win95/98/ME or
+-** WinNT/2K/XP so that we will know whether or not we can safely call
+-** the LockFileEx() API.
+-*/
+-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+-# define isNT()  (1)
+-#elif !defined(SQLITE_WIN32_HAS_WIDE)
+-# define isNT()  (0)
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
++  { "CreateMutexW",            (SYSCALL)CreateMutexW,            0 },
+ #else
+-  static int isNT(void){
+-    if( sqlite3_os_type==0 ){
+-      OSVERSIONINFOA sInfo;
+-      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+-      osGetVersionExA(&sInfo);
+-      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
+-    }
+-    return sqlite3_os_type==2;
+-  }
++  { "CreateMutexW",            (SYSCALL)0,                       0 },
+ #endif
+ 
+-#ifdef SQLITE_WIN32_MALLOC
+-/*
+-** Allocate nBytes of memory.
+-*/
+-static void *winMemMalloc(int nBytes){
+-  HANDLE hHeap;
+-  void *p;
++#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
++        LPCWSTR))aSyscall[8].pCurrent)
+ 
+-  winMemAssertMagic();
+-  hHeap = winMemGetHeap();
+-  assert( hHeap!=0 );
+-  assert( hHeap!=INVALID_HANDLE_VALUE );
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  { "DeleteFileA",             (SYSCALL)DeleteFileA,             0 },
++#else
++  { "DeleteFileA",             (SYSCALL)0,                       0 },
+ #endif
+-  assert( nBytes>=0 );
+-  p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+-  if( !p ){
+-    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
+-                nBytes, osGetLastError(), (void*)hHeap);
+-  }
+-  return p;
+-}
+ 
+-/*
+-** Free memory.
+-*/
+-static void winMemFree(void *pPrior){
+-  HANDLE hHeap;
++#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
+ 
+-  winMemAssertMagic();
+-  hHeap = winMemGetHeap();
+-  assert( hHeap!=0 );
+-  assert( hHeap!=INVALID_HANDLE_VALUE );
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
++#if defined(SQLITE_WIN32_HAS_WIDE)
++  { "DeleteFileW",             (SYSCALL)DeleteFileW,             0 },
++#else
++  { "DeleteFileW",             (SYSCALL)0,                       0 },
+ #endif
+-  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
+-  if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
+-    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
+-                pPrior, osGetLastError(), (void*)hHeap);
+-  }
+-}
+ 
+-/*
+-** Change the size of an existing memory allocation
+-*/
+-static void *winMemRealloc(void *pPrior, int nBytes){
+-  HANDLE hHeap;
+-  void *p;
++#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
+ 
+-  winMemAssertMagic();
+-  hHeap = winMemGetHeap();
+-  assert( hHeap!=0 );
+-  assert( hHeap!=INVALID_HANDLE_VALUE );
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
++#if SQLITE_OS_WINCE
++  { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
++#else
++  { "FileTimeToLocalFileTime", (SYSCALL)0,                       0 },
+ #endif
+-  assert( nBytes>=0 );
+-  if( !pPrior ){
+-    p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+-  }else{
+-    p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
+-  }
+-  if( !p ){
+-    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
+-                pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
+-                (void*)hHeap);
+-  }
+-  return p;
+-}
+ 
+-/*
+-** Return the size of an outstanding allocation, in bytes.
+-*/
+-static int winMemSize(void *p){
+-  HANDLE hHeap;
+-  SIZE_T n;
++#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
++        LPFILETIME))aSyscall[11].pCurrent)
+ 
+-  winMemAssertMagic();
+-  hHeap = winMemGetHeap();
+-  assert( hHeap!=0 );
+-  assert( hHeap!=INVALID_HANDLE_VALUE );
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
++#if SQLITE_OS_WINCE
++  { "FileTimeToSystemTime",    (SYSCALL)FileTimeToSystemTime,    0 },
++#else
++  { "FileTimeToSystemTime",    (SYSCALL)0,                       0 },
+ #endif
+-  if( !p ) return 0;
+-  n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
+-  if( n==(SIZE_T)-1 ){
+-    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
+-                p, osGetLastError(), (void*)hHeap);
+-    return 0;
+-  }
+-  return (int)n;
+-}
+ 
+-/*
+-** Round up a request size to the next valid allocation size.
+-*/
+-static int winMemRoundup(int n){
+-  return n;
+-}
++#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
++        LPSYSTEMTIME))aSyscall[12].pCurrent)
+ 
+-/*
+-** Initialize this module.
+-*/
+-static int winMemInit(void *pAppData){
+-  winMemData *pWinMemData = (winMemData *)pAppData;
++  { "FlushFileBuffers",        (SYSCALL)FlushFileBuffers,        0 },
+ 
+-  if( !pWinMemData ) return SQLITE_ERROR;
+-  assert( pWinMemData->magic==WINMEM_MAGIC );
++#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
+ 
+-#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
+-  if( !pWinMemData->hHeap ){
+-    pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
+-                                      SQLITE_WIN32_HEAP_INIT_SIZE,
+-                                      SQLITE_WIN32_HEAP_MAX_SIZE);
+-    if( !pWinMemData->hHeap ){
+-      sqlite3_log(SQLITE_NOMEM,
+-          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
+-          osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
+-          SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
+-      return SQLITE_NOMEM;
+-    }
+-    pWinMemData->bOwned = TRUE;
+-    assert( pWinMemData->bOwned );
+-  }
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  { "FormatMessageA",          (SYSCALL)FormatMessageA,          0 },
+ #else
+-  pWinMemData->hHeap = osGetProcessHeap();
+-  if( !pWinMemData->hHeap ){
+-    sqlite3_log(SQLITE_NOMEM,
+-        "failed to GetProcessHeap (%d)", osGetLastError());
+-    return SQLITE_NOMEM;
+-  }
+-  pWinMemData->bOwned = FALSE;
+-  assert( !pWinMemData->bOwned );
++  { "FormatMessageA",          (SYSCALL)0,                       0 },
+ #endif
+-  assert( pWinMemData->hHeap!=0 );
+-  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+-  assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
++
++#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
++        DWORD,va_list*))aSyscall[14].pCurrent)
++
++#if defined(SQLITE_WIN32_HAS_WIDE)
++  { "FormatMessageW",          (SYSCALL)FormatMessageW,          0 },
++#else
++  { "FormatMessageW",          (SYSCALL)0,                       0 },
+ #endif
+-  return SQLITE_OK;
+-}
+ 
+-/*
+-** Deinitialize this module.
+-*/
+-static void winMemShutdown(void *pAppData){
+-  winMemData *pWinMemData = (winMemData *)pAppData;
++#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
++        DWORD,va_list*))aSyscall[15].pCurrent)
+ 
+-  if( !pWinMemData ) return;
+-  if( pWinMemData->hHeap ){
+-    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+-    assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
++#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
++  { "FreeLibrary",             (SYSCALL)FreeLibrary,             0 },
++#else
++  { "FreeLibrary",             (SYSCALL)0,                       0 },
+ #endif
+-    if( pWinMemData->bOwned ){
+-      if( !osHeapDestroy(pWinMemData->hHeap) ){
+-        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
+-                    osGetLastError(), (void*)pWinMemData->hHeap);
+-      }
+-      pWinMemData->bOwned = FALSE;
+-    }
+-    pWinMemData->hHeap = NULL;
+-  }
+-}
+ 
+-/*
+-** Populate the low-level memory allocation function pointers in
+-** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+-** arguments specify the block of memory to manage.
+-**
+-** This routine is only called by sqlite3_config(), and therefore
+-** is not required to be threadsafe (it is not).
+-*/
+-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
+-  static const sqlite3_mem_methods winMemMethods = {
+-    winMemMalloc,
+-    winMemFree,
+-    winMemRealloc,
+-    winMemSize,
+-    winMemRoundup,
+-    winMemInit,
+-    winMemShutdown,
+-    &win_mem_data
+-  };
+-  return &winMemMethods;
+-}
++#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
+ 
+-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+-  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
+-}
+-#endif /* SQLITE_WIN32_MALLOC */
++  { "GetCurrentProcessId",     (SYSCALL)GetCurrentProcessId,     0 },
+ 
+-/*
+-** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). 
+-**
+-** Space to hold the returned string is obtained from malloc.
+-*/
+-static LPWSTR utf8ToUnicode(const char *zFilename){
+-  int nChar;
+-  LPWSTR zWideFilename;
++#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
+ 
+-  nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
+-  if( nChar==0 ){
+-    return 0;
+-  }
+-  zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
+-  if( zWideFilename==0 ){
+-    return 0;
+-  }
+-  nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
+-                                nChar);
+-  if( nChar==0 ){
+-    sqlite3_free(zWideFilename);
+-    zWideFilename = 0;
+-  }
+-  return zWideFilename;
+-}
++#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
++  { "GetDiskFreeSpaceA",       (SYSCALL)GetDiskFreeSpaceA,       0 },
++#else
++  { "GetDiskFreeSpaceA",       (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Convert Microsoft Unicode to UTF-8.  Space to hold the returned string is
+-** obtained from sqlite3_malloc().
+-*/
+-static char *unicodeToUtf8(LPCWSTR zWideFilename){
+-  int nByte;
+-  char *zFilename;
++#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
++        LPDWORD))aSyscall[18].pCurrent)
+ 
+-  nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
+-  if( nByte == 0 ){
+-    return 0;
+-  }
+-  zFilename = sqlite3MallocZero( nByte );
+-  if( zFilename==0 ){
+-    return 0;
+-  }
+-  nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
+-                                0, 0);
+-  if( nByte == 0 ){
+-    sqlite3_free(zFilename);
+-    zFilename = 0;
+-  }
+-  return zFilename;
+-}
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
++  { "GetDiskFreeSpaceW",       (SYSCALL)GetDiskFreeSpaceW,       0 },
++#else
++  { "GetDiskFreeSpaceW",       (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Convert an ANSI string to Microsoft Unicode, based on the
+-** current codepage settings for file apis.
+-** 
+-** Space to hold the returned string is obtained
+-** from sqlite3_malloc.
+-*/
+-static LPWSTR mbcsToUnicode(const char *zFilename){
+-  int nByte;
+-  LPWSTR zMbcsFilename;
+-  int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
++#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
++        LPDWORD))aSyscall[19].pCurrent)
+ 
+-  nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
+-                                0)*sizeof(WCHAR);
+-  if( nByte==0 ){
+-    return 0;
+-  }
+-  zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
+-  if( zMbcsFilename==0 ){
+-    return 0;
+-  }
+-  nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
+-                                nByte);
+-  if( nByte==0 ){
+-    sqlite3_free(zMbcsFilename);
+-    zMbcsFilename = 0;
+-  }
+-  return zMbcsFilename;
+-}
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  { "GetFileAttributesA",      (SYSCALL)GetFileAttributesA,      0 },
++#else
++  { "GetFileAttributesA",      (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Convert Microsoft Unicode to multi-byte character string, based on the
+-** user's ANSI codepage.
+-**
+-** Space to hold the returned string is obtained from
+-** sqlite3_malloc().
+-*/
+-static char *unicodeToMbcs(LPCWSTR zWideFilename){
+-  int nByte;
+-  char *zFilename;
+-  int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
++#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
+ 
+-  nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
+-  if( nByte == 0 ){
+-    return 0;
+-  }
+-  zFilename = sqlite3MallocZero( nByte );
+-  if( zFilename==0 ){
+-    return 0;
+-  }
+-  nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
+-                                nByte, 0, 0);
+-  if( nByte == 0 ){
+-    sqlite3_free(zFilename);
+-    zFilename = 0;
+-  }
+-  return zFilename;
+-}
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
++  { "GetFileAttributesW",      (SYSCALL)GetFileAttributesW,      0 },
++#else
++  { "GetFileAttributesW",      (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Convert multibyte character string to UTF-8.  Space to hold the
+-** returned string is obtained from sqlite3_malloc().
+-*/
+-SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
+-  char *zFilenameUtf8;
+-  LPWSTR zTmpWide;
++#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
+ 
+-  zTmpWide = mbcsToUnicode(zFilename);
+-  if( zTmpWide==0 ){
+-    return 0;
+-  }
+-  zFilenameUtf8 = unicodeToUtf8(zTmpWide);
+-  sqlite3_free(zTmpWide);
+-  return zFilenameUtf8;
+-}
++#if defined(SQLITE_WIN32_HAS_WIDE)
++  { "GetFileAttributesExW",    (SYSCALL)GetFileAttributesExW,    0 },
++#else
++  { "GetFileAttributesExW",    (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Convert UTF-8 to multibyte character string.  Space to hold the 
+-** returned string is obtained from sqlite3_malloc().
+-*/
+-SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
+-  char *zFilenameMbcs;
+-  LPWSTR zTmpWide;
++#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
++        LPVOID))aSyscall[22].pCurrent)
+ 
+-  zTmpWide = utf8ToUnicode(zFilename);
+-  if( zTmpWide==0 ){
+-    return 0;
+-  }
+-  zFilenameMbcs = unicodeToMbcs(zTmpWide);
+-  sqlite3_free(zTmpWide);
+-  return zFilenameMbcs;
+-}
++#if !SQLITE_OS_WINRT
++  { "GetFileSize",             (SYSCALL)GetFileSize,             0 },
++#else
++  { "GetFileSize",             (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** This function sets the data directory or the temporary directory based on
+-** the provided arguments.  The type argument must be 1 in order to set the
+-** data directory or 2 in order to set the temporary directory.  The zValue
+-** argument is the name of the directory to use.  The return value will be
+-** SQLITE_OK if successful.
+-*/
+-SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
+-  char **ppDirectory = 0;
+-#ifndef SQLITE_OMIT_AUTOINIT
+-  int rc = sqlite3_initialize();
+-  if( rc ) return rc;
++#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
++
++#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
++  { "GetFullPathNameA",        (SYSCALL)GetFullPathNameA,        0 },
++#else
++  { "GetFullPathNameA",        (SYSCALL)0,                       0 },
+ #endif
+-  if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
+-    ppDirectory = &sqlite3_data_directory;
+-  }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
+-    ppDirectory = &sqlite3_temp_directory;
+-  }
+-  assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
+-          || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
+-  );
+-  assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
+-  if( ppDirectory ){
+-    char *zValueUtf8 = 0;
+-    if( zValue && zValue[0] ){
+-      zValueUtf8 = unicodeToUtf8(zValue);
+-      if ( zValueUtf8==0 ){
+-        return SQLITE_NOMEM;
+-      }
+-    }
+-    sqlite3_free(*ppDirectory);
+-    *ppDirectory = zValueUtf8;
+-    return SQLITE_OK;
+-  }
+-  return SQLITE_ERROR;
+-}
+ 
+-/*
+-** The return value of getLastErrorMsg
+-** is zero if the error message fits in the buffer, or non-zero
+-** otherwise (if the message was truncated).
+-*/
+-static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
+-  /* FormatMessage returns 0 on failure.  Otherwise it
+-  ** returns the number of TCHARs written to the output
+-  ** buffer, excluding the terminating null char.
+-  */
+-  DWORD dwLen = 0;
+-  char *zOut = 0;
++#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
++        LPSTR*))aSyscall[24].pCurrent)
+ 
+-  if( isNT() ){
+-#if SQLITE_OS_WINRT
+-    WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
+-    dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+-                             FORMAT_MESSAGE_IGNORE_INSERTS,
+-                             NULL,
+-                             lastErrno,
+-                             0,
+-                             zTempWide,
+-                             MAX_PATH,
+-                             0);
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
++  { "GetFullPathNameW",        (SYSCALL)GetFullPathNameW,        0 },
+ #else
+-    LPWSTR zTempWide = NULL;
+-    dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+-                             FORMAT_MESSAGE_FROM_SYSTEM |
+-                             FORMAT_MESSAGE_IGNORE_INSERTS,
+-                             NULL,
+-                             lastErrno,
+-                             0,
+-                             (LPWSTR) &zTempWide,
+-                             0,
+-                             0);
++  { "GetFullPathNameW",        (SYSCALL)0,                       0 },
+ #endif
+-    if( dwLen > 0 ){
+-      /* allocate a buffer and convert to UTF8 */
+-      sqlite3BeginBenignMalloc();
+-      zOut = unicodeToUtf8(zTempWide);
+-      sqlite3EndBenignMalloc();
++
++#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
++        LPWSTR*))aSyscall[25].pCurrent)
++
++  { "GetLastError",            (SYSCALL)GetLastError,            0 },
++
++#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
++
++#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
++#if SQLITE_OS_WINCE
++  /* The GetProcAddressA() routine is only available on Windows CE. */
++  { "GetProcAddressA",         (SYSCALL)GetProcAddressA,         0 },
++#else
++  /* All other Windows platforms expect GetProcAddress() to take
++  ** an ANSI string regardless of the _UNICODE setting */
++  { "GetProcAddressA",         (SYSCALL)GetProcAddress,          0 },
++#endif
++#else
++  { "GetProcAddressA",         (SYSCALL)0,                       0 },
++#endif
++
++#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
++        LPCSTR))aSyscall[27].pCurrent)
++
+ #if !SQLITE_OS_WINRT
+-      /* free the system buffer allocated by FormatMessage */
+-      osLocalFree(zTempWide);
++  { "GetSystemInfo",           (SYSCALL)GetSystemInfo,           0 },
++#else
++  { "GetSystemInfo",           (SYSCALL)0,                       0 },
+ #endif
+-    }
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    char *zTemp = NULL;
+-    dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+-                             FORMAT_MESSAGE_FROM_SYSTEM |
+-                             FORMAT_MESSAGE_IGNORE_INSERTS,
+-                             NULL,
+-                             lastErrno,
+-                             0,
+-                             (LPSTR) &zTemp,
+-                             0,
+-                             0);
+-    if( dwLen > 0 ){
+-      /* allocate a buffer and convert to UTF8 */
+-      sqlite3BeginBenignMalloc();
+-      zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
+-      sqlite3EndBenignMalloc();
+-      /* free the system buffer allocated by FormatMessage */
+-      osLocalFree(zTemp);
+-    }
+-  }
++
++#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
++
++  { "GetSystemTime",           (SYSCALL)GetSystemTime,           0 },
++
++#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
++
++#if !SQLITE_OS_WINCE
++  { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
++#else
++  { "GetSystemTimeAsFileTime", (SYSCALL)0,                       0 },
++#endif
++
++#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
++        LPFILETIME))aSyscall[30].pCurrent)
++
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  { "GetTempPathA",            (SYSCALL)GetTempPathA,            0 },
++#else
++  { "GetTempPathA",            (SYSCALL)0,                       0 },
+ #endif
+-  if( 0 == dwLen ){
+-    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
+-  }else{
+-    /* copy a maximum of nBuf chars to output buffer */
+-    sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
+-    /* free the UTF8 buffer */
+-    sqlite3_free(zOut);
+-  }
+-  return 0;
+-}
+ 
+-/*
+-**
+-** This function - winLogErrorAtLine() - is only ever called via the macro
+-** winLogError().
+-**
+-** This routine is invoked after an error occurs in an OS function.
+-** It logs a message using sqlite3_log() containing the current value of
+-** error code and, if possible, the human-readable equivalent from 
+-** FormatMessage.
+-**
+-** The first argument passed to the macro should be the error code that
+-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). 
+-** The two subsequent arguments should be the name of the OS function that
+-** failed and the associated file-system path, if any.
+-*/
+-#define winLogError(a,b,c,d)   winLogErrorAtLine(a,b,c,d,__LINE__)
+-static int winLogErrorAtLine(
+-  int errcode,                    /* SQLite error code */
+-  DWORD lastErrno,                /* Win32 last error */
+-  const char *zFunc,              /* Name of OS function that failed */
+-  const char *zPath,              /* File path associated with error */
+-  int iLine                       /* Source line number where error occurred */
+-){
+-  char zMsg[500];                 /* Human readable error text */
+-  int i;                          /* Loop counter */
++#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
+ 
+-  zMsg[0] = 0;
+-  getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
+-  assert( errcode!=SQLITE_OK );
+-  if( zPath==0 ) zPath = "";
+-  for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
+-  zMsg[i] = 0;
+-  sqlite3_log(errcode,
+-      "os_win.c:%d: (%lu) %s(%s) - %s",
+-      iLine, lastErrno, zFunc, zPath, zMsg
+-  );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
++  { "GetTempPathW",            (SYSCALL)GetTempPathW,            0 },
++#else
++  { "GetTempPathW",            (SYSCALL)0,                       0 },
++#endif
+ 
+-  return errcode;
+-}
++#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
+ 
+-/*
+-** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
+-** will be retried following a locking error - probably caused by 
+-** antivirus software.  Also the initial delay before the first retry.
+-** The delay increases linearly with each retry.
+-*/
+-#ifndef SQLITE_WIN32_IOERR_RETRY
+-# define SQLITE_WIN32_IOERR_RETRY 10
++#if !SQLITE_OS_WINRT
++  { "GetTickCount",            (SYSCALL)GetTickCount,            0 },
++#else
++  { "GetTickCount",            (SYSCALL)0,                       0 },
+ #endif
+-#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
+-# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
++
++#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
++
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
++#else
++  { "GetVersionExA",           (SYSCALL)0,                       0 },
+ #endif
+-static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
+-static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+ 
+-/*
+-** If a ReadFile() or WriteFile() error occurs, invoke this routine
+-** to see if it should be retried.  Return TRUE to retry.  Return FALSE
+-** to give up with an error.
+-*/
+-static int retryIoerr(int *pnRetry, DWORD *pError){
+-  DWORD e = osGetLastError();
+-  if( *pnRetry>=win32IoerrRetry ){
+-    if( pError ){
+-      *pError = e;
+-    }
+-    return 0;
+-  }
+-  if( e==ERROR_ACCESS_DENIED ||
+-      e==ERROR_LOCK_VIOLATION ||
+-      e==ERROR_SHARING_VIOLATION ){
+-    sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
+-    ++*pnRetry;
+-    return 1;
+-  }
+-  if( pError ){
+-    *pError = e;
+-  }
+-  return 0;
+-}
++#define osGetVersionExA ((BOOL(WINAPI*)( \
++        LPOSVERSIONINFOA))aSyscall[34].pCurrent)
+ 
+-/*
+-** Log a I/O error retry episode.
+-*/
+-static void logIoerr(int nRetry){
+-  if( nRetry ){
+-    sqlite3_log(SQLITE_IOERR, 
+-      "delayed %dms for lock/sharing conflict",
+-      win32IoerrRetryDelay*nRetry*(nRetry+1)/2
+-    );
+-  }
+-}
++  { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },
+ 
+-#if SQLITE_OS_WINCE
+-/*************************************************************************
+-** This section contains code for WinCE only.
+-*/
+-#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
+-/*
+-** The MSVC CRT on Windows CE may not have a localtime() function.  So
+-** create a substitute.
+-*/
+-/* #include <time.h> */
+-struct tm *__cdecl localtime(const time_t *t)
+-{
+-  static struct tm y;
+-  FILETIME uTm, lTm;
+-  SYSTEMTIME pTm;
+-  sqlite3_int64 t64;
+-  t64 = *t;
+-  t64 = (t64 + 11644473600)*10000000;
+-  uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
+-  uTm.dwHighDateTime= (DWORD)(t64 >> 32);
+-  osFileTimeToLocalFileTime(&uTm,&lTm);
+-  osFileTimeToSystemTime(&lTm,&pTm);
+-  y.tm_year = pTm.wYear - 1900;
+-  y.tm_mon = pTm.wMonth - 1;
+-  y.tm_wday = pTm.wDayOfWeek;
+-  y.tm_mday = pTm.wDay;
+-  y.tm_hour = pTm.wHour;
+-  y.tm_min = pTm.wMinute;
+-  y.tm_sec = pTm.wSecond;
+-  return &y;
+-}
++#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
++        SIZE_T))aSyscall[35].pCurrent)
++
++#if !SQLITE_OS_WINRT
++  { "HeapCreate",              (SYSCALL)HeapCreate,              0 },
++#else
++  { "HeapCreate",              (SYSCALL)0,                       0 },
+ #endif
+ 
+-#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
++#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
++        SIZE_T))aSyscall[36].pCurrent)
+ 
+-/*
+-** Acquire a lock on the handle h
+-*/
+-static void winceMutexAcquire(HANDLE h){
+-   DWORD dwErr;
+-   do {
+-     dwErr = osWaitForSingleObject(h, INFINITE);
+-   } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
+-}
+-/*
+-** Release a lock acquired by winceMutexAcquire()
+-*/
+-#define winceMutexRelease(h) ReleaseMutex(h)
++#if !SQLITE_OS_WINRT
++  { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },
++#else
++  { "HeapDestroy",             (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Create the mutex and shared memory used for locking in the file
+-** descriptor pFile
+-*/
+-static int winceCreateLock(const char *zFilename, winFile *pFile){
+-  LPWSTR zTok;
+-  LPWSTR zName;
+-  DWORD lastErrno;
+-  BOOL bLogged = FALSE;
+-  BOOL bInit = TRUE;
++#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
+ 
+-  zName = utf8ToUnicode(zFilename);
+-  if( zName==0 ){
+-    /* out of memory */
+-    return SQLITE_IOERR_NOMEM;
+-  }
++  { "HeapFree",                (SYSCALL)HeapFree,                0 },
+ 
+-  /* Initialize the local lockdata */
+-  memset(&pFile->local, 0, sizeof(pFile->local));
++#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
+ 
+-  /* Replace the backslashes from the filename and lowercase it
+-  ** to derive a mutex name. */
+-  zTok = osCharLowerW(zName);
+-  for (;*zTok;zTok++){
+-    if (*zTok == '\\') *zTok = '_';
+-  }
++  { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },
+ 
+-  /* Create/open the named mutex */
+-  pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
+-  if (!pFile->hMutex){
+-    pFile->lastErrno = osGetLastError();
+-    winLogError(SQLITE_IOERR, pFile->lastErrno,
+-                "winceCreateLock1", zFilename);
+-    sqlite3_free(zName);
+-    return SQLITE_IOERR;
+-  }
++#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
++        SIZE_T))aSyscall[39].pCurrent)
+ 
+-  /* Acquire the mutex before continuing */
+-  winceMutexAcquire(pFile->hMutex);
+-  
+-  /* Since the names of named mutexes, semaphores, file mappings etc are 
+-  ** case-sensitive, take advantage of that by uppercasing the mutex name
+-  ** and using that as the shared filemapping name.
+-  */
+-  osCharUpperW(zName);
+-  pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
+-                                        PAGE_READWRITE, 0, sizeof(winceLock),
+-                                        zName);  
++  { "HeapSize",                (SYSCALL)HeapSize,                0 },
+ 
+-  /* Set a flag that indicates we're the first to create the memory so it 
+-  ** must be zero-initialized */
+-  lastErrno = osGetLastError();
+-  if (lastErrno == ERROR_ALREADY_EXISTS){
+-    bInit = FALSE;
+-  }
++#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
++        LPCVOID))aSyscall[40].pCurrent)
+ 
+-  sqlite3_free(zName);
++#if !SQLITE_OS_WINRT
++  { "HeapValidate",            (SYSCALL)HeapValidate,            0 },
++#else
++  { "HeapValidate",            (SYSCALL)0,                       0 },
++#endif
+ 
+-  /* If we succeeded in making the shared memory handle, map it. */
+-  if( pFile->hShared ){
+-    pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
+-             FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
+-    /* If mapping failed, close the shared memory handle and erase it */
+-    if( !pFile->shared ){
+-      pFile->lastErrno = osGetLastError();
+-      winLogError(SQLITE_IOERR, pFile->lastErrno,
+-                  "winceCreateLock2", zFilename);
+-      bLogged = TRUE;
+-      osCloseHandle(pFile->hShared);
+-      pFile->hShared = NULL;
+-    }
+-  }
++#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
++        LPCVOID))aSyscall[41].pCurrent)
+ 
+-  /* If shared memory could not be created, then close the mutex and fail */
+-  if( pFile->hShared==NULL ){
+-    if( !bLogged ){
+-      pFile->lastErrno = lastErrno;
+-      winLogError(SQLITE_IOERR, pFile->lastErrno,
+-                  "winceCreateLock3", zFilename);
+-      bLogged = TRUE;
+-    }
+-    winceMutexRelease(pFile->hMutex);
+-    osCloseHandle(pFile->hMutex);
+-    pFile->hMutex = NULL;
+-    return SQLITE_IOERR;
+-  }
+-  
+-  /* Initialize the shared memory if we're supposed to */
+-  if( bInit ){
+-    memset(pFile->shared, 0, sizeof(winceLock));
+-  }
++#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
++  { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
++#else
++  { "LoadLibraryA",            (SYSCALL)0,                       0 },
++#endif
+ 
+-  winceMutexRelease(pFile->hMutex);
+-  return SQLITE_OK;
+-}
++#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
+ 
+-/*
+-** Destroy the part of winFile that deals with wince locks
+-*/
+-static void winceDestroyLock(winFile *pFile){
+-  if (pFile->hMutex){
+-    /* Acquire the mutex */
+-    winceMutexAcquire(pFile->hMutex);
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
++        !defined(SQLITE_OMIT_LOAD_EXTENSION)
++  { "LoadLibraryW",            (SYSCALL)LoadLibraryW,            0 },
++#else
++  { "LoadLibraryW",            (SYSCALL)0,                       0 },
++#endif
+ 
+-    /* The following blocks should probably assert in debug mode, but they
+-       are to cleanup in case any locks remained open */
+-    if (pFile->local.nReaders){
+-      pFile->shared->nReaders --;
+-    }
+-    if (pFile->local.bReserved){
+-      pFile->shared->bReserved = FALSE;
+-    }
+-    if (pFile->local.bPending){
+-      pFile->shared->bPending = FALSE;
+-    }
+-    if (pFile->local.bExclusive){
+-      pFile->shared->bExclusive = FALSE;
+-    }
++#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
+ 
+-    /* De-reference and close our copy of the shared memory handle */
+-    osUnmapViewOfFile(pFile->shared);
+-    osCloseHandle(pFile->hShared);
++#if !SQLITE_OS_WINRT
++  { "LocalFree",               (SYSCALL)LocalFree,               0 },
++#else
++  { "LocalFree",               (SYSCALL)0,                       0 },
++#endif
+ 
+-    /* Done with the mutex */
+-    winceMutexRelease(pFile->hMutex);    
+-    osCloseHandle(pFile->hMutex);
+-    pFile->hMutex = NULL;
+-  }
+-}
++#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
+ 
+-/* 
+-** An implementation of the LockFile() API of Windows for CE
+-*/
+-static BOOL winceLockFile(
+-  LPHANDLE phFile,
+-  DWORD dwFileOffsetLow,
+-  DWORD dwFileOffsetHigh,
+-  DWORD nNumberOfBytesToLockLow,
+-  DWORD nNumberOfBytesToLockHigh
+-){
+-  winFile *pFile = HANDLE_TO_WINFILE(phFile);
+-  BOOL bReturn = FALSE;
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
++  { "LockFile",                (SYSCALL)LockFile,                0 },
++#else
++  { "LockFile",                (SYSCALL)0,                       0 },
++#endif
+ 
+-  UNUSED_PARAMETER(dwFileOffsetHigh);
+-  UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
++#ifndef osLockFile
++#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
++        DWORD))aSyscall[45].pCurrent)
++#endif
+ 
+-  if (!pFile->hMutex) return TRUE;
+-  winceMutexAcquire(pFile->hMutex);
++#if !SQLITE_OS_WINCE
++  { "LockFileEx",              (SYSCALL)LockFileEx,              0 },
++#else
++  { "LockFileEx",              (SYSCALL)0,                       0 },
++#endif
+ 
+-  /* Wanting an exclusive lock? */
+-  if (dwFileOffsetLow == (DWORD)SHARED_FIRST
+-       && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
+-    if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
+-       pFile->shared->bExclusive = TRUE;
+-       pFile->local.bExclusive = TRUE;
+-       bReturn = TRUE;
+-    }
+-  }
++#ifndef osLockFileEx
++#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
++        LPOVERLAPPED))aSyscall[46].pCurrent)
++#endif
+ 
+-  /* Want a read-only lock? */
+-  else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
+-           nNumberOfBytesToLockLow == 1){
+-    if (pFile->shared->bExclusive == 0){
+-      pFile->local.nReaders ++;
+-      if (pFile->local.nReaders == 1){
+-        pFile->shared->nReaders ++;
+-      }
+-      bReturn = TRUE;
+-    }
+-  }
++#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
++  { "MapViewOfFile",           (SYSCALL)MapViewOfFile,           0 },
++#else
++  { "MapViewOfFile",           (SYSCALL)0,                       0 },
++#endif
+ 
+-  /* Want a pending lock? */
+-  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+-           && nNumberOfBytesToLockLow == 1){
+-    /* If no pending lock has been acquired, then acquire it */
+-    if (pFile->shared->bPending == 0) {
+-      pFile->shared->bPending = TRUE;
+-      pFile->local.bPending = TRUE;
+-      bReturn = TRUE;
+-    }
+-  }
++#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
++        SIZE_T))aSyscall[47].pCurrent)
+ 
+-  /* Want a reserved lock? */
+-  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+-           && nNumberOfBytesToLockLow == 1){
+-    if (pFile->shared->bReserved == 0) {
+-      pFile->shared->bReserved = TRUE;
+-      pFile->local.bReserved = TRUE;
+-      bReturn = TRUE;
+-    }
+-  }
++  { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },
+ 
+-  winceMutexRelease(pFile->hMutex);
+-  return bReturn;
+-}
++#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
++        int))aSyscall[48].pCurrent)
+ 
+-/*
+-** An implementation of the UnlockFile API of Windows for CE
+-*/
+-static BOOL winceUnlockFile(
+-  LPHANDLE phFile,
+-  DWORD dwFileOffsetLow,
+-  DWORD dwFileOffsetHigh,
+-  DWORD nNumberOfBytesToUnlockLow,
+-  DWORD nNumberOfBytesToUnlockHigh
+-){
+-  winFile *pFile = HANDLE_TO_WINFILE(phFile);
+-  BOOL bReturn = FALSE;
++  { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
+ 
+-  UNUSED_PARAMETER(dwFileOffsetHigh);
+-  UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
++#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
++        LARGE_INTEGER*))aSyscall[49].pCurrent)
+ 
+-  if (!pFile->hMutex) return TRUE;
+-  winceMutexAcquire(pFile->hMutex);
++  { "ReadFile",                (SYSCALL)ReadFile,                0 },
+ 
+-  /* Releasing a reader lock or an exclusive lock */
+-  if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
+-    /* Did we have an exclusive lock? */
+-    if (pFile->local.bExclusive){
+-      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
+-      pFile->local.bExclusive = FALSE;
+-      pFile->shared->bExclusive = FALSE;
+-      bReturn = TRUE;
+-    }
++#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
++        LPOVERLAPPED))aSyscall[50].pCurrent)
+ 
+-    /* Did we just have a reader lock? */
+-    else if (pFile->local.nReaders){
+-      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
+-             || nNumberOfBytesToUnlockLow == 1);
+-      pFile->local.nReaders --;
+-      if (pFile->local.nReaders == 0)
+-      {
+-        pFile->shared->nReaders --;
+-      }
+-      bReturn = TRUE;
+-    }
+-  }
++  { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },
+ 
+-  /* Releasing a pending lock */
+-  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+-           && nNumberOfBytesToUnlockLow == 1){
+-    if (pFile->local.bPending){
+-      pFile->local.bPending = FALSE;
+-      pFile->shared->bPending = FALSE;
+-      bReturn = TRUE;
+-    }
+-  }
+-  /* Releasing a reserved lock */
+-  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+-           && nNumberOfBytesToUnlockLow == 1){
+-    if (pFile->local.bReserved) {
+-      pFile->local.bReserved = FALSE;
+-      pFile->shared->bReserved = FALSE;
+-      bReturn = TRUE;
+-    }
+-  }
++#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
+ 
+-  winceMutexRelease(pFile->hMutex);
+-  return bReturn;
+-}
+-/*
+-** End of the special code for wince
+-*****************************************************************************/
+-#endif /* SQLITE_OS_WINCE */
++#if !SQLITE_OS_WINRT
++  { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },
++#else
++  { "SetFilePointer",          (SYSCALL)0,                       0 },
++#endif
+ 
+-/*
+-** Lock a file region.
+-*/
+-static BOOL winLockFile(
+-  LPHANDLE phFile,
+-  DWORD flags,
+-  DWORD offsetLow,
+-  DWORD offsetHigh,
+-  DWORD numBytesLow,
+-  DWORD numBytesHigh
+-){
+-#if SQLITE_OS_WINCE
+-  /*
+-  ** NOTE: Windows CE is handled differently here due its lack of the Win32
+-  **       API LockFile.
+-  */
+-  return winceLockFile(phFile, offsetLow, offsetHigh,
+-                       numBytesLow, numBytesHigh);
++#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
++        DWORD))aSyscall[52].pCurrent)
++
++#if !SQLITE_OS_WINRT
++  { "Sleep",                   (SYSCALL)Sleep,                   0 },
++#else
++  { "Sleep",                   (SYSCALL)0,                       0 },
++#endif
++
++#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
++
++  { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },
++
++#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
++        LPFILETIME))aSyscall[54].pCurrent)
++
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
++  { "UnlockFile",              (SYSCALL)UnlockFile,              0 },
+ #else
+-  if( isNT() ){
+-    OVERLAPPED ovlp;
+-    memset(&ovlp, 0, sizeof(OVERLAPPED));
+-    ovlp.Offset = offsetLow;
+-    ovlp.OffsetHigh = offsetHigh;
+-    return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
+-  }else{
+-    return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
+-                      numBytesHigh);
+-  }
++  { "UnlockFile",              (SYSCALL)0,                       0 },
+ #endif
+-}
+ 
+-/*
+-** Unlock a file region.
+- */
+-static BOOL winUnlockFile(
+-  LPHANDLE phFile,
+-  DWORD offsetLow,
+-  DWORD offsetHigh,
+-  DWORD numBytesLow,
+-  DWORD numBytesHigh
+-){
+-#if SQLITE_OS_WINCE
+-  /*
+-  ** NOTE: Windows CE is handled differently here due its lack of the Win32
+-  **       API UnlockFile.
+-  */
+-  return winceUnlockFile(phFile, offsetLow, offsetHigh,
+-                         numBytesLow, numBytesHigh);
++#ifndef osUnlockFile
++#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
++        DWORD))aSyscall[55].pCurrent)
++#endif
++
++#if !SQLITE_OS_WINCE
++  { "UnlockFileEx",            (SYSCALL)UnlockFileEx,            0 },
+ #else
+-  if( isNT() ){
+-    OVERLAPPED ovlp;
+-    memset(&ovlp, 0, sizeof(OVERLAPPED));
+-    ovlp.Offset = offsetLow;
+-    ovlp.OffsetHigh = offsetHigh;
+-    return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
+-  }else{
+-    return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
+-                        numBytesHigh);
+-  }
++  { "UnlockFileEx",            (SYSCALL)0,                       0 },
+ #endif
+-}
+ 
+-/*****************************************************************************
+-** The next group of routines implement the I/O methods specified
+-** by the sqlite3_io_methods object.
+-******************************************************************************/
++#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
++        LPOVERLAPPED))aSyscall[56].pCurrent)
+ 
+-/*
+-** Some Microsoft compilers lack this definition.
+-*/
+-#ifndef INVALID_SET_FILE_POINTER
+-# define INVALID_SET_FILE_POINTER ((DWORD)-1)
++#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
++  { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },
++#else
++  { "UnmapViewOfFile",         (SYSCALL)0,                       0 },
+ #endif
+ 
+-/*
+-** Move the current position of the file handle passed as the first 
+-** argument to offset iOffset within the file. If successful, return 0. 
+-** Otherwise, set pFile->lastErrno and return non-zero.
+-*/
+-static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
+-#if !SQLITE_OS_WINRT
+-  LONG upperBits;                 /* Most sig. 32 bits of new offset */
+-  LONG lowerBits;                 /* Least sig. 32 bits of new offset */
+-  DWORD dwRet;                    /* Value returned by SetFilePointer() */
+-  DWORD lastErrno;                /* Value returned by GetLastError() */
++#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
+ 
+-  OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
++  { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },
+ 
+-  upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
+-  lowerBits = (LONG)(iOffset & 0xffffffff);
++#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
++        LPCSTR,LPBOOL))aSyscall[58].pCurrent)
+ 
+-  /* API oddity: If successful, SetFilePointer() returns a dword 
+-  ** containing the lower 32-bits of the new file-offset. Or, if it fails,
+-  ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
+-  ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
+-  ** whether an error has actually occurred, it is also necessary to call 
+-  ** GetLastError().
+-  */
+-  dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
++  { "WriteFile",               (SYSCALL)WriteFile,               0 },
+ 
+-  if( (dwRet==INVALID_SET_FILE_POINTER
+-      && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
+-    pFile->lastErrno = lastErrno;
+-    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
+-             "seekWinFile", pFile->zPath);
+-    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
+-    return 1;
+-  }
++#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
++        LPOVERLAPPED))aSyscall[59].pCurrent)
+ 
+-  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
+-  return 0;
++#if SQLITE_OS_WINRT
++  { "CreateEventExW",          (SYSCALL)CreateEventExW,          0 },
+ #else
+-  /*
+-  ** Same as above, except that this implementation works for WinRT.
+-  */
++  { "CreateEventExW",          (SYSCALL)0,                       0 },
++#endif
+ 
+-  LARGE_INTEGER x;                /* The new offset */
+-  BOOL bRet;                      /* Value returned by SetFilePointerEx() */
++#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
++        DWORD,DWORD))aSyscall[60].pCurrent)
+ 
+-  x.QuadPart = iOffset;
+-  bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
++#if !SQLITE_OS_WINRT
++  { "WaitForSingleObject",     (SYSCALL)WaitForSingleObject,     0 },
++#else
++  { "WaitForSingleObject",     (SYSCALL)0,                       0 },
++#endif
+ 
+-  if(!bRet){
+-    pFile->lastErrno = osGetLastError();
+-    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
+-             "seekWinFile", pFile->zPath);
+-    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
+-    return 1;
+-  }
++#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
++        DWORD))aSyscall[61].pCurrent)
+ 
+-  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
+-  return 0;
++#if SQLITE_OS_WINRT
++  { "WaitForSingleObjectEx",   (SYSCALL)WaitForSingleObjectEx,   0 },
++#else
++  { "WaitForSingleObjectEx",   (SYSCALL)0,                       0 },
+ #endif
+-}
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-/* Forward references to VFS methods */
+-static int winUnmapfile(winFile*);
++#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
++        BOOL))aSyscall[62].pCurrent)
++
++#if SQLITE_OS_WINRT
++  { "SetFilePointerEx",        (SYSCALL)SetFilePointerEx,        0 },
++#else
++  { "SetFilePointerEx",        (SYSCALL)0,                       0 },
+ #endif
+ 
+-/*
+-** Close a file.
+-**
+-** It is reported that an attempt to close a handle might sometimes
+-** fail.  This is a very unreasonable result, but Windows is notorious
+-** for being unreasonable so I do not doubt that it might happen.  If
+-** the close fails, we pause for 100 milliseconds and try again.  As
+-** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
+-** giving up and returning an error.
+-*/
+-#define MX_CLOSE_ATTEMPT 3
+-static int winClose(sqlite3_file *id){
+-  int rc, cnt = 0;
+-  winFile *pFile = (winFile*)id;
++#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
++        PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
+ 
+-  assert( id!=0 );
+-#ifndef SQLITE_OMIT_WAL
+-  assert( pFile->pShm==0 );
++#if SQLITE_OS_WINRT
++  { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
++#else
++  { "GetFileInformationByHandleEx", (SYSCALL)0,                  0 },
+ #endif
+-  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
+-  OSTRACE(("CLOSE file=%p\n", pFile->h));
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  rc = winUnmapfile(pFile);
+-  if( rc!=SQLITE_OK ) return rc;
+-#endif
++#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
++        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
+ 
+-  do{
+-    rc = osCloseHandle(pFile->h);
+-    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
+-  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
+-#if SQLITE_OS_WINCE
+-#define WINCE_DELETION_ATTEMPTS 3
+-  winceDestroyLock(pFile);
+-  if( pFile->zDeleteOnClose ){
+-    int cnt = 0;
+-    while(
+-           osDeleteFileW(pFile->zDeleteOnClose)==0
+-        && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff 
+-        && cnt++ < WINCE_DELETION_ATTEMPTS
+-    ){
+-       sqlite3_win32_sleep(100);  /* Wait a little before trying again */
+-    }
+-    sqlite3_free(pFile->zDeleteOnClose);
+-  }
++#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
++  { "MapViewOfFileFromApp",    (SYSCALL)MapViewOfFileFromApp,    0 },
++#else
++  { "MapViewOfFileFromApp",    (SYSCALL)0,                       0 },
+ #endif
+-  if( rc ){
+-    pFile->h = NULL;
+-  }
+-  OpenCounter(-1);
+-  OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
+-  return rc ? SQLITE_OK
+-            : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
+-                          "winClose", pFile->zPath);
+-}
+ 
+-/*
+-** Read data from a file into a buffer.  Return SQLITE_OK if all
+-** bytes were read successfully and SQLITE_IOERR if anything goes
+-** wrong.
+-*/
+-static int winRead(
+-  sqlite3_file *id,          /* File to read from */
+-  void *pBuf,                /* Write content into this buffer */
+-  int amt,                   /* Number of bytes to read */
+-  sqlite3_int64 offset       /* Begin reading at this offset */
+-){
+-#if !SQLITE_OS_WINCE
+-  OVERLAPPED overlapped;          /* The offset for ReadFile. */
++#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
++        SIZE_T))aSyscall[65].pCurrent)
++
++#if SQLITE_OS_WINRT
++  { "CreateFile2",             (SYSCALL)CreateFile2,             0 },
++#else
++  { "CreateFile2",             (SYSCALL)0,                       0 },
+ #endif
+-  winFile *pFile = (winFile*)id;  /* file handle */
+-  DWORD nRead;                    /* Number of bytes actually read from file */
+-  int nRetry = 0;                 /* Number of retrys */
+ 
+-  assert( id!=0 );
+-  assert( amt>0 );
+-  assert( offset>=0 );
+-  SimulateIOError(return SQLITE_IOERR_READ);
+-  OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
+-           pFile->h, pBuf, amt, offset, pFile->locktype));
++#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
++        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  /* Deal with as much of this read request as possible by transfering
+-  ** data from the memory mapping using memcpy().  */
+-  if( offset<pFile->mmapSize ){
+-    if( offset+amt <= pFile->mmapSize ){
+-      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
+-      OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }else{
+-      int nCopy = (int)(pFile->mmapSize - offset);
+-      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
+-      pBuf = &((u8 *)pBuf)[nCopy];
+-      amt -= nCopy;
+-      offset += nCopy;
+-    }
+-  }
++#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
++  { "LoadPackagedLibrary",     (SYSCALL)LoadPackagedLibrary,     0 },
++#else
++  { "LoadPackagedLibrary",     (SYSCALL)0,                       0 },
+ #endif
+ 
+-#if SQLITE_OS_WINCE
+-  if( seekWinFile(pFile, offset) ){
+-    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
+-    return SQLITE_FULL;
+-  }
+-  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
++#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
++        DWORD))aSyscall[67].pCurrent)
++
++#if SQLITE_OS_WINRT
++  { "GetTickCount64",          (SYSCALL)GetTickCount64,          0 },
+ #else
+-  memset(&overlapped, 0, sizeof(OVERLAPPED));
+-  overlapped.Offset = (LONG)(offset & 0xffffffff);
+-  overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+-  while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
+-         osGetLastError()!=ERROR_HANDLE_EOF ){
++  { "GetTickCount64",          (SYSCALL)0,                       0 },
+ #endif
+-    DWORD lastErrno;
+-    if( retryIoerr(&nRetry, &lastErrno) ) continue;
+-    pFile->lastErrno = lastErrno;
+-    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
+-    return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
+-             "winRead", pFile->zPath);
+-  }
+-  logIoerr(nRetry);
+-  if( nRead<(DWORD)amt ){
+-    /* Unread parts of the buffer must be zero-filled */
+-    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
+-    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
+-    return SQLITE_IOERR_SHORT_READ;
+-  }
+-
+-  OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
+-  return SQLITE_OK;
+-}
+ 
+-/*
+-** Write data from a buffer into a file.  Return SQLITE_OK on success
+-** or some other error code on failure.
+-*/
+-static int winWrite(
+-  sqlite3_file *id,               /* File to write into */
+-  const void *pBuf,               /* The bytes to be written */
+-  int amt,                        /* Number of bytes to write */
+-  sqlite3_int64 offset            /* Offset into the file to begin writing at */
+-){
+-  int rc = 0;                     /* True if error has occurred, else false */
+-  winFile *pFile = (winFile*)id;  /* File handle */
+-  int nRetry = 0;                 /* Number of retries */
++#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
+ 
+-  assert( amt>0 );
+-  assert( pFile );
+-  SimulateIOError(return SQLITE_IOERR_WRITE);
+-  SimulateDiskfullError(return SQLITE_FULL);
++#if SQLITE_OS_WINRT
++  { "GetNativeSystemInfo",     (SYSCALL)GetNativeSystemInfo,     0 },
++#else
++  { "GetNativeSystemInfo",     (SYSCALL)0,                       0 },
++#endif
+ 
+-  OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
+-           pFile->h, pBuf, amt, offset, pFile->locktype));
++#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
++        LPSYSTEM_INFO))aSyscall[69].pCurrent)
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  /* Deal with as much of this write request as possible by transfering
+-  ** data from the memory mapping using memcpy().  */
+-  if( offset<pFile->mmapSize ){
+-    if( offset+amt <= pFile->mmapSize ){
+-      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
+-      OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }else{
+-      int nCopy = (int)(pFile->mmapSize - offset);
+-      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
+-      pBuf = &((u8 *)pBuf)[nCopy];
+-      amt -= nCopy;
+-      offset += nCopy;
+-    }
+-  }
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  { "OutputDebugStringA",      (SYSCALL)OutputDebugStringA,      0 },
++#else
++  { "OutputDebugStringA",      (SYSCALL)0,                       0 },
+ #endif
+ 
+-#if SQLITE_OS_WINCE
+-  rc = seekWinFile(pFile, offset);
+-  if( rc==0 ){
++#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
++
++#if defined(SQLITE_WIN32_HAS_WIDE)
++  { "OutputDebugStringW",      (SYSCALL)OutputDebugStringW,      0 },
+ #else
+-  {
+-#endif
+-#if !SQLITE_OS_WINCE
+-    OVERLAPPED overlapped;        /* The offset for WriteFile. */
++  { "OutputDebugStringW",      (SYSCALL)0,                       0 },
+ #endif
+-    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
+-    int nRem = amt;               /* Number of bytes yet to be written */
+-    DWORD nWrite;                 /* Bytes written by each WriteFile() call */
+-    DWORD lastErrno = NO_ERROR;   /* Value returned by GetLastError() */
+ 
+-#if !SQLITE_OS_WINCE
+-    memset(&overlapped, 0, sizeof(OVERLAPPED));
+-    overlapped.Offset = (LONG)(offset & 0xffffffff);
+-    overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+-#endif
++#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
+ 
+-    while( nRem>0 ){
+-#if SQLITE_OS_WINCE
+-      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
++  { "GetProcessHeap",          (SYSCALL)GetProcessHeap,          0 },
++
++#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
++
++#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
++  { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
+ #else
+-      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
++  { "CreateFileMappingFromApp", (SYSCALL)0,                      0 },
+ #endif
+-        if( retryIoerr(&nRetry, &lastErrno) ) continue;
+-        break;
++
++#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
++        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
++
++}; /* End of the overrideable system calls */
++
++/*
++** This is the xSetSystemCall() method of sqlite3_vfs for all of the
++** "win32" VFSes.  Return SQLITE_OK opon successfully updating the
++** system call pointer, or SQLITE_NOTFOUND if there is no configurable
++** system call named zName.
++*/
++static int winSetSystemCall(
++  sqlite3_vfs *pNotUsed,        /* The VFS pointer.  Not used */
++  const char *zName,            /* Name of system call to override */
++  sqlite3_syscall_ptr pNewFunc  /* Pointer to new system call value */
++){
++  unsigned int i;
++  int rc = SQLITE_NOTFOUND;
++
++  UNUSED_PARAMETER(pNotUsed);
++  if( zName==0 ){
++    /* If no zName is given, restore all system calls to their default
++    ** settings and return NULL
++    */
++    rc = SQLITE_OK;
++    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
++      if( aSyscall[i].pDefault ){
++        aSyscall[i].pCurrent = aSyscall[i].pDefault;
+       }
+-      assert( nWrite==0 || nWrite<=(DWORD)nRem );
+-      if( nWrite==0 || nWrite>(DWORD)nRem ){
+-        lastErrno = osGetLastError();
++    }
++  }else{
++    /* If zName is specified, operate on only the one system call
++    ** specified.
++    */
++    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
++      if( strcmp(zName, aSyscall[i].zName)==0 ){
++        if( aSyscall[i].pDefault==0 ){
++          aSyscall[i].pDefault = aSyscall[i].pCurrent;
++        }
++        rc = SQLITE_OK;
++        if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
++        aSyscall[i].pCurrent = pNewFunc;
+         break;
+       }
+-#if !SQLITE_OS_WINCE
+-      offset += nWrite;
+-      overlapped.Offset = (LONG)(offset & 0xffffffff);
+-      overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+-#endif
+-      aRem += nWrite;
+-      nRem -= nWrite;
+-    }
+-    if( nRem>0 ){
+-      pFile->lastErrno = lastErrno;
+-      rc = 1;
+-    }
+-  }
+-
+-  if( rc ){
+-    if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
+-       || ( pFile->lastErrno==ERROR_DISK_FULL )){
+-      OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
+-      return SQLITE_FULL;
+     }
+-    OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
+-    return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
+-             "winWrite", pFile->zPath);
+-  }else{
+-    logIoerr(nRetry);
+   }
+-  OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
+-  return SQLITE_OK;
++  return rc;
+ }
+ 
+ /*
+-** Truncate an open file to a specified size
++** Return the value of a system call.  Return NULL if zName is not a
++** recognized system call name.  NULL is also returned if the system call
++** is currently undefined.
+ */
+-static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
+-  winFile *pFile = (winFile*)id;  /* File handle object */
+-  int rc = SQLITE_OK;             /* Return code for this function */
+-  DWORD lastErrno;
+-
+-  assert( pFile );
+-  SimulateIOError(return SQLITE_IOERR_TRUNCATE);
+-  OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
+-           pFile->h, nByte, pFile->locktype));
+-
+-  /* If the user has configured a chunk-size for this file, truncate the
+-  ** file so that it consists of an integer number of chunks (i.e. the
+-  ** actual file size after the operation may be larger than the requested
+-  ** size).
+-  */
+-  if( pFile->szChunk>0 ){
+-    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
+-  }
+-
+-  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
+-  if( seekWinFile(pFile, nByte) ){
+-    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
+-                     "winTruncate1", pFile->zPath);
+-  }else if( 0==osSetEndOfFile(pFile->h) &&
+-            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
+-    pFile->lastErrno = lastErrno;
+-    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
+-                     "winTruncate2", pFile->zPath);
+-  }
++static sqlite3_syscall_ptr winGetSystemCall(
++  sqlite3_vfs *pNotUsed,
++  const char *zName
++){
++  unsigned int i;
+ 
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  /* If the file was truncated to a size smaller than the currently
+-  ** mapped region, reduce the effective mapping size as well. SQLite will
+-  ** use read() and write() to access data beyond this point from now on.
+-  */
+-  if( pFile->pMapRegion && nByte<pFile->mmapSize ){
+-    pFile->mmapSize = nByte;
++  UNUSED_PARAMETER(pNotUsed);
++  for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
++    if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
+   }
+-#endif
+-
+-  OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+-  return rc;
++  return 0;
+ }
+ 
+-#ifdef SQLITE_TEST
+-/*
+-** Count the number of fullsyncs and normal syncs.  This is used to test
+-** that syncs and fullsyncs are occuring at the right times.
+-*/
+-SQLITE_API int sqlite3_sync_count = 0;
+-SQLITE_API int sqlite3_fullsync_count = 0;
+-#endif
+-
+ /*
+-** Make sure all writes to a particular file are committed to disk.
++** Return the name of the first system call after zName.  If zName==NULL
++** then return the name of the first system call.  Return NULL if zName
++** is the last system call or if zName is not the name of a valid
++** system call.
+ */
+-static int winSync(sqlite3_file *id, int flags){
+-#ifndef SQLITE_NO_SYNC
+-  /*
+-  ** Used only when SQLITE_NO_SYNC is not defined.
+-   */
+-  BOOL rc;
+-#endif
+-#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
+-    (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
+-  /*
+-  ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
+-  ** OSTRACE() macros.
+-   */
+-  winFile *pFile = (winFile*)id;
+-#else
+-  UNUSED_PARAMETER(id);
+-#endif
+-
+-  assert( pFile );
+-  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
+-  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
+-      || (flags&0x0F)==SQLITE_SYNC_FULL
+-  );
++static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
++  int i = -1;
+ 
+-  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
+-  ** line is to test that doing so does not cause any problems.
+-  */
+-  SimulateDiskfullError( return SQLITE_FULL );
++  UNUSED_PARAMETER(p);
++  if( zName ){
++    for(i=0; i<ArraySize(aSyscall)-1; i++){
++      if( strcmp(zName, aSyscall[i].zName)==0 ) break;
++    }
++  }
++  for(i++; i<ArraySize(aSyscall); i++){
++    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
++  }
++  return 0;
++}
+ 
+-  OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
+-           pFile->h, flags, pFile->locktype));
++/*
++** This function outputs the specified (ANSI) string to the Win32 debugger
++** (if available).
++*/
+ 
+-#ifndef SQLITE_TEST
+-  UNUSED_PARAMETER(flags);
+-#else
+-  if( (flags&0x0F)==SQLITE_SYNC_FULL ){
+-    sqlite3_fullsync_count++;
++SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
++  char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
++  int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
++  if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
++  assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
++#if defined(SQLITE_WIN32_HAS_ANSI)
++  if( nMin>0 ){
++    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
++    memcpy(zDbgBuf, zBuf, nMin);
++    osOutputDebugStringA(zDbgBuf);
++  }else{
++    osOutputDebugStringA(zBuf);
+   }
+-  sqlite3_sync_count++;
+-#endif
+-
+-  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
+-  ** no-op
+-  */
+-#ifdef SQLITE_NO_SYNC
+-  return SQLITE_OK;
++#elif defined(SQLITE_WIN32_HAS_WIDE)
++  memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
++  if ( osMultiByteToWideChar(
++          osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
++          nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
++    return;
++  }
++  osOutputDebugStringW((LPCWSTR)zDbgBuf);
+ #else
+-  rc = osFlushFileBuffers(pFile->h);
+-  SimulateIOError( rc=FALSE );
+-  if( rc ){
+-    OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
+-    return SQLITE_OK;
++  if( nMin>0 ){
++    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
++    memcpy(zDbgBuf, zBuf, nMin);
++    fprintf(stderr, "%s", zDbgBuf);
+   }else{
+-    pFile->lastErrno = osGetLastError();
+-    OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
+-    return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
+-             "winSync", pFile->zPath);
++    fprintf(stderr, "%s", zBuf);
+   }
+ #endif
+ }
+ 
+ /*
+-** Determine the current size of a file in bytes
++** The following routine suspends the current thread for at least ms
++** milliseconds.  This is equivalent to the Win32 Sleep() interface.
+ */
+-static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
+-  winFile *pFile = (winFile*)id;
+-  int rc = SQLITE_OK;
+-
+-  assert( id!=0 );
+-  assert( pSize!=0 );
+-  SimulateIOError(return SQLITE_IOERR_FSTAT);
+-  OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
++#if SQLITE_OS_WINRT
++static HANDLE sleepObj = NULL;
++#endif
+ 
++SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
+ #if SQLITE_OS_WINRT
+-  {
+-    FILE_STANDARD_INFO info;
+-    if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
+-                                     &info, sizeof(info)) ){
+-      *pSize = info.EndOfFile.QuadPart;
+-    }else{
+-      pFile->lastErrno = osGetLastError();
+-      rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
+-                       "winFileSize", pFile->zPath);
+-    }
++  if ( sleepObj==NULL ){
++    sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
++                                SYNCHRONIZE);
+   }
++  assert( sleepObj!=NULL );
++  osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
+ #else
+-  {
+-    DWORD upperBits;
+-    DWORD lowerBits;
+-    DWORD lastErrno;
+-
+-    lowerBits = osGetFileSize(pFile->h, &upperBits);
+-    *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
+-    if(   (lowerBits == INVALID_FILE_SIZE)
+-       && ((lastErrno = osGetLastError())!=NO_ERROR) ){
+-      pFile->lastErrno = lastErrno;
+-      rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
+-             "winFileSize", pFile->zPath);
+-    }
+-  }
++  osSleep(milliseconds);
+ #endif
+-  OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
+-           pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
+-  return rc;
+ }
+ 
+ /*
+-** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
++** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
++** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
++**
++** Here is an interesting observation:  Win95, Win98, and WinME lack
++** the LockFileEx() API.  But we can still statically link against that
++** API as long as we don't call it when running Win95/98/ME.  A call to
++** this routine is used to determine if the host is Win95/98/ME or
++** WinNT/2K/XP so that we will know whether or not we can safely call
++** the LockFileEx() API.
+ */
+-#ifndef LOCKFILE_FAIL_IMMEDIATELY
+-# define LOCKFILE_FAIL_IMMEDIATELY 1
+-#endif
+-
+-#ifndef LOCKFILE_EXCLUSIVE_LOCK
+-# define LOCKFILE_EXCLUSIVE_LOCK 2
++#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
++# define isNT()  (1)
++#elif !defined(SQLITE_WIN32_HAS_WIDE)
++# define isNT()  (0)
++#else
++  static int isNT(void){
++    if( sqlite3_os_type==0 ){
++      OSVERSIONINFOA sInfo;
++      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
++      osGetVersionExA(&sInfo);
++      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
++    }
++    return sqlite3_os_type==2;
++  }
+ #endif
+ 
++#ifdef SQLITE_WIN32_MALLOC
+ /*
+-** Historically, SQLite has used both the LockFile and LockFileEx functions.
+-** When the LockFile function was used, it was always expected to fail
+-** immediately if the lock could not be obtained.  Also, it always expected to
+-** obtain an exclusive lock.  These flags are used with the LockFileEx function
+-** and reflect those expectations; therefore, they should not be changed.
++** Allocate nBytes of memory.
+ */
+-#ifndef SQLITE_LOCKFILE_FLAGS
+-# define SQLITE_LOCKFILE_FLAGS   (LOCKFILE_FAIL_IMMEDIATELY | \
+-                                  LOCKFILE_EXCLUSIVE_LOCK)
++static void *winMemMalloc(int nBytes){
++  HANDLE hHeap;
++  void *p;
++
++  winMemAssertMagic();
++  hHeap = winMemGetHeap();
++  assert( hHeap!=0 );
++  assert( hHeap!=INVALID_HANDLE_VALUE );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
++  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+ #endif
++  assert( nBytes>=0 );
++  p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
++  if( !p ){
++    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
++                nBytes, osGetLastError(), (void*)hHeap);
++  }
++  return p;
++}
+ 
+ /*
+-** Currently, SQLite never calls the LockFileEx function without wanting the
+-** call to fail immediately if the lock cannot be obtained.
++** Free memory.
+ */
+-#ifndef SQLITE_LOCKFILEEX_FLAGS
+-# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
++static void winMemFree(void *pPrior){
++  HANDLE hHeap;
++
++  winMemAssertMagic();
++  hHeap = winMemGetHeap();
++  assert( hHeap!=0 );
++  assert( hHeap!=INVALID_HANDLE_VALUE );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
++  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+ #endif
++  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
++  if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
++    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
++                pPrior, osGetLastError(), (void*)hHeap);
++  }
++}
+ 
+ /*
+-** Acquire a reader lock.
+-** Different API routines are called depending on whether or not this
+-** is Win9x or WinNT.
++** Change the size of an existing memory allocation
+ */
+-static int getReadLock(winFile *pFile){
+-  int res;
+-  OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
+-  if( isNT() ){
+-#if SQLITE_OS_WINCE
+-    /*
+-    ** NOTE: Windows CE is handled differently here due its lack of the Win32
+-    **       API LockFileEx.
+-    */
+-    res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
+-#else
+-    res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
+-                      SHARED_SIZE, 0);
++static void *winMemRealloc(void *pPrior, int nBytes){
++  HANDLE hHeap;
++  void *p;
++
++  winMemAssertMagic();
++  hHeap = winMemGetHeap();
++  assert( hHeap!=0 );
++  assert( hHeap!=INVALID_HANDLE_VALUE );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
++  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+ #endif
++  assert( nBytes>=0 );
++  if( !pPrior ){
++    p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
++  }else{
++    p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
+   }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    int lk;
+-    sqlite3_randomness(sizeof(lk), &lk);
+-    pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
+-    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+-                      SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
+-  }
+-#endif
+-  if( res == 0 ){
+-    pFile->lastErrno = osGetLastError();
+-    /* No need to log a failure to lock */
++  if( !p ){
++    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
++                pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
++                (void*)hHeap);
+   }
+-  OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
+-  return res;
++  return p;
+ }
+ 
+ /*
+-** Undo a readlock
++** Return the size of an outstanding allocation, in bytes.
+ */
+-static int unlockReadLock(winFile *pFile){
+-  int res;
+-  DWORD lastErrno;
+-  OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
+-  if( isNT() ){
+-    res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
+-  }
++static int winMemSize(void *p){
++  HANDLE hHeap;
++  SIZE_T n;
++
++  winMemAssertMagic();
++  hHeap = winMemGetHeap();
++  assert( hHeap!=0 );
++  assert( hHeap!=INVALID_HANDLE_VALUE );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
++  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+ #endif
+-  if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
+-    pFile->lastErrno = lastErrno;
+-    winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
+-             "unlockReadLock", pFile->zPath);
++  if( !p ) return 0;
++  n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
++  if( n==(SIZE_T)-1 ){
++    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
++                p, osGetLastError(), (void*)hHeap);
++    return 0;
+   }
+-  OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
+-  return res;
++  return (int)n;
+ }
+ 
+ /*
+-** Lock the file with the lock specified by parameter locktype - one
+-** of the following:
+-**
+-**     (1) SHARED_LOCK
+-**     (2) RESERVED_LOCK
+-**     (3) PENDING_LOCK
+-**     (4) EXCLUSIVE_LOCK
+-**
+-** Sometimes when requesting one lock state, additional lock states
+-** are inserted in between.  The locking might fail on one of the later
+-** transitions leaving the lock state different from what it started but
+-** still short of its goal.  The following chart shows the allowed
+-** transitions and the inserted intermediate states:
+-**
+-**    UNLOCKED -> SHARED
+-**    SHARED -> RESERVED
+-**    SHARED -> (PENDING) -> EXCLUSIVE
+-**    RESERVED -> (PENDING) -> EXCLUSIVE
+-**    PENDING -> EXCLUSIVE
+-**
+-** This routine will only increase a lock.  The winUnlock() routine
+-** erases all locks at once and returns us immediately to locking level 0.
+-** It is not possible to lower the locking level one step at a time.  You
+-** must go straight to locking level 0.
++** Round up a request size to the next valid allocation size.
+ */
+-static int winLock(sqlite3_file *id, int locktype){
+-  int rc = SQLITE_OK;    /* Return code from subroutines */
+-  int res = 1;           /* Result of a Windows lock call */
+-  int newLocktype;       /* Set pFile->locktype to this value before exiting */
+-  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
+-  winFile *pFile = (winFile*)id;
+-  DWORD lastErrno = NO_ERROR;
+-
+-  assert( id!=0 );
+-  OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
+-           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
++static int winMemRoundup(int n){
++  return n;
++}
+ 
+-  /* If there is already a lock of this type or more restrictive on the
+-  ** OsFile, do nothing. Don't use the end_lock: exit path, as
+-  ** sqlite3OsEnterMutex() hasn't been called yet.
+-  */
+-  if( pFile->locktype>=locktype ){
+-    OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
+-    return SQLITE_OK;
+-  }
++/*
++** Initialize this module.
++*/
++static int winMemInit(void *pAppData){
++  winMemData *pWinMemData = (winMemData *)pAppData;
+ 
+-  /* Make sure the locking sequence is correct
+-  */
+-  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+-  assert( locktype!=PENDING_LOCK );
+-  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
++  if( !pWinMemData ) return SQLITE_ERROR;
++  assert( pWinMemData->magic==WINMEM_MAGIC );
+ 
+-  /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
+-  ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
+-  ** the PENDING_LOCK byte is temporary.
+-  */
+-  newLocktype = pFile->locktype;
+-  if(   (pFile->locktype==NO_LOCK)
+-     || (   (locktype==EXCLUSIVE_LOCK)
+-         && (pFile->locktype==RESERVED_LOCK))
+-  ){
+-    int cnt = 3;
+-    while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+-                                         PENDING_BYTE, 0, 1, 0))==0 ){
+-      /* Try 3 times to get the pending lock.  This is needed to work
+-      ** around problems caused by indexing and/or anti-virus software on
+-      ** Windows systems.
+-      ** If you are using this code as a model for alternative VFSes, do not
+-      ** copy this retry logic.  It is a hack intended for Windows only.
+-      */
+-      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
+-               pFile->h, cnt, sqlite3ErrName(res)));
+-      if( cnt ) sqlite3_win32_sleep(1);
+-    }
+-    gotPendingLock = res;
+-    if( !res ){
+-      lastErrno = osGetLastError();
++#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
++  if( !pWinMemData->hHeap ){
++    pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
++                                      SQLITE_WIN32_HEAP_INIT_SIZE,
++                                      SQLITE_WIN32_HEAP_MAX_SIZE);
++    if( !pWinMemData->hHeap ){
++      sqlite3_log(SQLITE_NOMEM,
++          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
++          osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
++          SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
++      return SQLITE_NOMEM;
+     }
++    pWinMemData->bOwned = TRUE;
++    assert( pWinMemData->bOwned );
+   }
+-
+-  /* Acquire a shared lock
+-  */
+-  if( locktype==SHARED_LOCK && res ){
+-    assert( pFile->locktype==NO_LOCK );
+-    res = getReadLock(pFile);
+-    if( res ){
+-      newLocktype = SHARED_LOCK;
+-    }else{
+-      lastErrno = osGetLastError();
+-    }
++#else
++  pWinMemData->hHeap = osGetProcessHeap();
++  if( !pWinMemData->hHeap ){
++    sqlite3_log(SQLITE_NOMEM,
++        "failed to GetProcessHeap (%d)", osGetLastError());
++    return SQLITE_NOMEM;
+   }
++  pWinMemData->bOwned = FALSE;
++  assert( !pWinMemData->bOwned );
++#endif
++  assert( pWinMemData->hHeap!=0 );
++  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
++  assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
++#endif
++  return SQLITE_OK;
++}
+ 
+-  /* Acquire a RESERVED lock
+-  */
+-  if( locktype==RESERVED_LOCK && res ){
+-    assert( pFile->locktype==SHARED_LOCK );
+-    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
+-    if( res ){
+-      newLocktype = RESERVED_LOCK;
+-    }else{
+-      lastErrno = osGetLastError();
++/*
++** Deinitialize this module.
++*/
++static void winMemShutdown(void *pAppData){
++  winMemData *pWinMemData = (winMemData *)pAppData;
++
++  if( !pWinMemData ) return;
++  if( pWinMemData->hHeap ){
++    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
++#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
++    assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
++#endif
++    if( pWinMemData->bOwned ){
++      if( !osHeapDestroy(pWinMemData->hHeap) ){
++        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
++                    osGetLastError(), (void*)pWinMemData->hHeap);
++      }
++      pWinMemData->bOwned = FALSE;
+     }
++    pWinMemData->hHeap = NULL;
+   }
++}
+ 
+-  /* Acquire a PENDING lock
+-  */
+-  if( locktype==EXCLUSIVE_LOCK && res ){
+-    newLocktype = PENDING_LOCK;
+-    gotPendingLock = 0;
+-  }
++/*
++** Populate the low-level memory allocation function pointers in
++** sqlite3GlobalConfig.m with pointers to the routines in this file. The
++** arguments specify the block of memory to manage.
++**
++** This routine is only called by sqlite3_config(), and therefore
++** is not required to be threadsafe (it is not).
++*/
++SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
++  static const sqlite3_mem_methods winMemMethods = {
++    winMemMalloc,
++    winMemFree,
++    winMemRealloc,
++    winMemSize,
++    winMemRoundup,
++    winMemInit,
++    winMemShutdown,
++    &win_mem_data
++  };
++  return &winMemMethods;
++}
+ 
+-  /* Acquire an EXCLUSIVE lock
+-  */
+-  if( locktype==EXCLUSIVE_LOCK && res ){
+-    assert( pFile->locktype>=SHARED_LOCK );
+-    res = unlockReadLock(pFile);
+-    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
+-                      SHARED_SIZE, 0);
+-    if( res ){
+-      newLocktype = EXCLUSIVE_LOCK;
+-    }else{
+-      lastErrno = osGetLastError();
+-      getReadLock(pFile);
+-    }
+-  }
++SQLITE_PRIVATE void sqlite3MemSetDefault(void){
++  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
++}
++#endif /* SQLITE_WIN32_MALLOC */
++
++/*
++** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). 
++**
++** Space to hold the returned string is obtained from malloc.
++*/
++static LPWSTR utf8ToUnicode(const char *zFilename){
++  int nChar;
++  LPWSTR zWideFilename;
+ 
+-  /* If we are holding a PENDING lock that ought to be released, then
+-  ** release it now.
+-  */
+-  if( gotPendingLock && locktype==SHARED_LOCK ){
+-    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
++  nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
++  if( nChar==0 ){
++    return 0;
+   }
+-
+-  /* Update the state of the lock has held in the file descriptor then
+-  ** return the appropriate result code.
+-  */
+-  if( res ){
+-    rc = SQLITE_OK;
+-  }else{
+-    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
+-             pFile->h, locktype, newLocktype));
+-    pFile->lastErrno = lastErrno;
+-    rc = SQLITE_BUSY;
++  zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
++  if( zWideFilename==0 ){
++    return 0;
+   }
+-  pFile->locktype = (u8)newLocktype;
+-  OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
+-           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
+-  return rc;
++  nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
++                                nChar);
++  if( nChar==0 ){
++    sqlite3_free(zWideFilename);
++    zWideFilename = 0;
++  }
++  return zWideFilename;
+ }
+ 
+ /*
+-** This routine checks if there is a RESERVED lock held on the specified
+-** file by this or any other process. If such a lock is held, return
+-** non-zero, otherwise zero.
++** Convert Microsoft Unicode to UTF-8.  Space to hold the returned string is
++** obtained from sqlite3_malloc().
+ */
+-static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
+-  int rc;
+-  winFile *pFile = (winFile*)id;
+-
+-  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+-  OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
++static char *unicodeToUtf8(LPCWSTR zWideFilename){
++  int nByte;
++  char *zFilename;
+ 
+-  assert( id!=0 );
+-  if( pFile->locktype>=RESERVED_LOCK ){
+-    rc = 1;
+-    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
+-  }else{
+-    rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
+-    if( rc ){
+-      winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
+-    }
+-    rc = !rc;
+-    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
++  nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
++  if( nByte == 0 ){
++    return 0;
+   }
+-  *pResOut = rc;
+-  OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
+-           pFile->h, pResOut, *pResOut));
+-  return SQLITE_OK;
++  zFilename = sqlite3MallocZero( nByte );
++  if( zFilename==0 ){
++    return 0;
++  }
++  nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
++                                0, 0);
++  if( nByte == 0 ){
++    sqlite3_free(zFilename);
++    zFilename = 0;
++  }
++  return zFilename;
+ }
+ 
+ /*
+-** Lower the locking level on file descriptor id to locktype.  locktype
+-** must be either NO_LOCK or SHARED_LOCK.
+-**
+-** If the locking level of the file descriptor is already at or below
+-** the requested locking level, this routine is a no-op.
+-**
+-** It is not possible for this routine to fail if the second argument
+-** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
+-** might return SQLITE_IOERR;
++** Convert an ANSI string to Microsoft Unicode, based on the
++** current codepage settings for file apis.
++** 
++** Space to hold the returned string is obtained
++** from sqlite3_malloc.
+ */
+-static int winUnlock(sqlite3_file *id, int locktype){
+-  int type;
+-  winFile *pFile = (winFile*)id;
+-  int rc = SQLITE_OK;
+-  assert( pFile!=0 );
+-  assert( locktype<=SHARED_LOCK );
+-  OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
+-           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
+-  type = pFile->locktype;
+-  if( type>=EXCLUSIVE_LOCK ){
+-    winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+-    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
+-      /* This should never happen.  We should always be able to
+-      ** reacquire the read lock */
+-      rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
+-               "winUnlock", pFile->zPath);
+-    }
+-  }
+-  if( type>=RESERVED_LOCK ){
+-    winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
++static LPWSTR mbcsToUnicode(const char *zFilename){
++  int nByte;
++  LPWSTR zMbcsFilename;
++  int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
++
++  nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
++                                0)*sizeof(WCHAR);
++  if( nByte==0 ){
++    return 0;
+   }
+-  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
+-    unlockReadLock(pFile);
++  zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
++  if( zMbcsFilename==0 ){
++    return 0;
+   }
+-  if( type>=PENDING_LOCK ){
+-    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
++  nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
++                                nByte);
++  if( nByte==0 ){
++    sqlite3_free(zMbcsFilename);
++    zMbcsFilename = 0;
+   }
+-  pFile->locktype = (u8)locktype;
+-  OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
+-           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
+-  return rc;
++  return zMbcsFilename;
+ }
+ 
+ /*
+-** If *pArg is inititially negative then this is a query.  Set *pArg to
+-** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
++** Convert Microsoft Unicode to multi-byte character string, based on the
++** user's ANSI codepage.
+ **
+-** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
++** Space to hold the returned string is obtained from
++** sqlite3_malloc().
+ */
+-static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
+-  if( *pArg<0 ){
+-    *pArg = (pFile->ctrlFlags & mask)!=0;
+-  }else if( (*pArg)==0 ){
+-    pFile->ctrlFlags &= ~mask;
+-  }else{
+-    pFile->ctrlFlags |= mask;
++static char *unicodeToMbcs(LPCWSTR zWideFilename){
++  int nByte;
++  char *zFilename;
++  int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
++
++  nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
++  if( nByte == 0 ){
++    return 0;
++  }
++  zFilename = sqlite3MallocZero( nByte );
++  if( zFilename==0 ){
++    return 0;
+   }
++  nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
++                                nByte, 0, 0);
++  if( nByte == 0 ){
++    sqlite3_free(zFilename);
++    zFilename = 0;
++  }
++  return zFilename;
+ }
+ 
+-/* Forward declaration */
+-static int getTempname(int nBuf, char *zBuf);
+-
+ /*
+-** Control and query of the open file handle.
++** Convert multibyte character string to UTF-8.  Space to hold the
++** returned string is obtained from sqlite3_malloc().
+ */
+-static int winFileControl(sqlite3_file *id, int op, void *pArg){
+-  winFile *pFile = (winFile*)id;
+-  OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
+-  switch( op ){
+-    case SQLITE_FCNTL_LOCKSTATE: {
+-      *(int*)pArg = pFile->locktype;
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_LAST_ERRNO: {
+-      *(int*)pArg = (int)pFile->lastErrno;
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_CHUNK_SIZE: {
+-      pFile->szChunk = *(int *)pArg;
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_SIZE_HINT: {
+-      if( pFile->szChunk>0 ){
+-        sqlite3_int64 oldSz;
+-        int rc = winFileSize(id, &oldSz);
+-        if( rc==SQLITE_OK ){
+-          sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
+-          if( newSz>oldSz ){
+-            SimulateIOErrorBenign(1);
+-            rc = winTruncate(id, newSz);
+-            SimulateIOErrorBenign(0);
+-          }
+-        }
+-        OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+-        return rc;
+-      }
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_PERSIST_WAL: {
+-      winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
+-      winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_VFSNAME: {
+-      *(char**)pArg = sqlite3_mprintf("win32");
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_WIN32_AV_RETRY: {
+-      int *a = (int*)pArg;
+-      if( a[0]>0 ){
+-        win32IoerrRetry = a[0];
+-      }else{
+-        a[0] = win32IoerrRetry;
+-      }
+-      if( a[1]>0 ){
+-        win32IoerrRetryDelay = a[1];
+-      }else{
+-        a[1] = win32IoerrRetryDelay;
+-      }
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-    case SQLITE_FCNTL_TEMPFILENAME: {
+-      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
+-      if( zTFile ){
+-        getTempname(pFile->pVfs->mxPathname, zTFile);
+-        *(char**)pArg = zTFile;
+-      }
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-#if SQLITE_MAX_MMAP_SIZE>0
+-    case SQLITE_FCNTL_MMAP_SIZE: {
+-      i64 newLimit = *(i64*)pArg;
+-      if( newLimit>sqlite3GlobalConfig.mxMmap ){
+-        newLimit = sqlite3GlobalConfig.mxMmap;
+-      }
+-      *(i64*)pArg = pFile->mmapSizeMax;
+-      if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
+-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+-      return SQLITE_OK;
+-    }
+-#endif
++SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
++  char *zFilenameUtf8;
++  LPWSTR zTmpWide;
++
++  zTmpWide = mbcsToUnicode(zFilename);
++  if( zTmpWide==0 ){
++    return 0;
+   }
+-  OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
+-  return SQLITE_NOTFOUND;
++  zFilenameUtf8 = unicodeToUtf8(zTmpWide);
++  sqlite3_free(zTmpWide);
++  return zFilenameUtf8;
+ }
+ 
+ /*
+-** Return the sector size in bytes of the underlying block device for
+-** the specified file. This is almost always 512 bytes, but may be
+-** larger for some devices.
+-**
+-** SQLite code assumes this function cannot fail. It also assumes that
+-** if two files are created in the same file-system directory (i.e.
+-** a database and its journal file) that the sector size will be the
+-** same for both.
++** Convert UTF-8 to multibyte character string.  Space to hold the 
++** returned string is obtained from sqlite3_malloc().
+ */
+-static int winSectorSize(sqlite3_file *id){
+-  (void)id;
+-  return SQLITE_DEFAULT_SECTOR_SIZE;
++SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
++  char *zFilenameMbcs;
++  LPWSTR zTmpWide;
++
++  zTmpWide = utf8ToUnicode(zFilename);
++  if( zTmpWide==0 ){
++    return 0;
++  }
++  zFilenameMbcs = unicodeToMbcs(zTmpWide);
++  sqlite3_free(zTmpWide);
++  return zFilenameMbcs;
+ }
+ 
+ /*
+-** Return a vector of device characteristics.
++** This function sets the data directory or the temporary directory based on
++** the provided arguments.  The type argument must be 1 in order to set the
++** data directory or 2 in order to set the temporary directory.  The zValue
++** argument is the name of the directory to use.  The return value will be
++** SQLITE_OK if successful.
+ */
+-static int winDeviceCharacteristics(sqlite3_file *id){
+-  winFile *p = (winFile*)id;
+-  return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
+-         ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
++SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
++  char **ppDirectory = 0;
++#ifndef SQLITE_OMIT_AUTOINIT
++  int rc = sqlite3_initialize();
++  if( rc ) return rc;
++#endif
++  if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
++    ppDirectory = &sqlite3_data_directory;
++  }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
++    ppDirectory = &sqlite3_temp_directory;
++  }
++  assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
++          || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
++  );
++  assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
++  if( ppDirectory ){
++    char *zValueUtf8 = 0;
++    if( zValue && zValue[0] ){
++      zValueUtf8 = unicodeToUtf8(zValue);
++      if ( zValueUtf8==0 ){
++        return SQLITE_NOMEM;
++      }
++    }
++    sqlite3_free(*ppDirectory);
++    *ppDirectory = zValueUtf8;
++    return SQLITE_OK;
++  }
++  return SQLITE_ERROR;
+ }
+ 
+-/* 
+-** Windows will only let you create file view mappings
+-** on allocation size granularity boundaries.
+-** During sqlite3_os_init() we do a GetSystemInfo()
+-** to get the granularity size.
+-*/
+-SYSTEM_INFO winSysInfo;
+-
+-#ifndef SQLITE_OMIT_WAL
+-
+ /*
+-** Helper functions to obtain and relinquish the global mutex. The
+-** global mutex is used to protect the winLockInfo objects used by 
+-** this file, all of which may be shared by multiple threads.
+-**
+-** Function winShmMutexHeld() is used to assert() that the global mutex 
+-** is held when required. This function is only used as part of assert() 
+-** statements. e.g.
+-**
+-**   winShmEnterMutex()
+-**     assert( winShmMutexHeld() );
+-**   winShmLeaveMutex()
++** The return value of getLastErrorMsg
++** is zero if the error message fits in the buffer, or non-zero
++** otherwise (if the message was truncated).
+ */
+-static void winShmEnterMutex(void){
+-  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-}
+-static void winShmLeaveMutex(void){
+-  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-}
+-#ifdef SQLITE_DEBUG
+-static int winShmMutexHeld(void) {
+-  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+-}
++static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
++  /* FormatMessage returns 0 on failure.  Otherwise it
++  ** returns the number of TCHARs written to the output
++  ** buffer, excluding the terminating null char.
++  */
++  DWORD dwLen = 0;
++  char *zOut = 0;
++
++  if( isNT() ){
++#if SQLITE_OS_WINRT
++    WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
++    dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
++                             FORMAT_MESSAGE_IGNORE_INSERTS,
++                             NULL,
++                             lastErrno,
++                             0,
++                             zTempWide,
++                             MAX_PATH,
++                             0);
++#else
++    LPWSTR zTempWide = NULL;
++    dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
++                             FORMAT_MESSAGE_FROM_SYSTEM |
++                             FORMAT_MESSAGE_IGNORE_INSERTS,
++                             NULL,
++                             lastErrno,
++                             0,
++                             (LPWSTR) &zTempWide,
++                             0,
++                             0);
++#endif
++    if( dwLen > 0 ){
++      /* allocate a buffer and convert to UTF8 */
++      sqlite3BeginBenignMalloc();
++      zOut = unicodeToUtf8(zTempWide);
++      sqlite3EndBenignMalloc();
++#if !SQLITE_OS_WINRT
++      /* free the system buffer allocated by FormatMessage */
++      osLocalFree(zTempWide);
+ #endif
++    }
++  }
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    char *zTemp = NULL;
++    dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
++                             FORMAT_MESSAGE_FROM_SYSTEM |
++                             FORMAT_MESSAGE_IGNORE_INSERTS,
++                             NULL,
++                             lastErrno,
++                             0,
++                             (LPSTR) &zTemp,
++                             0,
++                             0);
++    if( dwLen > 0 ){
++      /* allocate a buffer and convert to UTF8 */
++      sqlite3BeginBenignMalloc();
++      zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
++      sqlite3EndBenignMalloc();
++      /* free the system buffer allocated by FormatMessage */
++      osLocalFree(zTemp);
++    }
++  }
++#endif
++  if( 0 == dwLen ){
++    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
++  }else{
++    /* copy a maximum of nBuf chars to output buffer */
++    sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
++    /* free the UTF8 buffer */
++    sqlite3_free(zOut);
++  }
++  return 0;
++}
+ 
+ /*
+-** Object used to represent a single file opened and mmapped to provide
+-** shared memory.  When multiple threads all reference the same
+-** log-summary, each thread has its own winFile object, but they all
+-** point to a single instance of this object.  In other words, each
+-** log-summary is opened only once per process.
+-**
+-** winShmMutexHeld() must be true when creating or destroying
+-** this object or while reading or writing the following fields:
+-**
+-**      nRef
+-**      pNext 
+ **
+-** The following fields are read-only after the object is created:
+-** 
+-**      fid
+-**      zFilename
++** This function - winLogErrorAtLine() - is only ever called via the macro
++** winLogError().
+ **
+-** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
+-** winShmMutexHeld() is true when reading or writing any other field
+-** in this structure.
++** This routine is invoked after an error occurs in an OS function.
++** It logs a message using sqlite3_log() containing the current value of
++** error code and, if possible, the human-readable equivalent from 
++** FormatMessage.
+ **
++** The first argument passed to the macro should be the error code that
++** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). 
++** The two subsequent arguments should be the name of the OS function that
++** failed and the associated file-system path, if any.
+ */
+-struct winShmNode {
+-  sqlite3_mutex *mutex;      /* Mutex to access this object */
+-  char *zFilename;           /* Name of the file */
+-  winFile hFile;             /* File handle from winOpen */
+-
+-  int szRegion;              /* Size of shared-memory regions */
+-  int nRegion;               /* Size of array apRegion */
+-  struct ShmRegion {
+-    HANDLE hMap;             /* File handle from CreateFileMapping */
+-    void *pMap;
+-  } *aRegion;
+-  DWORD lastErrno;           /* The Windows errno from the last I/O error */
++#define winLogError(a,b,c,d)   winLogErrorAtLine(a,b,c,d,__LINE__)
++static int winLogErrorAtLine(
++  int errcode,                    /* SQLite error code */
++  DWORD lastErrno,                /* Win32 last error */
++  const char *zFunc,              /* Name of OS function that failed */
++  const char *zPath,              /* File path associated with error */
++  int iLine                       /* Source line number where error occurred */
++){
++  char zMsg[500];                 /* Human readable error text */
++  int i;                          /* Loop counter */
+ 
+-  int nRef;                  /* Number of winShm objects pointing to this */
+-  winShm *pFirst;            /* All winShm objects pointing to this */
+-  winShmNode *pNext;         /* Next in list of all winShmNode objects */
+-#ifdef SQLITE_DEBUG
+-  u8 nextShmId;              /* Next available winShm.id value */
+-#endif
+-};
++  zMsg[0] = 0;
++  getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
++  assert( errcode!=SQLITE_OK );
++  if( zPath==0 ) zPath = "";
++  for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
++  zMsg[i] = 0;
++  sqlite3_log(errcode,
++      "os_win.c:%d: (%lu) %s(%s) - %s",
++      iLine, lastErrno, zFunc, zPath, zMsg
++  );
+ 
+-/*
+-** A global array of all winShmNode objects.
+-**
+-** The winShmMutexHeld() must be true while reading or writing this list.
+-*/
+-static winShmNode *winShmNodeList = 0;
++  return errcode;
++}
+ 
+ /*
+-** Structure used internally by this VFS to record the state of an
+-** open shared memory connection.
+-**
+-** The following fields are initialized when this object is created and
+-** are read-only thereafter:
+-**
+-**    winShm.pShmNode
+-**    winShm.id
+-**
+-** All other fields are read/write.  The winShm.pShmNode->mutex must be held
+-** while accessing any read/write fields.
++** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
++** will be retried following a locking error - probably caused by 
++** antivirus software.  Also the initial delay before the first retry.
++** The delay increases linearly with each retry.
+ */
+-struct winShm {
+-  winShmNode *pShmNode;      /* The underlying winShmNode object */
+-  winShm *pNext;             /* Next winShm with the same winShmNode */
+-  u8 hasMutex;               /* True if holding the winShmNode mutex */
+-  u16 sharedMask;            /* Mask of shared locks held */
+-  u16 exclMask;              /* Mask of exclusive locks held */
+-#ifdef SQLITE_DEBUG
+-  u8 id;                     /* Id of this connection with its winShmNode */
++#ifndef SQLITE_WIN32_IOERR_RETRY
++# define SQLITE_WIN32_IOERR_RETRY 10
+ #endif
+-};
++#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
++# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
++#endif
++static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
++static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+ 
+ /*
+-** Constants used for locking
++** If a ReadFile() or WriteFile() error occurs, invoke this routine
++** to see if it should be retried.  Return TRUE to retry.  Return FALSE
++** to give up with an error.
+ */
+-#define WIN_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
+-#define WIN_SHM_DMS    (WIN_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
++static int retryIoerr(int *pnRetry, DWORD *pError){
++  DWORD e = osGetLastError();
++  if( *pnRetry>=win32IoerrRetry ){
++    if( pError ){
++      *pError = e;
++    }
++    return 0;
++  }
++  if( e==ERROR_ACCESS_DENIED ||
++      e==ERROR_LOCK_VIOLATION ||
++      e==ERROR_SHARING_VIOLATION ){
++    sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
++    ++*pnRetry;
++    return 1;
++  }
++  if( pError ){
++    *pError = e;
++  }
++  return 0;
++}
+ 
+ /*
+-** Apply advisory locks for all n bytes beginning at ofst.
++** Log a I/O error retry episode.
+ */
+-#define _SHM_UNLCK  1
+-#define _SHM_RDLCK  2
+-#define _SHM_WRLCK  3
+-static int winShmSystemLock(
+-  winShmNode *pFile,    /* Apply locks to this open shared-memory segment */
+-  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
+-  int ofst,             /* Offset to first byte to be locked/unlocked */
+-  int nByte             /* Number of bytes to lock or unlock */
+-){
+-  int rc = 0;           /* Result code form Lock/UnlockFileEx() */
+-
+-  /* Access to the winShmNode object is serialized by the caller */
+-  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
+-
+-  OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
+-           pFile->hFile.h, lockType, ofst, nByte));
+-
+-  /* Release/Acquire the system-level lock */
+-  if( lockType==_SHM_UNLCK ){
+-    rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
+-  }else{
+-    /* Initialize the locking parameters */
+-    DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
+-    if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
+-    rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
+-  }
+-  
+-  if( rc!= 0 ){
+-    rc = SQLITE_OK;
+-  }else{
+-    pFile->lastErrno =  osGetLastError();
+-    rc = SQLITE_BUSY;
++static void logIoerr(int nRetry){
++  if( nRetry ){
++    sqlite3_log(SQLITE_IOERR, 
++      "delayed %dms for lock/sharing conflict",
++      win32IoerrRetryDelay*nRetry*(nRetry+1)/2
++    );
+   }
++}
+ 
+-  OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
+-           pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" :
+-           "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
+-
+-  return rc;
++#if SQLITE_OS_WINCE
++/*************************************************************************
++** This section contains code for WinCE only.
++*/
++#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
++/*
++** The MSVC CRT on Windows CE may not have a localtime() function.  So
++** create a substitute.
++*/
++/* #include <time.h> */
++struct tm *__cdecl localtime(const time_t *t)
++{
++  static struct tm y;
++  FILETIME uTm, lTm;
++  SYSTEMTIME pTm;
++  sqlite3_int64 t64;
++  t64 = *t;
++  t64 = (t64 + 11644473600)*10000000;
++  uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
++  uTm.dwHighDateTime= (DWORD)(t64 >> 32);
++  osFileTimeToLocalFileTime(&uTm,&lTm);
++  osFileTimeToSystemTime(&lTm,&pTm);
++  y.tm_year = pTm.wYear - 1900;
++  y.tm_mon = pTm.wMonth - 1;
++  y.tm_wday = pTm.wDayOfWeek;
++  y.tm_mday = pTm.wDay;
++  y.tm_hour = pTm.wHour;
++  y.tm_min = pTm.wMinute;
++  y.tm_sec = pTm.wSecond;
++  return &y;
+ }
++#endif
+ 
+-/* Forward references to VFS methods */
+-static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
+-static int winDelete(sqlite3_vfs *,const char*,int);
++#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
+ 
+ /*
+-** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
+-**
+-** This is not a VFS shared-memory method; it is a utility function called
+-** by VFS shared-memory methods.
++** Acquire a lock on the handle h
+ */
+-static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
+-  winShmNode **pp;
+-  winShmNode *p;
+-  BOOL bRc;
+-  assert( winShmMutexHeld() );
+-  OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
+-           osGetCurrentProcessId(), deleteFlag));
+-  pp = &winShmNodeList;
+-  while( (p = *pp)!=0 ){
+-    if( p->nRef==0 ){
+-      int i;
+-      if( p->mutex ) sqlite3_mutex_free(p->mutex);
+-      for(i=0; i<p->nRegion; i++){
+-        bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
+-        OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
+-                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
+-        bRc = osCloseHandle(p->aRegion[i].hMap);
+-        OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
+-                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
+-      }
+-      if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
+-        SimulateIOErrorBenign(1);
+-        winClose((sqlite3_file *)&p->hFile);
+-        SimulateIOErrorBenign(0);
+-      }
+-      if( deleteFlag ){
+-        SimulateIOErrorBenign(1);
+-        sqlite3BeginBenignMalloc();
+-        winDelete(pVfs, p->zFilename, 0);
+-        sqlite3EndBenignMalloc();
+-        SimulateIOErrorBenign(0);
+-      }
+-      *pp = p->pNext;
+-      sqlite3_free(p->aRegion);
+-      sqlite3_free(p);
+-    }else{
+-      pp = &p->pNext;
+-    }
+-  }
++static void winceMutexAcquire(HANDLE h){
++   DWORD dwErr;
++   do {
++     dwErr = osWaitForSingleObject(h, INFINITE);
++   } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
+ }
+-
+ /*
+-** Open the shared-memory area associated with database file pDbFd.
+-**
+-** When opening a new shared-memory file, if no other instances of that
+-** file are currently open, in this process or in other processes, then
+-** the file must be truncated to zero length or have its header cleared.
++** Release a lock acquired by winceMutexAcquire()
+ */
+-static int winOpenSharedMemory(winFile *pDbFd){
+-  struct winShm *p;                  /* The connection to be opened */
+-  struct winShmNode *pShmNode = 0;   /* The underlying mmapped file */
+-  int rc;                            /* Result code */
+-  struct winShmNode *pNew;           /* Newly allocated winShmNode */
+-  int nName;                         /* Size of zName in bytes */
++#define winceMutexRelease(h) ReleaseMutex(h)
+ 
+-  assert( pDbFd->pShm==0 );    /* Not previously opened */
++/*
++** Create the mutex and shared memory used for locking in the file
++** descriptor pFile
++*/
++static int winceCreateLock(const char *zFilename, winFile *pFile){
++  LPWSTR zTok;
++  LPWSTR zName;
++  DWORD lastErrno;
++  BOOL bLogged = FALSE;
++  BOOL bInit = TRUE;
+ 
+-  /* Allocate space for the new sqlite3_shm object.  Also speculatively
+-  ** allocate space for a new winShmNode and filename.
+-  */
+-  p = sqlite3MallocZero( sizeof(*p) );
+-  if( p==0 ) return SQLITE_IOERR_NOMEM;
+-  nName = sqlite3Strlen30(pDbFd->zPath);
+-  pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
+-  if( pNew==0 ){
+-    sqlite3_free(p);
++  zName = utf8ToUnicode(zFilename);
++  if( zName==0 ){
++    /* out of memory */
+     return SQLITE_IOERR_NOMEM;
+   }
+-  pNew->zFilename = (char*)&pNew[1];
+-  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
+-  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); 
+ 
+-  /* Look to see if there is an existing winShmNode that can be used.
+-  ** If no matching winShmNode currently exists, create a new one.
++  /* Initialize the local lockdata */
++  memset(&pFile->local, 0, sizeof(pFile->local));
++
++  /* Replace the backslashes from the filename and lowercase it
++  ** to derive a mutex name. */
++  zTok = osCharLowerW(zName);
++  for (;*zTok;zTok++){
++    if (*zTok == '\\') *zTok = '_';
++  }
++
++  /* Create/open the named mutex */
++  pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
++  if (!pFile->hMutex){
++    pFile->lastErrno = osGetLastError();
++    winLogError(SQLITE_IOERR, pFile->lastErrno,
++                "winceCreateLock1", zFilename);
++    sqlite3_free(zName);
++    return SQLITE_IOERR;
++  }
++
++  /* Acquire the mutex before continuing */
++  winceMutexAcquire(pFile->hMutex);
++  
++  /* Since the names of named mutexes, semaphores, file mappings etc are 
++  ** case-sensitive, take advantage of that by uppercasing the mutex name
++  ** and using that as the shared filemapping name.
+   */
+-  winShmEnterMutex();
+-  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
+-    /* TBD need to come up with better match here.  Perhaps
+-    ** use FILE_ID_BOTH_DIR_INFO Structure.
+-    */
+-    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
++  osCharUpperW(zName);
++  pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
++                                        PAGE_READWRITE, 0, sizeof(winceLock),
++                                        zName);  
++
++  /* Set a flag that indicates we're the first to create the memory so it 
++  ** must be zero-initialized */
++  lastErrno = osGetLastError();
++  if (lastErrno == ERROR_ALREADY_EXISTS){
++    bInit = FALSE;
+   }
+-  if( pShmNode ){
+-    sqlite3_free(pNew);
+-  }else{
+-    pShmNode = pNew;
+-    pNew = 0;
+-    ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
+-    pShmNode->pNext = winShmNodeList;
+-    winShmNodeList = pShmNode;
+ 
+-    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+-    if( pShmNode->mutex==0 ){
+-      rc = SQLITE_IOERR_NOMEM;
+-      goto shm_open_err;
+-    }
++  sqlite3_free(zName);
+ 
+-    rc = winOpen(pDbFd->pVfs,
+-                 pShmNode->zFilename,             /* Name of the file (UTF-8) */
+-                 (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
+-                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+-                 0);
+-    if( SQLITE_OK!=rc ){
+-      goto shm_open_err;
++  /* If we succeeded in making the shared memory handle, map it. */
++  if( pFile->hShared ){
++    pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
++             FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
++    /* If mapping failed, close the shared memory handle and erase it */
++    if( !pFile->shared ){
++      pFile->lastErrno = osGetLastError();
++      winLogError(SQLITE_IOERR, pFile->lastErrno,
++                  "winceCreateLock2", zFilename);
++      bLogged = TRUE;
++      osCloseHandle(pFile->hShared);
++      pFile->hShared = NULL;
+     }
++  }
+ 
+-    /* Check to see if another process is holding the dead-man switch.
+-    ** If not, truncate the file to zero length. 
+-    */
+-    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
+-      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
+-      if( rc!=SQLITE_OK ){
+-        rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
+-                 "winOpenShm", pDbFd->zPath);
+-      }
+-    }
+-    if( rc==SQLITE_OK ){
+-      winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
+-      rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
++  /* If shared memory could not be created, then close the mutex and fail */
++  if( pFile->hShared==NULL ){
++    if( !bLogged ){
++      pFile->lastErrno = lastErrno;
++      winLogError(SQLITE_IOERR, pFile->lastErrno,
++                  "winceCreateLock3", zFilename);
++      bLogged = TRUE;
+     }
+-    if( rc ) goto shm_open_err;
++    winceMutexRelease(pFile->hMutex);
++    osCloseHandle(pFile->hMutex);
++    pFile->hMutex = NULL;
++    return SQLITE_IOERR;
++  }
++  
++  /* Initialize the shared memory if we're supposed to */
++  if( bInit ){
++    memset(pFile->shared, 0, sizeof(winceLock));
+   }
+ 
+-  /* Make the new connection a child of the winShmNode */
+-  p->pShmNode = pShmNode;
+-#ifdef SQLITE_DEBUG
+-  p->id = pShmNode->nextShmId++;
+-#endif
+-  pShmNode->nRef++;
+-  pDbFd->pShm = p;
+-  winShmLeaveMutex();
+-
+-  /* The reference count on pShmNode has already been incremented under
+-  ** the cover of the winShmEnterMutex() mutex and the pointer from the
+-  ** new (struct winShm) object to the pShmNode has been set. All that is
+-  ** left to do is to link the new object into the linked list starting
+-  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex 
+-  ** mutex.
+-  */
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  p->pNext = pShmNode->pFirst;
+-  pShmNode->pFirst = p;
+-  sqlite3_mutex_leave(pShmNode->mutex);
++  winceMutexRelease(pFile->hMutex);
+   return SQLITE_OK;
+-
+-  /* Jump here on any error */
+-shm_open_err:
+-  winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
+-  winShmPurge(pDbFd->pVfs, 0);      /* This call frees pShmNode if required */
+-  sqlite3_free(p);
+-  sqlite3_free(pNew);
+-  winShmLeaveMutex();
+-  return rc;
+ }
+ 
+ /*
+-** Close a connection to shared-memory.  Delete the underlying 
+-** storage if deleteFlag is true.
++** Destroy the part of winFile that deals with wince locks
+ */
+-static int winShmUnmap(
+-  sqlite3_file *fd,          /* Database holding shared memory */
+-  int deleteFlag             /* Delete after closing if true */
+-){
+-  winFile *pDbFd;       /* Database holding shared-memory */
+-  winShm *p;            /* The connection to be closed */
+-  winShmNode *pShmNode; /* The underlying shared-memory file */
+-  winShm **pp;          /* For looping over sibling connections */
+-
+-  pDbFd = (winFile*)fd;
+-  p = pDbFd->pShm;
+-  if( p==0 ) return SQLITE_OK;
+-  pShmNode = p->pShmNode;
++static void winceDestroyLock(winFile *pFile){
++  if (pFile->hMutex){
++    /* Acquire the mutex */
++    winceMutexAcquire(pFile->hMutex);
+ 
+-  /* Remove connection p from the set of connections associated
+-  ** with pShmNode */
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
+-  *pp = p->pNext;
++    /* The following blocks should probably assert in debug mode, but they
++       are to cleanup in case any locks remained open */
++    if (pFile->local.nReaders){
++      pFile->shared->nReaders --;
++    }
++    if (pFile->local.bReserved){
++      pFile->shared->bReserved = FALSE;
++    }
++    if (pFile->local.bPending){
++      pFile->shared->bPending = FALSE;
++    }
++    if (pFile->local.bExclusive){
++      pFile->shared->bExclusive = FALSE;
++    }
+ 
+-  /* Free the connection p */
+-  sqlite3_free(p);
+-  pDbFd->pShm = 0;
+-  sqlite3_mutex_leave(pShmNode->mutex);
++    /* De-reference and close our copy of the shared memory handle */
++    osUnmapViewOfFile(pFile->shared);
++    osCloseHandle(pFile->hShared);
+ 
+-  /* If pShmNode->nRef has reached 0, then close the underlying
+-  ** shared-memory file, too */
+-  winShmEnterMutex();
+-  assert( pShmNode->nRef>0 );
+-  pShmNode->nRef--;
+-  if( pShmNode->nRef==0 ){
+-    winShmPurge(pDbFd->pVfs, deleteFlag);
++    /* Done with the mutex */
++    winceMutexRelease(pFile->hMutex);    
++    osCloseHandle(pFile->hMutex);
++    pFile->hMutex = NULL;
+   }
+-  winShmLeaveMutex();
+-
+-  return SQLITE_OK;
+ }
+ 
+-/*
+-** Change the lock state for a shared-memory segment.
++/* 
++** An implementation of the LockFile() API of Windows for CE
+ */
+-static int winShmLock(
+-  sqlite3_file *fd,          /* Database file holding the shared memory */
+-  int ofst,                  /* First lock to acquire or release */
+-  int n,                     /* Number of locks to acquire or release */
+-  int flags                  /* What to do with the lock */
++static BOOL winceLockFile(
++  LPHANDLE phFile,
++  DWORD dwFileOffsetLow,
++  DWORD dwFileOffsetHigh,
++  DWORD nNumberOfBytesToLockLow,
++  DWORD nNumberOfBytesToLockHigh
+ ){
+-  winFile *pDbFd = (winFile*)fd;        /* Connection holding shared memory */
+-  winShm *p = pDbFd->pShm;              /* The shared memory being locked */
+-  winShm *pX;                           /* For looping over all siblings */
+-  winShmNode *pShmNode = p->pShmNode;
+-  int rc = SQLITE_OK;                   /* Result code */
+-  u16 mask;                             /* Mask of locks to take or release */
++  winFile *pFile = HANDLE_TO_WINFILE(phFile);
++  BOOL bReturn = FALSE;
+ 
+-  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
+-  assert( n>=1 );
+-  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
+-       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
+-       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
+-       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
+-  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
++  UNUSED_PARAMETER(dwFileOffsetHigh);
++  UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
+ 
+-  mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
+-  assert( n>1 || mask==(1<<ofst) );
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  if( flags & SQLITE_SHM_UNLOCK ){
+-    u16 allMask = 0; /* Mask of locks held by siblings */
++  if (!pFile->hMutex) return TRUE;
++  winceMutexAcquire(pFile->hMutex);
+ 
+-    /* See if any siblings hold this same lock */
+-    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+-      if( pX==p ) continue;
+-      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
+-      allMask |= pX->sharedMask;
++  /* Wanting an exclusive lock? */
++  if (dwFileOffsetLow == (DWORD)SHARED_FIRST
++       && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
++    if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
++       pFile->shared->bExclusive = TRUE;
++       pFile->local.bExclusive = TRUE;
++       bReturn = TRUE;
++    }
++  }
++
++  /* Want a read-only lock? */
++  else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
++           nNumberOfBytesToLockLow == 1){
++    if (pFile->shared->bExclusive == 0){
++      pFile->local.nReaders ++;
++      if (pFile->local.nReaders == 1){
++        pFile->shared->nReaders ++;
++      }
++      bReturn = TRUE;
++    }
++  }
++
++  /* Want a pending lock? */
++  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
++           && nNumberOfBytesToLockLow == 1){
++    /* If no pending lock has been acquired, then acquire it */
++    if (pFile->shared->bPending == 0) {
++      pFile->shared->bPending = TRUE;
++      pFile->local.bPending = TRUE;
++      bReturn = TRUE;
+     }
++  }
+ 
+-    /* Unlock the system-level locks */
+-    if( (mask & allMask)==0 ){
+-      rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
+-    }else{
+-      rc = SQLITE_OK;
++  /* Want a reserved lock? */
++  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
++           && nNumberOfBytesToLockLow == 1){
++    if (pFile->shared->bReserved == 0) {
++      pFile->shared->bReserved = TRUE;
++      pFile->local.bReserved = TRUE;
++      bReturn = TRUE;
+     }
++  }
+ 
+-    /* Undo the local locks */
+-    if( rc==SQLITE_OK ){
+-      p->exclMask &= ~mask;
+-      p->sharedMask &= ~mask;
+-    } 
+-  }else if( flags & SQLITE_SHM_SHARED ){
+-    u16 allShared = 0;  /* Union of locks held by connections other than "p" */
++  winceMutexRelease(pFile->hMutex);
++  return bReturn;
++}
+ 
+-    /* Find out which shared locks are already held by sibling connections.
+-    ** If any sibling already holds an exclusive lock, go ahead and return
+-    ** SQLITE_BUSY.
+-    */
+-    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+-      if( (pX->exclMask & mask)!=0 ){
+-        rc = SQLITE_BUSY;
+-        break;
+-      }
+-      allShared |= pX->sharedMask;
++/*
++** An implementation of the UnlockFile API of Windows for CE
++*/
++static BOOL winceUnlockFile(
++  LPHANDLE phFile,
++  DWORD dwFileOffsetLow,
++  DWORD dwFileOffsetHigh,
++  DWORD nNumberOfBytesToUnlockLow,
++  DWORD nNumberOfBytesToUnlockHigh
++){
++  winFile *pFile = HANDLE_TO_WINFILE(phFile);
++  BOOL bReturn = FALSE;
++
++  UNUSED_PARAMETER(dwFileOffsetHigh);
++  UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
++
++  if (!pFile->hMutex) return TRUE;
++  winceMutexAcquire(pFile->hMutex);
++
++  /* Releasing a reader lock or an exclusive lock */
++  if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
++    /* Did we have an exclusive lock? */
++    if (pFile->local.bExclusive){
++      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
++      pFile->local.bExclusive = FALSE;
++      pFile->shared->bExclusive = FALSE;
++      bReturn = TRUE;
+     }
+ 
+-    /* Get shared locks at the system level, if necessary */
+-    if( rc==SQLITE_OK ){
+-      if( (allShared & mask)==0 ){
+-        rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
+-      }else{
+-        rc = SQLITE_OK;
++    /* Did we just have a reader lock? */
++    else if (pFile->local.nReaders){
++      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
++             || nNumberOfBytesToUnlockLow == 1);
++      pFile->local.nReaders --;
++      if (pFile->local.nReaders == 0)
++      {
++        pFile->shared->nReaders --;
+       }
++      bReturn = TRUE;
+     }
++  }
+ 
+-    /* Get the local shared locks */
+-    if( rc==SQLITE_OK ){
+-      p->sharedMask |= mask;
+-    }
+-  }else{
+-    /* Make sure no sibling connections hold locks that will block this
+-    ** lock.  If any do, return SQLITE_BUSY right away.
+-    */
+-    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+-      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+-        rc = SQLITE_BUSY;
+-        break;
+-      }
++  /* Releasing a pending lock */
++  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
++           && nNumberOfBytesToUnlockLow == 1){
++    if (pFile->local.bPending){
++      pFile->local.bPending = FALSE;
++      pFile->shared->bPending = FALSE;
++      bReturn = TRUE;
+     }
+-  
+-    /* Get the exclusive locks at the system level.  Then if successful
+-    ** also mark the local connection as being locked.
+-    */
+-    if( rc==SQLITE_OK ){
+-      rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
+-      if( rc==SQLITE_OK ){
+-        assert( (p->sharedMask & mask)==0 );
+-        p->exclMask |= mask;
+-      }
++  }
++  /* Releasing a reserved lock */
++  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
++           && nNumberOfBytesToUnlockLow == 1){
++    if (pFile->local.bReserved) {
++      pFile->local.bReserved = FALSE;
++      pFile->shared->bReserved = FALSE;
++      bReturn = TRUE;
+     }
+   }
+-  sqlite3_mutex_leave(pShmNode->mutex);
+-  OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
+-           osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
+-           sqlite3ErrName(rc)));
+-  return rc;
++
++  winceMutexRelease(pFile->hMutex);
++  return bReturn;
+ }
++/*
++** End of the special code for wince
++*****************************************************************************/
++#endif /* SQLITE_OS_WINCE */
+ 
+ /*
+-** Implement a memory barrier or memory fence on shared memory.  
+-**
+-** All loads and stores begun before the barrier must complete before
+-** any load or store begun after the barrier.
++** Lock a file region.
+ */
+-static void winShmBarrier(
+-  sqlite3_file *fd          /* Database holding the shared memory */
++static BOOL winLockFile(
++  LPHANDLE phFile,
++  DWORD flags,
++  DWORD offsetLow,
++  DWORD offsetHigh,
++  DWORD numBytesLow,
++  DWORD numBytesHigh
+ ){
+-  UNUSED_PARAMETER(fd);
+-  /* MemoryBarrier(); // does not work -- do not know why not */
+-  winShmEnterMutex();
+-  winShmLeaveMutex();
++#if SQLITE_OS_WINCE
++  /*
++  ** NOTE: Windows CE is handled differently here due its lack of the Win32
++  **       API LockFile.
++  */
++  return winceLockFile(phFile, offsetLow, offsetHigh,
++                       numBytesLow, numBytesHigh);
++#else
++  if( isNT() ){
++    OVERLAPPED ovlp;
++    memset(&ovlp, 0, sizeof(OVERLAPPED));
++    ovlp.Offset = offsetLow;
++    ovlp.OffsetHigh = offsetHigh;
++    return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
++  }else{
++    return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
++                      numBytesHigh);
++  }
++#endif
+ }
+ 
+ /*
+-** This function is called to obtain a pointer to region iRegion of the 
+-** shared-memory associated with the database file fd. Shared-memory regions 
+-** are numbered starting from zero. Each shared-memory region is szRegion 
+-** bytes in size.
+-**
+-** If an error occurs, an error code is returned and *pp is set to NULL.
+-**
+-** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
+-** region has not been allocated (by any client, including one running in a
+-** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
+-** isWrite is non-zero and the requested shared-memory region has not yet 
+-** been allocated, it is allocated by this function.
+-**
+-** If the shared-memory region has already been allocated or is allocated by
+-** this call as described above, then it is mapped into this processes 
+-** address space (if it is not already), *pp is set to point to the mapped 
+-** memory and SQLITE_OK returned.
+-*/
+-static int winShmMap(
+-  sqlite3_file *fd,               /* Handle open on database file */
+-  int iRegion,                    /* Region to retrieve */
+-  int szRegion,                   /* Size of regions */
+-  int isWrite,                    /* True to extend file if necessary */
+-  void volatile **pp              /* OUT: Mapped memory */
++** Unlock a file region.
++ */
++static BOOL winUnlockFile(
++  LPHANDLE phFile,
++  DWORD offsetLow,
++  DWORD offsetHigh,
++  DWORD numBytesLow,
++  DWORD numBytesHigh
+ ){
+-  winFile *pDbFd = (winFile*)fd;
+-  winShm *p = pDbFd->pShm;
+-  winShmNode *pShmNode;
+-  int rc = SQLITE_OK;
++#if SQLITE_OS_WINCE
++  /*
++  ** NOTE: Windows CE is handled differently here due its lack of the Win32
++  **       API UnlockFile.
++  */
++  return winceUnlockFile(phFile, offsetLow, offsetHigh,
++                         numBytesLow, numBytesHigh);
++#else
++  if( isNT() ){
++    OVERLAPPED ovlp;
++    memset(&ovlp, 0, sizeof(OVERLAPPED));
++    ovlp.Offset = offsetLow;
++    ovlp.OffsetHigh = offsetHigh;
++    return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
++  }else{
++    return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
++                        numBytesHigh);
++  }
++#endif
++}
+ 
+-  if( !p ){
+-    rc = winOpenSharedMemory(pDbFd);
+-    if( rc!=SQLITE_OK ) return rc;
+-    p = pDbFd->pShm;
++/*****************************************************************************
++** The next group of routines implement the I/O methods specified
++** by the sqlite3_io_methods object.
++******************************************************************************/
++
++/*
++** Some Microsoft compilers lack this definition.
++*/
++#ifndef INVALID_SET_FILE_POINTER
++# define INVALID_SET_FILE_POINTER ((DWORD)-1)
++#endif
++
++/*
++** Move the current position of the file handle passed as the first 
++** argument to offset iOffset within the file. If successful, return 0. 
++** Otherwise, set pFile->lastErrno and return non-zero.
++*/
++static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
++#if !SQLITE_OS_WINRT
++  LONG upperBits;                 /* Most sig. 32 bits of new offset */
++  LONG lowerBits;                 /* Least sig. 32 bits of new offset */
++  DWORD dwRet;                    /* Value returned by SetFilePointer() */
++  DWORD lastErrno;                /* Value returned by GetLastError() */
++
++  OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
++
++  upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
++  lowerBits = (LONG)(iOffset & 0xffffffff);
++
++  /* API oddity: If successful, SetFilePointer() returns a dword 
++  ** containing the lower 32-bits of the new file-offset. Or, if it fails,
++  ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
++  ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
++  ** whether an error has actually occurred, it is also necessary to call 
++  ** GetLastError().
++  */
++  dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
++
++  if( (dwRet==INVALID_SET_FILE_POINTER
++      && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
++    pFile->lastErrno = lastErrno;
++    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
++             "seekWinFile", pFile->zPath);
++    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
++    return 1;
+   }
+-  pShmNode = p->pShmNode;
+ 
+-  sqlite3_mutex_enter(pShmNode->mutex);
+-  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
++  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
++  return 0;
++#else
++  /*
++  ** Same as above, except that this implementation works for WinRT.
++  */
+ 
+-  if( pShmNode->nRegion<=iRegion ){
+-    struct ShmRegion *apNew;           /* New aRegion[] array */
+-    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
+-    sqlite3_int64 sz;                  /* Current size of wal-index file */
++  LARGE_INTEGER x;                /* The new offset */
++  BOOL bRet;                      /* Value returned by SetFilePointerEx() */
+ 
+-    pShmNode->szRegion = szRegion;
++  x.QuadPart = iOffset;
++  bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+ 
+-    /* The requested region is not mapped into this processes address space.
+-    ** Check to see if it has been allocated (i.e. if the wal-index file is
+-    ** large enough to contain the requested region).
+-    */
+-    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
+-    if( rc!=SQLITE_OK ){
+-      rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
+-               "winShmMap1", pDbFd->zPath);
+-      goto shmpage_out;
+-    }
++  if(!bRet){
++    pFile->lastErrno = osGetLastError();
++    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
++             "seekWinFile", pFile->zPath);
++    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
++    return 1;
++  }
+ 
+-    if( sz<nByte ){
+-      /* The requested memory region does not exist. If isWrite is set to
+-      ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
+-      **
+-      ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
+-      ** the requested memory region.
+-      */
+-      if( !isWrite ) goto shmpage_out;
+-      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
+-      if( rc!=SQLITE_OK ){
+-        rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
+-                 "winShmMap2", pDbFd->zPath);
+-        goto shmpage_out;
+-      }
+-    }
++  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
++  return 0;
++#endif
++}
+ 
+-    /* Map the requested memory region into this processes address space. */
+-    apNew = (struct ShmRegion *)sqlite3_realloc(
+-        pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
+-    );
+-    if( !apNew ){
+-      rc = SQLITE_IOERR_NOMEM;
+-      goto shmpage_out;
+-    }
+-    pShmNode->aRegion = apNew;
++#if SQLITE_MAX_MMAP_SIZE>0
++/* Forward references to VFS methods */
++static int winUnmapfile(winFile*);
++#endif
+ 
+-    while( pShmNode->nRegion<=iRegion ){
+-      HANDLE hMap = NULL;         /* file-mapping handle */
+-      void *pMap = 0;             /* Mapped memory region */
+-     
+-#if SQLITE_OS_WINRT
+-      hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
+-          NULL, PAGE_READWRITE, nByte, NULL
+-      );
+-#elif defined(SQLITE_WIN32_HAS_WIDE)
+-      hMap = osCreateFileMappingW(pShmNode->hFile.h, 
+-          NULL, PAGE_READWRITE, 0, nByte, NULL
+-      );
+-#elif defined(SQLITE_WIN32_HAS_ANSI)
+-      hMap = osCreateFileMappingA(pShmNode->hFile.h, 
+-          NULL, PAGE_READWRITE, 0, nByte, NULL
+-      );
++/*
++** Close a file.
++**
++** It is reported that an attempt to close a handle might sometimes
++** fail.  This is a very unreasonable result, but Windows is notorious
++** for being unreasonable so I do not doubt that it might happen.  If
++** the close fails, we pause for 100 milliseconds and try again.  As
++** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
++** giving up and returning an error.
++*/
++#define MX_CLOSE_ATTEMPT 3
++static int winClose(sqlite3_file *id){
++  int rc, cnt = 0;
++  winFile *pFile = (winFile*)id;
++
++  assert( id!=0 );
++#ifndef SQLITE_OMIT_WAL
++  assert( pFile->pShm==0 );
+ #endif
+-      OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
+-               osGetCurrentProcessId(), pShmNode->nRegion, nByte,
+-               hMap ? "ok" : "failed"));
+-      if( hMap ){
+-        int iOffset = pShmNode->nRegion*szRegion;
+-        int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
+-#if SQLITE_OS_WINRT
+-        pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
+-            iOffset - iOffsetShift, szRegion + iOffsetShift
+-        );
+-#else
+-        pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
+-            0, iOffset - iOffsetShift, szRegion + iOffsetShift
+-        );
++  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
++  OSTRACE(("CLOSE file=%p\n", pFile->h));
++
++#if SQLITE_MAX_MMAP_SIZE>0
++  rc = winUnmapfile(pFile);
++  if( rc!=SQLITE_OK ) return rc;
+ #endif
+-        OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
+-                 osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
+-                 szRegion, pMap ? "ok" : "failed"));
+-      }
+-      if( !pMap ){
+-        pShmNode->lastErrno = osGetLastError();
+-        rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
+-                 "winShmMap3", pDbFd->zPath);
+-        if( hMap ) osCloseHandle(hMap);
+-        goto shmpage_out;
+-      }
+ 
+-      pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
+-      pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
+-      pShmNode->nRegion++;
++  do{
++    rc = osCloseHandle(pFile->h);
++    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
++  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
++#if SQLITE_OS_WINCE
++#define WINCE_DELETION_ATTEMPTS 3
++  winceDestroyLock(pFile);
++  if( pFile->zDeleteOnClose ){
++    int cnt = 0;
++    while(
++           osDeleteFileW(pFile->zDeleteOnClose)==0
++        && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff 
++        && cnt++ < WINCE_DELETION_ATTEMPTS
++    ){
++       sqlite3_win32_sleep(100);  /* Wait a little before trying again */
+     }
++    sqlite3_free(pFile->zDeleteOnClose);
+   }
+-
+-shmpage_out:
+-  if( pShmNode->nRegion>iRegion ){
+-    int iOffset = iRegion*szRegion;
+-    int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
+-    char *p = (char *)pShmNode->aRegion[iRegion].pMap;
+-    *pp = (void *)&p[iOffsetShift];
+-  }else{
+-    *pp = 0;
++#endif
++  if( rc ){
++    pFile->h = NULL;
+   }
+-  sqlite3_mutex_leave(pShmNode->mutex);
+-  return rc;
++  OpenCounter(-1);
++  OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
++  return rc ? SQLITE_OK
++            : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
++                          "winClose", pFile->zPath);
+ }
+ 
+-#else
+-# define winShmMap     0
+-# define winShmLock    0
+-# define winShmBarrier 0
+-# define winShmUnmap   0
+-#endif /* #ifndef SQLITE_OMIT_WAL */
+-
+ /*
+-** Cleans up the mapped region of the specified file, if any.
++** Read data from a file into a buffer.  Return SQLITE_OK if all
++** bytes were read successfully and SQLITE_IOERR if anything goes
++** wrong.
+ */
++static int winRead(
++  sqlite3_file *id,          /* File to read from */
++  void *pBuf,                /* Write content into this buffer */
++  int amt,                   /* Number of bytes to read */
++  sqlite3_int64 offset       /* Begin reading at this offset */
++){
++#if !SQLITE_OS_WINCE
++  OVERLAPPED overlapped;          /* The offset for ReadFile. */
++#endif
++  winFile *pFile = (winFile*)id;  /* file handle */
++  DWORD nRead;                    /* Number of bytes actually read from file */
++  int nRetry = 0;                 /* Number of retrys */
++
++  assert( id!=0 );
++  assert( amt>0 );
++  assert( offset>=0 );
++  SimulateIOError(return SQLITE_IOERR_READ);
++  OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
++           pFile->h, pBuf, amt, offset, pFile->locktype));
++
+ #if SQLITE_MAX_MMAP_SIZE>0
+-static int winUnmapfile(winFile *pFile){
+-  assert( pFile!=0 );
+-  OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
+-           "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
+-           osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
+-           pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
+-  if( pFile->pMapRegion ){
+-    if( !osUnmapViewOfFile(pFile->pMapRegion) ){
+-      pFile->lastErrno = osGetLastError();
+-      OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
+-               "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
+-               pFile->pMapRegion));
+-      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
+-                         "winUnmap1", pFile->zPath);
++  /* Deal with as much of this read request as possible by transfering
++  ** data from the memory mapping using memcpy().  */
++  if( offset<pFile->mmapSize ){
++    if( offset+amt <= pFile->mmapSize ){
++      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
++      OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }else{
++      int nCopy = (int)(pFile->mmapSize - offset);
++      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
++      pBuf = &((u8 *)pBuf)[nCopy];
++      amt -= nCopy;
++      offset += nCopy;
+     }
+-    pFile->pMapRegion = 0;
+-    pFile->mmapSize = 0;
+-    pFile->mmapSizeActual = 0;
+   }
+-  if( pFile->hMap!=NULL ){
+-    if( !osCloseHandle(pFile->hMap) ){
+-      pFile->lastErrno = osGetLastError();
+-      OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
+-               osGetCurrentProcessId(), pFile, pFile->hMap));
+-      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
+-                         "winUnmap2", pFile->zPath);
+-    }
+-    pFile->hMap = NULL;
++#endif
++
++#if SQLITE_OS_WINCE
++  if( seekWinFile(pFile, offset) ){
++    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
++    return SQLITE_FULL;
++  }
++  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
++#else
++  memset(&overlapped, 0, sizeof(OVERLAPPED));
++  overlapped.Offset = (LONG)(offset & 0xffffffff);
++  overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
++  while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
++         osGetLastError()!=ERROR_HANDLE_EOF ){
++#endif
++    DWORD lastErrno;
++    if( retryIoerr(&nRetry, &lastErrno) ) continue;
++    pFile->lastErrno = lastErrno;
++    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
++    return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
++             "winRead", pFile->zPath);
++  }
++  logIoerr(nRetry);
++  if( nRead<(DWORD)amt ){
++    /* Unread parts of the buffer must be zero-filled */
++    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
++    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
++    return SQLITE_IOERR_SHORT_READ;
+   }
+-  OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
+-           osGetCurrentProcessId(), pFile));
++
++  OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
+   return SQLITE_OK;
+ }
+ 
+ /*
+-** Memory map or remap the file opened by file-descriptor pFd (if the file
+-** is already mapped, the existing mapping is replaced by the new). Or, if 
+-** there already exists a mapping for this file, and there are still 
+-** outstanding xFetch() references to it, this function is a no-op.
+-**
+-** If parameter nByte is non-negative, then it is the requested size of 
+-** the mapping to create. Otherwise, if nByte is less than zero, then the 
+-** requested size is the size of the file on disk. The actual size of the
+-** created mapping is either the requested size or the value configured 
+-** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
+-**
+-** SQLITE_OK is returned if no error occurs (even if the mapping is not
+-** recreated as a result of outstanding references) or an SQLite error
+-** code otherwise.
++** Write data from a buffer into a file.  Return SQLITE_OK on success
++** or some other error code on failure.
+ */
+-static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
+-  sqlite3_int64 nMap = nByte;
+-  int rc;
++static int winWrite(
++  sqlite3_file *id,               /* File to write into */
++  const void *pBuf,               /* The bytes to be written */
++  int amt,                        /* Number of bytes to write */
++  sqlite3_int64 offset            /* Offset into the file to begin writing at */
++){
++  int rc = 0;                     /* True if error has occurred, else false */
++  winFile *pFile = (winFile*)id;  /* File handle */
++  int nRetry = 0;                 /* Number of retries */
+ 
+-  assert( nMap>=0 || pFd->nFetchOut==0 );
+-  OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
+-           osGetCurrentProcessId(), pFd, nByte));
++  assert( amt>0 );
++  assert( pFile );
++  SimulateIOError(return SQLITE_IOERR_WRITE);
++  SimulateDiskfullError(return SQLITE_FULL);
+ 
+-  if( pFd->nFetchOut>0 ) return SQLITE_OK;
++  OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
++           pFile->h, pBuf, amt, offset, pFile->locktype));
+ 
+-  if( nMap<0 ){
+-    rc = winFileSize((sqlite3_file*)pFd, &nMap);
+-    if( rc ){
+-      OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
+-               osGetCurrentProcessId(), pFd));
+-      return SQLITE_IOERR_FSTAT;
++#if SQLITE_MAX_MMAP_SIZE>0
++  /* Deal with as much of this write request as possible by transfering
++  ** data from the memory mapping using memcpy().  */
++  if( offset<pFile->mmapSize ){
++    if( offset+amt <= pFile->mmapSize ){
++      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
++      OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }else{
++      int nCopy = (int)(pFile->mmapSize - offset);
++      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
++      pBuf = &((u8 *)pBuf)[nCopy];
++      amt -= nCopy;
++      offset += nCopy;
+     }
+   }
+-  if( nMap>pFd->mmapSizeMax ){
+-    nMap = pFd->mmapSizeMax;
+-  }
+-  nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
+- 
+-  if( nMap==0 && pFd->mmapSize>0 ){
+-    winUnmapfile(pFd);
+-  }
+-  if( nMap!=pFd->mmapSize ){
+-    void *pNew = 0;
+-    DWORD protect = PAGE_READONLY;
+-    DWORD flags = FILE_MAP_READ;
++#endif
+ 
+-    winUnmapfile(pFd);
+-    if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
+-      protect = PAGE_READWRITE;
+-      flags |= FILE_MAP_WRITE;
+-    }
+-#if SQLITE_OS_WINRT
+-    pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
+-#elif defined(SQLITE_WIN32_HAS_WIDE)
+-    pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
+-                                (DWORD)((nMap>>32) & 0xffffffff),
+-                                (DWORD)(nMap & 0xffffffff), NULL);
+-#elif defined(SQLITE_WIN32_HAS_ANSI)
+-    pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
+-                                (DWORD)((nMap>>32) & 0xffffffff),
+-                                (DWORD)(nMap & 0xffffffff), NULL);
++#if SQLITE_OS_WINCE
++  rc = seekWinFile(pFile, offset);
++  if( rc==0 ){
++#else
++  {
+ #endif
+-    if( pFd->hMap==NULL ){
+-      pFd->lastErrno = osGetLastError();
+-      rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
+-                       "winMapfile", pFd->zPath);
+-      /* Log the error, but continue normal operation using xRead/xWrite */
+-      OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
+-               osGetCurrentProcessId(), pFd));
+-      return SQLITE_OK;
+-    }
+-    assert( (nMap % winSysInfo.dwPageSize)==0 );
+-#if SQLITE_OS_WINRT
+-    pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
++#if !SQLITE_OS_WINCE
++    OVERLAPPED overlapped;        /* The offset for WriteFile. */
++#endif
++    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
++    int nRem = amt;               /* Number of bytes yet to be written */
++    DWORD nWrite;                 /* Bytes written by each WriteFile() call */
++    DWORD lastErrno = NO_ERROR;   /* Value returned by GetLastError() */
++
++#if !SQLITE_OS_WINCE
++    memset(&overlapped, 0, sizeof(OVERLAPPED));
++    overlapped.Offset = (LONG)(offset & 0xffffffff);
++    overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
++#endif
++
++    while( nRem>0 ){
++#if SQLITE_OS_WINCE
++      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
+ #else
+-    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
+-    pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
++      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
+ #endif
+-    if( pNew==NULL ){
+-      osCloseHandle(pFd->hMap);
+-      pFd->hMap = NULL;
+-      pFd->lastErrno = osGetLastError();
+-      winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
+-                  "winMapfile", pFd->zPath);
+-      OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
+-               osGetCurrentProcessId(), pFd));
+-      return SQLITE_OK;
++        if( retryIoerr(&nRetry, &lastErrno) ) continue;
++        break;
++      }
++      assert( nWrite==0 || nWrite<=(DWORD)nRem );
++      if( nWrite==0 || nWrite>(DWORD)nRem ){
++        lastErrno = osGetLastError();
++        break;
++      }
++#if !SQLITE_OS_WINCE
++      offset += nWrite;
++      overlapped.Offset = (LONG)(offset & 0xffffffff);
++      overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
++#endif
++      aRem += nWrite;
++      nRem -= nWrite;
++    }
++    if( nRem>0 ){
++      pFile->lastErrno = lastErrno;
++      rc = 1;
+     }
+-    pFd->pMapRegion = pNew;
+-    pFd->mmapSize = nMap;
+-    pFd->mmapSizeActual = nMap;
+   }
+ 
+-  OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
+-           osGetCurrentProcessId(), pFd));
++  if( rc ){
++    if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
++       || ( pFile->lastErrno==ERROR_DISK_FULL )){
++      OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
++      return SQLITE_FULL;
++    }
++    OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
++    return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
++             "winWrite", pFile->zPath);
++  }else{
++    logIoerr(nRetry);
++  }
++  OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
+   return SQLITE_OK;
+ }
+-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+ 
+ /*
+-** If possible, return a pointer to a mapping of file fd starting at offset
+-** iOff. The mapping must be valid for at least nAmt bytes.
+-**
+-** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
+-** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
+-** Finally, if an error does occur, return an SQLite error code. The final
+-** value of *pp is undefined in this case.
+-**
+-** If this function does return a pointer, the caller must eventually 
+-** release the reference by calling winUnfetch().
++** Truncate an open file to a specified size
+ */
+-static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  winFile *pFd = (winFile*)fd;   /* The underlying database file */
+-#endif
+-  *pp = 0;
++static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
++  winFile *pFile = (winFile*)id;  /* File handle object */
++  int rc = SQLITE_OK;             /* Return code for this function */
++  DWORD lastErrno;
+ 
+-  OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
+-           osGetCurrentProcessId(), fd, iOff, nAmt, pp));
++  assert( pFile );
++  SimulateIOError(return SQLITE_IOERR_TRUNCATE);
++  OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
++           pFile->h, nByte, pFile->locktype));
++
++  /* If the user has configured a chunk-size for this file, truncate the
++  ** file so that it consists of an integer number of chunks (i.e. the
++  ** actual file size after the operation may be larger than the requested
++  ** size).
++  */
++  if( pFile->szChunk>0 ){
++    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
++  }
++
++  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
++  if( seekWinFile(pFile, nByte) ){
++    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
++                     "winTruncate1", pFile->zPath);
++  }else if( 0==osSetEndOfFile(pFile->h) &&
++            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
++    pFile->lastErrno = lastErrno;
++    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
++                     "winTruncate2", pFile->zPath);
++  }
+ 
+ #if SQLITE_MAX_MMAP_SIZE>0
+-  if( pFd->mmapSizeMax>0 ){
+-    if( pFd->pMapRegion==0 ){
+-      int rc = winMapfile(pFd, -1);
+-      if( rc!=SQLITE_OK ){
+-        OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
+-                 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
+-        return rc;
+-      }
+-    }
+-    if( pFd->mmapSize >= iOff+nAmt ){
+-      *pp = &((u8 *)pFd->pMapRegion)[iOff];
+-      pFd->nFetchOut++;
+-    }
++  /* If the file was truncated to a size smaller than the currently
++  ** mapped region, reduce the effective mapping size as well. SQLite will
++  ** use read() and write() to access data beyond this point from now on.
++  */
++  if( pFile->pMapRegion && nByte<pFile->mmapSize ){
++    pFile->mmapSize = nByte;
+   }
+ #endif
+ 
+-  OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
+-           osGetCurrentProcessId(), fd, pp, *pp));
+-  return SQLITE_OK;
++  OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
++  return rc;
+ }
+ 
++#ifdef SQLITE_TEST
+ /*
+-** If the third argument is non-NULL, then this function releases a 
+-** reference obtained by an earlier call to winFetch(). The second
+-** argument passed to this function must be the same as the corresponding
+-** argument that was passed to the winFetch() invocation. 
+-**
+-** Or, if the third argument is NULL, then this function is being called 
+-** to inform the VFS layer that, according to POSIX, any existing mapping 
+-** may now be invalid and should be unmapped.
++** Count the number of fullsyncs and normal syncs.  This is used to test
++** that syncs and fullsyncs are occuring at the right times.
+ */
+-static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  winFile *pFd = (winFile*)fd;   /* The underlying database file */
++SQLITE_API int sqlite3_sync_count = 0;
++SQLITE_API int sqlite3_fullsync_count = 0;
++#endif
+ 
+-  /* If p==0 (unmap the entire file) then there must be no outstanding 
+-  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
+-  ** then there must be at least one outstanding.  */
+-  assert( (p==0)==(pFd->nFetchOut==0) );
++/*
++** Make sure all writes to a particular file are committed to disk.
++*/
++static int winSync(sqlite3_file *id, int flags){
++#ifndef SQLITE_NO_SYNC
++  /*
++  ** Used only when SQLITE_NO_SYNC is not defined.
++   */
++  BOOL rc;
++#endif
++#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
++    (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
++  /*
++  ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
++  ** OSTRACE() macros.
++   */
++  winFile *pFile = (winFile*)id;
++#else
++  UNUSED_PARAMETER(id);
++#endif
+ 
+-  /* If p!=0, it must match the iOff value. */
+-  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
++  assert( pFile );
++  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
++  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
++      || (flags&0x0F)==SQLITE_SYNC_FULL
++  );
+ 
+-  OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
+-           osGetCurrentProcessId(), pFd, iOff, p));
++  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
++  ** line is to test that doing so does not cause any problems.
++  */
++  SimulateDiskfullError( return SQLITE_FULL );
+ 
+-  if( p ){
+-    pFd->nFetchOut--;
+-  }else{
+-    /* FIXME:  If Windows truly always prevents truncating or deleting a
+-    ** file while a mapping is held, then the following winUnmapfile() call
+-    ** is unnecessary can can be omitted - potentially improving
+-    ** performance.  */
+-    winUnmapfile(pFd);
+-  }
++  OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
++           pFile->h, flags, pFile->locktype));
+ 
+-  assert( pFd->nFetchOut>=0 );
++#ifndef SQLITE_TEST
++  UNUSED_PARAMETER(flags);
++#else
++  if( (flags&0x0F)==SQLITE_SYNC_FULL ){
++    sqlite3_fullsync_count++;
++  }
++  sqlite3_sync_count++;
+ #endif
+ 
+-  OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
+-           osGetCurrentProcessId(), fd));
++  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
++  ** no-op
++  */
++#ifdef SQLITE_NO_SYNC
+   return SQLITE_OK;
++#else
++  rc = osFlushFileBuffers(pFile->h);
++  SimulateIOError( rc=FALSE );
++  if( rc ){
++    OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
++    return SQLITE_OK;
++  }else{
++    pFile->lastErrno = osGetLastError();
++    OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
++    return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
++             "winSync", pFile->zPath);
++  }
++#endif
+ }
+ 
+ /*
+-** Here ends the implementation of all sqlite3_file methods.
+-**
+-********************** End sqlite3_file Methods *******************************
+-******************************************************************************/
+-
+-/*
+-** This vector defines all the methods that can operate on an
+-** sqlite3_file for win32.
++** Determine the current size of a file in bytes
+ */
+-static const sqlite3_io_methods winIoMethod = {
+-  3,                              /* iVersion */
+-  winClose,                       /* xClose */
+-  winRead,                        /* xRead */
+-  winWrite,                       /* xWrite */
+-  winTruncate,                    /* xTruncate */
+-  winSync,                        /* xSync */
+-  winFileSize,                    /* xFileSize */
+-  winLock,                        /* xLock */
+-  winUnlock,                      /* xUnlock */
+-  winCheckReservedLock,           /* xCheckReservedLock */
+-  winFileControl,                 /* xFileControl */
+-  winSectorSize,                  /* xSectorSize */
+-  winDeviceCharacteristics,       /* xDeviceCharacteristics */
+-  winShmMap,                      /* xShmMap */
+-  winShmLock,                     /* xShmLock */
+-  winShmBarrier,                  /* xShmBarrier */
+-  winShmUnmap,                    /* xShmUnmap */
+-  winFetch,                       /* xFetch */
+-  winUnfetch                      /* xUnfetch */
+-};
++static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
++  winFile *pFile = (winFile*)id;
++  int rc = SQLITE_OK;
+ 
+-/****************************************************************************
+-**************************** sqlite3_vfs methods ****************************
+-**
+-** This division contains the implementation of methods on the
+-** sqlite3_vfs object.
+-*/
++  assert( id!=0 );
++  assert( pSize!=0 );
++  SimulateIOError(return SQLITE_IOERR_FSTAT);
++  OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
+ 
+-/*
+-** Convert a UTF-8 filename into whatever form the underlying
+-** operating system wants filenames in.  Space to hold the result
+-** is obtained from malloc and must be freed by the calling
+-** function.
+-*/
+-static void *convertUtf8Filename(const char *zFilename){
+-  void *zConverted = 0;
+-  if( isNT() ){
+-    zConverted = utf8ToUnicode(zFilename);
++#if SQLITE_OS_WINRT
++  {
++    FILE_STANDARD_INFO info;
++    if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
++                                     &info, sizeof(info)) ){
++      *pSize = info.EndOfFile.QuadPart;
++    }else{
++      pFile->lastErrno = osGetLastError();
++      rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
++                       "winFileSize", pFile->zPath);
++    }
+   }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
++#else
++  {
++    DWORD upperBits;
++    DWORD lowerBits;
++    DWORD lastErrno;
++
++    lowerBits = osGetFileSize(pFile->h, &upperBits);
++    *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
++    if(   (lowerBits == INVALID_FILE_SIZE)
++       && ((lastErrno = osGetLastError())!=NO_ERROR) ){
++      pFile->lastErrno = lastErrno;
++      rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
++             "winFileSize", pFile->zPath);
++    }
+   }
+ #endif
+-  /* caller will handle out of memory */
+-  return zConverted;
++  OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
++           pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
++  return rc;
+ }
+ 
+ /*
+-** Create a temporary file name in zBuf.  zBuf must be big enough to
+-** hold at pVfs->mxPathname characters.
++** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
+ */
+-static int getTempname(int nBuf, char *zBuf){
+-  static char zChars[] =
+-    "abcdefghijklmnopqrstuvwxyz"
+-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+-    "0123456789";
+-  size_t i, j;
+-  int nTempPath;
+-  char zTempPath[MAX_PATH+2];
++#ifndef LOCKFILE_FAIL_IMMEDIATELY
++# define LOCKFILE_FAIL_IMMEDIATELY 1
++#endif
+ 
+-  /* It's odd to simulate an io-error here, but really this is just
+-  ** using the io-error infrastructure to test that SQLite handles this
+-  ** function failing. 
+-  */
+-  SimulateIOError( return SQLITE_IOERR );
++#ifndef LOCKFILE_EXCLUSIVE_LOCK
++# define LOCKFILE_EXCLUSIVE_LOCK 2
++#endif
+ 
+-  memset(zTempPath, 0, MAX_PATH+2);
++/*
++** Historically, SQLite has used both the LockFile and LockFileEx functions.
++** When the LockFile function was used, it was always expected to fail
++** immediately if the lock could not be obtained.  Also, it always expected to
++** obtain an exclusive lock.  These flags are used with the LockFileEx function
++** and reflect those expectations; therefore, they should not be changed.
++*/
++#ifndef SQLITE_LOCKFILE_FLAGS
++# define SQLITE_LOCKFILE_FLAGS   (LOCKFILE_FAIL_IMMEDIATELY | \
++                                  LOCKFILE_EXCLUSIVE_LOCK)
++#endif
+ 
+-  if( sqlite3_temp_directory ){
+-    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
+-  }
+-#if !SQLITE_OS_WINRT
+-  else if( isNT() ){
+-    char *zMulti;
+-    WCHAR zWidePath[MAX_PATH];
+-    osGetTempPathW(MAX_PATH-30, zWidePath);
+-    zMulti = unicodeToUtf8(zWidePath);
+-    if( zMulti ){
+-      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
+-      sqlite3_free(zMulti);
+-    }else{
+-      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+-      return SQLITE_IOERR_NOMEM;
+-    }
++/*
++** Currently, SQLite never calls the LockFileEx function without wanting the
++** call to fail immediately if the lock cannot be obtained.
++*/
++#ifndef SQLITE_LOCKFILEEX_FLAGS
++# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
++#endif
++
++/*
++** Acquire a reader lock.
++** Different API routines are called depending on whether or not this
++** is Win9x or WinNT.
++*/
++static int getReadLock(winFile *pFile){
++  int res;
++  OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
++  if( isNT() ){
++#if SQLITE_OS_WINCE
++    /*
++    ** NOTE: Windows CE is handled differently here due its lack of the Win32
++    **       API LockFileEx.
++    */
++    res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
++#else
++    res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
++                      SHARED_SIZE, 0);
++#endif
+   }
+ #ifdef SQLITE_WIN32_HAS_ANSI
+   else{
+-    char *zUtf8;
+-    char zMbcsPath[MAX_PATH];
+-    osGetTempPathA(MAX_PATH-30, zMbcsPath);
+-    zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
+-    if( zUtf8 ){
+-      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
+-      sqlite3_free(zUtf8);
+-    }else{
+-      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+-      return SQLITE_IOERR_NOMEM;
+-    }
++    int lk;
++    sqlite3_randomness(sizeof(lk), &lk);
++    pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
++    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
++                      SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
+   }
+ #endif
+-#endif
+-
+-  /* Check that the output buffer is large enough for the temporary file 
+-  ** name. If it is not, return SQLITE_ERROR.
+-  */
+-  nTempPath = sqlite3Strlen30(zTempPath);
+-
+-  if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
+-    OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
+-    return SQLITE_ERROR;
+-  }
+-
+-  for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
+-  zTempPath[i] = 0;
+-
+-  sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
+-                       "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
+-                   zTempPath);
+-  j = sqlite3Strlen30(zBuf);
+-  sqlite3_randomness(15, &zBuf[j]);
+-  for(i=0; i<15; i++, j++){
+-    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
++  if( res == 0 ){
++    pFile->lastErrno = osGetLastError();
++    /* No need to log a failure to lock */
+   }
+-  zBuf[j] = 0;
+-  zBuf[j+1] = 0;
+-
+-  OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
+-  return SQLITE_OK;
++  OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
++  return res;
+ }
+ 
+ /*
+-** Return TRUE if the named file is really a directory.  Return false if
+-** it is something other than a directory, or if there is any kind of memory
+-** allocation failure.
++** Undo a readlock
+ */
+-static int winIsDir(const void *zConverted){
+-  DWORD attr;
+-  int rc = 0;
++static int unlockReadLock(winFile *pFile){
++  int res;
+   DWORD lastErrno;
+-
++  OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
+   if( isNT() ){
+-    int cnt = 0;
+-    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+-    memset(&sAttrData, 0, sizeof(sAttrData));
+-    while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
+-                             GetFileExInfoStandard,
+-                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+-    if( !rc ){
+-      return 0; /* Invalid name? */
+-    }
+-    attr = sAttrData.dwFileAttributes;
+-#if SQLITE_OS_WINCE==0
+-  }else{
+-    attr = osGetFileAttributesA((char*)zConverted);
++    res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
++  }
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
++  }
+ #endif
++  if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
++    pFile->lastErrno = lastErrno;
++    winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
++             "unlockReadLock", pFile->zPath);
+   }
+-  return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
++  OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
++  return res;
+ }
+ 
+ /*
+-** Open a file.
++** Lock the file with the lock specified by parameter locktype - one
++** of the following:
++**
++**     (1) SHARED_LOCK
++**     (2) RESERVED_LOCK
++**     (3) PENDING_LOCK
++**     (4) EXCLUSIVE_LOCK
++**
++** Sometimes when requesting one lock state, additional lock states
++** are inserted in between.  The locking might fail on one of the later
++** transitions leaving the lock state different from what it started but
++** still short of its goal.  The following chart shows the allowed
++** transitions and the inserted intermediate states:
++**
++**    UNLOCKED -> SHARED
++**    SHARED -> RESERVED
++**    SHARED -> (PENDING) -> EXCLUSIVE
++**    RESERVED -> (PENDING) -> EXCLUSIVE
++**    PENDING -> EXCLUSIVE
++**
++** This routine will only increase a lock.  The winUnlock() routine
++** erases all locks at once and returns us immediately to locking level 0.
++** It is not possible to lower the locking level one step at a time.  You
++** must go straight to locking level 0.
+ */
+-static int winOpen(
+-  sqlite3_vfs *pVfs,        /* Not used */
+-  const char *zName,        /* Name of the file (UTF-8) */
+-  sqlite3_file *id,         /* Write the SQLite file handle here */
+-  int flags,                /* Open mode flags */
+-  int *pOutFlags            /* Status return flags */
+-){
+-  HANDLE h;
+-  DWORD lastErrno;
+-  DWORD dwDesiredAccess;
+-  DWORD dwShareMode;
+-  DWORD dwCreationDisposition;
+-  DWORD dwFlagsAndAttributes = 0;
+-#if SQLITE_OS_WINCE
+-  int isTemp = 0;
+-#endif
++static int winLock(sqlite3_file *id, int locktype){
++  int rc = SQLITE_OK;    /* Return code from subroutines */
++  int res = 1;           /* Result of a Windows lock call */
++  int newLocktype;       /* Set pFile->locktype to this value before exiting */
++  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
+   winFile *pFile = (winFile*)id;
+-  void *zConverted;              /* Filename in OS encoding */
+-  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
+-  int cnt = 0;
+-
+-  /* If argument zPath is a NULL pointer, this function is required to open
+-  ** a temporary file. Use this buffer to store the file name in.
+-  */
+-  char zTmpname[MAX_PATH+2];     /* Buffer used to create temp filename */
+-
+-  int rc = SQLITE_OK;            /* Function Return Code */
+-#if !defined(NDEBUG) || SQLITE_OS_WINCE
+-  int eType = flags&0xFFFFFF00;  /* Type of file to open */
+-#endif
+-
+-  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
+-  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
+-  int isCreate     = (flags & SQLITE_OPEN_CREATE);
+-  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
+-  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
+-
+-#ifndef NDEBUG
+-  int isOpenJournal = (isCreate && (
+-        eType==SQLITE_OPEN_MASTER_JOURNAL 
+-     || eType==SQLITE_OPEN_MAIN_JOURNAL 
+-     || eType==SQLITE_OPEN_WAL
+-  ));
+-#endif
++  DWORD lastErrno = NO_ERROR;
+ 
+-  OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
+-           zUtf8Name, id, flags, pOutFlags));
++  assert( id!=0 );
++  OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
++           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
+ 
+-  /* Check the following statements are true: 
+-  **
+-  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
+-  **   (b) if CREATE is set, then READWRITE must also be set, and
+-  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
+-  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
++  /* If there is already a lock of this type or more restrictive on the
++  ** OsFile, do nothing. Don't use the end_lock: exit path, as
++  ** sqlite3OsEnterMutex() hasn't been called yet.
+   */
+-  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
+-  assert(isCreate==0 || isReadWrite);
+-  assert(isExclusive==0 || isCreate);
+-  assert(isDelete==0 || isCreate);
+-
+-  /* The main DB, main journal, WAL file and master journal are never 
+-  ** automatically deleted. Nor are they ever temporary files.  */
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
+-  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
++  if( pFile->locktype>=locktype ){
++    OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
++    return SQLITE_OK;
++  }
+ 
+-  /* Assert that the upper layer has set one of the "file-type" flags. */
+-  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
+-       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
+-       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
+-       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
+-  );
++  /* Make sure the locking sequence is correct
++  */
++  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
++  assert( locktype!=PENDING_LOCK );
++  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
+ 
+-  assert( pFile!=0 );
+-  memset(pFile, 0, sizeof(winFile));
+-  pFile->h = INVALID_HANDLE_VALUE;
++  /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
++  ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
++  ** the PENDING_LOCK byte is temporary.
++  */
++  newLocktype = pFile->locktype;
++  if(   (pFile->locktype==NO_LOCK)
++     || (   (locktype==EXCLUSIVE_LOCK)
++         && (pFile->locktype==RESERVED_LOCK))
++  ){
++    int cnt = 3;
++    while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
++                                         PENDING_BYTE, 0, 1, 0))==0 ){
++      /* Try 3 times to get the pending lock.  This is needed to work
++      ** around problems caused by indexing and/or anti-virus software on
++      ** Windows systems.
++      ** If you are using this code as a model for alternative VFSes, do not
++      ** copy this retry logic.  It is a hack intended for Windows only.
++      */
++      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
++               pFile->h, cnt, sqlite3ErrName(res)));
++      if( cnt ) sqlite3_win32_sleep(1);
++    }
++    gotPendingLock = res;
++    if( !res ){
++      lastErrno = osGetLastError();
++    }
++  }
+ 
+-#if SQLITE_OS_WINRT
+-  if( !sqlite3_temp_directory ){
+-    sqlite3_log(SQLITE_ERROR,
+-        "sqlite3_temp_directory variable should be set for WinRT");
++  /* Acquire a shared lock
++  */
++  if( locktype==SHARED_LOCK && res ){
++    assert( pFile->locktype==NO_LOCK );
++    res = getReadLock(pFile);
++    if( res ){
++      newLocktype = SHARED_LOCK;
++    }else{
++      lastErrno = osGetLastError();
++    }
+   }
+-#endif
+ 
+-  /* If the second argument to this function is NULL, generate a 
+-  ** temporary file name to use 
++  /* Acquire a RESERVED lock
+   */
+-  if( !zUtf8Name ){
+-    assert(isDelete && !isOpenJournal);
+-    memset(zTmpname, 0, MAX_PATH+2);
+-    rc = getTempname(MAX_PATH+2, zTmpname);
+-    if( rc!=SQLITE_OK ){
+-      OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
+-      return rc;
++  if( locktype==RESERVED_LOCK && res ){
++    assert( pFile->locktype==SHARED_LOCK );
++    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
++    if( res ){
++      newLocktype = RESERVED_LOCK;
++    }else{
++      lastErrno = osGetLastError();
+     }
+-    zUtf8Name = zTmpname;
+   }
+ 
+-  /* Database filenames are double-zero terminated if they are not
+-  ** URIs with parameters.  Hence, they can always be passed into
+-  ** sqlite3_uri_parameter().
++  /* Acquire a PENDING lock
+   */
+-  assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
+-        zUtf8Name[strlen(zUtf8Name)+1]==0 );
++  if( locktype==EXCLUSIVE_LOCK && res ){
++    newLocktype = PENDING_LOCK;
++    gotPendingLock = 0;
++  }
+ 
+-  /* Convert the filename to the system encoding. */
+-  zConverted = convertUtf8Filename(zUtf8Name);
+-  if( zConverted==0 ){
+-    OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
+-    return SQLITE_IOERR_NOMEM;
++  /* Acquire an EXCLUSIVE lock
++  */
++  if( locktype==EXCLUSIVE_LOCK && res ){
++    assert( pFile->locktype>=SHARED_LOCK );
++    res = unlockReadLock(pFile);
++    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
++                      SHARED_SIZE, 0);
++    if( res ){
++      newLocktype = EXCLUSIVE_LOCK;
++    }else{
++      lastErrno = osGetLastError();
++      getReadLock(pFile);
++    }
+   }
+ 
+-  if( winIsDir(zConverted) ){
+-    sqlite3_free(zConverted);
+-    OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
+-    return SQLITE_CANTOPEN_ISDIR;
++  /* If we are holding a PENDING lock that ought to be released, then
++  ** release it now.
++  */
++  if( gotPendingLock && locktype==SHARED_LOCK ){
++    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
+   }
+ 
+-  if( isReadWrite ){
+-    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
++  /* Update the state of the lock has held in the file descriptor then
++  ** return the appropriate result code.
++  */
++  if( res ){
++    rc = SQLITE_OK;
+   }else{
+-    dwDesiredAccess = GENERIC_READ;
++    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
++             pFile->h, locktype, newLocktype));
++    pFile->lastErrno = lastErrno;
++    rc = SQLITE_BUSY;
+   }
++  pFile->locktype = (u8)newLocktype;
++  OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
++           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
++  return rc;
++}
+ 
+-  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 
+-  ** created. SQLite doesn't use it to indicate "exclusive access" 
+-  ** as it is usually understood.
+-  */
+-  if( isExclusive ){
+-    /* Creates a new file, only if it does not already exist. */
+-    /* If the file exists, it fails. */
+-    dwCreationDisposition = CREATE_NEW;
+-  }else if( isCreate ){
+-    /* Open existing file, or create if it doesn't exist */
+-    dwCreationDisposition = OPEN_ALWAYS;
++/*
++** This routine checks if there is a RESERVED lock held on the specified
++** file by this or any other process. If such a lock is held, return
++** non-zero, otherwise zero.
++*/
++static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
++  int rc;
++  winFile *pFile = (winFile*)id;
++
++  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
++  OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
++
++  assert( id!=0 );
++  if( pFile->locktype>=RESERVED_LOCK ){
++    rc = 1;
++    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
+   }else{
+-    /* Opens a file, only if it exists. */
+-    dwCreationDisposition = OPEN_EXISTING;
++    rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
++    if( rc ){
++      winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
++    }
++    rc = !rc;
++    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
+   }
++  *pResOut = rc;
++  OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
++           pFile->h, pResOut, *pResOut));
++  return SQLITE_OK;
++}
+ 
+-  dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
++/*
++** Lower the locking level on file descriptor id to locktype.  locktype
++** must be either NO_LOCK or SHARED_LOCK.
++**
++** If the locking level of the file descriptor is already at or below
++** the requested locking level, this routine is a no-op.
++**
++** It is not possible for this routine to fail if the second argument
++** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
++** might return SQLITE_IOERR;
++*/
++static int winUnlock(sqlite3_file *id, int locktype){
++  int type;
++  winFile *pFile = (winFile*)id;
++  int rc = SQLITE_OK;
++  assert( pFile!=0 );
++  assert( locktype<=SHARED_LOCK );
++  OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
++           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
++  type = pFile->locktype;
++  if( type>=EXCLUSIVE_LOCK ){
++    winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
++    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
++      /* This should never happen.  We should always be able to
++      ** reacquire the read lock */
++      rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
++               "winUnlock", pFile->zPath);
++    }
++  }
++  if( type>=RESERVED_LOCK ){
++    winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
++  }
++  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
++    unlockReadLock(pFile);
++  }
++  if( type>=PENDING_LOCK ){
++    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
++  }
++  pFile->locktype = (u8)locktype;
++  OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
++           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
++  return rc;
++}
+ 
+-  if( isDelete ){
+-#if SQLITE_OS_WINCE
+-    dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
+-    isTemp = 1;
+-#else
+-    dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
+-                               | FILE_ATTRIBUTE_HIDDEN
+-                               | FILE_FLAG_DELETE_ON_CLOSE;
+-#endif
++/*
++** If *pArg is inititially negative then this is a query.  Set *pArg to
++** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
++**
++** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
++*/
++static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
++  if( *pArg<0 ){
++    *pArg = (pFile->ctrlFlags & mask)!=0;
++  }else if( (*pArg)==0 ){
++    pFile->ctrlFlags &= ~mask;
+   }else{
+-    dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
++    pFile->ctrlFlags |= mask;
+   }
+-  /* Reports from the internet are that performance is always
+-  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
+-#if SQLITE_OS_WINCE
+-  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+-#endif
++}
+ 
+-  if( isNT() ){
+-#if SQLITE_OS_WINRT
+-    CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
+-    extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+-    extendedParameters.dwFileAttributes =
+-            dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
+-    extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
+-    extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+-    extendedParameters.lpSecurityAttributes = NULL;
+-    extendedParameters.hTemplateFile = NULL;
+-    while( (h = osCreateFile2((LPCWSTR)zConverted,
+-                              dwDesiredAccess,
+-                              dwShareMode,
+-                              dwCreationDisposition,
+-                              &extendedParameters))==INVALID_HANDLE_VALUE &&
+-                              retryIoerr(&cnt, &lastErrno) ){
+-               /* Noop */
++/* Forward declaration */
++static int getTempname(int nBuf, char *zBuf);
++
++/*
++** Control and query of the open file handle.
++*/
++static int winFileControl(sqlite3_file *id, int op, void *pArg){
++  winFile *pFile = (winFile*)id;
++  OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
++  switch( op ){
++    case SQLITE_FCNTL_LOCKSTATE: {
++      *(int*)pArg = pFile->locktype;
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }
++    case SQLITE_LAST_ERRNO: {
++      *(int*)pArg = (int)pFile->lastErrno;
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_CHUNK_SIZE: {
++      pFile->szChunk = *(int *)pArg;
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_SIZE_HINT: {
++      if( pFile->szChunk>0 ){
++        sqlite3_int64 oldSz;
++        int rc = winFileSize(id, &oldSz);
++        if( rc==SQLITE_OK ){
++          sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
++          if( newSz>oldSz ){
++            SimulateIOErrorBenign(1);
++            rc = winTruncate(id, newSz);
++            SimulateIOErrorBenign(0);
++          }
++        }
++        OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
++        return rc;
++      }
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_PERSIST_WAL: {
++      winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
++      winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
++    }
++    case SQLITE_FCNTL_VFSNAME: {
++      *(char**)pArg = sqlite3_mprintf("win32");
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
+     }
+-#else
+-    while( (h = osCreateFileW((LPCWSTR)zConverted,
+-                              dwDesiredAccess,
+-                              dwShareMode, NULL,
+-                              dwCreationDisposition,
+-                              dwFlagsAndAttributes,
+-                              NULL))==INVALID_HANDLE_VALUE &&
+-                              retryIoerr(&cnt, &lastErrno) ){
+-               /* Noop */
++    case SQLITE_FCNTL_WIN32_AV_RETRY: {
++      int *a = (int*)pArg;
++      if( a[0]>0 ){
++        win32IoerrRetry = a[0];
++      }else{
++        a[0] = win32IoerrRetry;
++      }
++      if( a[1]>0 ){
++        win32IoerrRetryDelay = a[1];
++      }else{
++        a[1] = win32IoerrRetryDelay;
++      }
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
+     }
+-#endif
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    while( (h = osCreateFileA((LPCSTR)zConverted,
+-                              dwDesiredAccess,
+-                              dwShareMode, NULL,
+-                              dwCreationDisposition,
+-                              dwFlagsAndAttributes,
+-                              NULL))==INVALID_HANDLE_VALUE &&
+-                              retryIoerr(&cnt, &lastErrno) ){
+-               /* Noop */
++    case SQLITE_FCNTL_TEMPFILENAME: {
++      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
++      if( zTFile ){
++        getTempname(pFile->pVfs->mxPathname, zTFile);
++        *(char**)pArg = zTFile;
++      }
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
+     }
+-  }
+-#endif
+-  logIoerr(cnt);
+-
+-  OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
+-           dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
+-
+-  if( h==INVALID_HANDLE_VALUE ){
+-    pFile->lastErrno = lastErrno;
+-    winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
+-    sqlite3_free(zConverted);
+-    if( isReadWrite && !isExclusive ){
+-      return winOpen(pVfs, zName, id, 
+-         ((flags|SQLITE_OPEN_READONLY) &
+-                     ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
+-         pOutFlags);
+-    }else{
+-      return SQLITE_CANTOPEN_BKPT;
++#if SQLITE_MAX_MMAP_SIZE>0
++    case SQLITE_FCNTL_MMAP_SIZE: {
++      i64 newLimit = *(i64*)pArg;
++      if( newLimit>sqlite3GlobalConfig.mxMmap ){
++        newLimit = sqlite3GlobalConfig.mxMmap;
++      }
++      *(i64*)pArg = pFile->mmapSizeMax;
++      if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
++      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
++      return SQLITE_OK;
+     }
++#endif
+   }
++  OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
++  return SQLITE_NOTFOUND;
++}
+ 
+-  if( pOutFlags ){
+-    if( isReadWrite ){
+-      *pOutFlags = SQLITE_OPEN_READWRITE;
+-    }else{
+-      *pOutFlags = SQLITE_OPEN_READONLY;
+-    }
+-  }
++/*
++** Return the sector size in bytes of the underlying block device for
++** the specified file. This is almost always 512 bytes, but may be
++** larger for some devices.
++**
++** SQLite code assumes this function cannot fail. It also assumes that
++** if two files are created in the same file-system directory (i.e.
++** a database and its journal file) that the sector size will be the
++** same for both.
++*/
++static int winSectorSize(sqlite3_file *id){
++  (void)id;
++  return SQLITE_DEFAULT_SECTOR_SIZE;
++}
+ 
+-  OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
+-           "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
+-           *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
++/*
++** Return a vector of device characteristics.
++*/
++static int winDeviceCharacteristics(sqlite3_file *id){
++  winFile *p = (winFile*)id;
++  return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
++         ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
++}
+ 
+-#if SQLITE_OS_WINCE
+-  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
+-       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
+-  ){
+-    osCloseHandle(h);
+-    sqlite3_free(zConverted);
+-    OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
+-    return rc;
+-  }
+-  if( isTemp ){
+-    pFile->zDeleteOnClose = zConverted;
+-  }else
+-#endif
+-  {
+-    sqlite3_free(zConverted);
+-  }
++/* 
++** Windows will only let you create file view mappings
++** on allocation size granularity boundaries.
++** During sqlite3_os_init() we do a GetSystemInfo()
++** to get the granularity size.
++*/
++SYSTEM_INFO winSysInfo;
+ 
+-  pFile->pMethod = &winIoMethod;
+-  pFile->pVfs = pVfs;
+-  pFile->h = h;
+-  if( isReadonly ){
+-    pFile->ctrlFlags |= WINFILE_RDONLY;
+-  }
+-  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+-    pFile->ctrlFlags |= WINFILE_PSOW;
+-  }
+-  pFile->lastErrno = NO_ERROR;
+-  pFile->zPath = zName;
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  pFile->hMap = NULL;
+-  pFile->pMapRegion = 0;
+-  pFile->mmapSize = 0;
+-  pFile->mmapSizeActual = 0;
+-  pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
+-#endif
++#ifndef SQLITE_OMIT_WAL
+ 
+-  OpenCounter(+1);
+-  return rc;
++/*
++** Helper functions to obtain and relinquish the global mutex. The
++** global mutex is used to protect the winLockInfo objects used by 
++** this file, all of which may be shared by multiple threads.
++**
++** Function winShmMutexHeld() is used to assert() that the global mutex 
++** is held when required. This function is only used as part of assert() 
++** statements. e.g.
++**
++**   winShmEnterMutex()
++**     assert( winShmMutexHeld() );
++**   winShmLeaveMutex()
++*/
++static void winShmEnterMutex(void){
++  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+ }
++static void winShmLeaveMutex(void){
++  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++}
++#ifdef SQLITE_DEBUG
++static int winShmMutexHeld(void) {
++  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++}
++#endif
+ 
+ /*
+-** Delete the named file.
++** Object used to represent a single file opened and mmapped to provide
++** shared memory.  When multiple threads all reference the same
++** log-summary, each thread has its own winFile object, but they all
++** point to a single instance of this object.  In other words, each
++** log-summary is opened only once per process.
++**
++** winShmMutexHeld() must be true when creating or destroying
++** this object or while reading or writing the following fields:
++**
++**      nRef
++**      pNext 
++**
++** The following fields are read-only after the object is created:
++** 
++**      fid
++**      zFilename
++**
++** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
++** winShmMutexHeld() is true when reading or writing any other field
++** in this structure.
+ **
+-** Note that Windows does not allow a file to be deleted if some other
+-** process has it open.  Sometimes a virus scanner or indexing program
+-** will open a journal file shortly after it is created in order to do
+-** whatever it does.  While this other process is holding the
+-** file open, we will be unable to delete it.  To work around this
+-** problem, we delay 100 milliseconds and try to delete again.  Up
+-** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
+-** up and returning an error.
+ */
+-static int winDelete(
+-  sqlite3_vfs *pVfs,          /* Not used on win32 */
+-  const char *zFilename,      /* Name of file to delete */
+-  int syncDir                 /* Not used on win32 */
+-){
+-  int cnt = 0;
+-  int rc;
+-  DWORD attr;
+-  DWORD lastErrno;
+-  void *zConverted;
+-  UNUSED_PARAMETER(pVfs);
+-  UNUSED_PARAMETER(syncDir);
++struct winShmNode {
++  sqlite3_mutex *mutex;      /* Mutex to access this object */
++  char *zFilename;           /* Name of the file */
++  winFile hFile;             /* File handle from winOpen */
+ 
+-  SimulateIOError(return SQLITE_IOERR_DELETE);
+-  OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
++  int szRegion;              /* Size of shared-memory regions */
++  int nRegion;               /* Size of array apRegion */
++  struct ShmRegion {
++    HANDLE hMap;             /* File handle from CreateFileMapping */
++    void *pMap;
++  } *aRegion;
++  DWORD lastErrno;           /* The Windows errno from the last I/O error */
+ 
+-  zConverted = convertUtf8Filename(zFilename);
+-  if( zConverted==0 ){
+-    return SQLITE_IOERR_NOMEM;
+-  }
+-  if( isNT() ){
+-    do {
+-#if SQLITE_OS_WINRT
+-      WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+-      memset(&sAttrData, 0, sizeof(sAttrData));
+-      if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
+-                                  &sAttrData) ){
+-        attr = sAttrData.dwFileAttributes;
+-      }else{
+-        lastErrno = osGetLastError();
+-        if( lastErrno==ERROR_FILE_NOT_FOUND
+-         || lastErrno==ERROR_PATH_NOT_FOUND ){
+-          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+-        }else{
+-          rc = SQLITE_ERROR;
+-        }
+-        break;
+-      }
+-#else
+-      attr = osGetFileAttributesW(zConverted);
++  int nRef;                  /* Number of winShm objects pointing to this */
++  winShm *pFirst;            /* All winShm objects pointing to this */
++  winShmNode *pNext;         /* Next in list of all winShmNode objects */
++#ifdef SQLITE_DEBUG
++  u8 nextShmId;              /* Next available winShm.id value */
+ #endif
+-      if ( attr==INVALID_FILE_ATTRIBUTES ){
+-        lastErrno = osGetLastError();
+-        if( lastErrno==ERROR_FILE_NOT_FOUND
+-         || lastErrno==ERROR_PATH_NOT_FOUND ){
+-          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+-        }else{
+-          rc = SQLITE_ERROR;
+-        }
+-        break;
+-      }
+-      if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
+-        rc = SQLITE_ERROR; /* Files only. */
+-        break;
+-      }
+-      if ( osDeleteFileW(zConverted) ){
+-        rc = SQLITE_OK; /* Deleted OK. */
+-        break;
+-      }
+-      if ( !retryIoerr(&cnt, &lastErrno) ){
+-        rc = SQLITE_ERROR; /* No more retries. */
+-        break;
+-      }
+-    } while(1);
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    do {
+-      attr = osGetFileAttributesA(zConverted);
+-      if ( attr==INVALID_FILE_ATTRIBUTES ){
+-        lastErrno = osGetLastError();
+-        if( lastErrno==ERROR_FILE_NOT_FOUND
+-         || lastErrno==ERROR_PATH_NOT_FOUND ){
+-          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+-        }else{
+-          rc = SQLITE_ERROR;
+-        }
+-        break;
+-      }
+-      if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
+-        rc = SQLITE_ERROR; /* Files only. */
+-        break;
+-      }
+-      if ( osDeleteFileA(zConverted) ){
+-        rc = SQLITE_OK; /* Deleted OK. */
+-        break;
+-      }
+-      if ( !retryIoerr(&cnt, &lastErrno) ){
+-        rc = SQLITE_ERROR; /* No more retries. */
+-        break;
+-      }
+-    } while(1);
+-  }
++};
++
++/*
++** A global array of all winShmNode objects.
++**
++** The winShmMutexHeld() must be true while reading or writing this list.
++*/
++static winShmNode *winShmNodeList = 0;
++
++/*
++** Structure used internally by this VFS to record the state of an
++** open shared memory connection.
++**
++** The following fields are initialized when this object is created and
++** are read-only thereafter:
++**
++**    winShm.pShmNode
++**    winShm.id
++**
++** All other fields are read/write.  The winShm.pShmNode->mutex must be held
++** while accessing any read/write fields.
++*/
++struct winShm {
++  winShmNode *pShmNode;      /* The underlying winShmNode object */
++  winShm *pNext;             /* Next winShm with the same winShmNode */
++  u8 hasMutex;               /* True if holding the winShmNode mutex */
++  u16 sharedMask;            /* Mask of shared locks held */
++  u16 exclMask;              /* Mask of exclusive locks held */
++#ifdef SQLITE_DEBUG
++  u8 id;                     /* Id of this connection with its winShmNode */
+ #endif
+-  if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
+-    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
+-             "winDelete", zFilename);
+-  }else{
+-    logIoerr(cnt);
+-  }
+-  sqlite3_free(zConverted);
+-  OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
+-  return rc;
+-}
++};
+ 
+ /*
+-** Check the existence and status of a file.
++** Constants used for locking
+ */
+-static int winAccess(
+-  sqlite3_vfs *pVfs,         /* Not used on win32 */
+-  const char *zFilename,     /* Name of file to check */
+-  int flags,                 /* Type of test to make on this file */
+-  int *pResOut               /* OUT: Result */
++#define WIN_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
++#define WIN_SHM_DMS    (WIN_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
++
++/*
++** Apply advisory locks for all n bytes beginning at ofst.
++*/
++#define _SHM_UNLCK  1
++#define _SHM_RDLCK  2
++#define _SHM_WRLCK  3
++static int winShmSystemLock(
++  winShmNode *pFile,    /* Apply locks to this open shared-memory segment */
++  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
++  int ofst,             /* Offset to first byte to be locked/unlocked */
++  int nByte             /* Number of bytes to lock or unlock */
+ ){
+-  DWORD attr;
+-  int rc = 0;
+-  DWORD lastErrno;
+-  void *zConverted;
+-  UNUSED_PARAMETER(pVfs);
++  int rc = 0;           /* Result code form Lock/UnlockFileEx() */
+ 
+-  SimulateIOError( return SQLITE_IOERR_ACCESS; );
+-  OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
+-           zFilename, flags, pResOut));
++  /* Access to the winShmNode object is serialized by the caller */
++  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
+ 
+-  zConverted = convertUtf8Filename(zFilename);
+-  if( zConverted==0 ){
+-    OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
+-    return SQLITE_IOERR_NOMEM;
+-  }
+-  if( isNT() ){
+-    int cnt = 0;
+-    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+-    memset(&sAttrData, 0, sizeof(sAttrData));
+-    while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
+-                             GetFileExInfoStandard, 
+-                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+-    if( rc ){
+-      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
+-      ** as if it does not exist.
+-      */
+-      if(    flags==SQLITE_ACCESS_EXISTS
+-          && sAttrData.nFileSizeHigh==0 
+-          && sAttrData.nFileSizeLow==0 ){
+-        attr = INVALID_FILE_ATTRIBUTES;
+-      }else{
+-        attr = sAttrData.dwFileAttributes;
+-      }
+-    }else{
+-      logIoerr(cnt);
+-      if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
+-        winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
+-        sqlite3_free(zConverted);
+-        return SQLITE_IOERR_ACCESS;
+-      }else{
+-        attr = INVALID_FILE_ATTRIBUTES;
+-      }
+-    }
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    attr = osGetFileAttributesA((char*)zConverted);
++  OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
++           pFile->hFile.h, lockType, ofst, nByte));
++
++  /* Release/Acquire the system-level lock */
++  if( lockType==_SHM_UNLCK ){
++    rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
++  }else{
++    /* Initialize the locking parameters */
++    DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
++    if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
++    rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
+   }
+-#endif
+-  sqlite3_free(zConverted);
+-  switch( flags ){
+-    case SQLITE_ACCESS_READ:
+-    case SQLITE_ACCESS_EXISTS:
+-      rc = attr!=INVALID_FILE_ATTRIBUTES;
+-      break;
+-    case SQLITE_ACCESS_READWRITE:
+-      rc = attr!=INVALID_FILE_ATTRIBUTES &&
+-             (attr & FILE_ATTRIBUTE_READONLY)==0;
+-      break;
+-    default:
+-      assert(!"Invalid flags argument");
++  
++  if( rc!= 0 ){
++    rc = SQLITE_OK;
++  }else{
++    pFile->lastErrno =  osGetLastError();
++    rc = SQLITE_BUSY;
+   }
+-  *pResOut = rc;
+-  OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
+-           zFilename, pResOut, *pResOut));
+-  return SQLITE_OK;
++
++  OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
++           pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" :
++           "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
++
++  return rc;
+ }
+ 
++/* Forward references to VFS methods */
++static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
++static int winDelete(sqlite3_vfs *,const char*,int);
+ 
+ /*
+-** Returns non-zero if the specified path name should be used verbatim.  If
+-** non-zero is returned from this function, the calling function must simply
+-** use the provided path name verbatim -OR- resolve it into a full path name
+-** using the GetFullPathName Win32 API function (if available).
++** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
++**
++** This is not a VFS shared-memory method; it is a utility function called
++** by VFS shared-memory methods.
+ */
+-static BOOL winIsVerbatimPathname(
+-  const char *zPathname
+-){
+-  /*
+-  ** If the path name starts with a forward slash or a backslash, it is either
+-  ** a legal UNC name, a volume relative path, or an absolute path name in the
+-  ** "Unix" format on Windows.  There is no easy way to differentiate between
+-  ** the final two cases; therefore, we return the safer return value of TRUE
+-  ** so that callers of this function will simply use it verbatim.
+-  */
+-  if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
+-    return TRUE;
+-  }
+-
+-  /*
+-  ** If the path name starts with a letter and a colon it is either a volume
+-  ** relative path or an absolute path.  Callers of this function must not
+-  ** attempt to treat it as a relative path name (i.e. they should simply use
+-  ** it verbatim).
+-  */
+-  if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
+-    return TRUE;
++static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
++  winShmNode **pp;
++  winShmNode *p;
++  BOOL bRc;
++  assert( winShmMutexHeld() );
++  OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
++           osGetCurrentProcessId(), deleteFlag));
++  pp = &winShmNodeList;
++  while( (p = *pp)!=0 ){
++    if( p->nRef==0 ){
++      int i;
++      if( p->mutex ) sqlite3_mutex_free(p->mutex);
++      for(i=0; i<p->nRegion; i++){
++        bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
++        OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
++                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
++        bRc = osCloseHandle(p->aRegion[i].hMap);
++        OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
++                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
++      }
++      if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
++        SimulateIOErrorBenign(1);
++        winClose((sqlite3_file *)&p->hFile);
++        SimulateIOErrorBenign(0);
++      }
++      if( deleteFlag ){
++        SimulateIOErrorBenign(1);
++        sqlite3BeginBenignMalloc();
++        winDelete(pVfs, p->zFilename, 0);
++        sqlite3EndBenignMalloc();
++        SimulateIOErrorBenign(0);
++      }
++      *pp = p->pNext;
++      sqlite3_free(p->aRegion);
++      sqlite3_free(p);
++    }else{
++      pp = &p->pNext;
++    }
+   }
+-
+-  /*
+-  ** If we get to this point, the path name should almost certainly be a purely
+-  ** relative one (i.e. not a UNC name, not absolute, and not volume relative).
+-  */
+-  return FALSE;
+ }
+ 
+ /*
+-** Turn a relative pathname into a full pathname.  Write the full
+-** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
+-** bytes in size.
++** Open the shared-memory area associated with database file pDbFd.
++**
++** When opening a new shared-memory file, if no other instances of that
++** file are currently open, in this process or in other processes, then
++** the file must be truncated to zero length or have its header cleared.
+ */
+-static int winFullPathname(
+-  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
+-  const char *zRelative,        /* Possibly relative input path */
+-  int nFull,                    /* Size of output buffer in bytes */
+-  char *zFull                   /* Output buffer */
+-){
+-  
+-#if defined(__CYGWIN__)
+-  SimulateIOError( return SQLITE_ERROR );
+-  UNUSED_PARAMETER(nFull);
+-  assert( pVfs->mxPathname>=MAX_PATH );
+-  assert( nFull>=pVfs->mxPathname );
+-  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
+-    /*
+-    ** NOTE: We are dealing with a relative path name and the data
+-    **       directory has been set.  Therefore, use it as the basis
+-    **       for converting the relative path name to an absolute
+-    **       one by prepending the data directory and a slash.
+-    */
+-    char zOut[MAX_PATH+1];
+-    memset(zOut, 0, MAX_PATH+1);
+-    cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
+-                     MAX_PATH+1);
+-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
+-                     sqlite3_data_directory, zOut);
+-  }else{
+-    cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
+-  }
+-  return SQLITE_OK;
+-#endif
+-
+-#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
+-  SimulateIOError( return SQLITE_ERROR );
+-  /* WinCE has no concept of a relative pathname, or so I am told. */
+-  /* WinRT has no way to convert a relative path to an absolute one. */
+-  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
+-    /*
+-    ** NOTE: We are dealing with a relative path name and the data
+-    **       directory has been set.  Therefore, use it as the basis
+-    **       for converting the relative path name to an absolute
+-    **       one by prepending the data directory and a backslash.
+-    */
+-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
+-                     sqlite3_data_directory, zRelative);
+-  }else{
+-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
+-  }
+-  return SQLITE_OK;
+-#endif
++static int winOpenSharedMemory(winFile *pDbFd){
++  struct winShm *p;                  /* The connection to be opened */
++  struct winShmNode *pShmNode = 0;   /* The underlying mmapped file */
++  int rc;                            /* Result code */
++  struct winShmNode *pNew;           /* Newly allocated winShmNode */
++  int nName;                         /* Size of zName in bytes */
+ 
+-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+-  DWORD nByte;
+-  void *zConverted;
+-  char *zOut;
++  assert( pDbFd->pShm==0 );    /* Not previously opened */
+ 
+-  /* If this path name begins with "/X:", where "X" is any alphabetic
+-  ** character, discard the initial "/" from the pathname.
++  /* Allocate space for the new sqlite3_shm object.  Also speculatively
++  ** allocate space for a new winShmNode and filename.
+   */
+-  if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
+-    zRelative++;
++  p = sqlite3MallocZero( sizeof(*p) );
++  if( p==0 ) return SQLITE_IOERR_NOMEM;
++  nName = sqlite3Strlen30(pDbFd->zPath);
++  pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
++  if( pNew==0 ){
++    sqlite3_free(p);
++    return SQLITE_IOERR_NOMEM;
+   }
++  pNew->zFilename = (char*)&pNew[1];
++  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
++  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); 
+ 
+-  /* It's odd to simulate an io-error here, but really this is just
+-  ** using the io-error infrastructure to test that SQLite handles this
+-  ** function failing. This function could fail if, for example, the
+-  ** current working directory has been unlinked.
++  /* Look to see if there is an existing winShmNode that can be used.
++  ** If no matching winShmNode currently exists, create a new one.
+   */
+-  SimulateIOError( return SQLITE_ERROR );
+-  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
+-    /*
+-    ** NOTE: We are dealing with a relative path name and the data
+-    **       directory has been set.  Therefore, use it as the basis
+-    **       for converting the relative path name to an absolute
+-    **       one by prepending the data directory and a backslash.
++  winShmEnterMutex();
++  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
++    /* TBD need to come up with better match here.  Perhaps
++    ** use FILE_ID_BOTH_DIR_INFO Structure.
+     */
+-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
+-                     sqlite3_data_directory, zRelative);
+-    return SQLITE_OK;
+-  }
+-  zConverted = convertUtf8Filename(zRelative);
+-  if( zConverted==0 ){
+-    return SQLITE_IOERR_NOMEM;
++    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
+   }
+-  if( isNT() ){
+-    LPWSTR zTemp;
+-    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
+-    if( nByte==0 ){
+-      winLogError(SQLITE_ERROR, osGetLastError(),
+-                  "GetFullPathNameW1", zConverted);
+-      sqlite3_free(zConverted);
+-      return SQLITE_CANTOPEN_FULLPATH;
+-    }
+-    nByte += 3;
+-    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+-    if( zTemp==0 ){
+-      sqlite3_free(zConverted);
+-      return SQLITE_IOERR_NOMEM;
+-    }
+-    nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+-    if( nByte==0 ){
+-      winLogError(SQLITE_ERROR, osGetLastError(),
+-                  "GetFullPathNameW2", zConverted);
+-      sqlite3_free(zConverted);
+-      sqlite3_free(zTemp);
+-      return SQLITE_CANTOPEN_FULLPATH;
++  if( pShmNode ){
++    sqlite3_free(pNew);
++  }else{
++    pShmNode = pNew;
++    pNew = 0;
++    ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
++    pShmNode->pNext = winShmNodeList;
++    winShmNodeList = pShmNode;
++
++    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
++    if( pShmNode->mutex==0 ){
++      rc = SQLITE_IOERR_NOMEM;
++      goto shm_open_err;
+     }
+-    sqlite3_free(zConverted);
+-    zOut = unicodeToUtf8(zTemp);
+-    sqlite3_free(zTemp);
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    char *zTemp;
+-    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
+-    if( nByte==0 ){
+-      winLogError(SQLITE_ERROR, osGetLastError(),
+-                  "GetFullPathNameA1", zConverted);
+-      sqlite3_free(zConverted);
+-      return SQLITE_CANTOPEN_FULLPATH;
++
++    rc = winOpen(pDbFd->pVfs,
++                 pShmNode->zFilename,             /* Name of the file (UTF-8) */
++                 (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
++                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
++                 0);
++    if( SQLITE_OK!=rc ){
++      goto shm_open_err;
+     }
+-    nByte += 3;
+-    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+-    if( zTemp==0 ){
+-      sqlite3_free(zConverted);
+-      return SQLITE_IOERR_NOMEM;
++
++    /* Check to see if another process is holding the dead-man switch.
++    ** If not, truncate the file to zero length. 
++    */
++    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
++      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
++      if( rc!=SQLITE_OK ){
++        rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
++                 "winOpenShm", pDbFd->zPath);
++      }
+     }
+-    nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+-    if( nByte==0 ){
+-      winLogError(SQLITE_ERROR, osGetLastError(),
+-                  "GetFullPathNameA2", zConverted);
+-      sqlite3_free(zConverted);
+-      sqlite3_free(zTemp);
+-      return SQLITE_CANTOPEN_FULLPATH;
++    if( rc==SQLITE_OK ){
++      winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
++      rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
+     }
+-    sqlite3_free(zConverted);
+-    zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
+-    sqlite3_free(zTemp);
+-  }
+-#endif
+-  if( zOut ){
+-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+-    sqlite3_free(zOut);
+-    return SQLITE_OK;
+-  }else{
+-    return SQLITE_IOERR_NOMEM;
++    if( rc ) goto shm_open_err;
+   }
++
++  /* Make the new connection a child of the winShmNode */
++  p->pShmNode = pShmNode;
++#ifdef SQLITE_DEBUG
++  p->id = pShmNode->nextShmId++;
+ #endif
++  pShmNode->nRef++;
++  pDbFd->pShm = p;
++  winShmLeaveMutex();
++
++  /* The reference count on pShmNode has already been incremented under
++  ** the cover of the winShmEnterMutex() mutex and the pointer from the
++  ** new (struct winShm) object to the pShmNode has been set. All that is
++  ** left to do is to link the new object into the linked list starting
++  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex 
++  ** mutex.
++  */
++  sqlite3_mutex_enter(pShmNode->mutex);
++  p->pNext = pShmNode->pFirst;
++  pShmNode->pFirst = p;
++  sqlite3_mutex_leave(pShmNode->mutex);
++  return SQLITE_OK;
++
++  /* Jump here on any error */
++shm_open_err:
++  winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
++  winShmPurge(pDbFd->pVfs, 0);      /* This call frees pShmNode if required */
++  sqlite3_free(p);
++  sqlite3_free(pNew);
++  winShmLeaveMutex();
++  return rc;
+ }
+ 
+-#ifndef SQLITE_OMIT_LOAD_EXTENSION
+-/*
+-** Interfaces for opening a shared library, finding entry points
+-** within the shared library, and closing the shared library.
+-*/
+ /*
+-** Interfaces for opening a shared library, finding entry points
+-** within the shared library, and closing the shared library.
++** Close a connection to shared-memory.  Delete the underlying 
++** storage if deleteFlag is true.
+ */
+-static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
+-  HANDLE h;
+-  void *zConverted = convertUtf8Filename(zFilename);
+-  UNUSED_PARAMETER(pVfs);
+-  if( zConverted==0 ){
+-    return 0;
+-  }
+-  if( isNT() ){
+-#if SQLITE_OS_WINRT
+-    h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
+-#else
+-    h = osLoadLibraryW((LPCWSTR)zConverted);
+-#endif
+-  }
+-#ifdef SQLITE_WIN32_HAS_ANSI
+-  else{
+-    h = osLoadLibraryA((char*)zConverted);
+-  }
+-#endif
+-  sqlite3_free(zConverted);
+-  return (void*)h;
+-}
+-static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
+-  UNUSED_PARAMETER(pVfs);
+-  getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
+-}
+-static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
+-  UNUSED_PARAMETER(pVfs);
+-  return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
+-}
+-static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
+-  UNUSED_PARAMETER(pVfs);
+-  osFreeLibrary((HANDLE)pHandle);
+-}
+-#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
+-  #define winDlOpen  0
+-  #define winDlError 0
+-  #define winDlSym   0
+-  #define winDlClose 0
+-#endif
++static int winShmUnmap(
++  sqlite3_file *fd,          /* Database holding shared memory */
++  int deleteFlag             /* Delete after closing if true */
++){
++  winFile *pDbFd;       /* Database holding shared-memory */
++  winShm *p;            /* The connection to be closed */
++  winShmNode *pShmNode; /* The underlying shared-memory file */
++  winShm **pp;          /* For looping over sibling connections */
+ 
++  pDbFd = (winFile*)fd;
++  p = pDbFd->pShm;
++  if( p==0 ) return SQLITE_OK;
++  pShmNode = p->pShmNode;
+ 
+-/*
+-** Write up to nBuf bytes of randomness into zBuf.
+-*/
+-static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+-  int n = 0;
+-  UNUSED_PARAMETER(pVfs);
+-#if defined(SQLITE_TEST)
+-  n = nBuf;
+-  memset(zBuf, 0, nBuf);
+-#else
+-  if( sizeof(SYSTEMTIME)<=nBuf-n ){
+-    SYSTEMTIME x;
+-    osGetSystemTime(&x);
+-    memcpy(&zBuf[n], &x, sizeof(x));
+-    n += sizeof(x);
+-  }
+-  if( sizeof(DWORD)<=nBuf-n ){
+-    DWORD pid = osGetCurrentProcessId();
+-    memcpy(&zBuf[n], &pid, sizeof(pid));
+-    n += sizeof(pid);
+-  }
+-#if SQLITE_OS_WINRT
+-  if( sizeof(ULONGLONG)<=nBuf-n ){
+-    ULONGLONG cnt = osGetTickCount64();
+-    memcpy(&zBuf[n], &cnt, sizeof(cnt));
+-    n += sizeof(cnt);
+-  }
+-#else
+-  if( sizeof(DWORD)<=nBuf-n ){
+-    DWORD cnt = osGetTickCount();
+-    memcpy(&zBuf[n], &cnt, sizeof(cnt));
+-    n += sizeof(cnt);
+-  }
+-#endif
+-  if( sizeof(LARGE_INTEGER)<=nBuf-n ){
+-    LARGE_INTEGER i;
+-    osQueryPerformanceCounter(&i);
+-    memcpy(&zBuf[n], &i, sizeof(i));
+-    n += sizeof(i);
+-  }
+-#endif
+-  return n;
+-}
++  /* Remove connection p from the set of connections associated
++  ** with pShmNode */
++  sqlite3_mutex_enter(pShmNode->mutex);
++  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
++  *pp = p->pNext;
+ 
++  /* Free the connection p */
++  sqlite3_free(p);
++  pDbFd->pShm = 0;
++  sqlite3_mutex_leave(pShmNode->mutex);
+ 
+-/*
+-** Sleep for a little while.  Return the amount of time slept.
+-*/
+-static int winSleep(sqlite3_vfs *pVfs, int microsec){
+-  sqlite3_win32_sleep((microsec+999)/1000);
+-  UNUSED_PARAMETER(pVfs);
+-  return ((microsec+999)/1000)*1000;
++  /* If pShmNode->nRef has reached 0, then close the underlying
++  ** shared-memory file, too */
++  winShmEnterMutex();
++  assert( pShmNode->nRef>0 );
++  pShmNode->nRef--;
++  if( pShmNode->nRef==0 ){
++    winShmPurge(pDbFd->pVfs, deleteFlag);
++  }
++  winShmLeaveMutex();
++
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** The following variable, if set to a non-zero value, is interpreted as
+-** the number of seconds since 1970 and is used to set the result of
+-** sqlite3OsCurrentTime() during testing.
++** Change the lock state for a shared-memory segment.
+ */
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_current_time = 0;  /* Fake system time in seconds since 1970. */
+-#endif
++static int winShmLock(
++  sqlite3_file *fd,          /* Database file holding the shared memory */
++  int ofst,                  /* First lock to acquire or release */
++  int n,                     /* Number of locks to acquire or release */
++  int flags                  /* What to do with the lock */
++){
++  winFile *pDbFd = (winFile*)fd;        /* Connection holding shared memory */
++  winShm *p = pDbFd->pShm;              /* The shared memory being locked */
++  winShm *pX;                           /* For looping over all siblings */
++  winShmNode *pShmNode = p->pShmNode;
++  int rc = SQLITE_OK;                   /* Result code */
++  u16 mask;                             /* Mask of locks to take or release */
+ 
+-/*
+-** Find the current time (in Universal Coordinated Time).  Write into *piNow
+-** the current time and date as a Julian Day number times 86_400_000.  In
+-** other words, write into *piNow the number of milliseconds since the Julian
+-** epoch of noon in Greenwich on November 24, 4714 B.C according to the
+-** proleptic Gregorian calendar.
+-**
+-** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date 
+-** cannot be found.
+-*/
+-static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
+-  /* FILETIME structure is a 64-bit value representing the number of 
+-     100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 
+-  */
+-  FILETIME ft;
+-  static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
+-#ifdef SQLITE_TEST
+-  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+-#endif
+-  /* 2^32 - to avoid use of LL and warnings in gcc */
+-  static const sqlite3_int64 max32BitValue = 
+-      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
+-      (sqlite3_int64)294967296;
++  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
++  assert( n>=1 );
++  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
++       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
++       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
++       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
++  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
+ 
+-#if SQLITE_OS_WINCE
+-  SYSTEMTIME time;
+-  osGetSystemTime(&time);
+-  /* if SystemTimeToFileTime() fails, it returns zero. */
+-  if (!osSystemTimeToFileTime(&time,&ft)){
+-    return SQLITE_ERROR;
+-  }
+-#else
+-  osGetSystemTimeAsFileTime( &ft );
+-#endif
++  mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
++  assert( n>1 || mask==(1<<ofst) );
++  sqlite3_mutex_enter(pShmNode->mutex);
++  if( flags & SQLITE_SHM_UNLOCK ){
++    u16 allMask = 0; /* Mask of locks held by siblings */
+ 
+-  *piNow = winFiletimeEpoch +
+-            ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + 
+-               (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
++    /* See if any siblings hold this same lock */
++    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
++      if( pX==p ) continue;
++      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
++      allMask |= pX->sharedMask;
++    }
+ 
+-#ifdef SQLITE_TEST
+-  if( sqlite3_current_time ){
+-    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
++    /* Unlock the system-level locks */
++    if( (mask & allMask)==0 ){
++      rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
++    }else{
++      rc = SQLITE_OK;
++    }
++
++    /* Undo the local locks */
++    if( rc==SQLITE_OK ){
++      p->exclMask &= ~mask;
++      p->sharedMask &= ~mask;
++    } 
++  }else if( flags & SQLITE_SHM_SHARED ){
++    u16 allShared = 0;  /* Union of locks held by connections other than "p" */
++
++    /* Find out which shared locks are already held by sibling connections.
++    ** If any sibling already holds an exclusive lock, go ahead and return
++    ** SQLITE_BUSY.
++    */
++    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
++      if( (pX->exclMask & mask)!=0 ){
++        rc = SQLITE_BUSY;
++        break;
++      }
++      allShared |= pX->sharedMask;
++    }
++
++    /* Get shared locks at the system level, if necessary */
++    if( rc==SQLITE_OK ){
++      if( (allShared & mask)==0 ){
++        rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
++      }else{
++        rc = SQLITE_OK;
++      }
++    }
++
++    /* Get the local shared locks */
++    if( rc==SQLITE_OK ){
++      p->sharedMask |= mask;
++    }
++  }else{
++    /* Make sure no sibling connections hold locks that will block this
++    ** lock.  If any do, return SQLITE_BUSY right away.
++    */
++    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
++      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
++        rc = SQLITE_BUSY;
++        break;
++      }
++    }
++  
++    /* Get the exclusive locks at the system level.  Then if successful
++    ** also mark the local connection as being locked.
++    */
++    if( rc==SQLITE_OK ){
++      rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
++      if( rc==SQLITE_OK ){
++        assert( (p->sharedMask & mask)==0 );
++        p->exclMask |= mask;
++      }
++    }
+   }
+-#endif
+-  UNUSED_PARAMETER(pVfs);
+-  return SQLITE_OK;
++  sqlite3_mutex_leave(pShmNode->mutex);
++  OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
++           osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
++           sqlite3ErrName(rc)));
++  return rc;
+ }
+ 
+ /*
+-** Find the current time (in Universal Coordinated Time).  Write the
+-** current time and date as a Julian Day number into *prNow and
+-** return 0.  Return 1 if the time and date cannot be found.
++** Implement a memory barrier or memory fence on shared memory.  
++**
++** All loads and stores begun before the barrier must complete before
++** any load or store begun after the barrier.
+ */
+-static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
+-  int rc;
+-  sqlite3_int64 i;
+-  rc = winCurrentTimeInt64(pVfs, &i);
+-  if( !rc ){
+-    *prNow = i/86400000.0;
+-  }
+-  return rc;
++static void winShmBarrier(
++  sqlite3_file *fd          /* Database holding the shared memory */
++){
++  UNUSED_PARAMETER(fd);
++  /* MemoryBarrier(); // does not work -- do not know why not */
++  winShmEnterMutex();
++  winShmLeaveMutex();
+ }
+ 
+ /*
+-** The idea is that this function works like a combination of
+-** GetLastError() and FormatMessage() on Windows (or errno and
+-** strerror_r() on Unix). After an error is returned by an OS
+-** function, SQLite calls this function with zBuf pointing to
+-** a buffer of nBuf bytes. The OS layer should populate the
+-** buffer with a nul-terminated UTF-8 encoded error message
+-** describing the last IO error to have occurred within the calling
+-** thread.
+-**
+-** If the error message is too large for the supplied buffer,
+-** it should be truncated. The return value of xGetLastError
+-** is zero if the error message fits in the buffer, or non-zero
+-** otherwise (if the message was truncated). If non-zero is returned,
+-** then it is not necessary to include the nul-terminator character
+-** in the output buffer.
++** This function is called to obtain a pointer to region iRegion of the 
++** shared-memory associated with the database file fd. Shared-memory regions 
++** are numbered starting from zero. Each shared-memory region is szRegion 
++** bytes in size.
+ **
+-** Not supplying an error message will have no adverse effect
+-** on SQLite. It is fine to have an implementation that never
+-** returns an error message:
++** If an error occurs, an error code is returned and *pp is set to NULL.
+ **
+-**   int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+-**     assert(zBuf[0]=='\0');
+-**     return 0;
+-**   }
++** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
++** region has not been allocated (by any client, including one running in a
++** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
++** isWrite is non-zero and the requested shared-memory region has not yet 
++** been allocated, it is allocated by this function.
+ **
+-** However if an error message is supplied, it will be incorporated
+-** by sqlite into the error message available to the user using
+-** sqlite3_errmsg(), possibly making IO errors easier to debug.
++** If the shared-memory region has already been allocated or is allocated by
++** this call as described above, then it is mapped into this processes 
++** address space (if it is not already), *pp is set to point to the mapped 
++** memory and SQLITE_OK returned.
+ */
+-static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+-  UNUSED_PARAMETER(pVfs);
+-  return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
+-}
++static int winShmMap(
++  sqlite3_file *fd,               /* Handle open on database file */
++  int iRegion,                    /* Region to retrieve */
++  int szRegion,                   /* Size of regions */
++  int isWrite,                    /* True to extend file if necessary */
++  void volatile **pp              /* OUT: Mapped memory */
++){
++  winFile *pDbFd = (winFile*)fd;
++  winShm *p = pDbFd->pShm;
++  winShmNode *pShmNode;
++  int rc = SQLITE_OK;
+ 
+-/*
+-** Initialize and deinitialize the operating system interface.
+-*/
+-SQLITE_API int sqlite3_os_init(void){
+-  static sqlite3_vfs winVfs = {
+-    3,                   /* iVersion */
+-    sizeof(winFile),     /* szOsFile */
+-    MAX_PATH,            /* mxPathname */
+-    0,                   /* pNext */
+-    "win32",             /* zName */
+-    0,                   /* pAppData */
+-    winOpen,             /* xOpen */
+-    winDelete,           /* xDelete */
+-    winAccess,           /* xAccess */
+-    winFullPathname,     /* xFullPathname */
+-    winDlOpen,           /* xDlOpen */
+-    winDlError,          /* xDlError */
+-    winDlSym,            /* xDlSym */
+-    winDlClose,          /* xDlClose */
+-    winRandomness,       /* xRandomness */
+-    winSleep,            /* xSleep */
+-    winCurrentTime,      /* xCurrentTime */
+-    winGetLastError,     /* xGetLastError */
+-    winCurrentTimeInt64, /* xCurrentTimeInt64 */
+-    winSetSystemCall,    /* xSetSystemCall */
+-    winGetSystemCall,    /* xGetSystemCall */
+-    winNextSystemCall,   /* xNextSystemCall */
+-  };
++  if( !p ){
++    rc = winOpenSharedMemory(pDbFd);
++    if( rc!=SQLITE_OK ) return rc;
++    p = pDbFd->pShm;
++  }
++  pShmNode = p->pShmNode;
+ 
+-  /* Double-check that the aSyscall[] array has been constructed
+-  ** correctly.  See ticket [bb3a86e890c8e96ab] */
+-  assert( ArraySize(aSyscall)==74 );
++  sqlite3_mutex_enter(pShmNode->mutex);
++  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+ 
+-  /* get memory map allocation granularity */
+-  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
++  if( pShmNode->nRegion<=iRegion ){
++    struct ShmRegion *apNew;           /* New aRegion[] array */
++    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
++    sqlite3_int64 sz;                  /* Current size of wal-index file */
++
++    pShmNode->szRegion = szRegion;
++
++    /* The requested region is not mapped into this processes address space.
++    ** Check to see if it has been allocated (i.e. if the wal-index file is
++    ** large enough to contain the requested region).
++    */
++    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
++    if( rc!=SQLITE_OK ){
++      rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
++               "winShmMap1", pDbFd->zPath);
++      goto shmpage_out;
++    }
++
++    if( sz<nByte ){
++      /* The requested memory region does not exist. If isWrite is set to
++      ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
++      **
++      ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
++      ** the requested memory region.
++      */
++      if( !isWrite ) goto shmpage_out;
++      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
++      if( rc!=SQLITE_OK ){
++        rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
++                 "winShmMap2", pDbFd->zPath);
++        goto shmpage_out;
++      }
++    }
++
++    /* Map the requested memory region into this processes address space. */
++    apNew = (struct ShmRegion *)sqlite3_realloc(
++        pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
++    );
++    if( !apNew ){
++      rc = SQLITE_IOERR_NOMEM;
++      goto shmpage_out;
++    }
++    pShmNode->aRegion = apNew;
++
++    while( pShmNode->nRegion<=iRegion ){
++      HANDLE hMap = NULL;         /* file-mapping handle */
++      void *pMap = 0;             /* Mapped memory region */
++     
+ #if SQLITE_OS_WINRT
+-  osGetNativeSystemInfo(&winSysInfo);
++      hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
++          NULL, PAGE_READWRITE, nByte, NULL
++      );
++#elif defined(SQLITE_WIN32_HAS_WIDE)
++      hMap = osCreateFileMappingW(pShmNode->hFile.h, 
++          NULL, PAGE_READWRITE, 0, nByte, NULL
++      );
++#elif defined(SQLITE_WIN32_HAS_ANSI)
++      hMap = osCreateFileMappingA(pShmNode->hFile.h, 
++          NULL, PAGE_READWRITE, 0, nByte, NULL
++      );
++#endif
++      OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
++               osGetCurrentProcessId(), pShmNode->nRegion, nByte,
++               hMap ? "ok" : "failed"));
++      if( hMap ){
++        int iOffset = pShmNode->nRegion*szRegion;
++        int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
++#if SQLITE_OS_WINRT
++        pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
++            iOffset - iOffsetShift, szRegion + iOffsetShift
++        );
+ #else
+-  osGetSystemInfo(&winSysInfo);
++        pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
++            0, iOffset - iOffsetShift, szRegion + iOffsetShift
++        );
+ #endif
+-  assert( winSysInfo.dwAllocationGranularity>0 );
+-  assert( winSysInfo.dwPageSize>0 );
++        OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
++                 osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
++                 szRegion, pMap ? "ok" : "failed"));
++      }
++      if( !pMap ){
++        pShmNode->lastErrno = osGetLastError();
++        rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
++                 "winShmMap3", pDbFd->zPath);
++        if( hMap ) osCloseHandle(hMap);
++        goto shmpage_out;
++      }
+ 
+-  sqlite3_vfs_register(&winVfs, 1);
+-  return SQLITE_OK; 
+-}
++      pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
++      pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
++      pShmNode->nRegion++;
++    }
++  }
+ 
+-SQLITE_API int sqlite3_os_end(void){ 
+-#if SQLITE_OS_WINRT
+-  if( sleepObj!=NULL ){
+-    osCloseHandle(sleepObj);
+-    sleepObj = NULL;
++shmpage_out:
++  if( pShmNode->nRegion>iRegion ){
++    int iOffset = iRegion*szRegion;
++    int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
++    char *p = (char *)pShmNode->aRegion[iRegion].pMap;
++    *pp = (void *)&p[iOffsetShift];
++  }else{
++    *pp = 0;
+   }
+-#endif
+-  return SQLITE_OK;
++  sqlite3_mutex_leave(pShmNode->mutex);
++  return rc;
+ }
+ 
+-#endif /* SQLITE_OS_WIN */
++#else
++# define winShmMap     0
++# define winShmLock    0
++# define winShmBarrier 0
++# define winShmUnmap   0
++#endif /* #ifndef SQLITE_OMIT_WAL */
+ 
+-/************** End of os_win.c **********************************************/
+-/************** Begin file bitvec.c ******************************************/
+ /*
+-** 2008 February 16
+-**
+-** 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 an object that represents a fixed-length
+-** bitmap.  Bits are numbered starting with 1.
+-**
+-** A bitmap is used to record which pages of a database file have been
+-** journalled during a transaction, or which pages have the "dont-write"
+-** property.  Usually only a few pages are meet either condition.
+-** So the bitmap is usually sparse and has low cardinality.
+-** But sometimes (for example when during a DROP of a large table) most
+-** or all of the pages in a database can get journalled.  In those cases, 
+-** the bitmap becomes dense with high cardinality.  The algorithm needs 
+-** to handle both cases well.
+-**
+-** The size of the bitmap is fixed when the object is created.
+-**
+-** All bits are clear when the bitmap is created.  Individual bits
+-** may be set or cleared one at a time.
+-**
+-** Test operations are about 100 times more common that set operations.
+-** Clear operations are exceedingly rare.  There are usually between
+-** 5 and 500 set operations per Bitvec object, though the number of sets can
+-** sometimes grow into tens of thousands or larger.  The size of the
+-** Bitvec object is the number of pages in the database file at the
+-** start of a transaction, and is thus usually less than a few thousand,
+-** but can be as large as 2 billion for a really big database.
++** Cleans up the mapped region of the specified file, if any.
+ */
+-
+-/* Size of the Bitvec structure in bytes. */
+-#define BITVEC_SZ        512
+-
+-/* Round the union size down to the nearest pointer boundary, since that's how 
+-** it will be aligned within the Bitvec struct. */
+-#define BITVEC_USIZE     (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
+-
+-/* Type of the array "element" for the bitmap representation. 
+-** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. 
+-** Setting this to the "natural word" size of your CPU may improve
+-** performance. */
+-#define BITVEC_TELEM     u8
+-/* Size, in bits, of the bitmap element. */
+-#define BITVEC_SZELEM    8
+-/* Number of elements in a bitmap array. */
+-#define BITVEC_NELEM     (BITVEC_USIZE/sizeof(BITVEC_TELEM))
+-/* Number of bits in the bitmap array. */
+-#define BITVEC_NBIT      (BITVEC_NELEM*BITVEC_SZELEM)
+-
+-/* Number of u32 values in hash table. */
+-#define BITVEC_NINT      (BITVEC_USIZE/sizeof(u32))
+-/* Maximum number of entries in hash table before 
+-** sub-dividing and re-hashing. */
+-#define BITVEC_MXHASH    (BITVEC_NINT/2)
+-/* Hashing function for the aHash representation.
+-** Empirical testing showed that the *37 multiplier 
+-** (an arbitrary prime)in the hash function provided 
+-** no fewer collisions than the no-op *1. */
+-#define BITVEC_HASH(X)   (((X)*1)%BITVEC_NINT)
+-
+-#define BITVEC_NPTR      (BITVEC_USIZE/sizeof(Bitvec *))
+-
++#if SQLITE_MAX_MMAP_SIZE>0
++static int winUnmapfile(winFile *pFile){
++  assert( pFile!=0 );
++  OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
++           "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
++           osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
++           pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
++  if( pFile->pMapRegion ){
++    if( !osUnmapViewOfFile(pFile->pMapRegion) ){
++      pFile->lastErrno = osGetLastError();
++      OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
++               "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
++               pFile->pMapRegion));
++      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
++                         "winUnmap1", pFile->zPath);
++    }
++    pFile->pMapRegion = 0;
++    pFile->mmapSize = 0;
++    pFile->mmapSizeActual = 0;
++  }
++  if( pFile->hMap!=NULL ){
++    if( !osCloseHandle(pFile->hMap) ){
++      pFile->lastErrno = osGetLastError();
++      OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
++               osGetCurrentProcessId(), pFile, pFile->hMap));
++      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
++                         "winUnmap2", pFile->zPath);
++    }
++    pFile->hMap = NULL;
++  }
++  OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
++           osGetCurrentProcessId(), pFile));
++  return SQLITE_OK;
++}
+ 
+ /*
+-** A bitmap is an instance of the following structure.
+-**
+-** This bitmap records the existence of zero or more bits
+-** with values between 1 and iSize, inclusive.
+-**
+-** There are three possible representations of the bitmap.
+-** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
+-** bitmap.  The least significant bit is bit 1.
++** Memory map or remap the file opened by file-descriptor pFd (if the file
++** is already mapped, the existing mapping is replaced by the new). Or, if 
++** there already exists a mapping for this file, and there are still 
++** outstanding xFetch() references to it, this function is a no-op.
+ **
+-** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
+-** a hash table that will hold up to BITVEC_MXHASH distinct values.
++** If parameter nByte is non-negative, then it is the requested size of 
++** the mapping to create. Otherwise, if nByte is less than zero, then the 
++** requested size is the size of the file on disk. The actual size of the
++** created mapping is either the requested size or the value configured 
++** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
+ **
+-** Otherwise, the value i is redirected into one of BITVEC_NPTR
+-** sub-bitmaps pointed to by Bitvec.u.apSub[].  Each subbitmap
+-** handles up to iDivisor separate values of i.  apSub[0] holds
+-** values between 1 and iDivisor.  apSub[1] holds values between
+-** iDivisor+1 and 2*iDivisor.  apSub[N] holds values between
+-** N*iDivisor+1 and (N+1)*iDivisor.  Each subbitmap is normalized
+-** to hold deal with values between 1 and iDivisor.
++** SQLITE_OK is returned if no error occurs (even if the mapping is not
++** recreated as a result of outstanding references) or an SQLite error
++** code otherwise.
+ */
+-struct Bitvec {
+-  u32 iSize;      /* Maximum bit index.  Max iSize is 4,294,967,296. */
+-  u32 nSet;       /* Number of bits that are set - only valid for aHash
+-                  ** element.  Max is BITVEC_NINT.  For BITVEC_SZ of 512,
+-                  ** this would be 125. */
+-  u32 iDivisor;   /* Number of bits handled by each apSub[] entry. */
+-                  /* Should >=0 for apSub element. */
+-                  /* Max iDivisor is max(u32) / BITVEC_NPTR + 1.  */
+-                  /* For a BITVEC_SZ of 512, this would be 34,359,739. */
+-  union {
+-    BITVEC_TELEM aBitmap[BITVEC_NELEM];    /* Bitmap representation */
+-    u32 aHash[BITVEC_NINT];      /* Hash table representation */
+-    Bitvec *apSub[BITVEC_NPTR];  /* Recursive representation */
+-  } u;
+-};
++static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
++  sqlite3_int64 nMap = nByte;
++  int rc;
+ 
+-/*
+-** Create a new bitmap object able to handle bits between 0 and iSize,
+-** inclusive.  Return a pointer to the new object.  Return NULL if 
+-** malloc fails.
+-*/
+-SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
+-  Bitvec *p;
+-  assert( sizeof(*p)==BITVEC_SZ );
+-  p = sqlite3MallocZero( sizeof(*p) );
+-  if( p ){
+-    p->iSize = iSize;
+-  }
+-  return p;
+-}
++  assert( nMap>=0 || pFd->nFetchOut==0 );
++  OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
++           osGetCurrentProcessId(), pFd, nByte));
+ 
+-/*
+-** Check to see if the i-th bit is set.  Return true or false.
+-** If p is NULL (if the bitmap has not been created) or if
+-** i is out of range, then return false.
+-*/
+-SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
+-  if( p==0 ) return 0;
+-  if( i>p->iSize || i==0 ) return 0;
+-  i--;
+-  while( p->iDivisor ){
+-    u32 bin = i/p->iDivisor;
+-    i = i%p->iDivisor;
+-    p = p->u.apSub[bin];
+-    if (!p) {
+-      return 0;
++  if( pFd->nFetchOut>0 ) return SQLITE_OK;
++
++  if( nMap<0 ){
++    rc = winFileSize((sqlite3_file*)pFd, &nMap);
++    if( rc ){
++      OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
++               osGetCurrentProcessId(), pFd));
++      return SQLITE_IOERR_FSTAT;
+     }
+   }
+-  if( p->iSize<=BITVEC_NBIT ){
+-    return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
+-  } else{
+-    u32 h = BITVEC_HASH(i++);
+-    while( p->u.aHash[h] ){
+-      if( p->u.aHash[h]==i ) return 1;
+-      h = (h+1) % BITVEC_NINT;
++  if( nMap>pFd->mmapSizeMax ){
++    nMap = pFd->mmapSizeMax;
++  }
++  nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
++ 
++  if( nMap==0 && pFd->mmapSize>0 ){
++    winUnmapfile(pFd);
++  }
++  if( nMap!=pFd->mmapSize ){
++    void *pNew = 0;
++    DWORD protect = PAGE_READONLY;
++    DWORD flags = FILE_MAP_READ;
++
++    winUnmapfile(pFd);
++    if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
++      protect = PAGE_READWRITE;
++      flags |= FILE_MAP_WRITE;
+     }
+-    return 0;
++#if SQLITE_OS_WINRT
++    pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
++#elif defined(SQLITE_WIN32_HAS_WIDE)
++    pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
++                                (DWORD)((nMap>>32) & 0xffffffff),
++                                (DWORD)(nMap & 0xffffffff), NULL);
++#elif defined(SQLITE_WIN32_HAS_ANSI)
++    pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
++                                (DWORD)((nMap>>32) & 0xffffffff),
++                                (DWORD)(nMap & 0xffffffff), NULL);
++#endif
++    if( pFd->hMap==NULL ){
++      pFd->lastErrno = osGetLastError();
++      rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
++                       "winMapfile", pFd->zPath);
++      /* Log the error, but continue normal operation using xRead/xWrite */
++      OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
++               osGetCurrentProcessId(), pFd));
++      return SQLITE_OK;
++    }
++    assert( (nMap % winSysInfo.dwPageSize)==0 );
++#if SQLITE_OS_WINRT
++    pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
++#else
++    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
++    pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
++#endif
++    if( pNew==NULL ){
++      osCloseHandle(pFd->hMap);
++      pFd->hMap = NULL;
++      pFd->lastErrno = osGetLastError();
++      winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
++                  "winMapfile", pFd->zPath);
++      OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
++               osGetCurrentProcessId(), pFd));
++      return SQLITE_OK;
++    }
++    pFd->pMapRegion = pNew;
++    pFd->mmapSize = nMap;
++    pFd->mmapSizeActual = nMap;
+   }
++
++  OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
++           osGetCurrentProcessId(), pFd));
++  return SQLITE_OK;
+ }
++#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+ 
+ /*
+-** Set the i-th bit.  Return 0 on success and an error code if
+-** anything goes wrong.
++** If possible, return a pointer to a mapping of file fd starting at offset
++** iOff. The mapping must be valid for at least nAmt bytes.
+ **
+-** This routine might cause sub-bitmaps to be allocated.  Failing
+-** to get the memory needed to hold the sub-bitmap is the only
+-** that can go wrong with an insert, assuming p and i are valid.
++** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
++** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
++** Finally, if an error does occur, return an SQLite error code. The final
++** value of *pp is undefined in this case.
+ **
+-** The calling function must ensure that p is a valid Bitvec object
+-** and that the value for "i" is within range of the Bitvec object.
+-** Otherwise the behavior is undefined.
++** If this function does return a pointer, the caller must eventually 
++** release the reference by calling winUnfetch().
+ */
+-SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
+-  u32 h;
+-  if( p==0 ) return SQLITE_OK;
+-  assert( i>0 );
+-  assert( i<=p->iSize );
+-  i--;
+-  while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
+-    u32 bin = i/p->iDivisor;
+-    i = i%p->iDivisor;
+-    if( p->u.apSub[bin]==0 ){
+-      p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
+-      if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
+-    }
+-    p = p->u.apSub[bin];
+-  }
+-  if( p->iSize<=BITVEC_NBIT ){
+-    p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
+-    return SQLITE_OK;
+-  }
+-  h = BITVEC_HASH(i++);
+-  /* if there wasn't a hash collision, and this doesn't */
+-  /* completely fill the hash, then just add it without */
+-  /* worring about sub-dividing and re-hashing. */
+-  if( !p->u.aHash[h] ){
+-    if (p->nSet<(BITVEC_NINT-1)) {
+-      goto bitvec_set_end;
+-    } else {
+-      goto bitvec_set_rehash;
+-    }
+-  }
+-  /* there was a collision, check to see if it's already */
+-  /* in hash, if not, try to find a spot for it */
+-  do {
+-    if( p->u.aHash[h]==i ) return SQLITE_OK;
+-    h++;
+-    if( h>=BITVEC_NINT ) h = 0;
+-  } while( p->u.aHash[h] );
+-  /* we didn't find it in the hash.  h points to the first */
+-  /* available free spot. check to see if this is going to */
+-  /* make our hash too "full".  */
+-bitvec_set_rehash:
+-  if( p->nSet>=BITVEC_MXHASH ){
+-    unsigned int j;
+-    int rc;
+-    u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
+-    if( aiValues==0 ){
+-      return SQLITE_NOMEM;
+-    }else{
+-      memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
+-      memset(p->u.apSub, 0, sizeof(p->u.apSub));
+-      p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+-      rc = sqlite3BitvecSet(p, i);
+-      for(j=0; j<BITVEC_NINT; j++){
+-        if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
++static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
++#if SQLITE_MAX_MMAP_SIZE>0
++  winFile *pFd = (winFile*)fd;   /* The underlying database file */
++#endif
++  *pp = 0;
++
++  OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
++           osGetCurrentProcessId(), fd, iOff, nAmt, pp));
++
++#if SQLITE_MAX_MMAP_SIZE>0
++  if( pFd->mmapSizeMax>0 ){
++    if( pFd->pMapRegion==0 ){
++      int rc = winMapfile(pFd, -1);
++      if( rc!=SQLITE_OK ){
++        OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
++                 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
++        return rc;
+       }
+-      sqlite3StackFree(0, aiValues);
+-      return rc;
++    }
++    if( pFd->mmapSize >= iOff+nAmt ){
++      *pp = &((u8 *)pFd->pMapRegion)[iOff];
++      pFd->nFetchOut++;
+     }
+   }
+-bitvec_set_end:
+-  p->nSet++;
+-  p->u.aHash[h] = i;
++#endif
++
++  OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
++           osGetCurrentProcessId(), fd, pp, *pp));
+   return SQLITE_OK;
+ }
+ 
+ /*
+-** Clear the i-th bit.
++** If the third argument is non-NULL, then this function releases a 
++** reference obtained by an earlier call to winFetch(). The second
++** argument passed to this function must be the same as the corresponding
++** argument that was passed to the winFetch() invocation. 
+ **
+-** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
+-** that BitvecClear can use to rebuilt its hash table.
++** Or, if the third argument is NULL, then this function is being called 
++** to inform the VFS layer that, according to POSIX, any existing mapping 
++** may now be invalid and should be unmapped.
+ */
+-SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
+-  if( p==0 ) return;
+-  assert( i>0 );
+-  i--;
+-  while( p->iDivisor ){
+-    u32 bin = i/p->iDivisor;
+-    i = i%p->iDivisor;
+-    p = p->u.apSub[bin];
+-    if (!p) {
+-      return;
+-    }
+-  }
+-  if( p->iSize<=BITVEC_NBIT ){
+-    p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
++static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
++#if SQLITE_MAX_MMAP_SIZE>0
++  winFile *pFd = (winFile*)fd;   /* The underlying database file */
++
++  /* If p==0 (unmap the entire file) then there must be no outstanding 
++  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
++  ** then there must be at least one outstanding.  */
++  assert( (p==0)==(pFd->nFetchOut==0) );
++
++  /* If p!=0, it must match the iOff value. */
++  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
++
++  OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
++           osGetCurrentProcessId(), pFd, iOff, p));
++
++  if( p ){
++    pFd->nFetchOut--;
+   }else{
+-    unsigned int j;
+-    u32 *aiValues = pBuf;
+-    memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
+-    memset(p->u.aHash, 0, sizeof(p->u.aHash));
+-    p->nSet = 0;
+-    for(j=0; j<BITVEC_NINT; j++){
+-      if( aiValues[j] && aiValues[j]!=(i+1) ){
+-        u32 h = BITVEC_HASH(aiValues[j]-1);
+-        p->nSet++;
+-        while( p->u.aHash[h] ){
+-          h++;
+-          if( h>=BITVEC_NINT ) h = 0;
+-        }
+-        p->u.aHash[h] = aiValues[j];
+-      }
+-    }
++    /* FIXME:  If Windows truly always prevents truncating or deleting a
++    ** file while a mapping is held, then the following winUnmapfile() call
++    ** is unnecessary can can be omitted - potentially improving
++    ** performance.  */
++    winUnmapfile(pFd);
+   }
++
++  assert( pFd->nFetchOut>=0 );
++#endif
++
++  OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
++           osGetCurrentProcessId(), fd));
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Destroy a bitmap object.  Reclaim all memory used.
+-*/
+-SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
+-  if( p==0 ) return;
+-  if( p->iDivisor ){
+-    unsigned int i;
+-    for(i=0; i<BITVEC_NPTR; i++){
+-      sqlite3BitvecDestroy(p->u.apSub[i]);
+-    }
+-  }
+-  sqlite3_free(p);
+-}
++** Here ends the implementation of all sqlite3_file methods.
++**
++********************** End sqlite3_file Methods *******************************
++******************************************************************************/
+ 
+ /*
+-** Return the value of the iSize parameter specified when Bitvec *p
+-** was created.
++** This vector defines all the methods that can operate on an
++** sqlite3_file for win32.
++*/
++static const sqlite3_io_methods winIoMethod = {
++  3,                              /* iVersion */
++  winClose,                       /* xClose */
++  winRead,                        /* xRead */
++  winWrite,                       /* xWrite */
++  winTruncate,                    /* xTruncate */
++  winSync,                        /* xSync */
++  winFileSize,                    /* xFileSize */
++  winLock,                        /* xLock */
++  winUnlock,                      /* xUnlock */
++  winCheckReservedLock,           /* xCheckReservedLock */
++  winFileControl,                 /* xFileControl */
++  winSectorSize,                  /* xSectorSize */
++  winDeviceCharacteristics,       /* xDeviceCharacteristics */
++  winShmMap,                      /* xShmMap */
++  winShmLock,                     /* xShmLock */
++  winShmBarrier,                  /* xShmBarrier */
++  winShmUnmap,                    /* xShmUnmap */
++  winFetch,                       /* xFetch */
++  winUnfetch                      /* xUnfetch */
++};
++
++/****************************************************************************
++**************************** sqlite3_vfs methods ****************************
++**
++** This division contains the implementation of methods on the
++** sqlite3_vfs object.
+ */
+-SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
+-  return p->iSize;
+-}
+ 
+-#ifndef SQLITE_OMIT_BUILTIN_TEST
+ /*
+-** Let V[] be an array of unsigned characters sufficient to hold
+-** up to N bits.  Let I be an integer between 0 and N.  0<=I<N.
+-** Then the following macros can be used to set, clear, or test
+-** individual bits within V.
++** Convert a UTF-8 filename into whatever form the underlying
++** operating system wants filenames in.  Space to hold the result
++** is obtained from malloc and must be freed by the calling
++** function.
+ */
+-#define SETBIT(V,I)      V[I>>3] |= (1<<(I&7))
+-#define CLEARBIT(V,I)    V[I>>3] &= ~(1<<(I&7))
+-#define TESTBIT(V,I)     (V[I>>3]&(1<<(I&7)))!=0
++static void *convertUtf8Filename(const char *zFilename){
++  void *zConverted = 0;
++  if( isNT() ){
++    zConverted = utf8ToUnicode(zFilename);
++  }
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
++  }
++#endif
++  /* caller will handle out of memory */
++  return zConverted;
++}
+ 
+ /*
+-** This routine runs an extensive test of the Bitvec code.
+-**
+-** The input is an array of integers that acts as a program
+-** to test the Bitvec.  The integers are opcodes followed
+-** by 0, 1, or 3 operands, depending on the opcode.  Another
+-** opcode follows immediately after the last operand.
+-**
+-** There are 6 opcodes numbered from 0 through 5.  0 is the
+-** "halt" opcode and causes the test to end.
+-**
+-**    0          Halt and return the number of errors
+-**    1 N S X    Set N bits beginning with S and incrementing by X
+-**    2 N S X    Clear N bits beginning with S and incrementing by X
+-**    3 N        Set N randomly chosen bits
+-**    4 N        Clear N randomly chosen bits
+-**    5 N S X    Set N bits from S increment X in array only, not in bitvec
+-**
+-** The opcodes 1 through 4 perform set and clear operations are performed
+-** on both a Bitvec object and on a linear array of bits obtained from malloc.
+-** Opcode 5 works on the linear array only, not on the Bitvec.
+-** Opcode 5 is used to deliberately induce a fault in order to
+-** confirm that error detection works.
+-**
+-** At the conclusion of the test the linear array is compared
+-** against the Bitvec object.  If there are any differences,
+-** an error is returned.  If they are the same, zero is returned.
+-**
+-** If a memory allocation error occurs, return -1.
++** Create a temporary file name in zBuf.  zBuf must be big enough to
++** hold at pVfs->mxPathname characters.
+ */
+-SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
+-  Bitvec *pBitvec = 0;
+-  unsigned char *pV = 0;
+-  int rc = -1;
+-  int i, nx, pc, op;
+-  void *pTmpSpace;
++static int getTempname(int nBuf, char *zBuf){
++  static char zChars[] =
++    "abcdefghijklmnopqrstuvwxyz"
++    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
++    "0123456789";
++  size_t i, j;
++  int nTempPath;
++  char zTempPath[MAX_PATH+2];
+ 
+-  /* Allocate the Bitvec to be tested and a linear array of
+-  ** bits to act as the reference */
+-  pBitvec = sqlite3BitvecCreate( sz );
+-  pV = sqlite3MallocZero( (sz+7)/8 + 1 );
+-  pTmpSpace = sqlite3_malloc(BITVEC_SZ);
+-  if( pBitvec==0 || pV==0 || pTmpSpace==0  ) goto bitvec_end;
++  /* It's odd to simulate an io-error here, but really this is just
++  ** using the io-error infrastructure to test that SQLite handles this
++  ** function failing. 
++  */
++  SimulateIOError( return SQLITE_IOERR );
+ 
+-  /* NULL pBitvec tests */
+-  sqlite3BitvecSet(0, 1);
+-  sqlite3BitvecClear(0, 1, pTmpSpace);
++  memset(zTempPath, 0, MAX_PATH+2);
+ 
+-  /* Run the program */
+-  pc = 0;
+-  while( (op = aOp[pc])!=0 ){
+-    switch( op ){
+-      case 1:
+-      case 2:
+-      case 5: {
+-        nx = 4;
+-        i = aOp[pc+2] - 1;
+-        aOp[pc+2] += aOp[pc+3];
+-        break;
+-      }
+-      case 3:
+-      case 4: 
+-      default: {
+-        nx = 2;
+-        sqlite3_randomness(sizeof(i), &i);
+-        break;
+-      }
++  if( sqlite3_temp_directory ){
++    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
++  }
++#if !SQLITE_OS_WINRT
++  else if( isNT() ){
++    char *zMulti;
++    WCHAR zWidePath[MAX_PATH];
++    osGetTempPathW(MAX_PATH-30, zWidePath);
++    zMulti = unicodeToUtf8(zWidePath);
++    if( zMulti ){
++      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
++      sqlite3_free(zMulti);
++    }else{
++      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
++      return SQLITE_IOERR_NOMEM;
+     }
+-    if( (--aOp[pc+1]) > 0 ) nx = 0;
+-    pc += nx;
+-    i = (i & 0x7fffffff)%sz;
+-    if( (op & 1)!=0 ){
+-      SETBIT(pV, (i+1));
+-      if( op!=5 ){
+-        if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
+-      }
++  }
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    char *zUtf8;
++    char zMbcsPath[MAX_PATH];
++    osGetTempPathA(MAX_PATH-30, zMbcsPath);
++    zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
++    if( zUtf8 ){
++      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
++      sqlite3_free(zUtf8);
+     }else{
+-      CLEARBIT(pV, (i+1));
+-      sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
++      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
++      return SQLITE_IOERR_NOMEM;
+     }
+   }
++#endif
++#endif
+ 
+-  /* Test to make sure the linear array exactly matches the
+-  ** Bitvec object.  Start with the assumption that they do
+-  ** match (rc==0).  Change rc to non-zero if a discrepancy
+-  ** is found.
++  /* Check that the output buffer is large enough for the temporary file 
++  ** name. If it is not, return SQLITE_ERROR.
+   */
+-  rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+-          + sqlite3BitvecTest(pBitvec, 0)
+-          + (sqlite3BitvecSize(pBitvec) - sz);
+-  for(i=1; i<=sz; i++){
+-    if(  (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
+-      rc = i;
+-      break;
+-    }
++  nTempPath = sqlite3Strlen30(zTempPath);
++
++  if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
++    OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
++    return SQLITE_ERROR;
+   }
+ 
+-  /* Free allocated structure */
+-bitvec_end:
+-  sqlite3_free(pTmpSpace);
+-  sqlite3_free(pV);
+-  sqlite3BitvecDestroy(pBitvec);
+-  return rc;
++  for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
++  zTempPath[i] = 0;
++
++  sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
++                       "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
++                   zTempPath);
++  j = sqlite3Strlen30(zBuf);
++  sqlite3_randomness(15, &zBuf[j]);
++  for(i=0; i<15; i++, j++){
++    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
++  }
++  zBuf[j] = 0;
++  zBuf[j+1] = 0;
++
++  OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
++  return SQLITE_OK;
+ }
+-#endif /* SQLITE_OMIT_BUILTIN_TEST */
+ 
+-/************** End of bitvec.c **********************************************/
+-/************** Begin file pcache.c ******************************************/
+ /*
+-** 2008 August 05
+-**
+-** 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 that page cache.
++** Return TRUE if the named file is really a directory.  Return false if
++** it is something other than a directory, or if there is any kind of memory
++** allocation failure.
++*/
++static int winIsDir(const void *zConverted){
++  DWORD attr;
++  int rc = 0;
++  DWORD lastErrno;
++
++  if( isNT() ){
++    int cnt = 0;
++    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
++    memset(&sAttrData, 0, sizeof(sAttrData));
++    while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
++                             GetFileExInfoStandard,
++                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
++    if( !rc ){
++      return 0; /* Invalid name? */
++    }
++    attr = sAttrData.dwFileAttributes;
++#if SQLITE_OS_WINCE==0
++  }else{
++    attr = osGetFileAttributesA((char*)zConverted);
++#endif
++  }
++  return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
++}
++
++/*
++** Open a file.
+ */
++static int winOpen(
++  sqlite3_vfs *pVfs,        /* Not used */
++  const char *zName,        /* Name of the file (UTF-8) */
++  sqlite3_file *id,         /* Write the SQLite file handle here */
++  int flags,                /* Open mode flags */
++  int *pOutFlags            /* Status return flags */
++){
++  HANDLE h;
++  DWORD lastErrno;
++  DWORD dwDesiredAccess;
++  DWORD dwShareMode;
++  DWORD dwCreationDisposition;
++  DWORD dwFlagsAndAttributes = 0;
++#if SQLITE_OS_WINCE
++  int isTemp = 0;
++#endif
++  winFile *pFile = (winFile*)id;
++  void *zConverted;              /* Filename in OS encoding */
++  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
++  int cnt = 0;
++
++  /* If argument zPath is a NULL pointer, this function is required to open
++  ** a temporary file. Use this buffer to store the file name in.
++  */
++  char zTmpname[MAX_PATH+2];     /* Buffer used to create temp filename */
++
++  int rc = SQLITE_OK;            /* Function Return Code */
++#if !defined(NDEBUG) || SQLITE_OS_WINCE
++  int eType = flags&0xFFFFFF00;  /* Type of file to open */
++#endif
++
++  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
++  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
++  int isCreate     = (flags & SQLITE_OPEN_CREATE);
++  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
++  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
++
++#ifndef NDEBUG
++  int isOpenJournal = (isCreate && (
++        eType==SQLITE_OPEN_MASTER_JOURNAL 
++     || eType==SQLITE_OPEN_MAIN_JOURNAL 
++     || eType==SQLITE_OPEN_WAL
++  ));
++#endif
++
++  OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
++           zUtf8Name, id, flags, pOutFlags));
++
++  /* Check the following statements are true: 
++  **
++  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
++  **   (b) if CREATE is set, then READWRITE must also be set, and
++  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
++  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
++  */
++  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
++  assert(isCreate==0 || isReadWrite);
++  assert(isExclusive==0 || isCreate);
++  assert(isDelete==0 || isCreate);
+ 
+-/*
+-** A complete page cache is an instance of this structure.
+-*/
+-struct PCache {
+-  PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
+-  PgHdr *pSynced;                     /* Last synced page in dirty page list */
+-  int nRef;                           /* Number of referenced pages */
+-  int szCache;                        /* Configured cache size */
+-  int szPage;                         /* Size of every page in this cache */
+-  int szExtra;                        /* Size of extra space for each page */
+-  int bPurgeable;                     /* True if pages are on backing store */
+-  int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
+-  void *pStress;                      /* Argument to xStress */
+-  sqlite3_pcache *pCache;             /* Pluggable cache module */
+-  PgHdr *pPage1;                      /* Reference to page 1 */
+-};
++  /* The main DB, main journal, WAL file and master journal are never 
++  ** automatically deleted. Nor are they ever temporary files.  */
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
++  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
+ 
+-/*
+-** Some of the assert() macros in this code are too expensive to run
+-** even during normal debugging.  Use them only rarely on long-running
+-** tests.  Enable the expensive asserts using the
+-** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
+-*/
+-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+-# define expensive_assert(X)  assert(X)
+-#else
+-# define expensive_assert(X)
+-#endif
++  /* Assert that the upper layer has set one of the "file-type" flags. */
++  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
++       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
++       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
++       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
++  );
+ 
+-/********************************** Linked List Management ********************/
++  assert( pFile!=0 );
++  memset(pFile, 0, sizeof(winFile));
++  pFile->h = INVALID_HANDLE_VALUE;
+ 
+-#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+-/*
+-** Check that the pCache->pSynced variable is set correctly. If it
+-** is not, either fail an assert or return zero. Otherwise, return
+-** non-zero. This is only used in debugging builds, as follows:
+-**
+-**   expensive_assert( pcacheCheckSynced(pCache) );
+-*/
+-static int pcacheCheckSynced(PCache *pCache){
+-  PgHdr *p;
+-  for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
+-    assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
++#if SQLITE_OS_WINRT
++  if( !sqlite3_temp_directory ){
++    sqlite3_log(SQLITE_ERROR,
++        "sqlite3_temp_directory variable should be set for WinRT");
+   }
+-  return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
+-}
+-#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
++#endif
+ 
+-/*
+-** Remove page pPage from the list of dirty pages.
+-*/
+-static void pcacheRemoveFromDirtyList(PgHdr *pPage){
+-  PCache *p = pPage->pCache;
++  /* If the second argument to this function is NULL, generate a 
++  ** temporary file name to use 
++  */
++  if( !zUtf8Name ){
++    assert(isDelete && !isOpenJournal);
++    memset(zTmpname, 0, MAX_PATH+2);
++    rc = getTempname(MAX_PATH+2, zTmpname);
++    if( rc!=SQLITE_OK ){
++      OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
++      return rc;
++    }
++    zUtf8Name = zTmpname;
++  }
+ 
+-  assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
+-  assert( pPage->pDirtyPrev || pPage==p->pDirty );
++  /* Database filenames are double-zero terminated if they are not
++  ** URIs with parameters.  Hence, they can always be passed into
++  ** sqlite3_uri_parameter().
++  */
++  assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
++        zUtf8Name[strlen(zUtf8Name)+1]==0 );
+ 
+-  /* Update the PCache1.pSynced variable if necessary. */
+-  if( p->pSynced==pPage ){
+-    PgHdr *pSynced = pPage->pDirtyPrev;
+-    while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
+-      pSynced = pSynced->pDirtyPrev;
+-    }
+-    p->pSynced = pSynced;
++  /* Convert the filename to the system encoding. */
++  zConverted = convertUtf8Filename(zUtf8Name);
++  if( zConverted==0 ){
++    OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
++    return SQLITE_IOERR_NOMEM;
+   }
+ 
+-  if( pPage->pDirtyNext ){
+-    pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
+-  }else{
+-    assert( pPage==p->pDirtyTail );
+-    p->pDirtyTail = pPage->pDirtyPrev;
++  if( winIsDir(zConverted) ){
++    sqlite3_free(zConverted);
++    OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
++    return SQLITE_CANTOPEN_ISDIR;
+   }
+-  if( pPage->pDirtyPrev ){
+-    pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
++
++  if( isReadWrite ){
++    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+   }else{
+-    assert( pPage==p->pDirty );
+-    p->pDirty = pPage->pDirtyNext;
++    dwDesiredAccess = GENERIC_READ;
+   }
+-  pPage->pDirtyNext = 0;
+-  pPage->pDirtyPrev = 0;
+-
+-  expensive_assert( pcacheCheckSynced(p) );
+-}
+ 
+-/*
+-** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
+-** pPage).
+-*/
+-static void pcacheAddToDirtyList(PgHdr *pPage){
+-  PCache *p = pPage->pCache;
++  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 
++  ** created. SQLite doesn't use it to indicate "exclusive access" 
++  ** as it is usually understood.
++  */
++  if( isExclusive ){
++    /* Creates a new file, only if it does not already exist. */
++    /* If the file exists, it fails. */
++    dwCreationDisposition = CREATE_NEW;
++  }else if( isCreate ){
++    /* Open existing file, or create if it doesn't exist */
++    dwCreationDisposition = OPEN_ALWAYS;
++  }else{
++    /* Opens a file, only if it exists. */
++    dwCreationDisposition = OPEN_EXISTING;
++  }
+ 
+-  assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
++  dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ 
+-  pPage->pDirtyNext = p->pDirty;
+-  if( pPage->pDirtyNext ){
+-    assert( pPage->pDirtyNext->pDirtyPrev==0 );
+-    pPage->pDirtyNext->pDirtyPrev = pPage;
++  if( isDelete ){
++#if SQLITE_OS_WINCE
++    dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
++    isTemp = 1;
++#else
++    dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
++                               | FILE_ATTRIBUTE_HIDDEN
++                               | FILE_FLAG_DELETE_ON_CLOSE;
++#endif
++  }else{
++    dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+   }
+-  p->pDirty = pPage;
+-  if( !p->pDirtyTail ){
+-    p->pDirtyTail = pPage;
++  /* Reports from the internet are that performance is always
++  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
++#if SQLITE_OS_WINCE
++  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
++#endif
++
++  if( isNT() ){
++#if SQLITE_OS_WINRT
++    CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
++    extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
++    extendedParameters.dwFileAttributes =
++            dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
++    extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
++    extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
++    extendedParameters.lpSecurityAttributes = NULL;
++    extendedParameters.hTemplateFile = NULL;
++    while( (h = osCreateFile2((LPCWSTR)zConverted,
++                              dwDesiredAccess,
++                              dwShareMode,
++                              dwCreationDisposition,
++                              &extendedParameters))==INVALID_HANDLE_VALUE &&
++                              retryIoerr(&cnt, &lastErrno) ){
++               /* Noop */
++    }
++#else
++    while( (h = osCreateFileW((LPCWSTR)zConverted,
++                              dwDesiredAccess,
++                              dwShareMode, NULL,
++                              dwCreationDisposition,
++                              dwFlagsAndAttributes,
++                              NULL))==INVALID_HANDLE_VALUE &&
++                              retryIoerr(&cnt, &lastErrno) ){
++               /* Noop */
++    }
++#endif
+   }
+-  if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
+-    p->pSynced = pPage;
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    while( (h = osCreateFileA((LPCSTR)zConverted,
++                              dwDesiredAccess,
++                              dwShareMode, NULL,
++                              dwCreationDisposition,
++                              dwFlagsAndAttributes,
++                              NULL))==INVALID_HANDLE_VALUE &&
++                              retryIoerr(&cnt, &lastErrno) ){
++               /* Noop */
++    }
+   }
+-  expensive_assert( pcacheCheckSynced(p) );
+-}
++#endif
++  logIoerr(cnt);
+ 
+-/*
+-** Wrapper around the pluggable caches xUnpin method. If the cache is
+-** being used for an in-memory database, this function is a no-op.
+-*/
+-static void pcacheUnpin(PgHdr *p){
+-  PCache *pCache = p->pCache;
+-  if( pCache->bPurgeable ){
+-    if( p->pgno==1 ){
+-      pCache->pPage1 = 0;
++  OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
++           dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
++
++  if( h==INVALID_HANDLE_VALUE ){
++    pFile->lastErrno = lastErrno;
++    winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
++    sqlite3_free(zConverted);
++    if( isReadWrite && !isExclusive ){
++      return winOpen(pVfs, zName, id, 
++         ((flags|SQLITE_OPEN_READONLY) &
++                     ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
++         pOutFlags);
++    }else{
++      return SQLITE_CANTOPEN_BKPT;
+     }
+-    sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
+   }
+-}
+ 
+-/*************************************************** General Interfaces ******
+-**
+-** Initialize and shutdown the page cache subsystem. Neither of these 
+-** functions are threadsafe.
+-*/
+-SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
+-  if( sqlite3GlobalConfig.pcache2.xInit==0 ){
+-    /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
+-    ** built-in default page cache is used instead of the application defined
+-    ** page cache. */
+-    sqlite3PCacheSetDefault();
+-  }
+-  return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
+-}
+-SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
+-  if( sqlite3GlobalConfig.pcache2.xShutdown ){
+-    /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
+-    sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
++  if( pOutFlags ){
++    if( isReadWrite ){
++      *pOutFlags = SQLITE_OPEN_READWRITE;
++    }else{
++      *pOutFlags = SQLITE_OPEN_READONLY;
++    }
+   }
+-}
+-
+-/*
+-** Return the size in bytes of a PCache object.
+-*/
+-SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
+ 
+-/*
+-** Create a new PCache object. Storage space to hold the object
+-** has already been allocated and is passed in as the p pointer. 
+-** The caller discovers how much space needs to be allocated by 
+-** calling sqlite3PcacheSize().
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheOpen(
+-  int szPage,                  /* Size of every page */
+-  int szExtra,                 /* Extra space associated with each page */
+-  int bPurgeable,              /* True if pages are on backing store */
+-  int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
+-  void *pStress,               /* Argument to xStress */
+-  PCache *p                    /* Preallocated space for the PCache */
+-){
+-  memset(p, 0, sizeof(PCache));
+-  p->szPage = szPage;
+-  p->szExtra = szExtra;
+-  p->bPurgeable = bPurgeable;
+-  p->xStress = xStress;
+-  p->pStress = pStress;
+-  p->szCache = 100;
+-}
++  OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
++           "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
++           *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
+ 
+-/*
+-** Change the page size for PCache object. The caller must ensure that there
+-** are no outstanding page references when this function is called.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
+-  assert( pCache->nRef==0 && pCache->pDirty==0 );
+-  if( pCache->pCache ){
+-    sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
+-    pCache->pCache = 0;
+-    pCache->pPage1 = 0;
++#if SQLITE_OS_WINCE
++  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
++       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
++  ){
++    osCloseHandle(h);
++    sqlite3_free(zConverted);
++    OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
++    return rc;
++  }
++  if( isTemp ){
++    pFile->zDeleteOnClose = zConverted;
++  }else
++#endif
++  {
++    sqlite3_free(zConverted);
+   }
+-  pCache->szPage = szPage;
+-}
+ 
+-/*
+-** Compute the number of pages of cache requested.
+-*/
+-static int numberOfCachePages(PCache *p){
+-  if( p->szCache>=0 ){
+-    return p->szCache;
+-  }else{
+-    return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
++  pFile->pMethod = &winIoMethod;
++  pFile->pVfs = pVfs;
++  pFile->h = h;
++  if( isReadonly ){
++    pFile->ctrlFlags |= WINFILE_RDONLY;
++  }
++  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
++    pFile->ctrlFlags |= WINFILE_PSOW;
+   }
++  pFile->lastErrno = NO_ERROR;
++  pFile->zPath = zName;
++#if SQLITE_MAX_MMAP_SIZE>0
++  pFile->hMap = NULL;
++  pFile->pMapRegion = 0;
++  pFile->mmapSize = 0;
++  pFile->mmapSizeActual = 0;
++  pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
++#endif
++
++  OpenCounter(+1);
++  return rc;
+ }
+ 
+ /*
+-** Try to obtain a page from the cache.
++** Delete the named file.
++**
++** Note that Windows does not allow a file to be deleted if some other
++** process has it open.  Sometimes a virus scanner or indexing program
++** will open a journal file shortly after it is created in order to do
++** whatever it does.  While this other process is holding the
++** file open, we will be unable to delete it.  To work around this
++** problem, we delay 100 milliseconds and try to delete again.  Up
++** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
++** up and returning an error.
+ */
+-SQLITE_PRIVATE int sqlite3PcacheFetch(
+-  PCache *pCache,       /* Obtain the page from this cache */
+-  Pgno pgno,            /* Page number to obtain */
+-  int createFlag,       /* If true, create page if it does not exist already */
+-  PgHdr **ppPage        /* Write the page here */
++static int winDelete(
++  sqlite3_vfs *pVfs,          /* Not used on win32 */
++  const char *zFilename,      /* Name of file to delete */
++  int syncDir                 /* Not used on win32 */
+ ){
+-  sqlite3_pcache_page *pPage = 0;
+-  PgHdr *pPgHdr = 0;
+-  int eCreate;
+-
+-  assert( pCache!=0 );
+-  assert( createFlag==1 || createFlag==0 );
+-  assert( pgno>0 );
++  int cnt = 0;
++  int rc;
++  DWORD attr;
++  DWORD lastErrno;
++  void *zConverted;
++  UNUSED_PARAMETER(pVfs);
++  UNUSED_PARAMETER(syncDir);
+ 
+-  /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
+-  ** allocate it now.
+-  */
+-  if( !pCache->pCache && createFlag ){
+-    sqlite3_pcache *p;
+-    p = sqlite3GlobalConfig.pcache2.xCreate(
+-        pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
+-    );
+-    if( !p ){
+-      return SQLITE_NOMEM;
+-    }
+-    sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
+-    pCache->pCache = p;
+-  }
++  SimulateIOError(return SQLITE_IOERR_DELETE);
++  OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
+ 
+-  eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
+-  if( pCache->pCache ){
+-    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
++  zConverted = convertUtf8Filename(zFilename);
++  if( zConverted==0 ){
++    return SQLITE_IOERR_NOMEM;
+   }
+-
+-  if( !pPage && eCreate==1 ){
+-    PgHdr *pPg;
+-
+-    /* Find a dirty page to write-out and recycle. First try to find a 
+-    ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
+-    ** cleared), but if that is not possible settle for any other 
+-    ** unreferenced dirty page.
+-    */
+-    expensive_assert( pcacheCheckSynced(pCache) );
+-    for(pPg=pCache->pSynced; 
+-        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
+-        pPg=pPg->pDirtyPrev
+-    );
+-    pCache->pSynced = pPg;
+-    if( !pPg ){
+-      for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
+-    }
+-    if( pPg ){
+-      int rc;
+-#ifdef SQLITE_LOG_CACHE_SPILL
+-      sqlite3_log(SQLITE_FULL, 
+-                  "spill page %d making room for %d - cache used: %d/%d",
+-                  pPg->pgno, pgno,
+-                  sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
+-                  numberOfCachePages(pCache));
++  if( isNT() ){
++    do {
++#if SQLITE_OS_WINRT
++      WIN32_FILE_ATTRIBUTE_DATA sAttrData;
++      memset(&sAttrData, 0, sizeof(sAttrData));
++      if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
++                                  &sAttrData) ){
++        attr = sAttrData.dwFileAttributes;
++      }else{
++        lastErrno = osGetLastError();
++        if( lastErrno==ERROR_FILE_NOT_FOUND
++         || lastErrno==ERROR_PATH_NOT_FOUND ){
++          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
++        }else{
++          rc = SQLITE_ERROR;
++        }
++        break;
++      }
++#else
++      attr = osGetFileAttributesW(zConverted);
+ #endif
+-      rc = pCache->xStress(pCache->pStress, pPg);
+-      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
+-        return rc;
++      if ( attr==INVALID_FILE_ATTRIBUTES ){
++        lastErrno = osGetLastError();
++        if( lastErrno==ERROR_FILE_NOT_FOUND
++         || lastErrno==ERROR_PATH_NOT_FOUND ){
++          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
++        }else{
++          rc = SQLITE_ERROR;
++        }
++        break;
+       }
+-    }
+-
+-    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
++      if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
++        rc = SQLITE_ERROR; /* Files only. */
++        break;
++      }
++      if ( osDeleteFileW(zConverted) ){
++        rc = SQLITE_OK; /* Deleted OK. */
++        break;
++      }
++      if ( !retryIoerr(&cnt, &lastErrno) ){
++        rc = SQLITE_ERROR; /* No more retries. */
++        break;
++      }
++    } while(1);
+   }
+-
+-  if( pPage ){
+-    pPgHdr = (PgHdr *)pPage->pExtra;
+-
+-    if( !pPgHdr->pPage ){
+-      memset(pPgHdr, 0, sizeof(PgHdr));
+-      pPgHdr->pPage = pPage;
+-      pPgHdr->pData = pPage->pBuf;
+-      pPgHdr->pExtra = (void *)&pPgHdr[1];
+-      memset(pPgHdr->pExtra, 0, pCache->szExtra);
+-      pPgHdr->pCache = pCache;
+-      pPgHdr->pgno = pgno;
+-    }
+-    assert( pPgHdr->pCache==pCache );
+-    assert( pPgHdr->pgno==pgno );
+-    assert( pPgHdr->pData==pPage->pBuf );
+-    assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
+-
+-    if( 0==pPgHdr->nRef ){
+-      pCache->nRef++;
+-    }
+-    pPgHdr->nRef++;
+-    if( pgno==1 ){
+-      pCache->pPage1 = pPgHdr;
+-    }
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    do {
++      attr = osGetFileAttributesA(zConverted);
++      if ( attr==INVALID_FILE_ATTRIBUTES ){
++        lastErrno = osGetLastError();
++        if( lastErrno==ERROR_FILE_NOT_FOUND
++         || lastErrno==ERROR_PATH_NOT_FOUND ){
++          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
++        }else{
++          rc = SQLITE_ERROR;
++        }
++        break;
++      }
++      if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
++        rc = SQLITE_ERROR; /* Files only. */
++        break;
++      }
++      if ( osDeleteFileA(zConverted) ){
++        rc = SQLITE_OK; /* Deleted OK. */
++        break;
++      }
++      if ( !retryIoerr(&cnt, &lastErrno) ){
++        rc = SQLITE_ERROR; /* No more retries. */
++        break;
++      }
++    } while(1);
+   }
+-  *ppPage = pPgHdr;
+-  return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
++#endif
++  if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
++    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
++             "winDelete", zFilename);
++  }else{
++    logIoerr(cnt);
++  }
++  sqlite3_free(zConverted);
++  OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
++  return rc;
+ }
+ 
+ /*
+-** Decrement the reference count on a page. If the page is clean and the
+-** reference count drops to 0, then it is made elible for recycling.
++** Check the existence and status of a file.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
+-  assert( p->nRef>0 );
+-  p->nRef--;
+-  if( p->nRef==0 ){
+-    PCache *pCache = p->pCache;
+-    pCache->nRef--;
+-    if( (p->flags&PGHDR_DIRTY)==0 ){
+-      pcacheUnpin(p);
++static int winAccess(
++  sqlite3_vfs *pVfs,         /* Not used on win32 */
++  const char *zFilename,     /* Name of file to check */
++  int flags,                 /* Type of test to make on this file */
++  int *pResOut               /* OUT: Result */
++){
++  DWORD attr;
++  int rc = 0;
++  DWORD lastErrno;
++  void *zConverted;
++  UNUSED_PARAMETER(pVfs);
++
++  SimulateIOError( return SQLITE_IOERR_ACCESS; );
++  OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
++           zFilename, flags, pResOut));
++
++  zConverted = convertUtf8Filename(zFilename);
++  if( zConverted==0 ){
++    OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
++    return SQLITE_IOERR_NOMEM;
++  }
++  if( isNT() ){
++    int cnt = 0;
++    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
++    memset(&sAttrData, 0, sizeof(sAttrData));
++    while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
++                             GetFileExInfoStandard, 
++                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
++    if( rc ){
++      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
++      ** as if it does not exist.
++      */
++      if(    flags==SQLITE_ACCESS_EXISTS
++          && sAttrData.nFileSizeHigh==0 
++          && sAttrData.nFileSizeLow==0 ){
++        attr = INVALID_FILE_ATTRIBUTES;
++      }else{
++        attr = sAttrData.dwFileAttributes;
++      }
+     }else{
+-      /* Move the page to the head of the dirty list. */
+-      pcacheRemoveFromDirtyList(p);
+-      pcacheAddToDirtyList(p);
++      logIoerr(cnt);
++      if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
++        winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
++        sqlite3_free(zConverted);
++        return SQLITE_IOERR_ACCESS;
++      }else{
++        attr = INVALID_FILE_ATTRIBUTES;
++      }
+     }
+   }
+-}
+-
+-/*
+-** Increase the reference count of a supplied page by 1.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
+-  assert(p->nRef>0);
+-  p->nRef++;
+-}
+-
+-/*
+-** Drop a page from the cache. There must be exactly one reference to the
+-** page. This function deletes that reference, so after it returns the
+-** page pointed to by p is invalid.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
+-  PCache *pCache;
+-  assert( p->nRef==1 );
+-  if( p->flags&PGHDR_DIRTY ){
+-    pcacheRemoveFromDirtyList(p);
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    attr = osGetFileAttributesA((char*)zConverted);
+   }
+-  pCache = p->pCache;
+-  pCache->nRef--;
+-  if( p->pgno==1 ){
+-    pCache->pPage1 = 0;
++#endif
++  sqlite3_free(zConverted);
++  switch( flags ){
++    case SQLITE_ACCESS_READ:
++    case SQLITE_ACCESS_EXISTS:
++      rc = attr!=INVALID_FILE_ATTRIBUTES;
++      break;
++    case SQLITE_ACCESS_READWRITE:
++      rc = attr!=INVALID_FILE_ATTRIBUTES &&
++             (attr & FILE_ATTRIBUTE_READONLY)==0;
++      break;
++    default:
++      assert(!"Invalid flags argument");
+   }
+-  sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
++  *pResOut = rc;
++  OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
++           zFilename, pResOut, *pResOut));
++  return SQLITE_OK;
+ }
+ 
++
+ /*
+-** Make sure the page is marked as dirty. If it isn't dirty already,
+-** make it so.
++** Returns non-zero if the specified path name should be used verbatim.  If
++** non-zero is returned from this function, the calling function must simply
++** use the provided path name verbatim -OR- resolve it into a full path name
++** using the GetFullPathName Win32 API function (if available).
+ */
+-SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
+-  p->flags &= ~PGHDR_DONT_WRITE;
+-  assert( p->nRef>0 );
+-  if( 0==(p->flags & PGHDR_DIRTY) ){
+-    p->flags |= PGHDR_DIRTY;
+-    pcacheAddToDirtyList( p);
++static BOOL winIsVerbatimPathname(
++  const char *zPathname
++){
++  /*
++  ** If the path name starts with a forward slash or a backslash, it is either
++  ** a legal UNC name, a volume relative path, or an absolute path name in the
++  ** "Unix" format on Windows.  There is no easy way to differentiate between
++  ** the final two cases; therefore, we return the safer return value of TRUE
++  ** so that callers of this function will simply use it verbatim.
++  */
++  if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
++    return TRUE;
+   }
+-}
+ 
+-/*
+-** Make sure the page is marked as clean. If it isn't clean already,
+-** make it so.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
+-  if( (p->flags & PGHDR_DIRTY) ){
+-    pcacheRemoveFromDirtyList(p);
+-    p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
+-    if( p->nRef==0 ){
+-      pcacheUnpin(p);
+-    }
++  /*
++  ** If the path name starts with a letter and a colon it is either a volume
++  ** relative path or an absolute path.  Callers of this function must not
++  ** attempt to treat it as a relative path name (i.e. they should simply use
++  ** it verbatim).
++  */
++  if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
++    return TRUE;
+   }
++
++  /*
++  ** If we get to this point, the path name should almost certainly be a purely
++  ** relative one (i.e. not a UNC name, not absolute, and not volume relative).
++  */
++  return FALSE;
+ }
+ 
+ /*
+-** Make every page in the cache clean.
++** Turn a relative pathname into a full pathname.  Write the full
++** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
++** bytes in size.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
+-  PgHdr *p;
+-  while( (p = pCache->pDirty)!=0 ){
+-    sqlite3PcacheMakeClean(p);
++static int winFullPathname(
++  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
++  const char *zRelative,        /* Possibly relative input path */
++  int nFull,                    /* Size of output buffer in bytes */
++  char *zFull                   /* Output buffer */
++){
++  
++#if defined(__CYGWIN__)
++  SimulateIOError( return SQLITE_ERROR );
++  UNUSED_PARAMETER(nFull);
++  assert( pVfs->mxPathname>=MAX_PATH );
++  assert( nFull>=pVfs->mxPathname );
++  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
++    /*
++    ** NOTE: We are dealing with a relative path name and the data
++    **       directory has been set.  Therefore, use it as the basis
++    **       for converting the relative path name to an absolute
++    **       one by prepending the data directory and a slash.
++    */
++    char zOut[MAX_PATH+1];
++    memset(zOut, 0, MAX_PATH+1);
++    cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
++                     MAX_PATH+1);
++    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
++                     sqlite3_data_directory, zOut);
++  }else{
++    cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
+   }
+-}
++  return SQLITE_OK;
++#endif
+ 
+-/*
+-** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
+-  PgHdr *p;
+-  for(p=pCache->pDirty; p; p=p->pDirtyNext){
+-    p->flags &= ~PGHDR_NEED_SYNC;
++#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
++  SimulateIOError( return SQLITE_ERROR );
++  /* WinCE has no concept of a relative pathname, or so I am told. */
++  /* WinRT has no way to convert a relative path to an absolute one. */
++  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
++    /*
++    ** NOTE: We are dealing with a relative path name and the data
++    **       directory has been set.  Therefore, use it as the basis
++    **       for converting the relative path name to an absolute
++    **       one by prepending the data directory and a backslash.
++    */
++    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
++                     sqlite3_data_directory, zRelative);
++  }else{
++    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
+   }
+-  pCache->pSynced = pCache->pDirtyTail;
+-}
++  return SQLITE_OK;
++#endif
+ 
+-/*
+-** Change the page number of page p to newPgno. 
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
+-  PCache *pCache = p->pCache;
+-  assert( p->nRef>0 );
+-  assert( newPgno>0 );
+-  sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
+-  p->pgno = newPgno;
+-  if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
+-    pcacheRemoveFromDirtyList(p);
+-    pcacheAddToDirtyList(p);
++#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
++  DWORD nByte;
++  void *zConverted;
++  char *zOut;
++
++  /* If this path name begins with "/X:", where "X" is any alphabetic
++  ** character, discard the initial "/" from the pathname.
++  */
++  if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
++    zRelative++;
+   }
+-}
+ 
+-/*
+-** Drop every cache entry whose page number is greater than "pgno". The
+-** caller must ensure that there are no outstanding references to any pages
+-** other than page 1 with a page number greater than pgno.
+-**
+-** If there is a reference to page 1 and the pgno parameter passed to this
+-** function is 0, then the data area associated with page 1 is zeroed, but
+-** the page object is not dropped.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
+-  if( pCache->pCache ){
+-    PgHdr *p;
+-    PgHdr *pNext;
+-    for(p=pCache->pDirty; p; p=pNext){
+-      pNext = p->pDirtyNext;
+-      /* This routine never gets call with a positive pgno except right
+-      ** after sqlite3PcacheCleanAll().  So if there are dirty pages,
+-      ** it must be that pgno==0.
+-      */
+-      assert( p->pgno>0 );
+-      if( ALWAYS(p->pgno>pgno) ){
+-        assert( p->flags&PGHDR_DIRTY );
+-        sqlite3PcacheMakeClean(p);
+-      }
++  /* It's odd to simulate an io-error here, but really this is just
++  ** using the io-error infrastructure to test that SQLite handles this
++  ** function failing. This function could fail if, for example, the
++  ** current working directory has been unlinked.
++  */
++  SimulateIOError( return SQLITE_ERROR );
++  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
++    /*
++    ** NOTE: We are dealing with a relative path name and the data
++    **       directory has been set.  Therefore, use it as the basis
++    **       for converting the relative path name to an absolute
++    **       one by prepending the data directory and a backslash.
++    */
++    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
++                     sqlite3_data_directory, zRelative);
++    return SQLITE_OK;
++  }
++  zConverted = convertUtf8Filename(zRelative);
++  if( zConverted==0 ){
++    return SQLITE_IOERR_NOMEM;
++  }
++  if( isNT() ){
++    LPWSTR zTemp;
++    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
++    if( nByte==0 ){
++      winLogError(SQLITE_ERROR, osGetLastError(),
++                  "GetFullPathNameW1", zConverted);
++      sqlite3_free(zConverted);
++      return SQLITE_CANTOPEN_FULLPATH;
+     }
+-    if( pgno==0 && pCache->pPage1 ){
+-      memset(pCache->pPage1->pData, 0, pCache->szPage);
+-      pgno = 1;
++    nByte += 3;
++    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
++    if( zTemp==0 ){
++      sqlite3_free(zConverted);
++      return SQLITE_IOERR_NOMEM;
+     }
+-    sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
++    nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
++    if( nByte==0 ){
++      winLogError(SQLITE_ERROR, osGetLastError(),
++                  "GetFullPathNameW2", zConverted);
++      sqlite3_free(zConverted);
++      sqlite3_free(zTemp);
++      return SQLITE_CANTOPEN_FULLPATH;
++    }
++    sqlite3_free(zConverted);
++    zOut = unicodeToUtf8(zTemp);
++    sqlite3_free(zTemp);
+   }
+-}
+-
+-/*
+-** Close a cache.
+-*/
+-SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
+-  if( pCache->pCache ){
+-    sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    char *zTemp;
++    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
++    if( nByte==0 ){
++      winLogError(SQLITE_ERROR, osGetLastError(),
++                  "GetFullPathNameA1", zConverted);
++      sqlite3_free(zConverted);
++      return SQLITE_CANTOPEN_FULLPATH;
++    }
++    nByte += 3;
++    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
++    if( zTemp==0 ){
++      sqlite3_free(zConverted);
++      return SQLITE_IOERR_NOMEM;
++    }
++    nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
++    if( nByte==0 ){
++      winLogError(SQLITE_ERROR, osGetLastError(),
++                  "GetFullPathNameA2", zConverted);
++      sqlite3_free(zConverted);
++      sqlite3_free(zTemp);
++      return SQLITE_CANTOPEN_FULLPATH;
++    }
++    sqlite3_free(zConverted);
++    zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
++    sqlite3_free(zTemp);
++  }
++#endif
++  if( zOut ){
++    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
++    sqlite3_free(zOut);
++    return SQLITE_OK;
++  }else{
++    return SQLITE_IOERR_NOMEM;
+   }
++#endif
+ }
+ 
+-/* 
+-** Discard the contents of the cache.
++#ifndef SQLITE_OMIT_LOAD_EXTENSION
++/*
++** Interfaces for opening a shared library, finding entry points
++** within the shared library, and closing the shared library.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
+-  sqlite3PcacheTruncate(pCache, 0);
+-}
+-
+ /*
+-** Merge two lists of pages connected by pDirty and in pgno order.
+-** Do not both fixing the pDirtyPrev pointers.
++** Interfaces for opening a shared library, finding entry points
++** within the shared library, and closing the shared library.
+ */
+-static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
+-  PgHdr result, *pTail;
+-  pTail = &result;
+-  while( pA && pB ){
+-    if( pA->pgno<pB->pgno ){
+-      pTail->pDirty = pA;
+-      pTail = pA;
+-      pA = pA->pDirty;
+-    }else{
+-      pTail->pDirty = pB;
+-      pTail = pB;
+-      pB = pB->pDirty;
+-    }
++static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
++  HANDLE h;
++  void *zConverted = convertUtf8Filename(zFilename);
++  UNUSED_PARAMETER(pVfs);
++  if( zConverted==0 ){
++    return 0;
+   }
+-  if( pA ){
+-    pTail->pDirty = pA;
+-  }else if( pB ){
+-    pTail->pDirty = pB;
+-  }else{
+-    pTail->pDirty = 0;
++  if( isNT() ){
++#if SQLITE_OS_WINRT
++    h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
++#else
++    h = osLoadLibraryW((LPCWSTR)zConverted);
++#endif
+   }
+-  return result.pDirty;
++#ifdef SQLITE_WIN32_HAS_ANSI
++  else{
++    h = osLoadLibraryA((char*)zConverted);
++  }
++#endif
++  sqlite3_free(zConverted);
++  return (void*)h;
++}
++static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
++  UNUSED_PARAMETER(pVfs);
++  getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
++}
++static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
++  UNUSED_PARAMETER(pVfs);
++  return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
++}
++static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
++  UNUSED_PARAMETER(pVfs);
++  osFreeLibrary((HANDLE)pHandle);
+ }
++#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
++  #define winDlOpen  0
++  #define winDlError 0
++  #define winDlSym   0
++  #define winDlClose 0
++#endif
++
+ 
+ /*
+-** Sort the list of pages in accending order by pgno.  Pages are
+-** connected by pDirty pointers.  The pDirtyPrev pointers are
+-** corrupted by this sort.
+-**
+-** Since there cannot be more than 2^31 distinct pages in a database,
+-** there cannot be more than 31 buckets required by the merge sorter.
+-** One extra bucket is added to catch overflow in case something
+-** ever changes to make the previous sentence incorrect.
++** Write up to nBuf bytes of randomness into zBuf.
+ */
+-#define N_SORT_BUCKET  32
+-static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
+-  PgHdr *a[N_SORT_BUCKET], *p;
+-  int i;
+-  memset(a, 0, sizeof(a));
+-  while( pIn ){
+-    p = pIn;
+-    pIn = p->pDirty;
+-    p->pDirty = 0;
+-    for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
+-      if( a[i]==0 ){
+-        a[i] = p;
+-        break;
+-      }else{
+-        p = pcacheMergeDirtyList(a[i], p);
+-        a[i] = 0;
+-      }
+-    }
+-    if( NEVER(i==N_SORT_BUCKET-1) ){
+-      /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
+-      ** the input list.  But that is impossible.
+-      */
+-      a[i] = pcacheMergeDirtyList(a[i], p);
+-    }
++static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
++  int n = 0;
++  UNUSED_PARAMETER(pVfs);
++#if defined(SQLITE_TEST)
++  n = nBuf;
++  memset(zBuf, 0, nBuf);
++#else
++  if( sizeof(SYSTEMTIME)<=nBuf-n ){
++    SYSTEMTIME x;
++    osGetSystemTime(&x);
++    memcpy(&zBuf[n], &x, sizeof(x));
++    n += sizeof(x);
+   }
+-  p = a[0];
+-  for(i=1; i<N_SORT_BUCKET; i++){
+-    p = pcacheMergeDirtyList(p, a[i]);
++  if( sizeof(DWORD)<=nBuf-n ){
++    DWORD pid = osGetCurrentProcessId();
++    memcpy(&zBuf[n], &pid, sizeof(pid));
++    n += sizeof(pid);
+   }
+-  return p;
++#if SQLITE_OS_WINRT
++  if( sizeof(ULONGLONG)<=nBuf-n ){
++    ULONGLONG cnt = osGetTickCount64();
++    memcpy(&zBuf[n], &cnt, sizeof(cnt));
++    n += sizeof(cnt);
++  }
++#else
++  if( sizeof(DWORD)<=nBuf-n ){
++    DWORD cnt = osGetTickCount();
++    memcpy(&zBuf[n], &cnt, sizeof(cnt));
++    n += sizeof(cnt);
++  }
++#endif
++  if( sizeof(LARGE_INTEGER)<=nBuf-n ){
++    LARGE_INTEGER i;
++    osQueryPerformanceCounter(&i);
++    memcpy(&zBuf[n], &i, sizeof(i));
++    n += sizeof(i);
++  }
++#endif
++  return n;
+ }
+ 
++
+ /*
+-** Return a list of all dirty pages in the cache, sorted by page number.
++** Sleep for a little while.  Return the amount of time slept.
+ */
+-SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
+-  PgHdr *p;
+-  for(p=pCache->pDirty; p; p=p->pDirtyNext){
+-    p->pDirty = p->pDirtyNext;
+-  }
+-  return pcacheSortDirtyList(pCache->pDirty);
++static int winSleep(sqlite3_vfs *pVfs, int microsec){
++  sqlite3_win32_sleep((microsec+999)/1000);
++  UNUSED_PARAMETER(pVfs);
++  return ((microsec+999)/1000)*1000;
+ }
+ 
+-/* 
+-** Return the total number of referenced pages held by the cache.
++/*
++** The following variable, if set to a non-zero value, is interpreted as
++** the number of seconds since 1970 and is used to set the result of
++** sqlite3OsCurrentTime() during testing.
+ */
+-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
+-  return pCache->nRef;
+-}
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_current_time = 0;  /* Fake system time in seconds since 1970. */
++#endif
+ 
+ /*
+-** Return the number of references to the page supplied as an argument.
++** Find the current time (in Universal Coordinated Time).  Write into *piNow
++** the current time and date as a Julian Day number times 86_400_000.  In
++** other words, write into *piNow the number of milliseconds since the Julian
++** epoch of noon in Greenwich on November 24, 4714 B.C according to the
++** proleptic Gregorian calendar.
++**
++** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date 
++** cannot be found.
+ */
+-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
+-  return p->nRef;
+-}
++static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
++  /* FILETIME structure is a 64-bit value representing the number of 
++     100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 
++  */
++  FILETIME ft;
++  static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
++#ifdef SQLITE_TEST
++  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
++#endif
++  /* 2^32 - to avoid use of LL and warnings in gcc */
++  static const sqlite3_int64 max32BitValue = 
++      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
++      (sqlite3_int64)294967296;
+ 
+-/* 
+-** Return the total number of pages in the cache.
+-*/
+-SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
+-  int nPage = 0;
+-  if( pCache->pCache ){
+-    nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
++#if SQLITE_OS_WINCE
++  SYSTEMTIME time;
++  osGetSystemTime(&time);
++  /* if SystemTimeToFileTime() fails, it returns zero. */
++  if (!osSystemTimeToFileTime(&time,&ft)){
++    return SQLITE_ERROR;
+   }
+-  return nPage;
+-}
++#else
++  osGetSystemTimeAsFileTime( &ft );
++#endif
++
++  *piNow = winFiletimeEpoch +
++            ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + 
++               (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
+ 
+ #ifdef SQLITE_TEST
+-/*
+-** Get the suggested cache-size value.
+-*/
+-SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
+-  return numberOfCachePages(pCache);
+-}
++  if( sqlite3_current_time ){
++    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
++  }
+ #endif
++  UNUSED_PARAMETER(pVfs);
++  return SQLITE_OK;
++}
+ 
+ /*
+-** Set the suggested cache-size value.
++** Find the current time (in Universal Coordinated Time).  Write the
++** current time and date as a Julian Day number into *prNow and
++** return 0.  Return 1 if the time and date cannot be found.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
+-  pCache->szCache = mxPage;
+-  if( pCache->pCache ){
+-    sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
+-                                           numberOfCachePages(pCache));
++static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
++  int rc;
++  sqlite3_int64 i;
++  rc = winCurrentTimeInt64(pVfs, &i);
++  if( !rc ){
++    *prNow = i/86400000.0;
+   }
++  return rc;
+ }
+ 
+ /*
+-** Free up as much memory as possible from the page cache.
++** The idea is that this function works like a combination of
++** GetLastError() and FormatMessage() on Windows (or errno and
++** strerror_r() on Unix). After an error is returned by an OS
++** function, SQLite calls this function with zBuf pointing to
++** a buffer of nBuf bytes. The OS layer should populate the
++** buffer with a nul-terminated UTF-8 encoded error message
++** describing the last IO error to have occurred within the calling
++** thread.
++**
++** If the error message is too large for the supplied buffer,
++** it should be truncated. The return value of xGetLastError
++** is zero if the error message fits in the buffer, or non-zero
++** otherwise (if the message was truncated). If non-zero is returned,
++** then it is not necessary to include the nul-terminator character
++** in the output buffer.
++**
++** Not supplying an error message will have no adverse effect
++** on SQLite. It is fine to have an implementation that never
++** returns an error message:
++**
++**   int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
++**     assert(zBuf[0]=='\0');
++**     return 0;
++**   }
++**
++** However if an error message is supplied, it will be incorporated
++** by sqlite into the error message available to the user using
++** sqlite3_errmsg(), possibly making IO errors easier to debug.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){
+-  if( pCache->pCache ){
+-    sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
+-  }
++static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
++  UNUSED_PARAMETER(pVfs);
++  return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
+ }
+ 
+-#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
+ /*
+-** For all dirty pages currently in the cache, invoke the specified
+-** callback. This is only used if the SQLITE_CHECK_PAGES macro is
+-** defined.
++** Initialize and deinitialize the operating system interface.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
+-  PgHdr *pDirty;
+-  for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
+-    xIter(pDirty);
+-  }
++SQLITE_API int sqlite3_os_init(void){
++  static sqlite3_vfs winVfs = {
++    3,                   /* iVersion */
++    sizeof(winFile),     /* szOsFile */
++    MAX_PATH,            /* mxPathname */
++    0,                   /* pNext */
++    "win32",             /* zName */
++    0,                   /* pAppData */
++    winOpen,             /* xOpen */
++    winDelete,           /* xDelete */
++    winAccess,           /* xAccess */
++    winFullPathname,     /* xFullPathname */
++    winDlOpen,           /* xDlOpen */
++    winDlError,          /* xDlError */
++    winDlSym,            /* xDlSym */
++    winDlClose,          /* xDlClose */
++    winRandomness,       /* xRandomness */
++    winSleep,            /* xSleep */
++    winCurrentTime,      /* xCurrentTime */
++    winGetLastError,     /* xGetLastError */
++    winCurrentTimeInt64, /* xCurrentTimeInt64 */
++    winSetSystemCall,    /* xSetSystemCall */
++    winGetSystemCall,    /* xGetSystemCall */
++    winNextSystemCall,   /* xNextSystemCall */
++  };
++
++  /* Double-check that the aSyscall[] array has been constructed
++  ** correctly.  See ticket [bb3a86e890c8e96ab] */
++  assert( ArraySize(aSyscall)==74 );
++
++  /* get memory map allocation granularity */
++  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
++#if SQLITE_OS_WINRT
++  osGetNativeSystemInfo(&winSysInfo);
++#else
++  osGetSystemInfo(&winSysInfo);
++#endif
++  assert( winSysInfo.dwAllocationGranularity>0 );
++  assert( winSysInfo.dwPageSize>0 );
++
++  sqlite3_vfs_register(&winVfs, 1);
++  return SQLITE_OK; 
+ }
++
++SQLITE_API int sqlite3_os_end(void){ 
++#if SQLITE_OS_WINRT
++  if( sleepObj!=NULL ){
++    osCloseHandle(sleepObj);
++    sleepObj = NULL;
++  }
+ #endif
++  return SQLITE_OK;
++}
+ 
+-/************** End of pcache.c **********************************************/
+-/************** Begin file pcache1.c *****************************************/
++#endif /* SQLITE_OS_WIN */
++
++/************** End of os_win.c **********************************************/
++/************** Begin file bitvec.c ******************************************/
+ /*
+-** 2008 November 05
++** 2008 February 16
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -36670,1019 +38609,1027 @@
+ **    May you share freely, never taking more than you give.
+ **
+ *************************************************************************
++** This file implements an object that represents a fixed-length
++** bitmap.  Bits are numbered starting with 1.
+ **
+-** This file implements the default page cache implementation (the
+-** sqlite3_pcache interface). It also contains part of the implementation
+-** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
+-** If the default page cache implementation is overriden, then neither of
+-** these two features are available.
+-*/
+-
+-
+-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.
++** A bitmap is used to record which pages of a database file have been
++** journalled during a transaction, or which pages have the "dont-write"
++** property.  Usually only a few pages are meet either condition.
++** So the bitmap is usually sparse and has low cardinality.
++** But sometimes (for example when during a DROP of a large table) most
++** or all of the pages in a database can get journalled.  In those cases, 
++** the bitmap becomes dense with high cardinality.  The algorithm needs 
++** to handle both cases well.
+ **
+-** 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 recycles pages more efficiently.
++** The size of the bitmap is fixed when the object is created.
+ **
+-** 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 */
+-  unsigned int nMaxPage;         /* Sum of nMax for purgeable caches */
+-  unsigned int nMinPage;         /* Sum of nMin for purgeable caches */
+-  unsigned int mxPinned;         /* nMaxpage + 10 - nMinPage */
+-  unsigned 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
+-** temporary or transient database) has a single page cache which
+-** is an instance of this object.
++** All bits are clear when the bitmap is created.  Individual bits
++** may be set or cleared one at a time.
+ **
+-** Pointers to structures of this type are cast and returned as 
+-** opaque sqlite3_pcache* handles.
+-*/
+-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 PGroup mutex must be held when accessing nMax.
+-  */
+-  PGroup *pGroup;                     /* PGroup this cache belongs to */
+-  int szPage;                         /* Size of allocated pages in bytes */
+-  int szExtra;                        /* Size of extra space 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 */
+-  unsigned int iMaxKey;               /* Largest key seen since xTruncate() */
+-
+-  /* Hash table of all pages. The following variables may only be accessed
+-  ** 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 */
+-  unsigned int nHash;                 /* Number of slots in apHash[] */
+-  PgHdr1 **apHash;                    /* Hash table for fast lookup by key */
+-};
+-
+-/*
+-** Each cache entry is represented by an instance of the following 
+-** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
+-** PgHdr1.pCache->szPage bytes is allocated directly before this structure 
+-** in memory.
++** Test operations are about 100 times more common that set operations.
++** Clear operations are exceedingly rare.  There are usually between
++** 5 and 500 set operations per Bitvec object, though the number of sets can
++** sometimes grow into tens of thousands or larger.  The size of the
++** Bitvec object is the number of pages in the database file at the
++** start of a transaction, and is thus usually less than a few thousand,
++** but can be as large as 2 billion for a really big database.
+ */
+-struct PgHdr1 {
+-  sqlite3_pcache_page page;
+-  unsigned int iKey;             /* Key value (page number) */
+-  PgHdr1 *pNext;                 /* Next in hash table chain */
+-  PCache1 *pCache;               /* Cache that currently owns this page */
+-  PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
+-  PgHdr1 *pLruPrev;              /* Previous in LRU list of unpinned pages */
+-};
+ 
+-/*
+-** Free slots in the allocator used to divide up the buffer provided using
+-** the SQLITE_CONFIG_PAGECACHE mechanism.
+-*/
+-struct PgFreeslot {
+-  PgFreeslot *pNext;  /* Next free slot */
+-};
++/* Size of the Bitvec structure in bytes. */
++#define BITVEC_SZ        512
+ 
+-/*
+-** Global data used by this cache.
+-*/
+-static SQLITE_WSD struct PCacheGlobal {
+-  PGroup grp;                    /* The global PGroup for mode (2) */
++/* Round the union size down to the nearest pointer boundary, since that's how 
++** it will be aligned within the Bitvec struct. */
++#define BITVEC_USIZE     (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
+ 
+-  /* 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: */
+-  PgFreeslot *pFree;             /* Free page blocks */
+-  int nFreeSlot;                 /* Number of unused pcache slots */
+-  /* 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;
++/* Type of the array "element" for the bitmap representation. 
++** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. 
++** Setting this to the "natural word" size of your CPU may improve
++** performance. */
++#define BITVEC_TELEM     u8
++/* Size, in bits, of the bitmap element. */
++#define BITVEC_SZELEM    8
++/* Number of elements in a bitmap array. */
++#define BITVEC_NELEM     (BITVEC_USIZE/sizeof(BITVEC_TELEM))
++/* Number of bits in the bitmap array. */
++#define BITVEC_NBIT      (BITVEC_NELEM*BITVEC_SZELEM)
+ 
+-/*
+-** All code in this file should access the global structure above via the
+-** alias "pcache1". This ensures that the WSD emulation is used when
+-** compiling for systems that do not support real WSD.
+-*/
+-#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
++/* Number of u32 values in hash table. */
++#define BITVEC_NINT      (BITVEC_USIZE/sizeof(u32))
++/* Maximum number of entries in hash table before 
++** sub-dividing and re-hashing. */
++#define BITVEC_MXHASH    (BITVEC_NINT/2)
++/* Hashing function for the aHash representation.
++** Empirical testing showed that the *37 multiplier 
++** (an arbitrary prime)in the hash function provided 
++** no fewer collisions than the no-op *1. */
++#define BITVEC_HASH(X)   (((X)*1)%BITVEC_NINT)
+ 
+-/*
+-** Macros to enter and leave the PCache LRU mutex.
+-*/
+-#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
+-#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
++#define BITVEC_NPTR      (BITVEC_USIZE/sizeof(Bitvec *))
+ 
+-/******************************************************************************/
+-/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
+ 
+ /*
+-** This function is called during initialization if a static buffer is 
+-** 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.
++** A bitmap is an instance of the following structure.
+ **
+-** This routine is called from sqlite3_initialize() and so it is guaranteed
+-** to be serialized already.  There is no need for further mutexing.
++** This bitmap records the existence of zero or more bits
++** with values between 1 and iSize, inclusive.
++**
++** There are three possible representations of the bitmap.
++** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
++** bitmap.  The least significant bit is bit 1.
++**
++** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
++** a hash table that will hold up to BITVEC_MXHASH distinct values.
++**
++** Otherwise, the value i is redirected into one of BITVEC_NPTR
++** sub-bitmaps pointed to by Bitvec.u.apSub[].  Each subbitmap
++** handles up to iDivisor separate values of i.  apSub[0] holds
++** values between 1 and iDivisor.  apSub[1] holds values between
++** iDivisor+1 and 2*iDivisor.  apSub[N] holds values between
++** N*iDivisor+1 and (N+1)*iDivisor.  Each subbitmap is normalized
++** to hold deal with values between 1 and iDivisor.
+ */
+-SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
+-  if( pcache1.isInit ){
+-    PgFreeslot *p;
+-    sz = ROUNDDOWN8(sz);
+-    pcache1.szSlot = sz;
+-    pcache1.nSlot = pcache1.nFreeSlot = 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;
+-      pcache1.pFree = p;
+-      pBuf = (void*)&((char*)pBuf)[sz];
+-    }
+-    pcache1.pEnd = pBuf;
+-  }
+-}
++struct Bitvec {
++  u32 iSize;      /* Maximum bit index.  Max iSize is 4,294,967,296. */
++  u32 nSet;       /* Number of bits that are set - only valid for aHash
++                  ** element.  Max is BITVEC_NINT.  For BITVEC_SZ of 512,
++                  ** this would be 125. */
++  u32 iDivisor;   /* Number of bits handled by each apSub[] entry. */
++                  /* Should >=0 for apSub element. */
++                  /* Max iDivisor is max(u32) / BITVEC_NPTR + 1.  */
++                  /* For a BITVEC_SZ of 512, this would be 34,359,739. */
++  union {
++    BITVEC_TELEM aBitmap[BITVEC_NELEM];    /* Bitmap representation */
++    u32 aHash[BITVEC_NINT];      /* Hash table representation */
++    Bitvec *apSub[BITVEC_NPTR];  /* Recursive representation */
++  } u;
++};
+ 
+ /*
+-** Malloc function used within this file to allocate space from the buffer
+-** 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 = 0;
+-  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
+-  sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
+-  if( nByte<=pcache1.szSlot ){
+-    sqlite3_mutex_enter(pcache1.mutex);
+-    p = (PgHdr1 *)pcache1.pFree;
+-    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.
+-    */
+-    p = sqlite3Malloc(nByte);
+-#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+-    if( p ){
+-      int sz = sqlite3MallocSize(p);
+-      sqlite3_mutex_enter(pcache1.mutex);
+-      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
+-      sqlite3_mutex_leave(pcache1.mutex);
+-    }
+-#endif
+-    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
++** Create a new bitmap object able to handle bits between 0 and iSize,
++** inclusive.  Return a pointer to the new object.  Return NULL if 
++** malloc fails.
++*/
++SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
++  Bitvec *p;
++  assert( sizeof(*p)==BITVEC_SZ );
++  p = sqlite3MallocZero( sizeof(*p) );
++  if( p ){
++    p->iSize = iSize;
+   }
+   return p;
+ }
+ 
+ /*
+-** Free an allocated buffer obtained from pcache1Alloc().
++** Check to see if the i-th bit is set.  Return true or false.
++** If p is NULL (if the bitmap has not been created) or if
++** i is out of range, then return false.
+ */
+-static int pcache1Free(void *p){
+-  int nFreed = 0;
++SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
+   if( p==0 ) return 0;
+-  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{
+-    assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
+-    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+-    nFreed = sqlite3MallocSize(p);
+-#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+-    sqlite3_mutex_enter(pcache1.mutex);
+-    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
+-    sqlite3_mutex_leave(pcache1.mutex);
+-#endif
+-    sqlite3_free(p);
++  if( i>p->iSize || i==0 ) return 0;
++  i--;
++  while( p->iDivisor ){
++    u32 bin = i/p->iDivisor;
++    i = i%p->iDivisor;
++    p = p->u.apSub[bin];
++    if (!p) {
++      return 0;
++    }
++  }
++  if( p->iSize<=BITVEC_NBIT ){
++    return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
++  } else{
++    u32 h = BITVEC_HASH(i++);
++    while( p->u.aHash[h] ){
++      if( p->u.aHash[h]==i ) return 1;
++      h = (h+1) % BITVEC_NINT;
++    }
++    return 0;
+   }
+-  return nFreed;
+ }
+ 
+-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ /*
+-** Return the size of a pcache allocation
++** Set the i-th bit.  Return 0 on success and an error code if
++** anything goes wrong.
++**
++** This routine might cause sub-bitmaps to be allocated.  Failing
++** to get the memory needed to hold the sub-bitmap is the only
++** that can go wrong with an insert, assuming p and i are valid.
++**
++** The calling function must ensure that p is a valid Bitvec object
++** and that the value for "i" is within range of the Bitvec object.
++** Otherwise the behavior is undefined.
+ */
+-static int pcache1MemSize(void *p){
+-  if( p>=pcache1.pStart && p<pcache1.pEnd ){
+-    return pcache1.szSlot;
+-  }else{
+-    int iSize;
+-    assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
+-    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+-    iSize = sqlite3MallocSize(p);
+-    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
+-    return iSize;
++SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
++  u32 h;
++  if( p==0 ) return SQLITE_OK;
++  assert( i>0 );
++  assert( i<=p->iSize );
++  i--;
++  while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
++    u32 bin = i/p->iDivisor;
++    i = i%p->iDivisor;
++    if( p->u.apSub[bin]==0 ){
++      p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
++      if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
++    }
++    p = p->u.apSub[bin];
++  }
++  if( p->iSize<=BITVEC_NBIT ){
++    p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
++    return SQLITE_OK;
++  }
++  h = BITVEC_HASH(i++);
++  /* if there wasn't a hash collision, and this doesn't */
++  /* completely fill the hash, then just add it without */
++  /* worring about sub-dividing and re-hashing. */
++  if( !p->u.aHash[h] ){
++    if (p->nSet<(BITVEC_NINT-1)) {
++      goto bitvec_set_end;
++    } else {
++      goto bitvec_set_rehash;
++    }
++  }
++  /* there was a collision, check to see if it's already */
++  /* in hash, if not, try to find a spot for it */
++  do {
++    if( p->u.aHash[h]==i ) return SQLITE_OK;
++    h++;
++    if( h>=BITVEC_NINT ) h = 0;
++  } while( p->u.aHash[h] );
++  /* we didn't find it in the hash.  h points to the first */
++  /* available free spot. check to see if this is going to */
++  /* make our hash too "full".  */
++bitvec_set_rehash:
++  if( p->nSet>=BITVEC_MXHASH ){
++    unsigned int j;
++    int rc;
++    u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
++    if( aiValues==0 ){
++      return SQLITE_NOMEM;
++    }else{
++      memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
++      memset(p->u.apSub, 0, sizeof(p->u.apSub));
++      p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
++      rc = sqlite3BitvecSet(p, i);
++      for(j=0; j<BITVEC_NINT; j++){
++        if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
++      }
++      sqlite3StackFree(0, aiValues);
++      return rc;
++    }
+   }
++bitvec_set_end:
++  p->nSet++;
++  p->u.aHash[h] = i;
++  return SQLITE_OK;
+ }
+-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+ 
+ /*
+-** Allocate a new page object initially associated with cache pCache.
++** Clear the i-th bit.
++**
++** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
++** that BitvecClear can use to rebuilt its hash table.
+ */
+-static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
+-  PgHdr1 *p = 0;
+-  void *pPg;
+-
+-  /* The group mutex must be released before pcache1Alloc() is called. This
+-  ** is because it may call sqlite3_release_memory(), which assumes that 
+-  ** this mutex is not held. */
+-  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+-  pcache1LeaveMutex(pCache->pGroup);
+-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+-  pPg = pcache1Alloc(pCache->szPage);
+-  p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
+-  if( !pPg || !p ){
+-    pcache1Free(pPg);
+-    sqlite3_free(p);
+-    pPg = 0;
++SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
++  if( p==0 ) return;
++  assert( i>0 );
++  i--;
++  while( p->iDivisor ){
++    u32 bin = i/p->iDivisor;
++    i = i%p->iDivisor;
++    p = p->u.apSub[bin];
++    if (!p) {
++      return;
++    }
+   }
+-#else
+-  pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
+-  p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
+-#endif
+-  pcache1EnterMutex(pCache->pGroup);
+-
+-  if( pPg ){
+-    p->page.pBuf = pPg;
+-    p->page.pExtra = &p[1];
+-    if( pCache->bPurgeable ){
+-      pCache->pGroup->nCurrentPage++;
++  if( p->iSize<=BITVEC_NBIT ){
++    p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
++  }else{
++    unsigned int j;
++    u32 *aiValues = pBuf;
++    memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
++    memset(p->u.aHash, 0, sizeof(p->u.aHash));
++    p->nSet = 0;
++    for(j=0; j<BITVEC_NINT; j++){
++      if( aiValues[j] && aiValues[j]!=(i+1) ){
++        u32 h = BITVEC_HASH(aiValues[j]-1);
++        p->nSet++;
++        while( p->u.aHash[h] ){
++          h++;
++          if( h>=BITVEC_NINT ) h = 0;
++        }
++        p->u.aHash[h] = aiValues[j];
++      }
+     }
+-    return p;
+   }
+-  return 0;
+ }
+ 
+ /*
+-** Free a page object allocated by pcache1AllocPage().
+-**
+-** The pointer is allowed to be NULL, which is prudent.  But it turns out
+-** that the current implementation happens to never call this routine
+-** with a NULL pointer, so we mark the NULL test with ALWAYS().
++** Destroy a bitmap object.  Reclaim all memory used.
+ */
+-static void pcache1FreePage(PgHdr1 *p){
+-  if( ALWAYS(p) ){
+-    PCache1 *pCache = p->pCache;
+-    assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
+-    pcache1Free(p->page.pBuf);
+-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+-    sqlite3_free(p);
+-#endif
+-    if( pCache->bPurgeable ){
+-      pCache->pGroup->nCurrentPage--;
++SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
++  if( p==0 ) return;
++  if( p->iDivisor ){
++    unsigned int i;
++    for(i=0; i<BITVEC_NPTR; i++){
++      sqlite3BitvecDestroy(p->u.apSub[i]);
+     }
+   }
++  sqlite3_free(p);
+ }
+ 
+ /*
+-** Malloc function used by SQLite to obtain space from the buffer configured
+-** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
+-** exists, this function falls back to sqlite3Malloc().
++** Return the value of the iSize parameter specified when Bitvec *p
++** was created.
+ */
+-SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
+-  return pcache1Alloc(sz);
++SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
++  return p->iSize;
+ }
+ 
++#ifndef SQLITE_OMIT_BUILTIN_TEST
+ /*
+-** Free an allocated buffer obtained from sqlite3PageMalloc().
++** Let V[] be an array of unsigned characters sufficient to hold
++** up to N bits.  Let I be an integer between 0 and N.  0<=I<N.
++** Then the following macros can be used to set, clear, or test
++** individual bits within V.
+ */
+-SQLITE_PRIVATE void sqlite3PageFree(void *p){
+-  pcache1Free(p);
+-}
+-
++#define SETBIT(V,I)      V[I>>3] |= (1<<(I&7))
++#define CLEARBIT(V,I)    V[I>>3] &= ~(1<<(I&7))
++#define TESTBIT(V,I)     (V[I>>3]&(1<<(I&7)))!=0
+ 
+ /*
+-** Return true if it desirable to avoid allocating a new page cache
+-** entry.
++** This routine runs an extensive test of the Bitvec code.
+ **
+-** If memory was allocated specifically to the page cache using
+-** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
+-** it is desirable to avoid allocating a new page cache entry because
+-** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
+-** for all page cache needs and we should not need to spill the
+-** allocation onto the heap.
++** The input is an array of integers that acts as a program
++** to test the Bitvec.  The integers are opcodes followed
++** by 0, 1, or 3 operands, depending on the opcode.  Another
++** opcode follows immediately after the last operand.
+ **
+-** Or, the heap is used for all page cache memory but the heap is
+-** under memory pressure, then again it is desirable to avoid
+-** allocating a new page cache entry in order to avoid stressing
+-** the heap even further.
+-*/
+-static int pcache1UnderMemoryPressure(PCache1 *pCache){
+-  if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
+-    return pcache1.bUnderPressure;
+-  }else{
+-    return sqlite3HeapNearlyFull();
+-  }
+-}
+-
+-/******************************************************************************/
+-/******** General Implementation Functions ************************************/
+-
+-/*
+-** This function is used to resize the hash table used by the cache passed
+-** as the first argument.
++** There are 6 opcodes numbered from 0 through 5.  0 is the
++** "halt" opcode and causes the test to end.
+ **
+-** The PCache mutex must be held when this function is called.
++**    0          Halt and return the number of errors
++**    1 N S X    Set N bits beginning with S and incrementing by X
++**    2 N S X    Clear N bits beginning with S and incrementing by X
++**    3 N        Set N randomly chosen bits
++**    4 N        Clear N randomly chosen bits
++**    5 N S X    Set N bits from S increment X in array only, not in bitvec
++**
++** The opcodes 1 through 4 perform set and clear operations are performed
++** on both a Bitvec object and on a linear array of bits obtained from malloc.
++** Opcode 5 works on the linear array only, not on the Bitvec.
++** Opcode 5 is used to deliberately induce a fault in order to
++** confirm that error detection works.
++**
++** At the conclusion of the test the linear array is compared
++** against the Bitvec object.  If there are any differences,
++** an error is returned.  If they are the same, zero is returned.
++**
++** If a memory allocation error occurs, return -1.
+ */
+-static int pcache1ResizeHash(PCache1 *p){
+-  PgHdr1 **apNew;
+-  unsigned int nNew;
+-  unsigned int i;
++SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
++  Bitvec *pBitvec = 0;
++  unsigned char *pV = 0;
++  int rc = -1;
++  int i, nx, pc, op;
++  void *pTmpSpace;
+ 
+-  assert( sqlite3_mutex_held(p->pGroup->mutex) );
++  /* Allocate the Bitvec to be tested and a linear array of
++  ** bits to act as the reference */
++  pBitvec = sqlite3BitvecCreate( sz );
++  pV = sqlite3MallocZero( (sz+7)/8 + 1 );
++  pTmpSpace = sqlite3_malloc(BITVEC_SZ);
++  if( pBitvec==0 || pV==0 || pTmpSpace==0  ) goto bitvec_end;
+ 
+-  nNew = p->nHash*2;
+-  if( nNew<256 ){
+-    nNew = 256;
+-  }
++  /* NULL pBitvec tests */
++  sqlite3BitvecSet(0, 1);
++  sqlite3BitvecClear(0, 1, pTmpSpace);
+ 
+-  pcache1LeaveMutex(p->pGroup);
+-  if( p->nHash ){ sqlite3BeginBenignMalloc(); }
+-  apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
+-  if( p->nHash ){ sqlite3EndBenignMalloc(); }
+-  pcache1EnterMutex(p->pGroup);
+-  if( apNew ){
+-    for(i=0; i<p->nHash; i++){
+-      PgHdr1 *pPage;
+-      PgHdr1 *pNext = p->apHash[i];
+-      while( (pPage = pNext)!=0 ){
+-        unsigned int h = pPage->iKey % nNew;
+-        pNext = pPage->pNext;
+-        pPage->pNext = apNew[h];
+-        apNew[h] = pPage;
++  /* Run the program */
++  pc = 0;
++  while( (op = aOp[pc])!=0 ){
++    switch( op ){
++      case 1:
++      case 2:
++      case 5: {
++        nx = 4;
++        i = aOp[pc+2] - 1;
++        aOp[pc+2] += aOp[pc+3];
++        break;
++      }
++      case 3:
++      case 4: 
++      default: {
++        nx = 2;
++        sqlite3_randomness(sizeof(i), &i);
++        break;
+       }
+     }
+-    sqlite3_free(p->apHash);
+-    p->apHash = apNew;
+-    p->nHash = nNew;
++    if( (--aOp[pc+1]) > 0 ) nx = 0;
++    pc += nx;
++    i = (i & 0x7fffffff)%sz;
++    if( (op & 1)!=0 ){
++      SETBIT(pV, (i+1));
++      if( op!=5 ){
++        if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
++      }
++    }else{
++      CLEARBIT(pV, (i+1));
++      sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
++    }
+   }
+ 
+-  return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
++  /* Test to make sure the linear array exactly matches the
++  ** Bitvec object.  Start with the assumption that they do
++  ** match (rc==0).  Change rc to non-zero if a discrepancy
++  ** is found.
++  */
++  rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
++          + sqlite3BitvecTest(pBitvec, 0)
++          + (sqlite3BitvecSize(pBitvec) - sz);
++  for(i=1; i<=sz; i++){
++    if(  (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
++      rc = i;
++      break;
++    }
++  }
++
++  /* Free allocated structure */
++bitvec_end:
++  sqlite3_free(pTmpSpace);
++  sqlite3_free(pV);
++  sqlite3BitvecDestroy(pBitvec);
++  return rc;
+ }
++#endif /* SQLITE_OMIT_BUILTIN_TEST */
+ 
++/************** End of bitvec.c **********************************************/
++/************** Begin file pcache.c ******************************************/
+ /*
+-** This function is used internally to remove the page pPage from the 
+-** 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.
++** 2008 August 05
+ **
+-** The PGroup mutex must be held when this function is called.
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-** If pPage is NULL then this routine is a no-op.
++**    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 that page cache.
+ */
+-static void pcache1PinPage(PgHdr1 *pPage){
+-  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( pGroup->pLruHead==pPage ){
+-      pGroup->pLruHead = pPage->pLruNext;
+-    }
+-    if( pGroup->pLruTail==pPage ){
+-      pGroup->pLruTail = pPage->pLruPrev;
+-    }
+-    pPage->pLruNext = 0;
+-    pPage->pLruPrev = 0;
+-    pPage->pCache->nRecyclable--;
+-  }
+-}
++/*
++** A complete page cache is an instance of this structure.
++*/
++struct PCache {
++  PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
++  PgHdr *pSynced;                     /* Last synced page in dirty page list */
++  int nRef;                           /* Number of referenced pages */
++  int szCache;                        /* Configured cache size */
++  int szPage;                         /* Size of every page in this cache */
++  int szExtra;                        /* Size of extra space for each page */
++  int bPurgeable;                     /* True if pages are on backing store */
++  int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
++  void *pStress;                      /* Argument to xStress */
++  sqlite3_pcache *pCache;             /* Pluggable cache module */
++  PgHdr *pPage1;                      /* Reference to page 1 */
++};
++
++/*
++** Some of the assert() macros in this code are too expensive to run
++** even during normal debugging.  Use them only rarely on long-running
++** tests.  Enable the expensive asserts using the
++** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
++*/
++#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
++# define expensive_assert(X)  assert(X)
++#else
++# define expensive_assert(X)
++#endif
+ 
++/********************************** Linked List Management ********************/
+ 
++#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+ /*
+-** Remove the page supplied as an argument from the hash table 
+-** (PCache1.apHash structure) that it is currently stored in.
++** Check that the pCache->pSynced variable is set correctly. If it
++** is not, either fail an assert or return zero. Otherwise, return
++** non-zero. This is only used in debugging builds, as follows:
+ **
+-** The PGroup mutex must be held when this function is called.
++**   expensive_assert( pcacheCheckSynced(pCache) );
+ */
+-static void pcache1RemoveFromHash(PgHdr1 *pPage){
+-  unsigned int h;
+-  PCache1 *pCache = pPage->pCache;
+-  PgHdr1 **pp;
++static int pcacheCheckSynced(PCache *pCache){
++  PgHdr *p;
++  for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
++    assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
++  }
++  return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
++}
++#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
+ 
+-  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;
++/*
++** Remove page pPage from the list of dirty pages.
++*/
++static void pcacheRemoveFromDirtyList(PgHdr *pPage){
++  PCache *p = pPage->pCache;
++
++  assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
++  assert( pPage->pDirtyPrev || pPage==p->pDirty );
++
++  /* Update the PCache1.pSynced variable if necessary. */
++  if( p->pSynced==pPage ){
++    PgHdr *pSynced = pPage->pDirtyPrev;
++    while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
++      pSynced = pSynced->pDirtyPrev;
++    }
++    p->pSynced = pSynced;
++  }
++
++  if( pPage->pDirtyNext ){
++    pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
++  }else{
++    assert( pPage==p->pDirtyTail );
++    p->pDirtyTail = pPage->pDirtyPrev;
++  }
++  if( pPage->pDirtyPrev ){
++    pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
++  }else{
++    assert( pPage==p->pDirty );
++    p->pDirty = pPage->pDirtyNext;
++  }
++  pPage->pDirtyNext = 0;
++  pPage->pDirtyPrev = 0;
+ 
+-  pCache->nPage--;
++  expensive_assert( pcacheCheckSynced(p) );
+ }
+ 
+ /*
+-** If there are currently more than nMaxPage pages allocated, try
+-** to recycle pages to reduce the number allocated to nMaxPage.
++** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
++** pPage).
+ */
+-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);
++static void pcacheAddToDirtyList(PgHdr *pPage){
++  PCache *p = pPage->pCache;
++
++  assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
++
++  pPage->pDirtyNext = p->pDirty;
++  if( pPage->pDirtyNext ){
++    assert( pPage->pDirtyNext->pDirtyPrev==0 );
++    pPage->pDirtyNext->pDirtyPrev = pPage;
+   }
++  p->pDirty = pPage;
++  if( !p->pDirtyTail ){
++    p->pDirtyTail = pPage;
++  }
++  if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
++    p->pSynced = pPage;
++  }
++  expensive_assert( pcacheCheckSynced(p) );
+ }
+ 
+ /*
+-** Discard all pages from cache pCache with a page number (key value) 
+-** greater than or equal to iLimit. Any pinned pages that meet this 
+-** criteria are unpinned before they are discarded.
+-**
+-** The PCache mutex must be held when this function is called.
++** Wrapper around the pluggable caches xUnpin method. If the cache is
++** being used for an in-memory database, this function is a no-op.
+ */
+-static void pcache1TruncateUnsafe(
+-  PCache1 *pCache,             /* The cache to truncate */
+-  unsigned int iLimit          /* Drop pages with this pgno or larger */
+-){
+-  TESTONLY( unsigned int nPage = 0; )  /* To assert pCache->nPage is correct */
+-  unsigned int h;
+-  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+-  for(h=0; h<pCache->nHash; h++){
+-    PgHdr1 **pp = &pCache->apHash[h]; 
+-    PgHdr1 *pPage;
+-    while( (pPage = *pp)!=0 ){
+-      if( pPage->iKey>=iLimit ){
+-        pCache->nPage--;
+-        *pp = pPage->pNext;
+-        pcache1PinPage(pPage);
+-        pcache1FreePage(pPage);
+-      }else{
+-        pp = &pPage->pNext;
+-        TESTONLY( nPage++; )
+-      }
++static void pcacheUnpin(PgHdr *p){
++  PCache *pCache = p->pCache;
++  if( pCache->bPurgeable ){
++    if( p->pgno==1 ){
++      pCache->pPage1 = 0;
+     }
++    sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
+   }
+-  assert( pCache->nPage==nPage );
+ }
+ 
+-/******************************************************************************/
+-/******** sqlite3_pcache Methods **********************************************/
+-
+-/*
+-** Implementation of the sqlite3_pcache.xInit method.
++/*************************************************** General Interfaces ******
++**
++** Initialize and shutdown the page cache subsystem. Neither of these 
++** functions are threadsafe.
+ */
+-static int pcache1Init(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  assert( pcache1.isInit==0 );
+-  memset(&pcache1, 0, sizeof(pcache1));
+-  if( sqlite3GlobalConfig.bCoreMutex ){
+-    pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
+-    pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
++SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
++  if( sqlite3GlobalConfig.pcache2.xInit==0 ){
++    /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
++    ** built-in default page cache is used instead of the application defined
++    ** page cache. */
++    sqlite3PCacheSetDefault();
+   }
+-  pcache1.grp.mxPinned = 10;
+-  pcache1.isInit = 1;
+-  return SQLITE_OK;
++  return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
+ }
+-
+-/*
+-** Implementation of the sqlite3_pcache.xShutdown method.
+-** Note that the static mutex allocated in xInit does 
+-** not need to be freed.
+-*/
+-static void pcache1Shutdown(void *NotUsed){
+-  UNUSED_PARAMETER(NotUsed);
+-  assert( pcache1.isInit!=0 );
+-  memset(&pcache1, 0, sizeof(pcache1));
++SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
++  if( sqlite3GlobalConfig.pcache2.xShutdown ){
++    /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
++    sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
++  }
+ }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xCreate method.
+-**
+-** Allocate a new cache.
++** Return the size in bytes of a PCache object.
+ */
+-static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
+-  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 */
+-
+-  /*
+-  ** 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
+-
+-  assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
+-  assert( szExtra < 300 );
+-
+-  sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
+-  pCache = (PCache1 *)sqlite3MallocZero(sz);
+-  if( pCache ){
+-    if( separateCache ){
+-      pGroup = (PGroup*)&pCache[1];
+-      pGroup->mxPinned = 10;
+-    }else{
+-      pGroup = &pcache1.grp;
+-    }
+-    pCache->pGroup = pGroup;
+-    pCache->szPage = szPage;
+-    pCache->szExtra = szExtra;
+-    pCache->bPurgeable = (bPurgeable ? 1 : 0);
+-    if( bPurgeable ){
+-      pCache->nMin = 10;
+-      pcache1EnterMutex(pGroup);
+-      pGroup->nMinPage += pCache->nMin;
+-      pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+-      pcache1LeaveMutex(pGroup);
+-    }
+-  }
+-  return (sqlite3_pcache *)pCache;
+-}
++SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xCachesize method. 
+-**
+-** Configure the cache_size limit for a cache.
++** Create a new PCache object. Storage space to hold the object
++** has already been allocated and is passed in as the p pointer. 
++** The caller discovers how much space needs to be allocated by 
++** calling sqlite3PcacheSize().
+ */
+-static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
+-  PCache1 *pCache = (PCache1 *)p;
+-  if( pCache->bPurgeable ){
+-    PGroup *pGroup = pCache->pGroup;
+-    pcache1EnterMutex(pGroup);
+-    pGroup->nMaxPage += (nMax - pCache->nMax);
+-    pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+-    pCache->nMax = nMax;
+-    pCache->n90pct = pCache->nMax*9/10;
+-    pcache1EnforceMaxPage(pGroup);
+-    pcache1LeaveMutex(pGroup);
+-  }
++SQLITE_PRIVATE void sqlite3PcacheOpen(
++  int szPage,                  /* Size of every page */
++  int szExtra,                 /* Extra space associated with each page */
++  int bPurgeable,              /* True if pages are on backing store */
++  int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
++  void *pStress,               /* Argument to xStress */
++  PCache *p                    /* Preallocated space for the PCache */
++){
++  memset(p, 0, sizeof(PCache));
++  p->szPage = szPage;
++  p->szExtra = szExtra;
++  p->bPurgeable = bPurgeable;
++  p->xStress = xStress;
++  p->pStress = pStress;
++  p->szCache = 100;
+ }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xShrink method. 
+-**
+-** Free up as much memory as possible.
++** Change the page size for PCache object. The caller must ensure that there
++** are no outstanding page references when this function is called.
+ */
+-static void pcache1Shrink(sqlite3_pcache *p){
+-  PCache1 *pCache = (PCache1*)p;
+-  if( pCache->bPurgeable ){
+-    PGroup *pGroup = pCache->pGroup;
+-    int savedMaxPage;
+-    pcache1EnterMutex(pGroup);
+-    savedMaxPage = pGroup->nMaxPage;
+-    pGroup->nMaxPage = 0;
+-    pcache1EnforceMaxPage(pGroup);
+-    pGroup->nMaxPage = savedMaxPage;
+-    pcache1LeaveMutex(pGroup);
++SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
++  assert( pCache->nRef==0 && pCache->pDirty==0 );
++  if( pCache->pCache ){
++    sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
++    pCache->pCache = 0;
++    pCache->pPage1 = 0;
+   }
++  pCache->szPage = szPage;
+ }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xPagecount method. 
++** Compute the number of pages of cache requested.
+ */
+-static int pcache1Pagecount(sqlite3_pcache *p){
+-  int n;
+-  PCache1 *pCache = (PCache1*)p;
+-  pcache1EnterMutex(pCache->pGroup);
+-  n = pCache->nPage;
+-  pcache1LeaveMutex(pCache->pGroup);
+-  return n;
++static int numberOfCachePages(PCache *p){
++  if( p->szCache>=0 ){
++    return p->szCache;
++  }else{
++    return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
++  }
+ }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xFetch method. 
+-**
+-** Fetch a page by key value.
+-**
+-** Whether or not a new page may be allocated by this function depends on
+-** the value of the createFlag argument.  0 means do not allocate a new
+-** page.  1 means allocate a new page if space is easily available.  2 
+-** means to try really hard to allocate a new page.
+-**
+-** For a non-purgeable cache (a cache used as the storage for an in-memory
+-** database) there is really no difference between createFlag 1 and 2.  So
+-** the calling function (pcache.c) will never have a createFlag of 1 on
+-** a non-purgeable cache.
+-**
+-** There are three different approaches to obtaining space for a page,
+-** depending on the value of parameter createFlag (which may be 0, 1 or 2).
+-**
+-**   1. Regardless of the value of createFlag, the cache is searched for a 
+-**      copy of the requested page. If one is found, it is returned.
+-**
+-**   2. If createFlag==0 and the page is not already in the cache, NULL is
+-**      returned.
+-**
+-**   3. If createFlag is 1, and the page is not already in the cache, then
+-**      return NULL (do not allocate a new page) if any of the following
+-**      conditions are true:
+-**
+-**       (a) the number of pages pinned by the cache is greater than
+-**           PCache1.nMax, or
+-**
+-**       (b) the number of pages pinned by the cache is greater than
+-**           the sum of nMax for all purgeable caches, less the sum of 
+-**           nMin for all other purgeable caches, or
+-**
+-**   4. If none of the first three conditions apply and the cache is marked
+-**      as purgeable, and if one of the following is true:
+-**
+-**       (a) The number of pages allocated for the cache is already 
+-**           PCache1.nMax, or
+-**
+-**       (b) The number of pages allocated for all purgeable caches is
+-**           already equal to or greater than the sum of nMax for all
+-**           purgeable caches,
+-**
+-**       (c) The system is under memory pressure and wants to avoid
+-**           unnecessary pages cache entry allocations
+-**
+-**      then attempt to recycle a page from the LRU list. If it is the right
+-**      size, return the recycled buffer. Otherwise, free the buffer and
+-**      proceed to step 5. 
+-**
+-**   5. Otherwise, allocate and return a new page buffer.
++** Try to obtain a page from the cache.
+ */
+-static sqlite3_pcache_page *pcache1Fetch(
+-  sqlite3_pcache *p, 
+-  unsigned int iKey, 
+-  int createFlag
++SQLITE_PRIVATE int sqlite3PcacheFetch(
++  PCache *pCache,       /* Obtain the page from this cache */
++  Pgno pgno,            /* Page number to obtain */
++  int createFlag,       /* If true, create page if it does not exist already */
++  PgHdr **ppPage        /* Write the page here */
+ ){
+-  unsigned int nPinned;
+-  PCache1 *pCache = (PCache1 *)p;
+-  PGroup *pGroup;
+-  PgHdr1 *pPage = 0;
++  sqlite3_pcache_page *pPage = 0;
++  PgHdr *pPgHdr = 0;
++  int eCreate;
+ 
+-  assert( pCache->bPurgeable || createFlag!=1 );
+-  assert( pCache->bPurgeable || pCache->nMin==0 );
+-  assert( pCache->bPurgeable==0 || pCache->nMin==10 );
+-  assert( pCache->nMin==0 || pCache->bPurgeable );
+-  pcache1EnterMutex(pGroup = pCache->pGroup);
++  assert( pCache!=0 );
++  assert( createFlag==1 || createFlag==0 );
++  assert( pgno>0 );
+ 
+-  /* 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);
++  /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
++  ** allocate it now.
++  */
++  if( !pCache->pCache && createFlag ){
++    sqlite3_pcache *p;
++    p = sqlite3GlobalConfig.pcache2.xCreate(
++        pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
++    );
++    if( !p ){
++      return SQLITE_NOMEM;
++    }
++    sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
++    pCache->pCache = p;
+   }
+ 
+-  /* Step 2: Abort if no existing page is found and createFlag is 0 */
+-  if( pPage || createFlag==0 ){
+-    pcache1PinPage(pPage);
+-    goto fetch_out;
++  eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
++  if( pCache->pCache ){
++    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
+   }
+ 
+-  /* 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;
++  if( !pPage && eCreate==1 ){
++    PgHdr *pPg;
++
++    /* Find a dirty page to write-out and recycle. First try to find a 
++    ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
++    ** cleared), but if that is not possible settle for any other 
++    ** unreferenced dirty page.
++    */
++    expensive_assert( pcacheCheckSynced(pCache) );
++    for(pPg=pCache->pSynced; 
++        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
++        pPg=pPg->pDirtyPrev
++    );
++    pCache->pSynced = pPg;
++    if( !pPg ){
++      for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
++    }
++    if( pPg ){
++      int rc;
++#ifdef SQLITE_LOG_CACHE_SPILL
++      sqlite3_log(SQLITE_FULL, 
++                  "spill page %d making room for %d - cache used: %d/%d",
++                  pPg->pgno, pgno,
++                  sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
++                  numberOfCachePages(pCache));
+ #endif
++      rc = pCache->xStress(pCache->pStress, pPg);
++      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
++        return rc;
++      }
++    }
+ 
+-  /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
+-  assert( pCache->nPage >= pCache->nRecyclable );
+-  nPinned = pCache->nPage - pCache->nRecyclable;
+-  assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
+-  assert( pCache->n90pct == pCache->nMax*9/10 );
+-  if( createFlag==1 && (
+-        nPinned>=pGroup->mxPinned
+-     || nPinned>=pCache->n90pct
+-     || pcache1UnderMemoryPressure(pCache)
+-  )){
+-    goto fetch_out;
++    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
+   }
+ 
+-  if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
+-    goto fetch_out;
+-  }
++  if( pPage ){
++    pPgHdr = (PgHdr *)pPage->pExtra;
+ 
+-  /* Step 4. Try to recycle a page. */
+-  if( pCache->bPurgeable && pGroup->pLruTail && (
+-         (pCache->nPage+1>=pCache->nMax)
+-      || pGroup->nCurrentPage>=pGroup->nMaxPage
+-      || pcache1UnderMemoryPressure(pCache)
+-  )){
+-    PCache1 *pOther;
+-    pPage = pGroup->pLruTail;
+-    pcache1RemoveFromHash(pPage);
+-    pcache1PinPage(pPage);
+-    pOther = pPage->pCache;
++    if( !pPgHdr->pPage ){
++      memset(pPgHdr, 0, sizeof(PgHdr));
++      pPgHdr->pPage = pPage;
++      pPgHdr->pData = pPage->pBuf;
++      pPgHdr->pExtra = (void *)&pPgHdr[1];
++      memset(pPgHdr->pExtra, 0, pCache->szExtra);
++      pPgHdr->pCache = pCache;
++      pPgHdr->pgno = pgno;
++    }
++    assert( pPgHdr->pCache==pCache );
++    assert( pPgHdr->pgno==pgno );
++    assert( pPgHdr->pData==pPage->pBuf );
++    assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
+ 
+-    /* We want to verify that szPage and szExtra are the same for pOther
+-    ** and pCache.  Assert that we can verify this by comparing sums. */
+-    assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
+-    assert( pCache->szExtra<512 );
+-    assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
+-    assert( pOther->szExtra<512 );
++    if( 0==pPgHdr->nRef ){
++      pCache->nRef++;
++    }
++    pPgHdr->nRef++;
++    if( pgno==1 ){
++      pCache->pPage1 = pPgHdr;
++    }
++  }
++  *ppPage = pPgHdr;
++  return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
++}
+ 
+-    if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
+-      pcache1FreePage(pPage);
+-      pPage = 0;
++/*
++** Decrement the reference count on a page. If the page is clean and the
++** reference count drops to 0, then it is made elible for recycling.
++*/
++SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
++  assert( p->nRef>0 );
++  p->nRef--;
++  if( p->nRef==0 ){
++    PCache *pCache = p->pCache;
++    pCache->nRef--;
++    if( (p->flags&PGHDR_DIRTY)==0 ){
++      pcacheUnpin(p);
+     }else{
+-      pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
++      /* Move the page to the head of the dirty list. */
++      pcacheRemoveFromDirtyList(p);
++      pcacheAddToDirtyList(p);
+     }
+   }
++}
+ 
+-  /* Step 5. If a usable page buffer has still not been found, 
+-  ** attempt to allocate a new one. 
+-  */
+-  if( !pPage ){
+-    if( createFlag==1 ) sqlite3BeginBenignMalloc();
+-    pPage = pcache1AllocPage(pCache);
+-    if( createFlag==1 ) sqlite3EndBenignMalloc();
++/*
++** Increase the reference count of a supplied page by 1.
++*/
++SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
++  assert(p->nRef>0);
++  p->nRef++;
++}
++
++/*
++** Drop a page from the cache. There must be exactly one reference to the
++** page. This function deletes that reference, so after it returns the
++** page pointed to by p is invalid.
++*/
++SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
++  PCache *pCache;
++  assert( p->nRef==1 );
++  if( p->flags&PGHDR_DIRTY ){
++    pcacheRemoveFromDirtyList(p);
++  }
++  pCache = p->pCache;
++  pCache->nRef--;
++  if( p->pgno==1 ){
++    pCache->pPage1 = 0;
++  }
++  sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
++}
++
++/*
++** Make sure the page is marked as dirty. If it isn't dirty already,
++** make it so.
++*/
++SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
++  p->flags &= ~PGHDR_DONT_WRITE;
++  assert( p->nRef>0 );
++  if( 0==(p->flags & PGHDR_DIRTY) ){
++    p->flags |= PGHDR_DIRTY;
++    pcacheAddToDirtyList( p);
++  }
++}
++
++/*
++** Make sure the page is marked as clean. If it isn't clean already,
++** make it so.
++*/
++SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
++  if( (p->flags & PGHDR_DIRTY) ){
++    pcacheRemoveFromDirtyList(p);
++    p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
++    if( p->nRef==0 ){
++      pcacheUnpin(p);
++    }
+   }
++}
+ 
+-  if( pPage ){
+-    unsigned int h = iKey % pCache->nHash;
+-    pCache->nPage++;
+-    pPage->iKey = iKey;
+-    pPage->pNext = pCache->apHash[h];
+-    pPage->pCache = pCache;
+-    pPage->pLruPrev = 0;
+-    pPage->pLruNext = 0;
+-    *(void **)pPage->page.pExtra = 0;
+-    pCache->apHash[h] = pPage;
++/*
++** Make every page in the cache clean.
++*/
++SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
++  PgHdr *p;
++  while( (p = pCache->pDirty)!=0 ){
++    sqlite3PcacheMakeClean(p);
+   }
++}
+ 
+-fetch_out:
+-  if( pPage && iKey>pCache->iMaxKey ){
+-    pCache->iMaxKey = iKey;
++/*
++** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
++*/
++SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
++  PgHdr *p;
++  for(p=pCache->pDirty; p; p=p->pDirtyNext){
++    p->flags &= ~PGHDR_NEED_SYNC;
+   }
+-  pcache1LeaveMutex(pGroup);
+-  return &pPage->page;
++  pCache->pSynced = pCache->pDirtyTail;
+ }
+ 
++/*
++** Change the page number of page p to newPgno. 
++*/
++SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
++  PCache *pCache = p->pCache;
++  assert( p->nRef>0 );
++  assert( newPgno>0 );
++  sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
++  p->pgno = newPgno;
++  if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
++    pcacheRemoveFromDirtyList(p);
++    pcacheAddToDirtyList(p);
++  }
++}
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xUnpin method.
++** Drop every cache entry whose page number is greater than "pgno". The
++** caller must ensure that there are no outstanding references to any pages
++** other than page 1 with a page number greater than pgno.
+ **
+-** Mark a page as unpinned (eligible for asynchronous recycling).
++** If there is a reference to page 1 and the pgno parameter passed to this
++** function is 0, then the data area associated with page 1 is zeroed, but
++** the page object is not dropped.
+ */
+-static void pcache1Unpin(
+-  sqlite3_pcache *p, 
+-  sqlite3_pcache_page *pPg, 
+-  int reuseUnlikely
+-){
+-  PCache1 *pCache = (PCache1 *)p;
+-  PgHdr1 *pPage = (PgHdr1 *)pPg;
+-  PGroup *pGroup = pCache->pGroup;
+- 
+-  assert( pPage->pCache==pCache );
+-  pcache1EnterMutex(pGroup);
++SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
++  if( pCache->pCache ){
++    PgHdr *p;
++    PgHdr *pNext;
++    for(p=pCache->pDirty; p; p=pNext){
++      pNext = p->pDirtyNext;
++      /* This routine never gets call with a positive pgno except right
++      ** after sqlite3PcacheCleanAll().  So if there are dirty pages,
++      ** it must be that pgno==0.
++      */
++      assert( p->pgno>0 );
++      if( ALWAYS(p->pgno>pgno) ){
++        assert( p->flags&PGHDR_DIRTY );
++        sqlite3PcacheMakeClean(p);
++      }
++    }
++    if( pgno==0 && pCache->pPage1 ){
++      memset(pCache->pPage1->pData, 0, pCache->szPage);
++      pgno = 1;
++    }
++    sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
++  }
++}
+ 
+-  /* It is an error to call this function if the page is already 
+-  ** part of the PGroup LRU list.
+-  */
+-  assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
+-  assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
++/*
++** Close a cache.
++*/
++SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
++  if( pCache->pCache ){
++    sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
++  }
++}
+ 
+-  if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
+-    pcache1RemoveFromHash(pPage);
+-    pcache1FreePage(pPage);
+-  }else{
+-    /* Add the page to the PGroup LRU list. */
+-    if( pGroup->pLruHead ){
+-      pGroup->pLruHead->pLruPrev = pPage;
+-      pPage->pLruNext = pGroup->pLruHead;
+-      pGroup->pLruHead = pPage;
++/* 
++** Discard the contents of the cache.
++*/
++SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
++  sqlite3PcacheTruncate(pCache, 0);
++}
++
++/*
++** Merge two lists of pages connected by pDirty and in pgno order.
++** Do not both fixing the pDirtyPrev pointers.
++*/
++static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
++  PgHdr result, *pTail;
++  pTail = &result;
++  while( pA && pB ){
++    if( pA->pgno<pB->pgno ){
++      pTail->pDirty = pA;
++      pTail = pA;
++      pA = pA->pDirty;
+     }else{
+-      pGroup->pLruTail = pPage;
+-      pGroup->pLruHead = pPage;
++      pTail->pDirty = pB;
++      pTail = pB;
++      pB = pB->pDirty;
+     }
+-    pCache->nRecyclable++;
+   }
+-
+-  pcache1LeaveMutex(pCache->pGroup);
++  if( pA ){
++    pTail->pDirty = pA;
++  }else if( pB ){
++    pTail->pDirty = pB;
++  }else{
++    pTail->pDirty = 0;
++  }
++  return result.pDirty;
+ }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xRekey method. 
++** Sort the list of pages in accending order by pgno.  Pages are
++** connected by pDirty pointers.  The pDirtyPrev pointers are
++** corrupted by this sort.
++**
++** Since there cannot be more than 2^31 distinct pages in a database,
++** there cannot be more than 31 buckets required by the merge sorter.
++** One extra bucket is added to catch overflow in case something
++** ever changes to make the previous sentence incorrect.
+ */
+-static void pcache1Rekey(
+-  sqlite3_pcache *p,
+-  sqlite3_pcache_page *pPg,
+-  unsigned int iOld,
+-  unsigned int iNew
+-){
+-  PCache1 *pCache = (PCache1 *)p;
+-  PgHdr1 *pPage = (PgHdr1 *)pPg;
+-  PgHdr1 **pp;
+-  unsigned int h; 
+-  assert( pPage->iKey==iOld );
+-  assert( pPage->pCache==pCache );
+-
+-  pcache1EnterMutex(pCache->pGroup);
+-
+-  h = iOld%pCache->nHash;
+-  pp = &pCache->apHash[h];
+-  while( (*pp)!=pPage ){
+-    pp = &(*pp)->pNext;
++#define N_SORT_BUCKET  32
++static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
++  PgHdr *a[N_SORT_BUCKET], *p;
++  int i;
++  memset(a, 0, sizeof(a));
++  while( pIn ){
++    p = pIn;
++    pIn = p->pDirty;
++    p->pDirty = 0;
++    for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
++      if( a[i]==0 ){
++        a[i] = p;
++        break;
++      }else{
++        p = pcacheMergeDirtyList(a[i], p);
++        a[i] = 0;
++      }
++    }
++    if( NEVER(i==N_SORT_BUCKET-1) ){
++      /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
++      ** the input list.  But that is impossible.
++      */
++      a[i] = pcacheMergeDirtyList(a[i], p);
++    }
+   }
+-  *pp = pPage->pNext;
++  p = a[0];
++  for(i=1; i<N_SORT_BUCKET; i++){
++    p = pcacheMergeDirtyList(p, a[i]);
++  }
++  return p;
++}
+ 
+-  h = iNew%pCache->nHash;
+-  pPage->iKey = iNew;
+-  pPage->pNext = pCache->apHash[h];
+-  pCache->apHash[h] = pPage;
+-  if( iNew>pCache->iMaxKey ){
+-    pCache->iMaxKey = iNew;
++/*
++** Return a list of all dirty pages in the cache, sorted by page number.
++*/
++SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
++  PgHdr *p;
++  for(p=pCache->pDirty; p; p=p->pDirtyNext){
++    p->pDirty = p->pDirtyNext;
+   }
++  return pcacheSortDirtyList(pCache->pDirty);
++}
+ 
+-  pcache1LeaveMutex(pCache->pGroup);
++/* 
++** Return the total number of referenced pages held by the cache.
++*/
++SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
++  return pCache->nRef;
+ }
+ 
+ /*
+-** Implementation of the sqlite3_pcache.xTruncate method. 
+-**
+-** Discard all unpinned pages in the cache with a page number equal to
+-** or greater than parameter iLimit. Any pinned pages with a page number
+-** equal to or greater than iLimit are implicitly unpinned.
++** Return the number of references to the page supplied as an argument.
+ */
+-static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
+-  PCache1 *pCache = (PCache1 *)p;
+-  pcache1EnterMutex(pCache->pGroup);
+-  if( iLimit<=pCache->iMaxKey ){
+-    pcache1TruncateUnsafe(pCache, iLimit);
+-    pCache->iMaxKey = iLimit-1;
++SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
++  return p->nRef;
++}
++
++/* 
++** Return the total number of pages in the cache.
++*/
++SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
++  int nPage = 0;
++  if( pCache->pCache ){
++    nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
+   }
+-  pcache1LeaveMutex(pCache->pGroup);
++  return nPage;
+ }
+ 
++#ifdef SQLITE_TEST
+ /*
+-** Implementation of the sqlite3_pcache.xDestroy method. 
+-**
+-** Destroy a cache allocated using pcache1Create().
++** Get the suggested cache-size value.
+ */
+-static void pcache1Destroy(sqlite3_pcache *p){
+-  PCache1 *pCache = (PCache1 *)p;
+-  PGroup *pGroup = pCache->pGroup;
+-  assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
+-  pcache1EnterMutex(pGroup);
+-  pcache1TruncateUnsafe(pCache, 0);
+-  assert( pGroup->nMaxPage >= pCache->nMax );
+-  pGroup->nMaxPage -= pCache->nMax;
+-  assert( pGroup->nMinPage >= pCache->nMin );
+-  pGroup->nMinPage -= pCache->nMin;
+-  pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+-  pcache1EnforceMaxPage(pGroup);
+-  pcache1LeaveMutex(pGroup);
+-  sqlite3_free(pCache->apHash);
+-  sqlite3_free(pCache);
++SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
++  return numberOfCachePages(pCache);
+ }
++#endif
+ 
+ /*
+-** This function is called during initialization (sqlite3_initialize()) to
+-** install the default pluggable cache module, assuming the user has not
+-** already provided an alternative.
++** Set the suggested cache-size value.
+ */
+-SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
+-  static const sqlite3_pcache_methods2 defaultMethods = {
+-    1,                       /* iVersion */
+-    0,                       /* pArg */
+-    pcache1Init,             /* xInit */
+-    pcache1Shutdown,         /* xShutdown */
+-    pcache1Create,           /* xCreate */
+-    pcache1Cachesize,        /* xCachesize */
+-    pcache1Pagecount,        /* xPagecount */
+-    pcache1Fetch,            /* xFetch */
+-    pcache1Unpin,            /* xUnpin */
+-    pcache1Rekey,            /* xRekey */
+-    pcache1Truncate,         /* xTruncate */
+-    pcache1Destroy,          /* xDestroy */
+-    pcache1Shrink            /* xShrink */
+-  };
+-  sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
++SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
++  pCache->szCache = mxPage;
++  if( pCache->pCache ){
++    sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
++                                           numberOfCachePages(pCache));
++  }
+ }
+ 
+-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ /*
+-** This function is called to free superfluous dynamically allocated memory
+-** held by the pager system. Memory in use by any SQLite pager allocated
+-** by the current thread may be sqlite3_free()ed.
+-**
+-** nReq is the number of bytes of memory required. Once this much has
+-** been released, the function returns. The return value is the total number 
+-** of bytes of memory released.
++** Free up as much memory as possible from the page cache.
+ */
+-SQLITE_PRIVATE 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(&pcache1.grp);
+-    while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
+-      nFree += pcache1MemSize(p->page.pBuf);
+-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+-      nFree += sqlite3MemSize(p);
+-#endif
+-      pcache1PinPage(p);
+-      pcache1RemoveFromHash(p);
+-      pcache1FreePage(p);
+-    }
+-    pcache1LeaveMutex(&pcache1.grp);
++SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){
++  if( pCache->pCache ){
++    sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
+   }
+-  return nFree;
+ }
+-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+ 
+-#ifdef SQLITE_TEST
++#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
+ /*
+-** This function is used by test procedures to inspect the internal state
+-** of the global cache.
++** For all dirty pages currently in the cache, invoke the specified
++** callback. This is only used if the SQLITE_CHECK_PAGES macro is
++** defined.
+ */
+-SQLITE_PRIVATE void sqlite3PcacheStats(
+-  int *pnCurrent,      /* OUT: Total number of pages cached */
+-  int *pnMax,          /* OUT: Global maximum cache size */
+-  int *pnMin,          /* OUT: Sum of PCache1.nMin for purgeable caches */
+-  int *pnRecyclable    /* OUT: Total number of pages available for recycling */
+-){
+-  PgHdr1 *p;
+-  int nRecyclable = 0;
+-  for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
+-    nRecyclable++;
++SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
++  PgHdr *pDirty;
++  for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
++    xIter(pDirty);
+   }
+-  *pnCurrent = pcache1.grp.nCurrentPage;
+-  *pnMax = (int)pcache1.grp.nMaxPage;
+-  *pnMin = (int)pcache1.grp.nMinPage;
+-  *pnRecyclable = nRecyclable;
+ }
+ #endif
+ 
+-/************** End of pcache1.c *********************************************/
+-/************** Begin file rowset.c ******************************************/
++/************** End of pcache.c **********************************************/
++/************** Begin file pcache1.c *****************************************/
+ /*
+-** 2008 December 3
++** 2008 November 05
+ **
+ ** The author disclaims copyright to this source code.  In place of
+ ** a legal notice, here is a blessing:
+@@ -37693,3176 +39640,3005 @@
+ **
+ *************************************************************************
+ **
+-** This module implements an object we call a "RowSet".
+-**
+-** The RowSet object is a collection of rowids.  Rowids
+-** are inserted into the RowSet in an arbitrary order.  Inserts
+-** can be intermixed with tests to see if a given rowid has been
+-** previously inserted into the RowSet.
+-**
+-** After all inserts are finished, it is possible to extract the
+-** elements of the RowSet in sorted order.  Once this extraction
+-** process has started, no new elements may be inserted.
+-**
+-** Hence, the primitive operations for a RowSet are:
+-**
+-**    CREATE
+-**    INSERT
+-**    TEST
+-**    SMALLEST
+-**    DESTROY
++** This file implements the default page cache implementation (the
++** sqlite3_pcache interface). It also contains part of the implementation
++** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
++** If the default page cache implementation is overriden, then neither of
++** these two features are available.
++*/
++
++
++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.
+ **
+-** The CREATE and DESTROY primitives are the constructor and destructor,
+-** obviously.  The INSERT primitive adds a new element to the RowSet.
+-** TEST checks to see if an element is already in the RowSet.  SMALLEST
+-** extracts the least value from the RowSet.
++** This page cache implementation works in one of two modes:
+ **
+-** The INSERT primitive might allocate additional memory.  Memory is
+-** allocated in chunks so most INSERTs do no allocation.  There is an 
+-** upper bound on the size of allocated memory.  No memory is freed
+-** until DESTROY.
++**   (1)  Every PCache is the sole member of its own PGroup.  There is
++**        one PGroup per PCache.
+ **
+-** The TEST primitive includes a "batch" number.  The TEST primitive
+-** will only see elements that were inserted before the last change
+-** in the batch number.  In other words, if an INSERT occurs between
+-** two TESTs where the TESTs have the same batch nubmer, then the
+-** value added by the INSERT will not be visible to the second TEST.
+-** The initial batch number is zero, so if the very first TEST contains
+-** a non-zero batch number, it will see all prior INSERTs.
++**   (2)  There is a single global PGroup that all PCaches are a member
++**        of.
+ **
+-** No INSERTs may occurs after a SMALLEST.  An assertion will fail if
+-** that is attempted.
++** 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 recycles pages more efficiently.
+ **
+-** The cost of an INSERT is roughly constant.  (Sometime new memory
+-** has to be allocated on an INSERT.)  The cost of a TEST with a new
+-** batch number is O(NlogN) where N is the number of elements in the RowSet.
+-** The cost of a TEST using the same batch number is O(logN).  The cost
+-** of the first SMALLEST is O(NlogN).  Second and subsequent SMALLEST
+-** primitives are constant time.  The cost of DESTROY is O(N).
++** 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 */
++  unsigned int nMaxPage;         /* Sum of nMax for purgeable caches */
++  unsigned int nMinPage;         /* Sum of nMin for purgeable caches */
++  unsigned int mxPinned;         /* nMaxpage + 10 - nMinPage */
++  unsigned 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
++** temporary or transient database) has a single page cache which
++** is an instance of this object.
+ **
+-** There is an added cost of O(N) when switching between TEST and
+-** SMALLEST primitives.
++** Pointers to structures of this type are cast and returned as 
++** opaque sqlite3_pcache* handles.
++*/
++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 PGroup mutex must be held when accessing nMax.
++  */
++  PGroup *pGroup;                     /* PGroup this cache belongs to */
++  int szPage;                         /* Size of allocated pages in bytes */
++  int szExtra;                        /* Size of extra space 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 */
++  unsigned int iMaxKey;               /* Largest key seen since xTruncate() */
++
++  /* Hash table of all pages. The following variables may only be accessed
++  ** 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 */
++  unsigned int nHash;                 /* Number of slots in apHash[] */
++  PgHdr1 **apHash;                    /* Hash table for fast lookup by key */
++};
++
++/*
++** Each cache entry is represented by an instance of the following 
++** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
++** PgHdr1.pCache->szPage bytes is allocated directly before this structure 
++** in memory.
++*/
++struct PgHdr1 {
++  sqlite3_pcache_page page;
++  unsigned int iKey;             /* Key value (page number) */
++  PgHdr1 *pNext;                 /* Next in hash table chain */
++  PCache1 *pCache;               /* Cache that currently owns this page */
++  PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
++  PgHdr1 *pLruPrev;              /* Previous in LRU list of unpinned pages */
++};
++
++/*
++** Free slots in the allocator used to divide up the buffer provided using
++** the SQLITE_CONFIG_PAGECACHE mechanism.
++*/
++struct PgFreeslot {
++  PgFreeslot *pNext;  /* Next free slot */
++};
++
++/*
++** Global data used by this cache.
+ */
++static SQLITE_WSD struct PCacheGlobal {
++  PGroup grp;                    /* The global PGroup for mode (2) */
++
++  /* 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: */
++  PgFreeslot *pFree;             /* Free page blocks */
++  int nFreeSlot;                 /* Number of unused pcache slots */
++  /* 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;
+ 
++/*
++** All code in this file should access the global structure above via the
++** alias "pcache1". This ensures that the WSD emulation is used when
++** compiling for systems that do not support real WSD.
++*/
++#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
+ 
+ /*
+-** Target size for allocation chunks.
++** Macros to enter and leave the PCache LRU mutex.
+ */
+-#define ROWSET_ALLOCATION_SIZE 1024
++#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
++#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
++
++/******************************************************************************/
++/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
+ 
+ /*
+-** The number of rowset entries per allocation chunk.
++** This function is called during initialization if a static buffer is 
++** 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.
+ */
+-#define ROWSET_ENTRY_PER_CHUNK  \
+-                       ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
++SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
++  if( pcache1.isInit ){
++    PgFreeslot *p;
++    sz = ROUNDDOWN8(sz);
++    pcache1.szSlot = sz;
++    pcache1.nSlot = pcache1.nFreeSlot = 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;
++      pcache1.pFree = p;
++      pBuf = (void*)&((char*)pBuf)[sz];
++    }
++    pcache1.pEnd = pBuf;
++  }
++}
+ 
+ /*
+-** Each entry in a RowSet is an instance of the following object.
++** Malloc function used within this file to allocate space from the buffer
++** 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().
+ **
+-** This same object is reused to store a linked list of trees of RowSetEntry
+-** objects.  In that alternative use, pRight points to the next entry
+-** in the list, pLeft points to the tree, and v is unused.  The
+-** RowSet.pForest value points to the head of this forest list.
++** Multiple threads can run this routine at the same time.  Global variables
++** in pcache1 need to be protected via mutex.
+ */
+-struct RowSetEntry {            
+-  i64 v;                        /* ROWID value for this entry */
+-  struct RowSetEntry *pRight;   /* Right subtree (larger entries) or list */
+-  struct RowSetEntry *pLeft;    /* Left subtree (smaller entries) */
+-};
++static void *pcache1Alloc(int nByte){
++  void *p = 0;
++  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
++  sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
++  if( nByte<=pcache1.szSlot ){
++    sqlite3_mutex_enter(pcache1.mutex);
++    p = (PgHdr1 *)pcache1.pFree;
++    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.
++    */
++    p = sqlite3Malloc(nByte);
++#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
++    if( p ){
++      int sz = sqlite3MallocSize(p);
++      sqlite3_mutex_enter(pcache1.mutex);
++      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
++      sqlite3_mutex_leave(pcache1.mutex);
++    }
++#endif
++    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
++  }
++  return p;
++}
+ 
+ /*
+-** RowSetEntry objects are allocated in large chunks (instances of the
+-** following structure) to reduce memory allocation overhead.  The
+-** chunks are kept on a linked list so that they can be deallocated
+-** when the RowSet is destroyed.
++** Free an allocated buffer obtained from pcache1Alloc().
+ */
+-struct RowSetChunk {
+-  struct RowSetChunk *pNextChunk;        /* Next chunk on list of them all */
+-  struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
+-};
++static int pcache1Free(void *p){
++  int nFreed = 0;
++  if( p==0 ) return 0;
++  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{
++    assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
++    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
++    nFreed = sqlite3MallocSize(p);
++#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
++    sqlite3_mutex_enter(pcache1.mutex);
++    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
++    sqlite3_mutex_leave(pcache1.mutex);
++#endif
++    sqlite3_free(p);
++  }
++  return nFreed;
++}
+ 
++#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ /*
+-** A RowSet in an instance of the following structure.
+-**
+-** A typedef of this structure if found in sqliteInt.h.
++** Return the size of a pcache allocation
+ */
+-struct RowSet {
+-  struct RowSetChunk *pChunk;    /* List of all chunk allocations */
+-  sqlite3 *db;                   /* The database connection */
+-  struct RowSetEntry *pEntry;    /* List of entries using pRight */
+-  struct RowSetEntry *pLast;     /* Last entry on the pEntry list */
+-  struct RowSetEntry *pFresh;    /* Source of new entry objects */
+-  struct RowSetEntry *pForest;   /* List of binary trees of entries */
+-  u16 nFresh;                    /* Number of objects on pFresh */
+-  u8 rsFlags;                    /* Various flags */
+-  u8 iBatch;                     /* Current insert batch */
+-};
++static int pcache1MemSize(void *p){
++  if( p>=pcache1.pStart && p<pcache1.pEnd ){
++    return pcache1.szSlot;
++  }else{
++    int iSize;
++    assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
++    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
++    iSize = sqlite3MallocSize(p);
++    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
++    return iSize;
++  }
++}
++#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+ 
+ /*
+-** Allowed values for RowSet.rsFlags
++** Allocate a new page object initially associated with cache pCache.
+ */
+-#define ROWSET_SORTED  0x01   /* True if RowSet.pEntry is sorted */
+-#define ROWSET_NEXT    0x02   /* True if sqlite3RowSetNext() has been called */
++static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
++  PgHdr1 *p = 0;
++  void *pPg;
++
++  /* The group mutex must be released before pcache1Alloc() is called. This
++  ** is because it may call sqlite3_release_memory(), which assumes that 
++  ** this mutex is not held. */
++  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
++  pcache1LeaveMutex(pCache->pGroup);
++#ifdef SQLITE_PCACHE_SEPARATE_HEADER
++  pPg = pcache1Alloc(pCache->szPage);
++  p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
++  if( !pPg || !p ){
++    pcache1Free(pPg);
++    sqlite3_free(p);
++    pPg = 0;
++  }
++#else
++  pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
++  p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
++#endif
++  pcache1EnterMutex(pCache->pGroup);
++
++  if( pPg ){
++    p->page.pBuf = pPg;
++    p->page.pExtra = &p[1];
++    if( pCache->bPurgeable ){
++      pCache->pGroup->nCurrentPage++;
++    }
++    return p;
++  }
++  return 0;
++}
+ 
+ /*
+-** Turn bulk memory into a RowSet object.  N bytes of memory
+-** are available at pSpace.  The db pointer is used as a memory context
+-** for any subsequent allocations that need to occur.
+-** Return a pointer to the new RowSet object.
++** Free a page object allocated by pcache1AllocPage().
+ **
+-** It must be the case that N is sufficient to make a Rowset.  If not
+-** an assertion fault occurs.
+-** 
+-** If N is larger than the minimum, use the surplus as an initial
+-** allocation of entries available to be filled.
++** The pointer is allowed to be NULL, which is prudent.  But it turns out
++** that the current implementation happens to never call this routine
++** with a NULL pointer, so we mark the NULL test with ALWAYS().
+ */
+-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
+-  RowSet *p;
+-  assert( N >= ROUND8(sizeof(*p)) );
+-  p = pSpace;
+-  p->pChunk = 0;
+-  p->db = db;
+-  p->pEntry = 0;
+-  p->pLast = 0;
+-  p->pForest = 0;
+-  p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
+-  p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
+-  p->rsFlags = ROWSET_SORTED;
+-  p->iBatch = 0;
+-  return p;
++static void pcache1FreePage(PgHdr1 *p){
++  if( ALWAYS(p) ){
++    PCache1 *pCache = p->pCache;
++    assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
++    pcache1Free(p->page.pBuf);
++#ifdef SQLITE_PCACHE_SEPARATE_HEADER
++    sqlite3_free(p);
++#endif
++    if( pCache->bPurgeable ){
++      pCache->pGroup->nCurrentPage--;
++    }
++  }
+ }
+ 
+ /*
+-** Deallocate all chunks from a RowSet.  This frees all memory that
+-** the RowSet has allocated over its lifetime.  This routine is
+-** the destructor for the RowSet.
++** Malloc function used by SQLite to obtain space from the buffer configured
++** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
++** exists, this function falls back to sqlite3Malloc().
+ */
+-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
+-  struct RowSetChunk *pChunk, *pNextChunk;
+-  for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
+-    pNextChunk = pChunk->pNextChunk;
+-    sqlite3DbFree(p->db, pChunk);
+-  }
+-  p->pChunk = 0;
+-  p->nFresh = 0;
+-  p->pEntry = 0;
+-  p->pLast = 0;
+-  p->pForest = 0;
+-  p->rsFlags = ROWSET_SORTED;
++SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
++  return pcache1Alloc(sz);
+ }
+ 
+ /*
+-** Allocate a new RowSetEntry object that is associated with the
+-** given RowSet.  Return a pointer to the new and completely uninitialized
+-** objected.
++** Free an allocated buffer obtained from sqlite3PageMalloc().
++*/
++SQLITE_PRIVATE void sqlite3PageFree(void *p){
++  pcache1Free(p);
++}
++
++
++/*
++** Return true if it desirable to avoid allocating a new page cache
++** entry.
+ **
+-** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
+-** routine returns NULL.
++** If memory was allocated specifically to the page cache using
++** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
++** it is desirable to avoid allocating a new page cache entry because
++** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
++** for all page cache needs and we should not need to spill the
++** allocation onto the heap.
++**
++** Or, the heap is used for all page cache memory but the heap is
++** under memory pressure, then again it is desirable to avoid
++** allocating a new page cache entry in order to avoid stressing
++** the heap even further.
+ */
+-static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
+-  assert( p!=0 );
+-  if( p->nFresh==0 ){
+-    struct RowSetChunk *pNew;
+-    pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
+-    if( pNew==0 ){
+-      return 0;
+-    }
+-    pNew->pNextChunk = p->pChunk;
+-    p->pChunk = pNew;
+-    p->pFresh = pNew->aEntry;
+-    p->nFresh = ROWSET_ENTRY_PER_CHUNK;
++static int pcache1UnderMemoryPressure(PCache1 *pCache){
++  if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
++    return pcache1.bUnderPressure;
++  }else{
++    return sqlite3HeapNearlyFull();
+   }
+-  p->nFresh--;
+-  return p->pFresh++;
+ }
+ 
++/******************************************************************************/
++/******** General Implementation Functions ************************************/
++
+ /*
+-** Insert a new value into a RowSet.
++** This function is used to resize the hash table used by the cache passed
++** as the first argument.
+ **
+-** The mallocFailed flag of the database connection is set if a
+-** memory allocation fails.
++** The PCache mutex must be held when this function is called.
+ */
+-SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
+-  struct RowSetEntry *pEntry;  /* The new entry */
+-  struct RowSetEntry *pLast;   /* The last prior entry */
++static int pcache1ResizeHash(PCache1 *p){
++  PgHdr1 **apNew;
++  unsigned int nNew;
++  unsigned int i;
+ 
+-  /* This routine is never called after sqlite3RowSetNext() */
+-  assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
++  assert( sqlite3_mutex_held(p->pGroup->mutex) );
+ 
+-  pEntry = rowSetEntryAlloc(p);
+-  if( pEntry==0 ) return;
+-  pEntry->v = rowid;
+-  pEntry->pRight = 0;
+-  pLast = p->pLast;
+-  if( pLast ){
+-    if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
+-      p->rsFlags &= ~ROWSET_SORTED;
++  nNew = p->nHash*2;
++  if( nNew<256 ){
++    nNew = 256;
++  }
++
++  pcache1LeaveMutex(p->pGroup);
++  if( p->nHash ){ sqlite3BeginBenignMalloc(); }
++  apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
++  if( p->nHash ){ sqlite3EndBenignMalloc(); }
++  pcache1EnterMutex(p->pGroup);
++  if( apNew ){
++    for(i=0; i<p->nHash; i++){
++      PgHdr1 *pPage;
++      PgHdr1 *pNext = p->apHash[i];
++      while( (pPage = pNext)!=0 ){
++        unsigned int h = pPage->iKey % nNew;
++        pNext = pPage->pNext;
++        pPage->pNext = apNew[h];
++        apNew[h] = pPage;
++      }
+     }
+-    pLast->pRight = pEntry;
+-  }else{
+-    p->pEntry = pEntry;
++    sqlite3_free(p->apHash);
++    p->apHash = apNew;
++    p->nHash = nNew;
+   }
+-  p->pLast = pEntry;
++
++  return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
+ }
+ 
+ /*
+-** Merge two lists of RowSetEntry objects.  Remove duplicates.
++** This function is used internally to remove the page pPage from the 
++** 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 input lists are connected via pRight pointers and are 
+-** assumed to each already be in sorted order.
++** The PGroup mutex must be held when this function is called.
++**
++** If pPage is NULL then this routine is a no-op.
+ */
+-static struct RowSetEntry *rowSetEntryMerge(
+-  struct RowSetEntry *pA,    /* First sorted list to be merged */
+-  struct RowSetEntry *pB     /* Second sorted list to be merged */
+-){
+-  struct RowSetEntry head;
+-  struct RowSetEntry *pTail;
++static void pcache1PinPage(PgHdr1 *pPage){
++  PCache1 *pCache;
++  PGroup *pGroup;
+ 
+-  pTail = &head;
+-  while( pA && pB ){
+-    assert( pA->pRight==0 || pA->v<=pA->pRight->v );
+-    assert( pB->pRight==0 || pB->v<=pB->pRight->v );
+-    if( pA->v<pB->v ){
+-      pTail->pRight = pA;
+-      pA = pA->pRight;
+-      pTail = pTail->pRight;
+-    }else if( pB->v<pA->v ){
+-      pTail->pRight = pB;
+-      pB = pB->pRight;
+-      pTail = pTail->pRight;
+-    }else{
+-      pA = pA->pRight;
++  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( pGroup->pLruHead==pPage ){
++      pGroup->pLruHead = pPage->pLruNext;
++    }
++    if( pGroup->pLruTail==pPage ){
++      pGroup->pLruTail = pPage->pLruPrev;
++    }
++    pPage->pLruNext = 0;
++    pPage->pLruPrev = 0;
++    pPage->pCache->nRecyclable--;
+   }
+-  if( pA ){
+-    assert( pA->pRight==0 || pA->v<=pA->pRight->v );
+-    pTail->pRight = pA;
+-  }else{
+-    assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v );
+-    pTail->pRight = pB;
+-  }
+-  return head.pRight;
+ }
+ 
++
+ /*
+-** Sort all elements on the list of RowSetEntry objects into order of
+-** increasing v.
+-*/ 
+-static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
+-  unsigned int i;
+-  struct RowSetEntry *pNext, *aBucket[40];
++** Remove the page supplied as an argument from the hash table 
++** (PCache1.apHash structure) that it is currently stored in.
++**
++** 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;
+ 
+-  memset(aBucket, 0, sizeof(aBucket));
+-  while( pIn ){
+-    pNext = pIn->pRight;
+-    pIn->pRight = 0;
+-    for(i=0; aBucket[i]; i++){
+-      pIn = rowSetEntryMerge(aBucket[i], pIn);
+-      aBucket[i] = 0;
+-    }
+-    aBucket[i] = pIn;
+-    pIn = pNext;
+-  }
+-  pIn = 0;
+-  for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
+-    pIn = rowSetEntryMerge(pIn, aBucket[i]);
+-  }
+-  return pIn;
++  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;
++
++  pCache->nPage--;
+ }
+ 
++/*
++** If there are currently more than nMaxPage pages allocated, try
++** to recycle pages to reduce the number allocated to nMaxPage.
++*/
++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);
++  }
++}
+ 
+ /*
+-** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
+-** Convert this tree into a linked list connected by the pRight pointers
+-** and return pointers to the first and last elements of the new list.
++** Discard all pages from cache pCache with a page number (key value) 
++** greater than or equal to iLimit. Any pinned pages that meet this 
++** criteria are unpinned before they are discarded.
++**
++** The PCache mutex must be held when this function is called.
+ */
+-static void rowSetTreeToList(
+-  struct RowSetEntry *pIn,         /* Root of the input tree */
+-  struct RowSetEntry **ppFirst,    /* Write head of the output list here */
+-  struct RowSetEntry **ppLast      /* Write tail of the output list here */
++static void pcache1TruncateUnsafe(
++  PCache1 *pCache,             /* The cache to truncate */
++  unsigned int iLimit          /* Drop pages with this pgno or larger */
+ ){
+-  assert( pIn!=0 );
+-  if( pIn->pLeft ){
+-    struct RowSetEntry *p;
+-    rowSetTreeToList(pIn->pLeft, ppFirst, &p);
+-    p->pRight = pIn;
+-  }else{
+-    *ppFirst = pIn;
+-  }
+-  if( pIn->pRight ){
+-    rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
+-  }else{
+-    *ppLast = pIn;
++  TESTONLY( unsigned int nPage = 0; )  /* To assert pCache->nPage is correct */
++  unsigned int h;
++  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
++  for(h=0; h<pCache->nHash; h++){
++    PgHdr1 **pp = &pCache->apHash[h]; 
++    PgHdr1 *pPage;
++    while( (pPage = *pp)!=0 ){
++      if( pPage->iKey>=iLimit ){
++        pCache->nPage--;
++        *pp = pPage->pNext;
++        pcache1PinPage(pPage);
++        pcache1FreePage(pPage);
++      }else{
++        pp = &pPage->pNext;
++        TESTONLY( nPage++; )
++      }
++    }
+   }
+-  assert( (*ppLast)->pRight==0 );
++  assert( pCache->nPage==nPage );
+ }
+ 
++/******************************************************************************/
++/******** sqlite3_pcache Methods **********************************************/
+ 
+ /*
+-** Convert a sorted list of elements (connected by pRight) into a binary
+-** tree with depth of iDepth.  A depth of 1 means the tree contains a single
+-** node taken from the head of *ppList.  A depth of 2 means a tree with
+-** three nodes.  And so forth.
+-**
+-** Use as many entries from the input list as required and update the
+-** *ppList to point to the unused elements of the list.  If the input
+-** list contains too few elements, then construct an incomplete tree
+-** and leave *ppList set to NULL.
+-**
+-** Return a pointer to the root of the constructed binary tree.
++** Implementation of the sqlite3_pcache.xInit method.
+ */
+-static struct RowSetEntry *rowSetNDeepTree(
+-  struct RowSetEntry **ppList,
+-  int iDepth
+-){
+-  struct RowSetEntry *p;         /* Root of the new tree */
+-  struct RowSetEntry *pLeft;     /* Left subtree */
+-  if( *ppList==0 ){
+-    return 0;
+-  }
+-  if( iDepth==1 ){
+-    p = *ppList;
+-    *ppList = p->pRight;
+-    p->pLeft = p->pRight = 0;
+-    return p;
+-  }
+-  pLeft = rowSetNDeepTree(ppList, iDepth-1);
+-  p = *ppList;
+-  if( p==0 ){
+-    return pLeft;
++static int pcache1Init(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  assert( pcache1.isInit==0 );
++  memset(&pcache1, 0, sizeof(pcache1));
++  if( sqlite3GlobalConfig.bCoreMutex ){
++    pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
++    pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
+   }
+-  p->pLeft = pLeft;
+-  *ppList = p->pRight;
+-  p->pRight = rowSetNDeepTree(ppList, iDepth-1);
+-  return p;
++  pcache1.grp.mxPinned = 10;
++  pcache1.isInit = 1;
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Convert a sorted list of elements into a binary tree. Make the tree
+-** as deep as it needs to be in order to contain the entire list.
++** Implementation of the sqlite3_pcache.xShutdown method.
++** Note that the static mutex allocated in xInit does 
++** not need to be freed.
+ */
+-static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
+-  int iDepth;           /* Depth of the tree so far */
+-  struct RowSetEntry *p;       /* Current tree root */
+-  struct RowSetEntry *pLeft;   /* Left subtree */
+-
+-  assert( pList!=0 );
+-  p = pList;
+-  pList = p->pRight;
+-  p->pLeft = p->pRight = 0;
+-  for(iDepth=1; pList; iDepth++){
+-    pLeft = p;
+-    p = pList;
+-    pList = p->pRight;
+-    p->pLeft = pLeft;
+-    p->pRight = rowSetNDeepTree(&pList, iDepth);
+-  }
+-  return p;
++static void pcache1Shutdown(void *NotUsed){
++  UNUSED_PARAMETER(NotUsed);
++  assert( pcache1.isInit!=0 );
++  memset(&pcache1, 0, sizeof(pcache1));
+ }
+ 
+ /*
+-** Take all the entries on p->pEntry and on the trees in p->pForest and
+-** sort them all together into one big ordered list on p->pEntry.
++** Implementation of the sqlite3_pcache.xCreate method.
+ **
+-** This routine should only be called once in the life of a RowSet.
++** Allocate a new cache.
+ */
+-static void rowSetToList(RowSet *p){
++static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
++  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 */
+ 
+-  /* This routine is called only once */
+-  assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
++  /*
++  ** 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
+ 
+-  if( (p->rsFlags & ROWSET_SORTED)==0 ){
+-    p->pEntry = rowSetEntrySort(p->pEntry);
+-  }
++  assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
++  assert( szExtra < 300 );
+ 
+-  /* While this module could theoretically support it, sqlite3RowSetNext()
+-  ** is never called after sqlite3RowSetText() for the same RowSet.  So
+-  ** there is never a forest to deal with.  Should this change, simply
+-  ** remove the assert() and the #if 0. */
+-  assert( p->pForest==0 );
+-#if 0
+-  while( p->pForest ){
+-    struct RowSetEntry *pTree = p->pForest->pLeft;
+-    if( pTree ){
+-      struct RowSetEntry *pHead, *pTail;
+-      rowSetTreeToList(pTree, &pHead, &pTail);
+-      p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
++  sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
++  pCache = (PCache1 *)sqlite3MallocZero(sz);
++  if( pCache ){
++    if( separateCache ){
++      pGroup = (PGroup*)&pCache[1];
++      pGroup->mxPinned = 10;
++    }else{
++      pGroup = &pcache1.grp;
++    }
++    pCache->pGroup = pGroup;
++    pCache->szPage = szPage;
++    pCache->szExtra = szExtra;
++    pCache->bPurgeable = (bPurgeable ? 1 : 0);
++    if( bPurgeable ){
++      pCache->nMin = 10;
++      pcache1EnterMutex(pGroup);
++      pGroup->nMinPage += pCache->nMin;
++      pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
++      pcache1LeaveMutex(pGroup);
+     }
+-    p->pForest = p->pForest->pRight;
+   }
+-#endif
+-  p->rsFlags |= ROWSET_NEXT;  /* Verify this routine is never called again */
++  return (sqlite3_pcache *)pCache;
+ }
+ 
+ /*
+-** Extract the smallest element from the RowSet.
+-** Write the element into *pRowid.  Return 1 on success.  Return
+-** 0 if the RowSet is already empty.
++** Implementation of the sqlite3_pcache.xCachesize method. 
+ **
+-** After this routine has been called, the sqlite3RowSetInsert()
+-** routine may not be called again.  
++** Configure the cache_size limit for a cache.
+ */
+-SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
+-  assert( p!=0 );
+-
+-  /* Merge the forest into a single sorted list on first call */
+-  if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
+-
+-  /* Return the next entry on the list */
+-  if( p->pEntry ){
+-    *pRowid = p->pEntry->v;
+-    p->pEntry = p->pEntry->pRight;
+-    if( p->pEntry==0 ){
+-      sqlite3RowSetClear(p);
+-    }
+-    return 1;
+-  }else{
+-    return 0;
++static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
++  PCache1 *pCache = (PCache1 *)p;
++  if( pCache->bPurgeable ){
++    PGroup *pGroup = pCache->pGroup;
++    pcache1EnterMutex(pGroup);
++    pGroup->nMaxPage += (nMax - pCache->nMax);
++    pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
++    pCache->nMax = nMax;
++    pCache->n90pct = pCache->nMax*9/10;
++    pcache1EnforceMaxPage(pGroup);
++    pcache1LeaveMutex(pGroup);
+   }
+ }
+ 
+ /*
+-** Check to see if element iRowid was inserted into the rowset as
+-** part of any insert batch prior to iBatch.  Return 1 or 0.
++** Implementation of the sqlite3_pcache.xShrink method. 
+ **
+-** If this is the first test of a new batch and if there exist entires
+-** on pRowSet->pEntry, then sort those entires into the forest at
+-** pRowSet->pForest so that they can be tested.
++** Free up as much memory as possible.
+ */
+-SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
+-  struct RowSetEntry *p, *pTree;
+-
+-  /* This routine is never called after sqlite3RowSetNext() */
+-  assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
+-
+-  /* Sort entries into the forest on the first test of a new batch 
+-  */
+-  if( iBatch!=pRowSet->iBatch ){
+-    p = pRowSet->pEntry;
+-    if( p ){
+-      struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
+-      if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
+-        p = rowSetEntrySort(p);
+-      }
+-      for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
+-        ppPrevTree = &pTree->pRight;
+-        if( pTree->pLeft==0 ){
+-          pTree->pLeft = rowSetListToTree(p);
+-          break;
+-        }else{
+-          struct RowSetEntry *pAux, *pTail;
+-          rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
+-          pTree->pLeft = 0;
+-          p = rowSetEntryMerge(pAux, p);
+-        }
+-      }
+-      if( pTree==0 ){
+-        *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
+-        if( pTree ){
+-          pTree->v = 0;
+-          pTree->pRight = 0;
+-          pTree->pLeft = rowSetListToTree(p);
+-        }
+-      }
+-      pRowSet->pEntry = 0;
+-      pRowSet->pLast = 0;
+-      pRowSet->rsFlags |= ROWSET_SORTED;
+-    }
+-    pRowSet->iBatch = iBatch;
++static void pcache1Shrink(sqlite3_pcache *p){
++  PCache1 *pCache = (PCache1*)p;
++  if( pCache->bPurgeable ){
++    PGroup *pGroup = pCache->pGroup;
++    int savedMaxPage;
++    pcache1EnterMutex(pGroup);
++    savedMaxPage = pGroup->nMaxPage;
++    pGroup->nMaxPage = 0;
++    pcache1EnforceMaxPage(pGroup);
++    pGroup->nMaxPage = savedMaxPage;
++    pcache1LeaveMutex(pGroup);
+   }
++}
+ 
+-  /* Test to see if the iRowid value appears anywhere in the forest.
+-  ** Return 1 if it does and 0 if not.
+-  */
+-  for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
+-    p = pTree->pLeft;
+-    while( p ){
+-      if( p->v<iRowid ){
+-        p = p->pRight;
+-      }else if( p->v>iRowid ){
+-        p = p->pLeft;
+-      }else{
+-        return 1;
+-      }
+-    }
+-  }
+-  return 0;
++/*
++** Implementation of the sqlite3_pcache.xPagecount method. 
++*/
++static int pcache1Pagecount(sqlite3_pcache *p){
++  int n;
++  PCache1 *pCache = (PCache1*)p;
++  pcache1EnterMutex(pCache->pGroup);
++  n = pCache->nPage;
++  pcache1LeaveMutex(pCache->pGroup);
++  return n;
+ }
+ 
+-/************** End of rowset.c **********************************************/
+-/************** Begin file pager.c *******************************************/
+ /*
+-** 2001 September 15
++** Implementation of the sqlite3_pcache.xFetch method. 
+ **
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
++** Fetch a page by key value.
+ **
+-**    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.
++** Whether or not a new page may be allocated by this function depends on
++** the value of the createFlag argument.  0 means do not allocate a new
++** page.  1 means allocate a new page if space is easily available.  2 
++** means to try really hard to allocate a new page.
+ **
+-*************************************************************************
+-** This is the implementation of the page cache subsystem or "pager".
+-** 
+-** The pager is used to access a database disk file.  It implements
+-** atomic commit and rollback through the use of a journal file that
+-** is separate from the database file.  The pager also implements file
+-** locking to prevent two processes from writing the same database
+-** file simultaneously, or one process from reading the database while
+-** another is writing.
+-*/
+-#ifndef SQLITE_OMIT_DISKIO
+-/************** Include wal.h in the middle of pager.c ***********************/
+-/************** Begin file wal.h *********************************************/
+-/*
+-** 2010 February 1
++** For a non-purgeable cache (a cache used as the storage for an in-memory
++** database) there is really no difference between createFlag 1 and 2.  So
++** the calling function (pcache.c) will never have a createFlag of 1 on
++** a non-purgeable cache.
+ **
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
++** There are three different approaches to obtaining space for a page,
++** depending on the value of parameter createFlag (which may be 0, 1 or 2).
+ **
+-**    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.
++**   1. Regardless of the value of createFlag, the cache is searched for a 
++**      copy of the requested page. If one is found, it is returned.
+ **
+-*************************************************************************
+-** This header file defines the interface to the write-ahead logging 
+-** system. Refer to the comments below and the header comment attached to 
+-** the implementation of each function in log.c for further details.
++**   2. If createFlag==0 and the page is not already in the cache, NULL is
++**      returned.
++**
++**   3. If createFlag is 1, and the page is not already in the cache, then
++**      return NULL (do not allocate a new page) if any of the following
++**      conditions are true:
++**
++**       (a) the number of pages pinned by the cache is greater than
++**           PCache1.nMax, or
++**
++**       (b) the number of pages pinned by the cache is greater than
++**           the sum of nMax for all purgeable caches, less the sum of 
++**           nMin for all other purgeable caches, or
++**
++**   4. If none of the first three conditions apply and the cache is marked
++**      as purgeable, and if one of the following is true:
++**
++**       (a) The number of pages allocated for the cache is already 
++**           PCache1.nMax, or
++**
++**       (b) The number of pages allocated for all purgeable caches is
++**           already equal to or greater than the sum of nMax for all
++**           purgeable caches,
++**
++**       (c) The system is under memory pressure and wants to avoid
++**           unnecessary pages cache entry allocations
++**
++**      then attempt to recycle a page from the LRU list. If it is the right
++**      size, return the recycled buffer. Otherwise, free the buffer and
++**      proceed to step 5. 
++**
++**   5. Otherwise, allocate and return a new page buffer.
+ */
++static sqlite3_pcache_page *pcache1Fetch(
++  sqlite3_pcache *p, 
++  unsigned int iKey, 
++  int createFlag
++){
++  unsigned int nPinned;
++  PCache1 *pCache = (PCache1 *)p;
++  PGroup *pGroup;
++  PgHdr1 *pPage = 0;
+ 
+-#ifndef _WAL_H_
+-#define _WAL_H_
+-
+-
+-/* Additional values that can be added to the sync_flags argument of
+-** sqlite3WalFrames():
+-*/
+-#define WAL_SYNC_TRANSACTIONS  0x20   /* Sync at the end of each transaction */
+-#define SQLITE_SYNC_MASK       0x13   /* Mask off the SQLITE_SYNC_* values */
++  assert( pCache->bPurgeable || createFlag!=1 );
++  assert( pCache->bPurgeable || pCache->nMin==0 );
++  assert( pCache->bPurgeable==0 || pCache->nMin==10 );
++  assert( pCache->nMin==0 || pCache->bPurgeable );
++  pcache1EnterMutex(pGroup = pCache->pGroup);
+ 
+-#ifdef SQLITE_OMIT_WAL
+-# define sqlite3WalOpen(x,y,z)                   0
+-# define sqlite3WalLimit(x,y)
+-# define sqlite3WalClose(w,x,y,z)                0
+-# define sqlite3WalBeginReadTransaction(y,z)     0
+-# define sqlite3WalEndReadTransaction(z)
+-# define sqlite3WalDbsize(y)                     0
+-# define sqlite3WalBeginWriteTransaction(y)      0
+-# define sqlite3WalEndWriteTransaction(x)        0
+-# define sqlite3WalUndo(x,y,z)                   0
+-# define sqlite3WalSavepoint(y,z)
+-# define sqlite3WalSavepointUndo(y,z)            0
+-# define sqlite3WalFrames(u,v,w,x,y,z)           0
+-# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
+-# define sqlite3WalCallback(z)                   0
+-# define sqlite3WalExclusiveMode(y,z)            0
+-# define sqlite3WalHeapMemory(z)                 0
+-# define sqlite3WalFramesize(z)                  0
+-# define sqlite3WalFindFrame(x,y,z)              0
+-#else
++  /* 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);
++  }
+ 
+-#define WAL_SAVEPOINT_NDATA 4
++  /* Step 2: Abort if no existing page is found and createFlag is 0 */
++  if( pPage || createFlag==0 ){
++    pcache1PinPage(pPage);
++    goto fetch_out;
++  }
+ 
+-/* Connection to a write-ahead log (WAL) file. 
+-** There is one object of this type for each pager. 
+-*/
+-typedef struct Wal Wal;
++  /* 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
+ 
+-/* Open and close a connection to a write-ahead log. */
+-SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
+-SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
++  /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
++  assert( pCache->nPage >= pCache->nRecyclable );
++  nPinned = pCache->nPage - pCache->nRecyclable;
++  assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
++  assert( pCache->n90pct == pCache->nMax*9/10 );
++  if( createFlag==1 && (
++        nPinned>=pGroup->mxPinned
++     || nPinned>=pCache->n90pct
++     || pcache1UnderMemoryPressure(pCache)
++  )){
++    goto fetch_out;
++  }
+ 
+-/* Set the limiting size of a WAL file. */
+-SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
++  if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
++    goto fetch_out;
++  }
+ 
+-/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
+-** snapshot is like a read-transaction.  It is the state of the database
+-** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
+-** preserves the current state even if the other threads or processes
+-** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
+-** transaction and releases the lock.
+-*/
+-SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
+-SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
++  /* Step 4. Try to recycle a page. */
++  if( pCache->bPurgeable && pGroup->pLruTail && (
++         (pCache->nPage+1>=pCache->nMax)
++      || pGroup->nCurrentPage>=pGroup->nMaxPage
++      || pcache1UnderMemoryPressure(pCache)
++  )){
++    PCache1 *pOther;
++    pPage = pGroup->pLruTail;
++    pcache1RemoveFromHash(pPage);
++    pcache1PinPage(pPage);
++    pOther = pPage->pCache;
+ 
+-/* Read a page from the write-ahead log, if it is present. */
+-SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
+-SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
++    /* We want to verify that szPage and szExtra are the same for pOther
++    ** and pCache.  Assert that we can verify this by comparing sums. */
++    assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
++    assert( pCache->szExtra<512 );
++    assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
++    assert( pOther->szExtra<512 );
+ 
+-/* If the WAL is not empty, return the size of the database. */
+-SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
++    if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
++      pcache1FreePage(pPage);
++      pPage = 0;
++    }else{
++      pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
++    }
++  }
+ 
+-/* Obtain or release the WRITER lock. */
+-SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal);
+-SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal);
++  /* Step 5. If a usable page buffer has still not been found, 
++  ** attempt to allocate a new one. 
++  */
++  if( !pPage ){
++    if( createFlag==1 ) sqlite3BeginBenignMalloc();
++    pPage = pcache1AllocPage(pCache);
++    if( createFlag==1 ) sqlite3EndBenignMalloc();
++  }
+ 
+-/* Undo any frames written (but not committed) to the log */
+-SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
++  if( pPage ){
++    unsigned int h = iKey % pCache->nHash;
++    pCache->nPage++;
++    pPage->iKey = iKey;
++    pPage->pNext = pCache->apHash[h];
++    pPage->pCache = pCache;
++    pPage->pLruPrev = 0;
++    pPage->pLruNext = 0;
++    *(void **)pPage->page.pExtra = 0;
++    pCache->apHash[h] = pPage;
++  }
+ 
+-/* Return an integer that records the current (uncommitted) write
+-** position in the WAL */
+-SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
++fetch_out:
++  if( pPage && iKey>pCache->iMaxKey ){
++    pCache->iMaxKey = iKey;
++  }
++  pcache1LeaveMutex(pGroup);
++  return &pPage->page;
++}
+ 
+-/* Move the write position of the WAL back to iFrame.  Called in
+-** response to a ROLLBACK TO command. */
+-SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
+ 
+-/* Write a frame or frames to the log. */
+-SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
++/*
++** Implementation of the sqlite3_pcache.xUnpin method.
++**
++** Mark a page as unpinned (eligible for asynchronous recycling).
++*/
++static void pcache1Unpin(
++  sqlite3_pcache *p, 
++  sqlite3_pcache_page *pPg, 
++  int reuseUnlikely
++){
++  PCache1 *pCache = (PCache1 *)p;
++  PgHdr1 *pPage = (PgHdr1 *)pPg;
++  PGroup *pGroup = pCache->pGroup;
++ 
++  assert( pPage->pCache==pCache );
++  pcache1EnterMutex(pGroup);
+ 
+-/* Copy pages from the log to the database file */ 
+-SQLITE_PRIVATE int sqlite3WalCheckpoint(
+-  Wal *pWal,                      /* Write-ahead log connection */
+-  int eMode,                      /* One of PASSIVE, FULL and RESTART */
+-  int (*xBusy)(void*),            /* Function to call when busy */
+-  void *pBusyArg,                 /* Context argument for xBusyHandler */
+-  int sync_flags,                 /* Flags to sync db file with (or 0) */
+-  int nBuf,                       /* Size of buffer nBuf */
+-  u8 *zBuf,                       /* Temporary buffer to use */
+-  int *pnLog,                     /* OUT: Number of frames in WAL */
+-  int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
+-);
++  /* It is an error to call this function if the page is already 
++  ** part of the PGroup LRU list.
++  */
++  assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
++  assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
+ 
+-/* Return the value to pass to a sqlite3_wal_hook callback, the
+-** number of frames in the WAL at the point of the last commit since
+-** sqlite3WalCallback() was called.  If no commits have occurred since
+-** the last call, then return 0.
+-*/
+-SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
++  if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
++    pcache1RemoveFromHash(pPage);
++    pcache1FreePage(pPage);
++  }else{
++    /* Add the page to the PGroup LRU list. */
++    if( pGroup->pLruHead ){
++      pGroup->pLruHead->pLruPrev = pPage;
++      pPage->pLruNext = pGroup->pLruHead;
++      pGroup->pLruHead = pPage;
++    }else{
++      pGroup->pLruTail = pPage;
++      pGroup->pLruHead = pPage;
++    }
++    pCache->nRecyclable++;
++  }
+ 
+-/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
+-** by the pager layer on the database file.
+-*/
+-SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
++  pcache1LeaveMutex(pCache->pGroup);
++}
+ 
+-/* Return true if the argument is non-NULL and the WAL module is using
+-** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+-** WAL module is using shared-memory, return false. 
++/*
++** Implementation of the sqlite3_pcache.xRekey method. 
+ */
+-SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
++static void pcache1Rekey(
++  sqlite3_pcache *p,
++  sqlite3_pcache_page *pPg,
++  unsigned int iOld,
++  unsigned int iNew
++){
++  PCache1 *pCache = (PCache1 *)p;
++  PgHdr1 *pPage = (PgHdr1 *)pPg;
++  PgHdr1 **pp;
++  unsigned int h; 
++  assert( pPage->iKey==iOld );
++  assert( pPage->pCache==pCache );
+ 
+-#ifdef SQLITE_ENABLE_ZIPVFS
+-/* If the WAL file is not empty, return the number of bytes of content
+-** stored in each frame (i.e. the db page-size when the WAL was created).
+-*/
+-SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
+-#endif
++  pcache1EnterMutex(pCache->pGroup);
+ 
+-#endif /* ifndef SQLITE_OMIT_WAL */
+-#endif /* _WAL_H_ */
++  h = iOld%pCache->nHash;
++  pp = &pCache->apHash[h];
++  while( (*pp)!=pPage ){
++    pp = &(*pp)->pNext;
++  }
++  *pp = pPage->pNext;
+ 
+-/************** End of wal.h *************************************************/
+-/************** Continuing where we left off in pager.c **********************/
++  h = iNew%pCache->nHash;
++  pPage->iKey = iNew;
++  pPage->pNext = pCache->apHash[h];
++  pCache->apHash[h] = pPage;
++  if( iNew>pCache->iMaxKey ){
++    pCache->iMaxKey = iNew;
++  }
+ 
++  pcache1LeaveMutex(pCache->pGroup);
++}
+ 
+-/******************* NOTES ON THE DESIGN OF THE PAGER ************************
+-**
+-** This comment block describes invariants that hold when using a rollback
+-** journal.  These invariants do not apply for journal_mode=WAL,
+-** journal_mode=MEMORY, or journal_mode=OFF.
+-**
+-** Within this comment block, a page is deemed to have been synced
+-** automatically as soon as it is written when PRAGMA synchronous=OFF.
+-** Otherwise, the page is not synced until the xSync method of the VFS
+-** is called successfully on the file containing the page.
+-**
+-** Definition:  A page of the database file is said to be "overwriteable" if
+-** one or more of the following are true about the page:
+-** 
+-**     (a)  The original content of the page as it was at the beginning of
+-**          the transaction has been written into the rollback journal and
+-**          synced.
+-** 
+-**     (b)  The page was a freelist leaf page at the start of the transaction.
+-** 
+-**     (c)  The page number is greater than the largest page that existed in
+-**          the database file at the start of the transaction.
+-** 
+-** (1) A page of the database file is never overwritten unless one of the
+-**     following are true:
+-** 
+-**     (a) The page and all other pages on the same sector are overwriteable.
+-** 
+-**     (b) The atomic page write optimization is enabled, and the entire
+-**         transaction other than the update of the transaction sequence
+-**         number consists of a single page change.
+-** 
+-** (2) The content of a page written into the rollback journal exactly matches
+-**     both the content in the database when the rollback journal was written
+-**     and the content in the database at the beginning of the current
+-**     transaction.
+-** 
+-** (3) Writes to the database file are an integer multiple of the page size
+-**     in length and are aligned on a page boundary.
+-** 
+-** (4) Reads from the database file are either aligned on a page boundary and
+-**     an integer multiple of the page size in length or are taken from the
+-**     first 100 bytes of the database file.
+-** 
+-** (5) All writes to the database file are synced prior to the rollback journal
+-**     being deleted, truncated, or zeroed.
+-** 
+-** (6) If a master journal file is used, then all writes to the database file
+-**     are synced prior to the master journal being deleted.
+-** 
+-** Definition: Two databases (or the same database at two points it time)
+-** are said to be "logically equivalent" if they give the same answer to
+-** all queries.  Note in particular the content of freelist leaf
+-** pages can be changed arbitarily without effecting the logical equivalence
+-** of the database.
+-** 
+-** (7) At any time, if any subset, including the empty set and the total set,
+-**     of the unsynced changes to a rollback journal are removed and the 
+-**     journal is rolled back, the resulting database file will be logical
+-**     equivalent to the database file at the beginning of the transaction.
+-** 
+-** (8) When a transaction is rolled back, the xTruncate method of the VFS
+-**     is called to restore the database file to the same size it was at
+-**     the beginning of the transaction.  (In some VFSes, the xTruncate
+-**     method is a no-op, but that does not change the fact the SQLite will
+-**     invoke it.)
+-** 
+-** (9) Whenever the database file is modified, at least one bit in the range
+-**     of bytes from 24 through 39 inclusive will be changed prior to releasing
+-**     the EXCLUSIVE lock, thus signaling other connections on the same
+-**     database to flush their caches.
+-**
+-** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
+-**      than one billion transactions.
+-**
+-** (11) A database file is well-formed at the beginning and at the conclusion
+-**      of every transaction.
+-**
+-** (12) An EXCLUSIVE lock is held on the database file when writing to
+-**      the database file.
++/*
++** Implementation of the sqlite3_pcache.xTruncate method. 
+ **
+-** (13) A SHARED lock is held on the database file while reading any
+-**      content out of the database file.
++** Discard all unpinned pages in the cache with a page number equal to
++** or greater than parameter iLimit. Any pinned pages with a page number
++** equal to or greater than iLimit are implicitly unpinned.
++*/
++static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
++  PCache1 *pCache = (PCache1 *)p;
++  pcache1EnterMutex(pCache->pGroup);
++  if( iLimit<=pCache->iMaxKey ){
++    pcache1TruncateUnsafe(pCache, iLimit);
++    pCache->iMaxKey = iLimit-1;
++  }
++  pcache1LeaveMutex(pCache->pGroup);
++}
++
++/*
++** Implementation of the sqlite3_pcache.xDestroy method. 
+ **
+-******************************************************************************/
++** Destroy a cache allocated using pcache1Create().
++*/
++static void pcache1Destroy(sqlite3_pcache *p){
++  PCache1 *pCache = (PCache1 *)p;
++  PGroup *pGroup = pCache->pGroup;
++  assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
++  pcache1EnterMutex(pGroup);
++  pcache1TruncateUnsafe(pCache, 0);
++  assert( pGroup->nMaxPage >= pCache->nMax );
++  pGroup->nMaxPage -= pCache->nMax;
++  assert( pGroup->nMinPage >= pCache->nMin );
++  pGroup->nMinPage -= pCache->nMin;
++  pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
++  pcache1EnforceMaxPage(pGroup);
++  pcache1LeaveMutex(pGroup);
++  sqlite3_free(pCache->apHash);
++  sqlite3_free(pCache);
++}
+ 
+ /*
+-** Macros for troubleshooting.  Normally turned off
++** This function is called during initialization (sqlite3_initialize()) to
++** install the default pluggable cache module, assuming the user has not
++** already provided an alternative.
+ */
+-#if 0
+-int sqlite3PagerTrace=1;  /* True to enable tracing */
+-#define sqlite3DebugPrintf printf
+-#define PAGERTRACE(X)     if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
+-#else
+-#define PAGERTRACE(X)
+-#endif
++SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
++  static const sqlite3_pcache_methods2 defaultMethods = {
++    1,                       /* iVersion */
++    0,                       /* pArg */
++    pcache1Init,             /* xInit */
++    pcache1Shutdown,         /* xShutdown */
++    pcache1Create,           /* xCreate */
++    pcache1Cachesize,        /* xCachesize */
++    pcache1Pagecount,        /* xPagecount */
++    pcache1Fetch,            /* xFetch */
++    pcache1Unpin,            /* xUnpin */
++    pcache1Rekey,            /* xRekey */
++    pcache1Truncate,         /* xTruncate */
++    pcache1Destroy,          /* xDestroy */
++    pcache1Shrink            /* xShrink */
++  };
++  sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
++}
+ 
++#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ /*
+-** The following two macros are used within the PAGERTRACE() macros above
+-** to print out file-descriptors. 
++** This function is called to free superfluous dynamically allocated memory
++** held by the pager system. Memory in use by any SQLite pager allocated
++** by the current thread may be sqlite3_free()ed.
+ **
+-** PAGERID() takes a pointer to a Pager struct as its argument. The
+-** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
+-** struct as its argument.
++** nReq is the number of bytes of memory required. Once this much has
++** been released, the function returns. The return value is the total number 
++** of bytes of memory released.
+ */
+-#define PAGERID(p) ((int)(p->fd))
+-#define FILEHANDLEID(fd) ((int)fd)
++SQLITE_PRIVATE 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(&pcache1.grp);
++    while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
++      nFree += pcache1MemSize(p->page.pBuf);
++#ifdef SQLITE_PCACHE_SEPARATE_HEADER
++      nFree += sqlite3MemSize(p);
++#endif
++      pcache1PinPage(p);
++      pcache1RemoveFromHash(p);
++      pcache1FreePage(p);
++    }
++    pcache1LeaveMutex(&pcache1.grp);
++  }
++  return nFree;
++}
++#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+ 
++#ifdef SQLITE_TEST
+ /*
+-** The Pager.eState variable stores the current 'state' of a pager. A
+-** pager may be in any one of the seven states shown in the following
+-** state diagram.
+-**
+-**                            OPEN <------+------+
+-**                              |         |      |
+-**                              V         |      |
+-**               +---------> READER-------+      |
+-**               |              |                |
+-**               |              V                |
+-**               |<-------WRITER_LOCKED------> ERROR
+-**               |              |                ^  
+-**               |              V                |
+-**               |<------WRITER_CACHEMOD-------->|
+-**               |              |                |
+-**               |              V                |
+-**               |<-------WRITER_DBMOD---------->|
+-**               |              |                |
+-**               |              V                |
+-**               +<------WRITER_FINISHED-------->+
+-**
+-**
+-** List of state transitions and the C [function] that performs each:
+-** 
+-**   OPEN              -> READER              [sqlite3PagerSharedLock]
+-**   READER            -> OPEN                [pager_unlock]
+-**
+-**   READER            -> WRITER_LOCKED       [sqlite3PagerBegin]
+-**   WRITER_LOCKED     -> WRITER_CACHEMOD     [pager_open_journal]
+-**   WRITER_CACHEMOD   -> WRITER_DBMOD        [syncJournal]
+-**   WRITER_DBMOD      -> WRITER_FINISHED     [sqlite3PagerCommitPhaseOne]
+-**   WRITER_***        -> READER              [pager_end_transaction]
+-**
+-**   WRITER_***        -> ERROR               [pager_error]
+-**   ERROR             -> OPEN                [pager_unlock]
+-** 
+-**
+-**  OPEN:
+-**
+-**    The pager starts up in this state. Nothing is guaranteed in this
+-**    state - the file may or may not be locked and the database size is
+-**    unknown. The database may not be read or written.
+-**
+-**    * No read or write transaction is active.
+-**    * Any lock, or no lock at all, may be held on the database file.
+-**    * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
+-**
+-**  READER:
+-**
+-**    In this state all the requirements for reading the database in 
+-**    rollback (non-WAL) mode are met. Unless the pager is (or recently
+-**    was) in exclusive-locking mode, a user-level read transaction is 
+-**    open. The database size is known in this state.
+-**
+-**    A connection running with locking_mode=normal enters this state when
+-**    it opens a read-transaction on the database and returns to state
+-**    OPEN after the read-transaction is completed. However a connection
+-**    running in locking_mode=exclusive (including temp databases) remains in
+-**    this state even after the read-transaction is closed. The only way
+-**    a locking_mode=exclusive connection can transition from READER to OPEN
+-**    is via the ERROR state (see below).
+-** 
+-**    * A read transaction may be active (but a write-transaction cannot).
+-**    * A SHARED or greater lock is held on the database file.
+-**    * The dbSize variable may be trusted (even if a user-level read 
+-**      transaction is not active). The dbOrigSize and dbFileSize variables
+-**      may not be trusted at this point.
+-**    * If the database is a WAL database, then the WAL connection is open.
+-**    * Even if a read-transaction is not open, it is guaranteed that 
+-**      there is no hot-journal in the file-system.
+-**
+-**  WRITER_LOCKED:
+-**
+-**    The pager moves to this state from READER when a write-transaction
+-**    is first opened on the database. In WRITER_LOCKED state, all locks 
+-**    required to start a write-transaction are held, but no actual 
+-**    modifications to the cache or database have taken place.
+-**
+-**    In rollback mode, a RESERVED or (if the transaction was opened with 
+-**    BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
+-**    moving to this state, but the journal file is not written to or opened 
+-**    to in this state. If the transaction is committed or rolled back while 
+-**    in WRITER_LOCKED state, all that is required is to unlock the database 
+-**    file.
+-**
+-**    IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
+-**    If the connection is running with locking_mode=exclusive, an attempt
+-**    is made to obtain an EXCLUSIVE lock on the database file.
+-**
+-**    * A write transaction is active.
+-**    * If the connection is open in rollback-mode, a RESERVED or greater 
+-**      lock is held on the database file.
+-**    * If the connection is open in WAL-mode, a WAL write transaction
+-**      is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
+-**      called).
+-**    * The dbSize, dbOrigSize and dbFileSize variables are all valid.
+-**    * The contents of the pager cache have not been modified.
+-**    * The journal file may or may not be open.
+-**    * Nothing (not even the first header) has been written to the journal.
+-**
+-**  WRITER_CACHEMOD:
+-**
+-**    A pager moves from WRITER_LOCKED state to this state when a page is
+-**    first modified by the upper layer. In rollback mode the journal file
+-**    is opened (if it is not already open) and a header written to the
+-**    start of it. The database file on disk has not been modified.
+-**
+-**    * A write transaction is active.
+-**    * A RESERVED or greater lock is held on the database file.
+-**    * The journal file is open and the first header has been written 
+-**      to it, but the header has not been synced to disk.
+-**    * The contents of the page cache have been modified.
+-**
+-**  WRITER_DBMOD:
+-**
+-**    The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
+-**    when it modifies the contents of the database file. WAL connections
+-**    never enter this state (since they do not modify the database file,
+-**    just the log file).
+-**
+-**    * A write transaction is active.
+-**    * An EXCLUSIVE or greater lock is held on the database file.
+-**    * The journal file is open and the first header has been written 
+-**      and synced to disk.
+-**    * The contents of the page cache have been modified (and possibly
+-**      written to disk).
+-**
+-**  WRITER_FINISHED:
+-**
+-**    It is not possible for a WAL connection to enter this state.
+-**
+-**    A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
+-**    state after the entire transaction has been successfully written into the
+-**    database file. In this state the transaction may be committed simply
+-**    by finalizing the journal file. Once in WRITER_FINISHED state, it is 
+-**    not possible to modify the database further. At this point, the upper 
+-**    layer must either commit or rollback the transaction.
+-**
+-**    * A write transaction is active.
+-**    * An EXCLUSIVE or greater lock is held on the database file.
+-**    * All writing and syncing of journal and database data has finished.
+-**      If no error occurred, all that remains is to finalize the journal to
+-**      commit the transaction. If an error did occur, the caller will need
+-**      to rollback the transaction. 
+-**
+-**  ERROR:
+-**
+-**    The ERROR state is entered when an IO or disk-full error (including
+-**    SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it 
+-**    difficult to be sure that the in-memory pager state (cache contents, 
+-**    db size etc.) are consistent with the contents of the file-system.
+-**
+-**    Temporary pager files may enter the ERROR state, but in-memory pagers
+-**    cannot.
+-**
+-**    For example, if an IO error occurs while performing a rollback, 
+-**    the contents of the page-cache may be left in an inconsistent state.
+-**    At this point it would be dangerous to change back to READER state
+-**    (as usually happens after a rollback). Any subsequent readers might
+-**    report database corruption (due to the inconsistent cache), and if
+-**    they upgrade to writers, they may inadvertently corrupt the database
+-**    file. To avoid this hazard, the pager switches into the ERROR state
+-**    instead of READER following such an error.
+-**
+-**    Once it has entered the ERROR state, any attempt to use the pager
+-**    to read or write data returns an error. Eventually, once all 
+-**    outstanding transactions have been abandoned, the pager is able to
+-**    transition back to OPEN state, discarding the contents of the 
+-**    page-cache and any other in-memory state at the same time. Everything
+-**    is reloaded from disk (and, if necessary, hot-journal rollback peformed)
+-**    when a read-transaction is next opened on the pager (transitioning
+-**    the pager into READER state). At that point the system has recovered 
+-**    from the error.
+-**
+-**    Specifically, the pager jumps into the ERROR state if:
+-**
+-**      1. An error occurs while attempting a rollback. This happens in
+-**         function sqlite3PagerRollback().
+-**
+-**      2. An error occurs while attempting to finalize a journal file
+-**         following a commit in function sqlite3PagerCommitPhaseTwo().
++** This function is used by test procedures to inspect the internal state
++** of the global cache.
++*/
++SQLITE_PRIVATE void sqlite3PcacheStats(
++  int *pnCurrent,      /* OUT: Total number of pages cached */
++  int *pnMax,          /* OUT: Global maximum cache size */
++  int *pnMin,          /* OUT: Sum of PCache1.nMin for purgeable caches */
++  int *pnRecyclable    /* OUT: Total number of pages available for recycling */
++){
++  PgHdr1 *p;
++  int nRecyclable = 0;
++  for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
++    nRecyclable++;
++  }
++  *pnCurrent = pcache1.grp.nCurrentPage;
++  *pnMax = (int)pcache1.grp.nMaxPage;
++  *pnMin = (int)pcache1.grp.nMinPage;
++  *pnRecyclable = nRecyclable;
++}
++#endif
++
++/************** End of pcache1.c *********************************************/
++/************** Begin file rowset.c ******************************************/
++/*
++** 2008 December 3
+ **
+-**      3. An error occurs while attempting to write to the journal or
+-**         database file in function pagerStress() in order to free up
+-**         memory.
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
+ **
+-**    In other cases, the error is returned to the b-tree layer. The b-tree
+-**    layer then attempts a rollback operation. If the error condition 
+-**    persists, the pager enters the ERROR state via condition (1) above.
++**    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.
+ **
+-**    Condition (3) is necessary because it can be triggered by a read-only
+-**    statement executed within a transaction. In this case, if the error
+-**    code were simply returned to the user, the b-tree layer would not
+-**    automatically attempt a rollback, as it assumes that an error in a
+-**    read-only statement cannot leave the pager in an internally inconsistent 
+-**    state.
++*************************************************************************
+ **
+-**    * The Pager.errCode variable is set to something other than SQLITE_OK.
+-**    * There are one or more outstanding references to pages (after the
+-**      last reference is dropped the pager should move back to OPEN state).
+-**    * The pager is not an in-memory pager.
+-**    
++** This module implements an object we call a "RowSet".
+ **
+-** Notes:
++** The RowSet object is a collection of rowids.  Rowids
++** are inserted into the RowSet in an arbitrary order.  Inserts
++** can be intermixed with tests to see if a given rowid has been
++** previously inserted into the RowSet.
+ **
+-**   * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
+-**     connection is open in WAL mode. A WAL connection is always in one
+-**     of the first four states.
++** After all inserts are finished, it is possible to extract the
++** elements of the RowSet in sorted order.  Once this extraction
++** process has started, no new elements may be inserted.
+ **
+-**   * Normally, a connection open in exclusive mode is never in PAGER_OPEN
+-**     state. There are two exceptions: immediately after exclusive-mode has
+-**     been turned on (and before any read or write transactions are 
+-**     executed), and when the pager is leaving the "error state".
++** Hence, the primitive operations for a RowSet are:
+ **
+-**   * See also: assert_pager_state().
+-*/
+-#define PAGER_OPEN                  0
+-#define PAGER_READER                1
+-#define PAGER_WRITER_LOCKED         2
+-#define PAGER_WRITER_CACHEMOD       3
+-#define PAGER_WRITER_DBMOD          4
+-#define PAGER_WRITER_FINISHED       5
+-#define PAGER_ERROR                 6
+-
+-/*
+-** The Pager.eLock variable is almost always set to one of the 
+-** following locking-states, according to the lock currently held on
+-** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
+-** This variable is kept up to date as locks are taken and released by
+-** the pagerLockDb() and pagerUnlockDb() wrappers.
++**    CREATE
++**    INSERT
++**    TEST
++**    SMALLEST
++**    DESTROY
+ **
+-** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
+-** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
+-** the operation was successful. In these circumstances pagerLockDb() and
+-** pagerUnlockDb() take a conservative approach - eLock is always updated
+-** when unlocking the file, and only updated when locking the file if the
+-** VFS call is successful. This way, the Pager.eLock variable may be set
+-** to a less exclusive (lower) value than the lock that is actually held
+-** at the system level, but it is never set to a more exclusive value.
++** The CREATE and DESTROY primitives are the constructor and destructor,
++** obviously.  The INSERT primitive adds a new element to the RowSet.
++** TEST checks to see if an element is already in the RowSet.  SMALLEST
++** extracts the least value from the RowSet.
+ **
+-** This is usually safe. If an xUnlock fails or appears to fail, there may 
+-** be a few redundant xLock() calls or a lock may be held for longer than
+-** required, but nothing really goes wrong.
++** The INSERT primitive might allocate additional memory.  Memory is
++** allocated in chunks so most INSERTs do no allocation.  There is an 
++** upper bound on the size of allocated memory.  No memory is freed
++** until DESTROY.
+ **
+-** The exception is when the database file is unlocked as the pager moves
+-** from ERROR to OPEN state. At this point there may be a hot-journal file 
+-** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
+-** transition, by the same pager or any other). If the call to xUnlock()
+-** fails at this point and the pager is left holding an EXCLUSIVE lock, this
+-** can confuse the call to xCheckReservedLock() call made later as part
+-** of hot-journal detection.
++** The TEST primitive includes a "batch" number.  The TEST primitive
++** will only see elements that were inserted before the last change
++** in the batch number.  In other words, if an INSERT occurs between
++** two TESTs where the TESTs have the same batch nubmer, then the
++** value added by the INSERT will not be visible to the second TEST.
++** The initial batch number is zero, so if the very first TEST contains
++** a non-zero batch number, it will see all prior INSERTs.
+ **
+-** xCheckReservedLock() is defined as returning true "if there is a RESERVED 
+-** lock held by this process or any others". So xCheckReservedLock may 
+-** return true because the caller itself is holding an EXCLUSIVE lock (but
+-** doesn't know it because of a previous error in xUnlock). If this happens
+-** a hot-journal may be mistaken for a journal being created by an active
+-** transaction in another process, causing SQLite to read from the database
+-** without rolling it back.
++** No INSERTs may occurs after a SMALLEST.  An assertion will fail if
++** that is attempted.
+ **
+-** To work around this, if a call to xUnlock() fails when unlocking the
+-** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
+-** is only changed back to a real locking state after a successful call
+-** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
+-** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK 
+-** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
+-** lock on the database file before attempting to roll it back. See function
+-** PagerSharedLock() for more detail.
++** The cost of an INSERT is roughly constant.  (Sometime new memory
++** has to be allocated on an INSERT.)  The cost of a TEST with a new
++** batch number is O(NlogN) where N is the number of elements in the RowSet.
++** The cost of a TEST using the same batch number is O(logN).  The cost
++** of the first SMALLEST is O(NlogN).  Second and subsequent SMALLEST
++** primitives are constant time.  The cost of DESTROY is O(N).
+ **
+-** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in 
+-** PAGER_OPEN state.
++** There is an added cost of O(N) when switching between TEST and
++** SMALLEST primitives.
+ */
+-#define UNKNOWN_LOCK                (EXCLUSIVE_LOCK+1)
++
+ 
+ /*
+-** A macro used for invoking the codec if there is one
++** Target size for allocation chunks.
+ */
+-#ifdef SQLITE_HAS_CODEC
+-# define CODEC1(P,D,N,X,E) \
+-    if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
+-# define CODEC2(P,D,N,X,E,O) \
+-    if( P->xCodec==0 ){ O=(char*)D; }else \
+-    if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
+-#else
+-# define CODEC1(P,D,N,X,E)   /* NO-OP */
+-# define CODEC2(P,D,N,X,E,O) O=(char*)D
+-#endif
++#define ROWSET_ALLOCATION_SIZE 1024
+ 
+ /*
+-** The maximum allowed sector size. 64KiB. If the xSectorsize() method 
+-** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
+-** This could conceivably cause corruption following a power failure on
+-** such a system. This is currently an undocumented limit.
++** The number of rowset entries per allocation chunk.
+ */
+-#define MAX_SECTOR_SIZE 0x10000
++#define ROWSET_ENTRY_PER_CHUNK  \
++                       ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
+ 
+ /*
+-** An instance of the following structure is allocated for each active
+-** savepoint and statement transaction in the system. All such structures
+-** are stored in the Pager.aSavepoint[] array, which is allocated and
+-** resized using sqlite3Realloc().
++** Each entry in a RowSet is an instance of the following object.
+ **
+-** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
+-** set to 0. If a journal-header is written into the main journal while
+-** the savepoint is active, then iHdrOffset is set to the byte offset 
+-** immediately following the last journal record written into the main
+-** journal before the journal-header. This is required during savepoint
+-** rollback (see pagerPlaybackSavepoint()).
++** This same object is reused to store a linked list of trees of RowSetEntry
++** objects.  In that alternative use, pRight points to the next entry
++** in the list, pLeft points to the tree, and v is unused.  The
++** RowSet.pForest value points to the head of this forest list.
+ */
+-typedef struct PagerSavepoint PagerSavepoint;
+-struct PagerSavepoint {
+-  i64 iOffset;                 /* Starting offset in main journal */
+-  i64 iHdrOffset;              /* See above */
+-  Bitvec *pInSavepoint;        /* Set of pages in this savepoint */
+-  Pgno nOrig;                  /* Original number of pages in file */
+-  Pgno iSubRec;                /* Index of first record in sub-journal */
+-#ifndef SQLITE_OMIT_WAL
+-  u32 aWalData[WAL_SAVEPOINT_NDATA];        /* WAL savepoint context */
+-#endif
++struct RowSetEntry {            
++  i64 v;                        /* ROWID value for this entry */
++  struct RowSetEntry *pRight;   /* Right subtree (larger entries) or list */
++  struct RowSetEntry *pLeft;    /* Left subtree (smaller entries) */
+ };
+ 
+ /*
+-** A open page cache is an instance of struct Pager. A description of
+-** some of the more important member variables follows:
+-**
+-** eState
+-**
+-**   The current 'state' of the pager object. See the comment and state
+-**   diagram above for a description of the pager state.
+-**
+-** eLock
+-**
+-**   For a real on-disk database, the current lock held on the database file -
+-**   NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
+-**
+-**   For a temporary or in-memory database (neither of which require any
+-**   locks), this variable is always set to EXCLUSIVE_LOCK. Since such
+-**   databases always have Pager.exclusiveMode==1, this tricks the pager
+-**   logic into thinking that it already has all the locks it will ever
+-**   need (and no reason to release them).
+-**
+-**   In some (obscure) circumstances, this variable may also be set to
+-**   UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
+-**   details.
+-**
+-** changeCountDone
+-**
+-**   This boolean variable is used to make sure that the change-counter 
+-**   (the 4-byte header field at byte offset 24 of the database file) is 
+-**   not updated more often than necessary. 
+-**
+-**   It is set to true when the change-counter field is updated, which 
+-**   can only happen if an exclusive lock is held on the database file.
+-**   It is cleared (set to false) whenever an exclusive lock is 
+-**   relinquished on the database file. Each time a transaction is committed,
+-**   The changeCountDone flag is inspected. If it is true, the work of
+-**   updating the change-counter is omitted for the current transaction.
+-**
+-**   This mechanism means that when running in exclusive mode, a connection 
+-**   need only update the change-counter once, for the first transaction
+-**   committed.
+-**
+-** setMaster
+-**
+-**   When PagerCommitPhaseOne() is called to commit a transaction, it may
+-**   (or may not) specify a master-journal name to be written into the 
+-**   journal file before it is synced to disk.
+-**
+-**   Whether or not a journal file contains a master-journal pointer affects 
+-**   the way in which the journal file is finalized after the transaction is 
+-**   committed or rolled back when running in "journal_mode=PERSIST" mode.
+-**   If a journal file does not contain a master-journal pointer, it is
+-**   finalized by overwriting the first journal header with zeroes. If
+-**   it does contain a master-journal pointer the journal file is finalized 
+-**   by truncating it to zero bytes, just as if the connection were 
+-**   running in "journal_mode=truncate" mode.
+-**
+-**   Journal files that contain master journal pointers cannot be finalized
+-**   simply by overwriting the first journal-header with zeroes, as the
+-**   master journal pointer could interfere with hot-journal rollback of any
+-**   subsequently interrupted transaction that reuses the journal file.
+-**
+-**   The flag is cleared as soon as the journal file is finalized (either
+-**   by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
+-**   journal file from being successfully finalized, the setMaster flag
+-**   is cleared anyway (and the pager will move to ERROR state).
+-**
+-** doNotSpill, doNotSyncSpill
++** RowSetEntry objects are allocated in large chunks (instances of the
++** following structure) to reduce memory allocation overhead.  The
++** chunks are kept on a linked list so that they can be deallocated
++** when the RowSet is destroyed.
++*/
++struct RowSetChunk {
++  struct RowSetChunk *pNextChunk;        /* Next chunk on list of them all */
++  struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
++};
++
++/*
++** A RowSet in an instance of the following structure.
+ **
+-**   These two boolean variables control the behavior of cache-spills
+-**   (calls made by the pcache module to the pagerStress() routine to
+-**   write cached data to the file-system in order to free up memory).
++** A typedef of this structure if found in sqliteInt.h.
++*/
++struct RowSet {
++  struct RowSetChunk *pChunk;    /* List of all chunk allocations */
++  sqlite3 *db;                   /* The database connection */
++  struct RowSetEntry *pEntry;    /* List of entries using pRight */
++  struct RowSetEntry *pLast;     /* Last entry on the pEntry list */
++  struct RowSetEntry *pFresh;    /* Source of new entry objects */
++  struct RowSetEntry *pForest;   /* List of binary trees of entries */
++  u16 nFresh;                    /* Number of objects on pFresh */
++  u8 rsFlags;                    /* Various flags */
++  u8 iBatch;                     /* Current insert batch */
++};
++
++/*
++** Allowed values for RowSet.rsFlags
++*/
++#define ROWSET_SORTED  0x01   /* True if RowSet.pEntry is sorted */
++#define ROWSET_NEXT    0x02   /* True if sqlite3RowSetNext() has been called */
++
++/*
++** Turn bulk memory into a RowSet object.  N bytes of memory
++** are available at pSpace.  The db pointer is used as a memory context
++** for any subsequent allocations that need to occur.
++** Return a pointer to the new RowSet object.
+ **
+-**   When doNotSpill is non-zero, writing to the database from pagerStress()
+-**   is disabled altogether. This is done in a very obscure case that
+-**   comes up during savepoint rollback that requires the pcache module
+-**   to allocate a new page to prevent the journal file from being written
+-**   while it is being traversed by code in pager_playback().
++** It must be the case that N is sufficient to make a Rowset.  If not
++** an assertion fault occurs.
+ ** 
+-**   If doNotSyncSpill is non-zero, writing to the database from pagerStress()
+-**   is permitted, but syncing the journal file is not. This flag is set
+-**   by sqlite3PagerWrite() when the file-system sector-size is larger than
+-**   the database page-size in order to prevent a journal sync from happening 
+-**   in between the journalling of two pages on the same sector. 
+-**
+-** subjInMemory
+-**
+-**   This is a boolean variable. If true, then any required sub-journal
+-**   is opened as an in-memory journal file. If false, then in-memory
+-**   sub-journals are only used for in-memory pager files.
+-**
+-**   This variable is updated by the upper layer each time a new 
+-**   write-transaction is opened.
+-**
+-** dbSize, dbOrigSize, dbFileSize
+-**
+-**   Variable dbSize is set to the number of pages in the database file.
+-**   It is valid in PAGER_READER and higher states (all states except for
+-**   OPEN and ERROR). 
+-**
+-**   dbSize is set based on the size of the database file, which may be 
+-**   larger than the size of the database (the value stored at offset
+-**   28 of the database header by the btree). If the size of the file
+-**   is not an integer multiple of the page-size, the value stored in
+-**   dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
+-**   Except, any file that is greater than 0 bytes in size is considered
+-**   to have at least one page. (i.e. a 1KB file with 2K page-size leads
+-**   to dbSize==1).
+-**
+-**   During a write-transaction, if pages with page-numbers greater than
+-**   dbSize are modified in the cache, dbSize is updated accordingly.
+-**   Similarly, if the database is truncated using PagerTruncateImage(), 
+-**   dbSize is updated.
+-**
+-**   Variables dbOrigSize and dbFileSize are valid in states 
+-**   PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
+-**   variable at the start of the transaction. It is used during rollback,
+-**   and to determine whether or not pages need to be journalled before
+-**   being modified.
+-**
+-**   Throughout a write-transaction, dbFileSize contains the size of
+-**   the file on disk in pages. It is set to a copy of dbSize when the
+-**   write-transaction is first opened, and updated when VFS calls are made
+-**   to write or truncate the database file on disk. 
+-**
+-**   The only reason the dbFileSize variable is required is to suppress 
+-**   unnecessary calls to xTruncate() after committing a transaction. If, 
+-**   when a transaction is committed, the dbFileSize variable indicates 
+-**   that the database file is larger than the database image (Pager.dbSize), 
+-**   pager_truncate() is called. The pager_truncate() call uses xFilesize()
+-**   to measure the database file on disk, and then truncates it if required.
+-**   dbFileSize is not used when rolling back a transaction. In this case
+-**   pager_truncate() is called unconditionally (which means there may be
+-**   a call to xFilesize() that is not strictly required). In either case,
+-**   pager_truncate() may cause the file to become smaller or larger.
+-**
+-** dbHintSize
+-**
+-**   The dbHintSize variable is used to limit the number of calls made to
+-**   the VFS xFileControl(FCNTL_SIZE_HINT) method. 
+-**
+-**   dbHintSize is set to a copy of the dbSize variable when a
+-**   write-transaction is opened (at the same time as dbFileSize and
+-**   dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
+-**   dbHintSize is increased to the number of pages that correspond to the
+-**   size-hint passed to the method call. See pager_write_pagelist() for 
+-**   details.
+-**
+-** errCode
++** If N is larger than the minimum, use the surplus as an initial
++** allocation of entries available to be filled.
++*/
++SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
++  RowSet *p;
++  assert( N >= ROUND8(sizeof(*p)) );
++  p = pSpace;
++  p->pChunk = 0;
++  p->db = db;
++  p->pEntry = 0;
++  p->pLast = 0;
++  p->pForest = 0;
++  p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
++  p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
++  p->rsFlags = ROWSET_SORTED;
++  p->iBatch = 0;
++  return p;
++}
++
++/*
++** Deallocate all chunks from a RowSet.  This frees all memory that
++** the RowSet has allocated over its lifetime.  This routine is
++** the destructor for the RowSet.
++*/
++SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
++  struct RowSetChunk *pChunk, *pNextChunk;
++  for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
++    pNextChunk = pChunk->pNextChunk;
++    sqlite3DbFree(p->db, pChunk);
++  }
++  p->pChunk = 0;
++  p->nFresh = 0;
++  p->pEntry = 0;
++  p->pLast = 0;
++  p->pForest = 0;
++  p->rsFlags = ROWSET_SORTED;
++}
++
++/*
++** Allocate a new RowSetEntry object that is associated with the
++** given RowSet.  Return a pointer to the new and completely uninitialized
++** objected.
+ **
+-**   The Pager.errCode variable is only ever used in PAGER_ERROR state. It
+-**   is set to zero in all other states. In PAGER_ERROR state, Pager.errCode 
+-**   is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX 
+-**   sub-codes.
++** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
++** routine returns NULL.
+ */
+-struct Pager {
+-  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
+-  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
+-  u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
+-  u8 useJournal;              /* Use a rollback journal on this file */
+-  u8 noSync;                  /* Do not sync the journal if true */
+-  u8 fullSync;                /* Do extra syncs of the journal for robustness */
+-  u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
+-  u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
+-  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
+-  u8 tempFile;                /* zFilename is a temporary file */
+-  u8 readOnly;                /* True for a read-only database */
+-  u8 memDb;                   /* True to inhibit all file I/O */
++static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
++  assert( p!=0 );
++  if( p->nFresh==0 ){
++    struct RowSetChunk *pNew;
++    pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
++    if( pNew==0 ){
++      return 0;
++    }
++    pNew->pNextChunk = p->pChunk;
++    p->pChunk = pNew;
++    p->pFresh = pNew->aEntry;
++    p->nFresh = ROWSET_ENTRY_PER_CHUNK;
++  }
++  p->nFresh--;
++  return p->pFresh++;
++}
+ 
+-  /**************************************************************************
+-  ** The following block contains those class members that change during
+-  ** routine opertion.  Class members not in this block are either fixed
+-  ** when the pager is first created or else only change when there is a
+-  ** significant mode change (such as changing the page_size, locking_mode,
+-  ** or the journal_mode).  From another view, these class members describe
+-  ** the "state" of the pager, while other class members describe the
+-  ** "configuration" of the pager.
+-  */
+-  u8 eState;                  /* Pager state (OPEN, READER, WRITER_LOCKED..) */
+-  u8 eLock;                   /* Current lock held on database file */
+-  u8 changeCountDone;         /* Set after incrementing the change-counter */
+-  u8 setMaster;               /* True if a m-j name has been written to jrnl */
+-  u8 doNotSpill;              /* Do not spill the cache when non-zero */
+-  u8 doNotSyncSpill;          /* Do not do a spill that requires jrnl sync */
+-  u8 subjInMemory;            /* True to use in-memory sub-journals */
+-  Pgno dbSize;                /* Number of pages in the database */
+-  Pgno dbOrigSize;            /* dbSize before the current transaction */
+-  Pgno dbFileSize;            /* Number of pages in the database file */
+-  Pgno dbHintSize;            /* Value passed to FCNTL_SIZE_HINT call */
+-  int errCode;                /* One of several kinds of errors */
+-  int nRec;                   /* Pages journalled since last j-header written */
+-  u32 cksumInit;              /* Quasi-random value added to every checksum */
+-  u32 nSubRec;                /* Number of records written to sub-journal */
+-  Bitvec *pInJournal;         /* One bit for each page in the database file */
+-  sqlite3_file *fd;           /* File descriptor for database */
+-  sqlite3_file *jfd;          /* File descriptor for main journal */
+-  sqlite3_file *sjfd;         /* File descriptor for sub-journal */
+-  i64 journalOff;             /* Current write offset in the journal file */
+-  i64 journalHdr;             /* Byte offset to previous journal header */
+-  sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
+-  PagerSavepoint *aSavepoint; /* Array of active savepoints */
+-  int nSavepoint;             /* Number of elements in aSavepoint[] */
+-  char dbFileVers[16];        /* Changes whenever database file changes */
++/*
++** Insert a new value into a RowSet.
++**
++** The mallocFailed flag of the database connection is set if a
++** memory allocation fails.
++*/
++SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
++  struct RowSetEntry *pEntry;  /* The new entry */
++  struct RowSetEntry *pLast;   /* The last prior entry */
+ 
+-  u8 bUseFetch;               /* True to use xFetch() */
+-  int nMmapOut;               /* Number of mmap pages currently outstanding */
+-  sqlite3_int64 szMmap;       /* Desired maximum mmap size */
+-  PgHdr *pMmapFreelist;       /* List of free mmap page headers (pDirty) */
+-  /*
+-  ** End of the routinely-changing class members
+-  ***************************************************************************/
++  /* This routine is never called after sqlite3RowSetNext() */
++  assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
+ 
+-  u16 nExtra;                 /* Add this many bytes to each in-memory page */
+-  i16 nReserve;               /* Number of unused bytes at end of each page */
+-  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
+-  u32 sectorSize;             /* Assumed sector size during rollback */
+-  int pageSize;               /* Number of bytes in a page */
+-  Pgno mxPgno;                /* Maximum allowed size of the database */
+-  i64 journalSizeLimit;       /* Size limit for persistent journal files */
+-  char *zFilename;            /* Name of the database file */
+-  char *zJournal;             /* Name of the journal file */
+-  int (*xBusyHandler)(void*); /* Function to call when busy */
+-  void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
+-  int aStat[3];               /* Total cache hits, misses and writes */
+-#ifdef SQLITE_TEST
+-  int nRead;                  /* Database pages read */
+-#endif
+-  void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
+-#ifdef SQLITE_HAS_CODEC
+-  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
+-  void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
+-  void (*xCodecFree)(void*);             /* Destructor for the codec */
+-  void *pCodec;               /* First argument to xCodec... methods */
+-#endif
+-  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
+-  PCache *pPCache;            /* Pointer to page cache object */
+-#ifndef SQLITE_OMIT_WAL
+-  Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
+-  char *zWal;                 /* File name for write-ahead log */
+-#endif
+-};
++  pEntry = rowSetEntryAlloc(p);
++  if( pEntry==0 ) return;
++  pEntry->v = rowid;
++  pEntry->pRight = 0;
++  pLast = p->pLast;
++  if( pLast ){
++    if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
++      p->rsFlags &= ~ROWSET_SORTED;
++    }
++    pLast->pRight = pEntry;
++  }else{
++    p->pEntry = pEntry;
++  }
++  p->pLast = pEntry;
++}
+ 
+ /*
+-** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
+-** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS 
+-** or CACHE_WRITE to sqlite3_db_status().
++** Merge two lists of RowSetEntry objects.  Remove duplicates.
++**
++** The input lists are connected via pRight pointers and are 
++** assumed to each already be in sorted order.
+ */
+-#define PAGER_STAT_HIT   0
+-#define PAGER_STAT_MISS  1
+-#define PAGER_STAT_WRITE 2
++static struct RowSetEntry *rowSetEntryMerge(
++  struct RowSetEntry *pA,    /* First sorted list to be merged */
++  struct RowSetEntry *pB     /* Second sorted list to be merged */
++){
++  struct RowSetEntry head;
++  struct RowSetEntry *pTail;
++
++  pTail = &head;
++  while( pA && pB ){
++    assert( pA->pRight==0 || pA->v<=pA->pRight->v );
++    assert( pB->pRight==0 || pB->v<=pB->pRight->v );
++    if( pA->v<pB->v ){
++      pTail->pRight = pA;
++      pA = pA->pRight;
++      pTail = pTail->pRight;
++    }else if( pB->v<pA->v ){
++      pTail->pRight = pB;
++      pB = pB->pRight;
++      pTail = pTail->pRight;
++    }else{
++      pA = pA->pRight;
++    }
++  }
++  if( pA ){
++    assert( pA->pRight==0 || pA->v<=pA->pRight->v );
++    pTail->pRight = pA;
++  }else{
++    assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v );
++    pTail->pRight = pB;
++  }
++  return head.pRight;
++}
+ 
+ /*
+-** The following global variables hold counters used for
+-** testing purposes only.  These variables do not exist in
+-** a non-testing build.  These variables are not thread-safe.
+-*/
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */
+-SQLITE_API int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */
+-SQLITE_API int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */
+-# define PAGER_INCR(v)  v++
+-#else
+-# define PAGER_INCR(v)
+-#endif
++** Sort all elements on the list of RowSetEntry objects into order of
++** increasing v.
++*/ 
++static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
++  unsigned int i;
++  struct RowSetEntry *pNext, *aBucket[40];
+ 
++  memset(aBucket, 0, sizeof(aBucket));
++  while( pIn ){
++    pNext = pIn->pRight;
++    pIn->pRight = 0;
++    for(i=0; aBucket[i]; i++){
++      pIn = rowSetEntryMerge(aBucket[i], pIn);
++      aBucket[i] = 0;
++    }
++    aBucket[i] = pIn;
++    pIn = pNext;
++  }
++  pIn = 0;
++  for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
++    pIn = rowSetEntryMerge(pIn, aBucket[i]);
++  }
++  return pIn;
++}
+ 
+ 
+ /*
+-** Journal files begin with the following magic string.  The data
+-** was obtained from /dev/random.  It is used only as a sanity check.
+-**
+-** Since version 2.8.0, the journal format contains additional sanity
+-** checking information.  If the power fails while the journal is being
+-** written, semi-random garbage data might appear in the journal
+-** file after power is restored.  If an attempt is then made
+-** to roll the journal back, the database could be corrupted.  The additional
+-** sanity checking data is an attempt to discover the garbage in the
+-** journal and ignore it.
+-**
+-** The sanity checking information for the new journal format consists
+-** of a 32-bit checksum on each page of data.  The checksum covers both
+-** the page number and the pPager->pageSize bytes of data for the page.
+-** This cksum is initialized to a 32-bit random value that appears in the
+-** journal file right after the header.  The random initializer is important,
+-** because garbage data that appears at the end of a journal is likely
+-** data that was once in other files that have now been deleted.  If the
+-** garbage data came from an obsolete journal file, the checksums might
+-** be correct.  But by initializing the checksum to random value which
+-** is different for every journal, we minimize that risk.
++** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
++** Convert this tree into a linked list connected by the pRight pointers
++** and return pointers to the first and last elements of the new list.
+ */
+-static const unsigned char aJournalMagic[] = {
+-  0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
+-};
++static void rowSetTreeToList(
++  struct RowSetEntry *pIn,         /* Root of the input tree */
++  struct RowSetEntry **ppFirst,    /* Write head of the output list here */
++  struct RowSetEntry **ppLast      /* Write tail of the output list here */
++){
++  assert( pIn!=0 );
++  if( pIn->pLeft ){
++    struct RowSetEntry *p;
++    rowSetTreeToList(pIn->pLeft, ppFirst, &p);
++    p->pRight = pIn;
++  }else{
++    *ppFirst = pIn;
++  }
++  if( pIn->pRight ){
++    rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
++  }else{
++    *ppLast = pIn;
++  }
++  assert( (*ppLast)->pRight==0 );
++}
+ 
+-/*
+-** The size of the of each page record in the journal is given by
+-** the following macro.
+-*/
+-#define JOURNAL_PG_SZ(pPager)  ((pPager->pageSize) + 8)
+ 
+ /*
+-** The journal header size for this pager. This is usually the same 
+-** size as a single disk sector. See also setSectorSize().
++** Convert a sorted list of elements (connected by pRight) into a binary
++** tree with depth of iDepth.  A depth of 1 means the tree contains a single
++** node taken from the head of *ppList.  A depth of 2 means a tree with
++** three nodes.  And so forth.
++**
++** Use as many entries from the input list as required and update the
++** *ppList to point to the unused elements of the list.  If the input
++** list contains too few elements, then construct an incomplete tree
++** and leave *ppList set to NULL.
++**
++** Return a pointer to the root of the constructed binary tree.
+ */
+-#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
++static struct RowSetEntry *rowSetNDeepTree(
++  struct RowSetEntry **ppList,
++  int iDepth
++){
++  struct RowSetEntry *p;         /* Root of the new tree */
++  struct RowSetEntry *pLeft;     /* Left subtree */
++  if( *ppList==0 ){
++    return 0;
++  }
++  if( iDepth==1 ){
++    p = *ppList;
++    *ppList = p->pRight;
++    p->pLeft = p->pRight = 0;
++    return p;
++  }
++  pLeft = rowSetNDeepTree(ppList, iDepth-1);
++  p = *ppList;
++  if( p==0 ){
++    return pLeft;
++  }
++  p->pLeft = pLeft;
++  *ppList = p->pRight;
++  p->pRight = rowSetNDeepTree(ppList, iDepth-1);
++  return p;
++}
+ 
+ /*
+-** The macro MEMDB is true if we are dealing with an in-memory database.
+-** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
+-** the value of MEMDB will be a constant and the compiler will optimize
+-** out code that would never execute.
++** Convert a sorted list of elements into a binary tree. Make the tree
++** as deep as it needs to be in order to contain the entire list.
+ */
+-#ifdef SQLITE_OMIT_MEMORYDB
+-# define MEMDB 0
+-#else
+-# define MEMDB pPager->memDb
+-#endif
++static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
++  int iDepth;           /* Depth of the tree so far */
++  struct RowSetEntry *p;       /* Current tree root */
++  struct RowSetEntry *pLeft;   /* Left subtree */
+ 
+-/*
+-** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
+-** interfaces to access the database using memory-mapped I/O.
+-*/
+-#if SQLITE_MAX_MMAP_SIZE>0
+-# define USEFETCH(x) ((x)->bUseFetch)
+-#else
+-# define USEFETCH(x) 0
+-#endif
++  assert( pList!=0 );
++  p = pList;
++  pList = p->pRight;
++  p->pLeft = p->pRight = 0;
++  for(iDepth=1; pList; iDepth++){
++    pLeft = p;
++    p = pList;
++    pList = p->pRight;
++    p->pLeft = pLeft;
++    p->pRight = rowSetNDeepTree(&pList, iDepth);
++  }
++  return p;
++}
+ 
+ /*
+-** The maximum legal page number is (2^31 - 1).
++** Take all the entries on p->pEntry and on the trees in p->pForest and
++** sort them all together into one big ordered list on p->pEntry.
++**
++** This routine should only be called once in the life of a RowSet.
+ */
+-#define PAGER_MAX_PGNO 2147483647
++static void rowSetToList(RowSet *p){
++
++  /* This routine is called only once */
++  assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
++
++  if( (p->rsFlags & ROWSET_SORTED)==0 ){
++    p->pEntry = rowSetEntrySort(p->pEntry);
++  }
++
++  /* While this module could theoretically support it, sqlite3RowSetNext()
++  ** is never called after sqlite3RowSetText() for the same RowSet.  So
++  ** there is never a forest to deal with.  Should this change, simply
++  ** remove the assert() and the #if 0. */
++  assert( p->pForest==0 );
++#if 0
++  while( p->pForest ){
++    struct RowSetEntry *pTree = p->pForest->pLeft;
++    if( pTree ){
++      struct RowSetEntry *pHead, *pTail;
++      rowSetTreeToList(pTree, &pHead, &pTail);
++      p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
++    }
++    p->pForest = p->pForest->pRight;
++  }
++#endif
++  p->rsFlags |= ROWSET_NEXT;  /* Verify this routine is never called again */
++}
+ 
+ /*
+-** The argument to this macro is a file descriptor (type sqlite3_file*).
+-** Return 0 if it is not open, or non-zero (but not 1) if it is.
+-**
+-** This is so that expressions can be written as:
+-**
+-**   if( isOpen(pPager->jfd) ){ ...
+-**
+-** instead of
++** Extract the smallest element from the RowSet.
++** Write the element into *pRowid.  Return 1 on success.  Return
++** 0 if the RowSet is already empty.
+ **
+-**   if( pPager->jfd->pMethods ){ ...
++** After this routine has been called, the sqlite3RowSetInsert()
++** routine may not be called again.  
+ */
+-#define isOpen(pFd) ((pFd)->pMethods)
++SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
++  assert( p!=0 );
+ 
+-/*
+-** Return true if this pager uses a write-ahead log instead of the usual
+-** rollback journal. Otherwise false.
+-*/
+-#ifndef SQLITE_OMIT_WAL
+-static int pagerUseWal(Pager *pPager){
+-  return (pPager->pWal!=0);
++  /* Merge the forest into a single sorted list on first call */
++  if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
++
++  /* Return the next entry on the list */
++  if( p->pEntry ){
++    *pRowid = p->pEntry->v;
++    p->pEntry = p->pEntry->pRight;
++    if( p->pEntry==0 ){
++      sqlite3RowSetClear(p);
++    }
++    return 1;
++  }else{
++    return 0;
++  }
+ }
+-#else
+-# define pagerUseWal(x) 0
+-# define pagerRollbackWal(x) 0
+-# define pagerWalFrames(v,w,x,y) 0
+-# define pagerOpenWalIfPresent(z) SQLITE_OK
+-# define pagerBeginReadTransaction(z) SQLITE_OK
+-#endif
+ 
+-#ifndef NDEBUG 
+ /*
+-** Usage:
+-**
+-**   assert( assert_pager_state(pPager) );
++** Check to see if element iRowid was inserted into the rowset as
++** part of any insert batch prior to iBatch.  Return 1 or 0.
+ **
+-** This function runs many asserts to try to find inconsistencies in
+-** the internal state of the Pager object.
++** If this is the first test of a new batch and if there exist entires
++** on pRowSet->pEntry, then sort those entires into the forest at
++** pRowSet->pForest so that they can be tested.
+ */
+-static int assert_pager_state(Pager *p){
+-  Pager *pPager = p;
+-
+-  /* State must be valid. */
+-  assert( p->eState==PAGER_OPEN
+-       || p->eState==PAGER_READER
+-       || p->eState==PAGER_WRITER_LOCKED
+-       || p->eState==PAGER_WRITER_CACHEMOD
+-       || p->eState==PAGER_WRITER_DBMOD
+-       || p->eState==PAGER_WRITER_FINISHED
+-       || p->eState==PAGER_ERROR
+-  );
++SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
++  struct RowSetEntry *p, *pTree;
+ 
+-  /* Regardless of the current state, a temp-file connection always behaves
+-  ** as if it has an exclusive lock on the database file. It never updates
+-  ** the change-counter field, so the changeCountDone flag is always set.
+-  */
+-  assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
+-  assert( p->tempFile==0 || pPager->changeCountDone );
++  /* This routine is never called after sqlite3RowSetNext() */
++  assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
+ 
+-  /* If the useJournal flag is clear, the journal-mode must be "OFF". 
+-  ** And if the journal-mode is "OFF", the journal file must not be open.
++  /* Sort entries into the forest on the first test of a new batch 
+   */
+-  assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
+-  assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
++  if( iBatch!=pRowSet->iBatch ){
++    p = pRowSet->pEntry;
++    if( p ){
++      struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
++      if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
++        p = rowSetEntrySort(p);
++      }
++      for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
++        ppPrevTree = &pTree->pRight;
++        if( pTree->pLeft==0 ){
++          pTree->pLeft = rowSetListToTree(p);
++          break;
++        }else{
++          struct RowSetEntry *pAux, *pTail;
++          rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
++          pTree->pLeft = 0;
++          p = rowSetEntryMerge(pAux, p);
++        }
++      }
++      if( pTree==0 ){
++        *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
++        if( pTree ){
++          pTree->v = 0;
++          pTree->pRight = 0;
++          pTree->pLeft = rowSetListToTree(p);
++        }
++      }
++      pRowSet->pEntry = 0;
++      pRowSet->pLast = 0;
++      pRowSet->rsFlags |= ROWSET_SORTED;
++    }
++    pRowSet->iBatch = iBatch;
++  }
+ 
+-  /* Check that MEMDB implies noSync. And an in-memory journal. Since 
+-  ** this means an in-memory pager performs no IO at all, it cannot encounter 
+-  ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing 
+-  ** a journal file. (although the in-memory journal implementation may 
+-  ** return SQLITE_IOERR_NOMEM while the journal file is being written). It 
+-  ** is therefore not possible for an in-memory pager to enter the ERROR 
+-  ** state.
++  /* Test to see if the iRowid value appears anywhere in the forest.
++  ** Return 1 if it does and 0 if not.
+   */
+-  if( MEMDB ){
+-    assert( p->noSync );
+-    assert( p->journalMode==PAGER_JOURNALMODE_OFF 
+-         || p->journalMode==PAGER_JOURNALMODE_MEMORY 
+-    );
+-    assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
+-    assert( pagerUseWal(p)==0 );
++  for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
++    p = pTree->pLeft;
++    while( p ){
++      if( p->v<iRowid ){
++        p = p->pRight;
++      }else if( p->v>iRowid ){
++        p = p->pLeft;
++      }else{
++        return 1;
++      }
++    }
+   }
++  return 0;
++}
+ 
+-  /* If changeCountDone is set, a RESERVED lock or greater must be held
+-  ** on the file.
+-  */
+-  assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
+-  assert( p->eLock!=PENDING_LOCK );
++/************** End of rowset.c **********************************************/
++/************** Begin file pager.c *******************************************/
++/*
++** 2001 September 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 is the implementation of the page cache subsystem or "pager".
++** 
++** The pager is used to access a database disk file.  It implements
++** atomic commit and rollback through the use of a journal file that
++** is separate from the database file.  The pager also implements file
++** locking to prevent two processes from writing the same database
++** file simultaneously, or one process from reading the database while
++** another is writing.
++*/
++#ifndef SQLITE_OMIT_DISKIO
++/************** Include wal.h in the middle of pager.c ***********************/
++/************** Begin file wal.h *********************************************/
++/*
++** 2010 February 1
++**
++** 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 header file defines the interface to the write-ahead logging 
++** system. Refer to the comments below and the header comment attached to 
++** the implementation of each function in log.c for further details.
++*/
+ 
+-  switch( p->eState ){
+-    case PAGER_OPEN:
+-      assert( !MEMDB );
+-      assert( pPager->errCode==SQLITE_OK );
+-      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
+-      break;
++#ifndef _WAL_H_
++#define _WAL_H_
+ 
+-    case PAGER_READER:
+-      assert( pPager->errCode==SQLITE_OK );
+-      assert( p->eLock!=UNKNOWN_LOCK );
+-      assert( p->eLock>=SHARED_LOCK );
+-      break;
+ 
+-    case PAGER_WRITER_LOCKED:
+-      assert( p->eLock!=UNKNOWN_LOCK );
+-      assert( pPager->errCode==SQLITE_OK );
+-      if( !pagerUseWal(pPager) ){
+-        assert( p->eLock>=RESERVED_LOCK );
+-      }
+-      assert( pPager->dbSize==pPager->dbOrigSize );
+-      assert( pPager->dbOrigSize==pPager->dbFileSize );
+-      assert( pPager->dbOrigSize==pPager->dbHintSize );
+-      assert( pPager->setMaster==0 );
+-      break;
++/* Additional values that can be added to the sync_flags argument of
++** sqlite3WalFrames():
++*/
++#define WAL_SYNC_TRANSACTIONS  0x20   /* Sync at the end of each transaction */
++#define SQLITE_SYNC_MASK       0x13   /* Mask off the SQLITE_SYNC_* values */
+ 
+-    case PAGER_WRITER_CACHEMOD:
+-      assert( p->eLock!=UNKNOWN_LOCK );
+-      assert( pPager->errCode==SQLITE_OK );
+-      if( !pagerUseWal(pPager) ){
+-        /* It is possible that if journal_mode=wal here that neither the
+-        ** journal file nor the WAL file are open. This happens during
+-        ** a rollback transaction that switches from journal_mode=off
+-        ** to journal_mode=wal.
+-        */
+-        assert( p->eLock>=RESERVED_LOCK );
+-        assert( isOpen(p->jfd) 
+-             || p->journalMode==PAGER_JOURNALMODE_OFF 
+-             || p->journalMode==PAGER_JOURNALMODE_WAL 
+-        );
+-      }
+-      assert( pPager->dbOrigSize==pPager->dbFileSize );
+-      assert( pPager->dbOrigSize==pPager->dbHintSize );
+-      break;
++#ifdef SQLITE_OMIT_WAL
++# define sqlite3WalOpen(x,y,z)                   0
++# define sqlite3WalLimit(x,y)
++# define sqlite3WalClose(w,x,y,z)                0
++# define sqlite3WalBeginReadTransaction(y,z)     0
++# define sqlite3WalEndReadTransaction(z)
++# define sqlite3WalDbsize(y)                     0
++# define sqlite3WalBeginWriteTransaction(y)      0
++# define sqlite3WalEndWriteTransaction(x)        0
++# define sqlite3WalUndo(x,y,z)                   0
++# define sqlite3WalSavepoint(y,z)
++# define sqlite3WalSavepointUndo(y,z)            0
++# define sqlite3WalFrames(u,v,w,x,y,z)           0
++# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
++# define sqlite3WalCallback(z)                   0
++# define sqlite3WalExclusiveMode(y,z)            0
++# define sqlite3WalHeapMemory(z)                 0
++# define sqlite3WalFramesize(z)                  0
++# define sqlite3WalFindFrame(x,y,z)              0
++#else
+ 
+-    case PAGER_WRITER_DBMOD:
+-      assert( p->eLock==EXCLUSIVE_LOCK );
+-      assert( pPager->errCode==SQLITE_OK );
+-      assert( !pagerUseWal(pPager) );
+-      assert( p->eLock>=EXCLUSIVE_LOCK );
+-      assert( isOpen(p->jfd) 
+-           || p->journalMode==PAGER_JOURNALMODE_OFF 
+-           || p->journalMode==PAGER_JOURNALMODE_WAL 
+-      );
+-      assert( pPager->dbOrigSize<=pPager->dbHintSize );
+-      break;
++#define WAL_SAVEPOINT_NDATA 4
+ 
+-    case PAGER_WRITER_FINISHED:
+-      assert( p->eLock==EXCLUSIVE_LOCK );
+-      assert( pPager->errCode==SQLITE_OK );
+-      assert( !pagerUseWal(pPager) );
+-      assert( isOpen(p->jfd) 
+-           || p->journalMode==PAGER_JOURNALMODE_OFF 
+-           || p->journalMode==PAGER_JOURNALMODE_WAL 
+-      );
+-      break;
++/* Connection to a write-ahead log (WAL) file. 
++** There is one object of this type for each pager. 
++*/
++typedef struct Wal Wal;
+ 
+-    case PAGER_ERROR:
+-      /* There must be at least one outstanding reference to the pager if
+-      ** in ERROR state. Otherwise the pager should have already dropped
+-      ** back to OPEN state.
+-      */
+-      assert( pPager->errCode!=SQLITE_OK );
+-      assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
+-      break;
+-  }
++/* Open and close a connection to a write-ahead log. */
++SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
++SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
+ 
+-  return 1;
+-}
+-#endif /* ifndef NDEBUG */
++/* Set the limiting size of a WAL file. */
++SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
+ 
+-#ifdef SQLITE_DEBUG 
+-/*
+-** Return a pointer to a human readable string in a static buffer
+-** containing the state of the Pager object passed as an argument. This
+-** is intended to be used within debuggers. For example, as an alternative
+-** to "print *pPager" in gdb:
+-**
+-** (gdb) printf "%s", print_pager_state(pPager)
++/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
++** snapshot is like a read-transaction.  It is the state of the database
++** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
++** preserves the current state even if the other threads or processes
++** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
++** transaction and releases the lock.
+ */
+-static char *print_pager_state(Pager *p){
+-  static char zRet[1024];
++SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
++SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
+ 
+-  sqlite3_snprintf(1024, zRet,
+-      "Filename:      %s\n"
+-      "State:         %s errCode=%d\n"
+-      "Lock:          %s\n"
+-      "Locking mode:  locking_mode=%s\n"
+-      "Journal mode:  journal_mode=%s\n"
+-      "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
+-      "Journal:       journalOff=%lld journalHdr=%lld\n"
+-      "Size:          dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
+-      , p->zFilename
+-      , p->eState==PAGER_OPEN            ? "OPEN" :
+-        p->eState==PAGER_READER          ? "READER" :
+-        p->eState==PAGER_WRITER_LOCKED   ? "WRITER_LOCKED" :
+-        p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
+-        p->eState==PAGER_WRITER_DBMOD    ? "WRITER_DBMOD" :
+-        p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
+-        p->eState==PAGER_ERROR           ? "ERROR" : "?error?"
+-      , (int)p->errCode
+-      , p->eLock==NO_LOCK         ? "NO_LOCK" :
+-        p->eLock==RESERVED_LOCK   ? "RESERVED" :
+-        p->eLock==EXCLUSIVE_LOCK  ? "EXCLUSIVE" :
+-        p->eLock==SHARED_LOCK     ? "SHARED" :
+-        p->eLock==UNKNOWN_LOCK    ? "UNKNOWN" : "?error?"
+-      , p->exclusiveMode ? "exclusive" : "normal"
+-      , p->journalMode==PAGER_JOURNALMODE_MEMORY   ? "memory" :
+-        p->journalMode==PAGER_JOURNALMODE_OFF      ? "off" :
+-        p->journalMode==PAGER_JOURNALMODE_DELETE   ? "delete" :
+-        p->journalMode==PAGER_JOURNALMODE_PERSIST  ? "persist" :
+-        p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
+-        p->journalMode==PAGER_JOURNALMODE_WAL      ? "wal" : "?error?"
+-      , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
+-      , p->journalOff, p->journalHdr
+-      , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
+-  );
++/* Read a page from the write-ahead log, if it is present. */
++SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
++SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
+ 
+-  return zRet;
+-}
+-#endif
++/* If the WAL is not empty, return the size of the database. */
++SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
+ 
+-/*
+-** Return true if it is necessary to write page *pPg into the sub-journal.
+-** A page needs to be written into the sub-journal if there exists one
+-** or more open savepoints for which:
+-**
+-**   * The page-number is less than or equal to PagerSavepoint.nOrig, and
+-**   * The bit corresponding to the page-number is not set in
+-**     PagerSavepoint.pInSavepoint.
++/* Obtain or release the WRITER lock. */
++SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal);
++SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal);
++
++/* Undo any frames written (but not committed) to the log */
++SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
++
++/* Return an integer that records the current (uncommitted) write
++** position in the WAL */
++SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
++
++/* Move the write position of the WAL back to iFrame.  Called in
++** response to a ROLLBACK TO command. */
++SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
++
++/* Write a frame or frames to the log. */
++SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
++
++/* Copy pages from the log to the database file */ 
++SQLITE_PRIVATE int sqlite3WalCheckpoint(
++  Wal *pWal,                      /* Write-ahead log connection */
++  int eMode,                      /* One of PASSIVE, FULL and RESTART */
++  int (*xBusy)(void*),            /* Function to call when busy */
++  void *pBusyArg,                 /* Context argument for xBusyHandler */
++  int sync_flags,                 /* Flags to sync db file with (or 0) */
++  int nBuf,                       /* Size of buffer nBuf */
++  u8 *zBuf,                       /* Temporary buffer to use */
++  int *pnLog,                     /* OUT: Number of frames in WAL */
++  int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
++);
++
++/* Return the value to pass to a sqlite3_wal_hook callback, the
++** number of frames in the WAL at the point of the last commit since
++** sqlite3WalCallback() was called.  If no commits have occurred since
++** the last call, then return 0.
+ */
+-static int subjRequiresPage(PgHdr *pPg){
+-  Pgno pgno = pPg->pgno;
+-  Pager *pPager = pPg->pPager;
+-  int i;
+-  for(i=0; i<pPager->nSavepoint; i++){
+-    PagerSavepoint *p = &pPager->aSavepoint[i];
+-    if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
+-      return 1;
+-    }
+-  }
+-  return 0;
+-}
++SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
+ 
+-/*
+-** Return true if the page is already in the journal file.
++/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
++** by the pager layer on the database file.
+ */
+-static int pageInJournal(PgHdr *pPg){
+-  return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
+-}
++SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
+ 
+-/*
+-** Read a 32-bit integer from the given file descriptor.  Store the integer
+-** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
+-** error code is something goes wrong.
+-**
+-** All values are stored on disk as big-endian.
++/* Return true if the argument is non-NULL and the WAL module is using
++** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
++** WAL module is using shared-memory, return false. 
+ */
+-static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
+-  unsigned char ac[4];
+-  int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
+-  if( rc==SQLITE_OK ){
+-    *pRes = sqlite3Get4byte(ac);
+-  }
+-  return rc;
+-}
++SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
+ 
+-/*
+-** Write a 32-bit integer into a string buffer in big-endian byte order.
++#ifdef SQLITE_ENABLE_ZIPVFS
++/* If the WAL file is not empty, return the number of bytes of content
++** stored in each frame (i.e. the db page-size when the WAL was created).
+ */
+-#define put32bits(A,B)  sqlite3Put4byte((u8*)A,B)
++SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
++#endif
++
++#endif /* ifndef SQLITE_OMIT_WAL */
++#endif /* _WAL_H_ */
+ 
++/************** End of wal.h *************************************************/
++/************** Continuing where we left off in pager.c **********************/
++
++
++/******************* NOTES ON THE DESIGN OF THE PAGER ************************
++**
++** This comment block describes invariants that hold when using a rollback
++** journal.  These invariants do not apply for journal_mode=WAL,
++** journal_mode=MEMORY, or journal_mode=OFF.
++**
++** Within this comment block, a page is deemed to have been synced
++** automatically as soon as it is written when PRAGMA synchronous=OFF.
++** Otherwise, the page is not synced until the xSync method of the VFS
++** is called successfully on the file containing the page.
++**
++** Definition:  A page of the database file is said to be "overwriteable" if
++** one or more of the following are true about the page:
++** 
++**     (a)  The original content of the page as it was at the beginning of
++**          the transaction has been written into the rollback journal and
++**          synced.
++** 
++**     (b)  The page was a freelist leaf page at the start of the transaction.
++** 
++**     (c)  The page number is greater than the largest page that existed in
++**          the database file at the start of the transaction.
++** 
++** (1) A page of the database file is never overwritten unless one of the
++**     following are true:
++** 
++**     (a) The page and all other pages on the same sector are overwriteable.
++** 
++**     (b) The atomic page write optimization is enabled, and the entire
++**         transaction other than the update of the transaction sequence
++**         number consists of a single page change.
++** 
++** (2) The content of a page written into the rollback journal exactly matches
++**     both the content in the database when the rollback journal was written
++**     and the content in the database at the beginning of the current
++**     transaction.
++** 
++** (3) Writes to the database file are an integer multiple of the page size
++**     in length and are aligned on a page boundary.
++** 
++** (4) Reads from the database file are either aligned on a page boundary and
++**     an integer multiple of the page size in length or are taken from the
++**     first 100 bytes of the database file.
++** 
++** (5) All writes to the database file are synced prior to the rollback journal
++**     being deleted, truncated, or zeroed.
++** 
++** (6) If a master journal file is used, then all writes to the database file
++**     are synced prior to the master journal being deleted.
++** 
++** Definition: Two databases (or the same database at two points it time)
++** are said to be "logically equivalent" if they give the same answer to
++** all queries.  Note in particular the content of freelist leaf
++** pages can be changed arbitarily without effecting the logical equivalence
++** of the database.
++** 
++** (7) At any time, if any subset, including the empty set and the total set,
++**     of the unsynced changes to a rollback journal are removed and the 
++**     journal is rolled back, the resulting database file will be logical
++**     equivalent to the database file at the beginning of the transaction.
++** 
++** (8) When a transaction is rolled back, the xTruncate method of the VFS
++**     is called to restore the database file to the same size it was at
++**     the beginning of the transaction.  (In some VFSes, the xTruncate
++**     method is a no-op, but that does not change the fact the SQLite will
++**     invoke it.)
++** 
++** (9) Whenever the database file is modified, at least one bit in the range
++**     of bytes from 24 through 39 inclusive will be changed prior to releasing
++**     the EXCLUSIVE lock, thus signaling other connections on the same
++**     database to flush their caches.
++**
++** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
++**      than one billion transactions.
++**
++** (11) A database file is well-formed at the beginning and at the conclusion
++**      of every transaction.
++**
++** (12) An EXCLUSIVE lock is held on the database file when writing to
++**      the database file.
++**
++** (13) A SHARED lock is held on the database file while reading any
++**      content out of the database file.
++**
++******************************************************************************/
+ 
+ /*
+-** Write a 32-bit integer into the given file descriptor.  Return SQLITE_OK
+-** on success or an error code is something goes wrong.
++** Macros for troubleshooting.  Normally turned off
+ */
+-static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
+-  char ac[4];
+-  put32bits(ac, val);
+-  return sqlite3OsWrite(fd, ac, 4, offset);
+-}
++#if 0
++int sqlite3PagerTrace=1;  /* True to enable tracing */
++#define sqlite3DebugPrintf printf
++#define PAGERTRACE(X)     if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
++#else
++#define PAGERTRACE(X)
++#endif
+ 
+ /*
+-** Unlock the database file to level eLock, which must be either NO_LOCK
+-** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
+-** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
++** The following two macros are used within the PAGERTRACE() macros above
++** to print out file-descriptors. 
+ **
+-** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
+-** called, do not modify it. See the comment above the #define of 
+-** UNKNOWN_LOCK for an explanation of this.
++** PAGERID() takes a pointer to a Pager struct as its argument. The
++** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
++** struct as its argument.
+ */
+-static int pagerUnlockDb(Pager *pPager, int eLock){
+-  int rc = SQLITE_OK;
+-
+-  assert( !pPager->exclusiveMode || pPager->eLock==eLock );
+-  assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
+-  assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
+-  if( isOpen(pPager->fd) ){
+-    assert( pPager->eLock>=eLock );
+-    rc = sqlite3OsUnlock(pPager->fd, eLock);
+-    if( pPager->eLock!=UNKNOWN_LOCK ){
+-      pPager->eLock = (u8)eLock;
+-    }
+-    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
+-  }
+-  return rc;
+-}
++#define PAGERID(p) ((int)(p->fd))
++#define FILEHANDLEID(fd) ((int)fd)
+ 
+ /*
+-** Lock the database file to level eLock, which must be either SHARED_LOCK,
+-** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
+-** Pager.eLock variable to the new locking state. 
++** The Pager.eState variable stores the current 'state' of a pager. A
++** pager may be in any one of the seven states shown in the following
++** state diagram.
++**
++**                            OPEN <------+------+
++**                              |         |      |
++**                              V         |      |
++**               +---------> READER-------+      |
++**               |              |                |
++**               |              V                |
++**               |<-------WRITER_LOCKED------> ERROR
++**               |              |                ^  
++**               |              V                |
++**               |<------WRITER_CACHEMOD-------->|
++**               |              |                |
++**               |              V                |
++**               |<-------WRITER_DBMOD---------->|
++**               |              |                |
++**               |              V                |
++**               +<------WRITER_FINISHED-------->+
++**
++**
++** List of state transitions and the C [function] that performs each:
++** 
++**   OPEN              -> READER              [sqlite3PagerSharedLock]
++**   READER            -> OPEN                [pager_unlock]
++**
++**   READER            -> WRITER_LOCKED       [sqlite3PagerBegin]
++**   WRITER_LOCKED     -> WRITER_CACHEMOD     [pager_open_journal]
++**   WRITER_CACHEMOD   -> WRITER_DBMOD        [syncJournal]
++**   WRITER_DBMOD      -> WRITER_FINISHED     [sqlite3PagerCommitPhaseOne]
++**   WRITER_***        -> READER              [pager_end_transaction]
++**
++**   WRITER_***        -> ERROR               [pager_error]
++**   ERROR             -> OPEN                [pager_unlock]
++** 
++**
++**  OPEN:
++**
++**    The pager starts up in this state. Nothing is guaranteed in this
++**    state - the file may or may not be locked and the database size is
++**    unknown. The database may not be read or written.
++**
++**    * No read or write transaction is active.
++**    * Any lock, or no lock at all, may be held on the database file.
++**    * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
++**
++**  READER:
++**
++**    In this state all the requirements for reading the database in 
++**    rollback (non-WAL) mode are met. Unless the pager is (or recently
++**    was) in exclusive-locking mode, a user-level read transaction is 
++**    open. The database size is known in this state.
++**
++**    A connection running with locking_mode=normal enters this state when
++**    it opens a read-transaction on the database and returns to state
++**    OPEN after the read-transaction is completed. However a connection
++**    running in locking_mode=exclusive (including temp databases) remains in
++**    this state even after the read-transaction is closed. The only way
++**    a locking_mode=exclusive connection can transition from READER to OPEN
++**    is via the ERROR state (see below).
++** 
++**    * A read transaction may be active (but a write-transaction cannot).
++**    * A SHARED or greater lock is held on the database file.
++**    * The dbSize variable may be trusted (even if a user-level read 
++**      transaction is not active). The dbOrigSize and dbFileSize variables
++**      may not be trusted at this point.
++**    * If the database is a WAL database, then the WAL connection is open.
++**    * Even if a read-transaction is not open, it is guaranteed that 
++**      there is no hot-journal in the file-system.
++**
++**  WRITER_LOCKED:
++**
++**    The pager moves to this state from READER when a write-transaction
++**    is first opened on the database. In WRITER_LOCKED state, all locks 
++**    required to start a write-transaction are held, but no actual 
++**    modifications to the cache or database have taken place.
++**
++**    In rollback mode, a RESERVED or (if the transaction was opened with 
++**    BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
++**    moving to this state, but the journal file is not written to or opened 
++**    to in this state. If the transaction is committed or rolled back while 
++**    in WRITER_LOCKED state, all that is required is to unlock the database 
++**    file.
++**
++**    IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
++**    If the connection is running with locking_mode=exclusive, an attempt
++**    is made to obtain an EXCLUSIVE lock on the database file.
++**
++**    * A write transaction is active.
++**    * If the connection is open in rollback-mode, a RESERVED or greater 
++**      lock is held on the database file.
++**    * If the connection is open in WAL-mode, a WAL write transaction
++**      is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
++**      called).
++**    * The dbSize, dbOrigSize and dbFileSize variables are all valid.
++**    * The contents of the pager cache have not been modified.
++**    * The journal file may or may not be open.
++**    * Nothing (not even the first header) has been written to the journal.
++**
++**  WRITER_CACHEMOD:
++**
++**    A pager moves from WRITER_LOCKED state to this state when a page is
++**    first modified by the upper layer. In rollback mode the journal file
++**    is opened (if it is not already open) and a header written to the
++**    start of it. The database file on disk has not been modified.
++**
++**    * A write transaction is active.
++**    * A RESERVED or greater lock is held on the database file.
++**    * The journal file is open and the first header has been written 
++**      to it, but the header has not been synced to disk.
++**    * The contents of the page cache have been modified.
++**
++**  WRITER_DBMOD:
++**
++**    The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
++**    when it modifies the contents of the database file. WAL connections
++**    never enter this state (since they do not modify the database file,
++**    just the log file).
++**
++**    * A write transaction is active.
++**    * An EXCLUSIVE or greater lock is held on the database file.
++**    * The journal file is open and the first header has been written 
++**      and synced to disk.
++**    * The contents of the page cache have been modified (and possibly
++**      written to disk).
++**
++**  WRITER_FINISHED:
++**
++**    It is not possible for a WAL connection to enter this state.
++**
++**    A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
++**    state after the entire transaction has been successfully written into the
++**    database file. In this state the transaction may be committed simply
++**    by finalizing the journal file. Once in WRITER_FINISHED state, it is 
++**    not possible to modify the database further. At this point, the upper 
++**    layer must either commit or rollback the transaction.
++**
++**    * A write transaction is active.
++**    * An EXCLUSIVE or greater lock is held on the database file.
++**    * All writing and syncing of journal and database data has finished.
++**      If no error occurred, all that remains is to finalize the journal to
++**      commit the transaction. If an error did occur, the caller will need
++**      to rollback the transaction. 
++**
++**  ERROR:
++**
++**    The ERROR state is entered when an IO or disk-full error (including
++**    SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it 
++**    difficult to be sure that the in-memory pager state (cache contents, 
++**    db size etc.) are consistent with the contents of the file-system.
++**
++**    Temporary pager files may enter the ERROR state, but in-memory pagers
++**    cannot.
++**
++**    For example, if an IO error occurs while performing a rollback, 
++**    the contents of the page-cache may be left in an inconsistent state.
++**    At this point it would be dangerous to change back to READER state
++**    (as usually happens after a rollback). Any subsequent readers might
++**    report database corruption (due to the inconsistent cache), and if
++**    they upgrade to writers, they may inadvertently corrupt the database
++**    file. To avoid this hazard, the pager switches into the ERROR state
++**    instead of READER following such an error.
++**
++**    Once it has entered the ERROR state, any attempt to use the pager
++**    to read or write data returns an error. Eventually, once all 
++**    outstanding transactions have been abandoned, the pager is able to
++**    transition back to OPEN state, discarding the contents of the 
++**    page-cache and any other in-memory state at the same time. Everything
++**    is reloaded from disk (and, if necessary, hot-journal rollback peformed)
++**    when a read-transaction is next opened on the pager (transitioning
++**    the pager into READER state). At that point the system has recovered 
++**    from the error.
++**
++**    Specifically, the pager jumps into the ERROR state if:
++**
++**      1. An error occurs while attempting a rollback. This happens in
++**         function sqlite3PagerRollback().
++**
++**      2. An error occurs while attempting to finalize a journal file
++**         following a commit in function sqlite3PagerCommitPhaseTwo().
++**
++**      3. An error occurs while attempting to write to the journal or
++**         database file in function pagerStress() in order to free up
++**         memory.
++**
++**    In other cases, the error is returned to the b-tree layer. The b-tree
++**    layer then attempts a rollback operation. If the error condition 
++**    persists, the pager enters the ERROR state via condition (1) above.
++**
++**    Condition (3) is necessary because it can be triggered by a read-only
++**    statement executed within a transaction. In this case, if the error
++**    code were simply returned to the user, the b-tree layer would not
++**    automatically attempt a rollback, as it assumes that an error in a
++**    read-only statement cannot leave the pager in an internally inconsistent 
++**    state.
+ **
+-** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is 
+-** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. 
+-** See the comment above the #define of UNKNOWN_LOCK for an explanation 
+-** of this.
++**    * The Pager.errCode variable is set to something other than SQLITE_OK.
++**    * There are one or more outstanding references to pages (after the
++**      last reference is dropped the pager should move back to OPEN state).
++**    * The pager is not an in-memory pager.
++**    
++**
++** Notes:
++**
++**   * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
++**     connection is open in WAL mode. A WAL connection is always in one
++**     of the first four states.
++**
++**   * Normally, a connection open in exclusive mode is never in PAGER_OPEN
++**     state. There are two exceptions: immediately after exclusive-mode has
++**     been turned on (and before any read or write transactions are 
++**     executed), and when the pager is leaving the "error state".
++**
++**   * See also: assert_pager_state().
+ */
+-static int pagerLockDb(Pager *pPager, int eLock){
+-  int rc = SQLITE_OK;
+-
+-  assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
+-  if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
+-    rc = sqlite3OsLock(pPager->fd, eLock);
+-    if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
+-      pPager->eLock = (u8)eLock;
+-      IOTRACE(("LOCK %p %d\n", pPager, eLock))
+-    }
+-  }
+-  return rc;
+-}
++#define PAGER_OPEN                  0
++#define PAGER_READER                1
++#define PAGER_WRITER_LOCKED         2
++#define PAGER_WRITER_CACHEMOD       3
++#define PAGER_WRITER_DBMOD          4
++#define PAGER_WRITER_FINISHED       5
++#define PAGER_ERROR                 6
+ 
+ /*
+-** This function determines whether or not the atomic-write optimization
+-** can be used with this pager. The optimization can be used if:
++** The Pager.eLock variable is almost always set to one of the 
++** following locking-states, according to the lock currently held on
++** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
++** This variable is kept up to date as locks are taken and released by
++** the pagerLockDb() and pagerUnlockDb() wrappers.
+ **
+-**  (a) the value returned by OsDeviceCharacteristics() indicates that
+-**      a database page may be written atomically, and
+-**  (b) the value returned by OsSectorSize() is less than or equal
+-**      to the page size.
++** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
++** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
++** the operation was successful. In these circumstances pagerLockDb() and
++** pagerUnlockDb() take a conservative approach - eLock is always updated
++** when unlocking the file, and only updated when locking the file if the
++** VFS call is successful. This way, the Pager.eLock variable may be set
++** to a less exclusive (lower) value than the lock that is actually held
++** at the system level, but it is never set to a more exclusive value.
+ **
+-** The optimization is also always enabled for temporary files. It is
+-** an error to call this function if pPager is opened on an in-memory
+-** database.
++** This is usually safe. If an xUnlock fails or appears to fail, there may 
++** be a few redundant xLock() calls or a lock may be held for longer than
++** required, but nothing really goes wrong.
+ **
+-** If the optimization cannot be used, 0 is returned. If it can be used,
+-** then the value returned is the size of the journal file when it
+-** contains rollback data for exactly one page.
++** The exception is when the database file is unlocked as the pager moves
++** from ERROR to OPEN state. At this point there may be a hot-journal file 
++** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
++** transition, by the same pager or any other). If the call to xUnlock()
++** fails at this point and the pager is left holding an EXCLUSIVE lock, this
++** can confuse the call to xCheckReservedLock() call made later as part
++** of hot-journal detection.
++**
++** xCheckReservedLock() is defined as returning true "if there is a RESERVED 
++** lock held by this process or any others". So xCheckReservedLock may 
++** return true because the caller itself is holding an EXCLUSIVE lock (but
++** doesn't know it because of a previous error in xUnlock). If this happens
++** a hot-journal may be mistaken for a journal being created by an active
++** transaction in another process, causing SQLite to read from the database
++** without rolling it back.
++**
++** To work around this, if a call to xUnlock() fails when unlocking the
++** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
++** is only changed back to a real locking state after a successful call
++** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
++** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK 
++** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
++** lock on the database file before attempting to roll it back. See function
++** PagerSharedLock() for more detail.
++**
++** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in 
++** PAGER_OPEN state.
+ */
+-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+-static int jrnlBufferSize(Pager *pPager){
+-  assert( !MEMDB );
+-  if( !pPager->tempFile ){
+-    int dc;                           /* Device characteristics */
+-    int nSector;                      /* Sector size */
+-    int szPage;                       /* Page size */
+-
+-    assert( isOpen(pPager->fd) );
+-    dc = sqlite3OsDeviceCharacteristics(pPager->fd);
+-    nSector = pPager->sectorSize;
+-    szPage = pPager->pageSize;
+-
+-    assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
+-    assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+-    if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
+-      return 0;
+-    }
+-  }
+-
+-  return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
+-}
+-#endif
++#define UNKNOWN_LOCK                (EXCLUSIVE_LOCK+1)
+ 
+ /*
+-** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
+-** on the cache using a hash function.  This is used for testing
+-** and debugging only.
++** A macro used for invoking the codec if there is one
+ */
+-#ifdef SQLITE_CHECK_PAGES
 +#ifdef SQLITE_HAS_CODEC
-+SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx) {
-+  *ctx = pPager->pCodec;
++# define CODEC1(P,D,N,X,E) \
++    if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
++# define CODEC2(P,D,N,X,E,O) \
++    if( P->xCodec==0 ){ O=(char*)D; }else \
++    if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
++#else
++# define CODEC1(P,D,N,X,E)   /* NO-OP */
++# define CODEC2(P,D,N,X,E,O) O=(char*)D
++#endif
++
+ /*
+-** Return a 32-bit hash of the page data for pPage.
++** The maximum allowed sector size. 64KiB. If the xSectorsize() method 
++** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
++** This could conceivably cause corruption following a power failure on
++** such a system. This is currently an undocumented limit.
+ */
+-static u32 pager_datahash(int nByte, unsigned char *pData){
+-  u32 hash = 0;
+-  int i;
+-  for(i=0; i<nByte; i++){
+-    hash = (hash*1039) + pData[i];
+-  }
+-  return hash;
+-}
+-static u32 pager_pagehash(PgHdr *pPage){
+-  return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
+-}
+-static void pager_set_pagehash(PgHdr *pPage){
+-  pPage->pageHash = pager_pagehash(pPage);
+-}
++#define MAX_SECTOR_SIZE 0x10000
+ 
+ /*
+-** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
+-** is defined, and NDEBUG is not defined, an assert() statement checks
+-** that the page is either dirty or still matches the calculated page-hash.
++** An instance of the following structure is allocated for each active
++** savepoint and statement transaction in the system. All such structures
++** are stored in the Pager.aSavepoint[] array, which is allocated and
++** resized using sqlite3Realloc().
++**
++** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
++** set to 0. If a journal-header is written into the main journal while
++** the savepoint is active, then iHdrOffset is set to the byte offset 
++** immediately following the last journal record written into the main
++** journal before the journal-header. This is required during savepoint
++** rollback (see pagerPlaybackSavepoint()).
+ */
+-#define CHECK_PAGE(x) checkPage(x)
+-static void checkPage(PgHdr *pPg){
+-  Pager *pPager = pPg->pPager;
+-  assert( pPager->eState!=PAGER_ERROR );
+-  assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
+-}
+-
+-#else
+-#define pager_datahash(X,Y)  0
+-#define pager_pagehash(X)  0
+-#define pager_set_pagehash(X)
+-#define CHECK_PAGE(x)
+-#endif  /* SQLITE_CHECK_PAGES */
++typedef struct PagerSavepoint PagerSavepoint;
++struct PagerSavepoint {
++  i64 iOffset;                 /* Starting offset in main journal */
++  i64 iHdrOffset;              /* See above */
++  Bitvec *pInSavepoint;        /* Set of pages in this savepoint */
++  Pgno nOrig;                  /* Original number of pages in file */
++  Pgno iSubRec;                /* Index of first record in sub-journal */
++#ifndef SQLITE_OMIT_WAL
++  u32 aWalData[WAL_SAVEPOINT_NDATA];        /* WAL savepoint context */
++#endif
++};
+ 
+ /*
+-** When this is called the journal file for pager pPager must be open.
+-** This function attempts to read a master journal file name from the 
+-** end of the file and, if successful, copies it into memory supplied 
+-** by the caller. See comments above writeMasterJournal() for the format
+-** used to store a master journal file name at the end of a journal file.
++** A open page cache is an instance of struct Pager. A description of
++** some of the more important member variables follows:
+ **
+-** zMaster must point to a buffer of at least nMaster bytes allocated by
+-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
+-** enough space to write the master journal name). If the master journal
+-** name in the journal is longer than nMaster bytes (including a
+-** nul-terminator), then this is handled as if no master journal name
+-** were present in the journal.
++** eState
+ **
+-** If a master journal file name is present at the end of the journal
+-** file, then it is copied into the buffer pointed to by zMaster. A
+-** nul-terminator byte is appended to the buffer following the master
+-** journal file name.
++**   The current 'state' of the pager object. See the comment and state
++**   diagram above for a description of the pager state.
+ **
+-** If it is determined that no master journal file name is present 
+-** zMaster[0] is set to 0 and SQLITE_OK returned.
++** eLock
+ **
+-** If an error occurs while reading from the journal file, an SQLite
+-** error code is returned.
++**   For a real on-disk database, the current lock held on the database file -
++**   NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
++**
++**   For a temporary or in-memory database (neither of which require any
++**   locks), this variable is always set to EXCLUSIVE_LOCK. Since such
++**   databases always have Pager.exclusiveMode==1, this tricks the pager
++**   logic into thinking that it already has all the locks it will ever
++**   need (and no reason to release them).
++**
++**   In some (obscure) circumstances, this variable may also be set to
++**   UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
++**   details.
++**
++** changeCountDone
++**
++**   This boolean variable is used to make sure that the change-counter 
++**   (the 4-byte header field at byte offset 24 of the database file) is 
++**   not updated more often than necessary. 
++**
++**   It is set to true when the change-counter field is updated, which 
++**   can only happen if an exclusive lock is held on the database file.
++**   It is cleared (set to false) whenever an exclusive lock is 
++**   relinquished on the database file. Each time a transaction is committed,
++**   The changeCountDone flag is inspected. If it is true, the work of
++**   updating the change-counter is omitted for the current transaction.
++**
++**   This mechanism means that when running in exclusive mode, a connection 
++**   need only update the change-counter once, for the first transaction
++**   committed.
++**
++** setMaster
++**
++**   When PagerCommitPhaseOne() is called to commit a transaction, it may
++**   (or may not) specify a master-journal name to be written into the 
++**   journal file before it is synced to disk.
++**
++**   Whether or not a journal file contains a master-journal pointer affects 
++**   the way in which the journal file is finalized after the transaction is 
++**   committed or rolled back when running in "journal_mode=PERSIST" mode.
++**   If a journal file does not contain a master-journal pointer, it is
++**   finalized by overwriting the first journal header with zeroes. If
++**   it does contain a master-journal pointer the journal file is finalized 
++**   by truncating it to zero bytes, just as if the connection were 
++**   running in "journal_mode=truncate" mode.
++**
++**   Journal files that contain master journal pointers cannot be finalized
++**   simply by overwriting the first journal-header with zeroes, as the
++**   master journal pointer could interfere with hot-journal rollback of any
++**   subsequently interrupted transaction that reuses the journal file.
++**
++**   The flag is cleared as soon as the journal file is finalized (either
++**   by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
++**   journal file from being successfully finalized, the setMaster flag
++**   is cleared anyway (and the pager will move to ERROR state).
++**
++** doNotSpill, doNotSyncSpill
++**
++**   These two boolean variables control the behavior of cache-spills
++**   (calls made by the pcache module to the pagerStress() routine to
++**   write cached data to the file-system in order to free up memory).
++**
++**   When doNotSpill is non-zero, writing to the database from pagerStress()
++**   is disabled altogether. This is done in a very obscure case that
++**   comes up during savepoint rollback that requires the pcache module
++**   to allocate a new page to prevent the journal file from being written
++**   while it is being traversed by code in pager_playback().
++** 
++**   If doNotSyncSpill is non-zero, writing to the database from pagerStress()
++**   is permitted, but syncing the journal file is not. This flag is set
++**   by sqlite3PagerWrite() when the file-system sector-size is larger than
++**   the database page-size in order to prevent a journal sync from happening 
++**   in between the journalling of two pages on the same sector. 
++**
++** subjInMemory
++**
++**   This is a boolean variable. If true, then any required sub-journal
++**   is opened as an in-memory journal file. If false, then in-memory
++**   sub-journals are only used for in-memory pager files.
++**
++**   This variable is updated by the upper layer each time a new 
++**   write-transaction is opened.
++**
++** dbSize, dbOrigSize, dbFileSize
++**
++**   Variable dbSize is set to the number of pages in the database file.
++**   It is valid in PAGER_READER and higher states (all states except for
++**   OPEN and ERROR). 
++**
++**   dbSize is set based on the size of the database file, which may be 
++**   larger than the size of the database (the value stored at offset
++**   28 of the database header by the btree). If the size of the file
++**   is not an integer multiple of the page-size, the value stored in
++**   dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
++**   Except, any file that is greater than 0 bytes in size is considered
++**   to have at least one page. (i.e. a 1KB file with 2K page-size leads
++**   to dbSize==1).
++**
++**   During a write-transaction, if pages with page-numbers greater than
++**   dbSize are modified in the cache, dbSize is updated accordingly.
++**   Similarly, if the database is truncated using PagerTruncateImage(), 
++**   dbSize is updated.
++**
++**   Variables dbOrigSize and dbFileSize are valid in states 
++**   PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
++**   variable at the start of the transaction. It is used during rollback,
++**   and to determine whether or not pages need to be journalled before
++**   being modified.
++**
++**   Throughout a write-transaction, dbFileSize contains the size of
++**   the file on disk in pages. It is set to a copy of dbSize when the
++**   write-transaction is first opened, and updated when VFS calls are made
++**   to write or truncate the database file on disk. 
++**
++**   The only reason the dbFileSize variable is required is to suppress 
++**   unnecessary calls to xTruncate() after committing a transaction. If, 
++**   when a transaction is committed, the dbFileSize variable indicates 
++**   that the database file is larger than the database image (Pager.dbSize), 
++**   pager_truncate() is called. The pager_truncate() call uses xFilesize()
++**   to measure the database file on disk, and then truncates it if required.
++**   dbFileSize is not used when rolling back a transaction. In this case
++**   pager_truncate() is called unconditionally (which means there may be
++**   a call to xFilesize() that is not strictly required). In either case,
++**   pager_truncate() may cause the file to become smaller or larger.
++**
++** dbHintSize
++**
++**   The dbHintSize variable is used to limit the number of calls made to
++**   the VFS xFileControl(FCNTL_SIZE_HINT) method. 
++**
++**   dbHintSize is set to a copy of the dbSize variable when a
++**   write-transaction is opened (at the same time as dbFileSize and
++**   dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
++**   dbHintSize is increased to the number of pages that correspond to the
++**   size-hint passed to the method call. See pager_write_pagelist() for 
++**   details.
++**
++** errCode
++**
++**   The Pager.errCode variable is only ever used in PAGER_ERROR state. It
++**   is set to zero in all other states. In PAGER_ERROR state, Pager.errCode 
++**   is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX 
++**   sub-codes.
+ */
+-static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
+-  int rc;                    /* Return code */
+-  u32 len;                   /* Length in bytes of master journal name */
+-  i64 szJ;                   /* Total size in bytes of journal file pJrnl */
+-  u32 cksum;                 /* MJ checksum value read from journal */
+-  u32 u;                     /* Unsigned loop counter */
+-  unsigned char aMagic[8];   /* A buffer to hold the magic header */
+-  zMaster[0] = '\0';
++struct Pager {
++  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
++  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
++  u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
++  u8 useJournal;              /* Use a rollback journal on this file */
++  u8 noSync;                  /* Do not sync the journal if true */
++  u8 fullSync;                /* Do extra syncs of the journal for robustness */
++  u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
++  u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
++  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
++  u8 tempFile;                /* zFilename is a temporary file */
++  u8 readOnly;                /* True for a read-only database */
++  u8 memDb;                   /* True to inhibit all file I/O */
+ 
+-  if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
+-   || szJ<16
+-   || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
+-   || len>=nMaster 
+-   || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
+-   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
+-   || memcmp(aMagic, aJournalMagic, 8)
+-   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
+-  ){
+-    return rc;
+-  }
++  /**************************************************************************
++  ** The following block contains those class members that change during
++  ** routine opertion.  Class members not in this block are either fixed
++  ** when the pager is first created or else only change when there is a
++  ** significant mode change (such as changing the page_size, locking_mode,
++  ** or the journal_mode).  From another view, these class members describe
++  ** the "state" of the pager, while other class members describe the
++  ** "configuration" of the pager.
++  */
++  u8 eState;                  /* Pager state (OPEN, READER, WRITER_LOCKED..) */
++  u8 eLock;                   /* Current lock held on database file */
++  u8 changeCountDone;         /* Set after incrementing the change-counter */
++  u8 setMaster;               /* True if a m-j name has been written to jrnl */
++  u8 doNotSpill;              /* Do not spill the cache when non-zero */
++  u8 doNotSyncSpill;          /* Do not do a spill that requires jrnl sync */
++  u8 subjInMemory;            /* True to use in-memory sub-journals */
++  Pgno dbSize;                /* Number of pages in the database */
++  Pgno dbOrigSize;            /* dbSize before the current transaction */
++  Pgno dbFileSize;            /* Number of pages in the database file */
++  Pgno dbHintSize;            /* Value passed to FCNTL_SIZE_HINT call */
++  int errCode;                /* One of several kinds of errors */
++  int nRec;                   /* Pages journalled since last j-header written */
++  u32 cksumInit;              /* Quasi-random value added to every checksum */
++  u32 nSubRec;                /* Number of records written to sub-journal */
++  Bitvec *pInJournal;         /* One bit for each page in the database file */
++  sqlite3_file *fd;           /* File descriptor for database */
++  sqlite3_file *jfd;          /* File descriptor for main journal */
++  sqlite3_file *sjfd;         /* File descriptor for sub-journal */
++  i64 journalOff;             /* Current write offset in the journal file */
++  i64 journalHdr;             /* Byte offset to previous journal header */
++  sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
++  PagerSavepoint *aSavepoint; /* Array of active savepoints */
++  int nSavepoint;             /* Number of elements in aSavepoint[] */
++  char dbFileVers[16];        /* Changes whenever database file changes */
+ 
+-  /* See if the checksum matches the master journal name */
+-  for(u=0; u<len; u++){
+-    cksum -= zMaster[u];
+-  }
+-  if( cksum ){
+-    /* If the checksum doesn't add up, then one or more of the disk sectors
+-    ** containing the master journal filename is corrupted. This means
+-    ** definitely roll back, so just return SQLITE_OK and report a (nul)
+-    ** master-journal filename.
+-    */
+-    len = 0;
+-  }
+-  zMaster[len] = '\0';
+-   
+-  return SQLITE_OK;
+-}
++  u8 bUseFetch;               /* True to use xFetch() */
++  int nMmapOut;               /* Number of mmap pages currently outstanding */
++  sqlite3_int64 szMmap;       /* Desired maximum mmap size */
++  PgHdr *pMmapFreelist;       /* List of free mmap page headers (pDirty) */
++  /*
++  ** End of the routinely-changing class members
++  ***************************************************************************/
++
++  u16 nExtra;                 /* Add this many bytes to each in-memory page */
++  i16 nReserve;               /* Number of unused bytes at end of each page */
++  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
++  u32 sectorSize;             /* Assumed sector size during rollback */
++  int pageSize;               /* Number of bytes in a page */
++  Pgno mxPgno;                /* Maximum allowed size of the database */
++  i64 journalSizeLimit;       /* Size limit for persistent journal files */
++  char *zFilename;            /* Name of the database file */
++  char *zJournal;             /* Name of the journal file */
++  int (*xBusyHandler)(void*); /* Function to call when busy */
++  void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
++  int aStat[3];               /* Total cache hits, misses and writes */
++#ifdef SQLITE_TEST
++  int nRead;                  /* Database pages read */
++#endif
++  void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
++#ifdef SQLITE_HAS_CODEC
++  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
++  void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
++  void (*xCodecFree)(void*);             /* Destructor for the codec */
++  void *pCodec;               /* First argument to xCodec... methods */
++#endif
++  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
++  PCache *pPCache;            /* Pointer to page cache object */
++#ifndef SQLITE_OMIT_WAL
++  Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
++  char *zWal;                 /* File name for write-ahead log */
++#endif
++};
+ 
+ /*
+-** Return the offset of the sector boundary at or immediately 
+-** following the value in pPager->journalOff, assuming a sector 
+-** size of pPager->sectorSize bytes.
+-**
+-** i.e for a sector size of 512:
+-**
+-**   Pager.journalOff          Return value
+-**   ---------------------------------------
+-**   0                         0
+-**   512                       512
+-**   100                       512
+-**   2000                      2048
+-** 
+-*/
+-static i64 journalHdrOffset(Pager *pPager){
+-  i64 offset = 0;
+-  i64 c = pPager->journalOff;
+-  if( c ){
+-    offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
+-  }
+-  assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
+-  assert( offset>=c );
+-  assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
+-  return offset;
+-}
++** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
++** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS 
++** or CACHE_WRITE to sqlite3_db_status().
++*/
++#define PAGER_STAT_HIT   0
++#define PAGER_STAT_MISS  1
++#define PAGER_STAT_WRITE 2
+ 
+ /*
+-** The journal file must be open when this function is called.
+-**
+-** This function is a no-op if the journal file has not been written to
+-** within the current transaction (i.e. if Pager.journalOff==0).
+-**
+-** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
+-** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
+-** zero the 28-byte header at the start of the journal file. In either case, 
+-** if the pager is not in no-sync mode, sync the journal file immediately 
+-** after writing or truncating it.
+-**
+-** If Pager.journalSizeLimit is set to a positive, non-zero value, and
+-** following the truncation or zeroing described above the size of the 
+-** journal file in bytes is larger than this value, then truncate the
+-** journal file to Pager.journalSizeLimit bytes. The journal file does
+-** not need to be synced following this operation.
+-**
+-** If an IO error occurs, abandon processing and return the IO error code.
+-** Otherwise, return SQLITE_OK.
++** The following global variables hold counters used for
++** testing purposes only.  These variables do not exist in
++** a non-testing build.  These variables are not thread-safe.
+ */
+-static int zeroJournalHdr(Pager *pPager, int doTruncate){
+-  int rc = SQLITE_OK;                               /* Return code */
+-  assert( isOpen(pPager->jfd) );
+-  if( pPager->journalOff ){
+-    const i64 iLimit = pPager->journalSizeLimit;    /* Local cache of jsl */
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */
++SQLITE_API int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */
++SQLITE_API int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */
++# define PAGER_INCR(v)  v++
++#else
++# define PAGER_INCR(v)
++#endif
+ 
+-    IOTRACE(("JZEROHDR %p\n", pPager))
+-    if( doTruncate || iLimit==0 ){
+-      rc = sqlite3OsTruncate(pPager->jfd, 0);
+-    }else{
+-      static const char zeroHdr[28] = {0};
+-      rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
+-    }
+-    if( rc==SQLITE_OK && !pPager->noSync ){
+-      rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
+-    }
+ 
+-    /* At this point the transaction is committed but the write lock 
+-    ** is still held on the file. If there is a size limit configured for 
+-    ** the persistent journal and the journal file currently consumes more
+-    ** space than that limit allows for, truncate it now. There is no need
+-    ** to sync the file following this operation.
+-    */
+-    if( rc==SQLITE_OK && iLimit>0 ){
+-      i64 sz;
+-      rc = sqlite3OsFileSize(pPager->jfd, &sz);
+-      if( rc==SQLITE_OK && sz>iLimit ){
+-        rc = sqlite3OsTruncate(pPager->jfd, iLimit);
+-      }
+-    }
+-  }
+-  return rc;
+-}
+ 
+ /*
+-** The journal file must be open when this routine is called. A journal
+-** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
+-** current location.
++** Journal files begin with the following magic string.  The data
++** was obtained from /dev/random.  It is used only as a sanity check.
+ **
+-** The format for the journal header is as follows:
+-** - 8 bytes: Magic identifying journal format.
+-** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
+-** - 4 bytes: Random number used for page hash.
+-** - 4 bytes: Initial database page count.
+-** - 4 bytes: Sector size used by the process that wrote this journal.
+-** - 4 bytes: Database page size.
+-** 
+-** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
++** Since version 2.8.0, the journal format contains additional sanity
++** checking information.  If the power fails while the journal is being
++** written, semi-random garbage data might appear in the journal
++** file after power is restored.  If an attempt is then made
++** to roll the journal back, the database could be corrupted.  The additional
++** sanity checking data is an attempt to discover the garbage in the
++** journal and ignore it.
++**
++** The sanity checking information for the new journal format consists
++** of a 32-bit checksum on each page of data.  The checksum covers both
++** the page number and the pPager->pageSize bytes of data for the page.
++** This cksum is initialized to a 32-bit random value that appears in the
++** journal file right after the header.  The random initializer is important,
++** because garbage data that appears at the end of a journal is likely
++** data that was once in other files that have now been deleted.  If the
++** garbage data came from an obsolete journal file, the checksums might
++** be correct.  But by initializing the checksum to random value which
++** is different for every journal, we minimize that risk.
+ */
+-static int writeJournalHdr(Pager *pPager){
+-  int rc = SQLITE_OK;                 /* Return code */
+-  char *zHeader = pPager->pTmpSpace;  /* Temporary space used to build header */
+-  u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
+-  u32 nWrite;                         /* Bytes of header sector written */
+-  int ii;                             /* Loop counter */
+-
+-  assert( isOpen(pPager->jfd) );      /* Journal file must be open. */
+-
+-  if( nHeader>JOURNAL_HDR_SZ(pPager) ){
+-    nHeader = JOURNAL_HDR_SZ(pPager);
+-  }
+-
+-  /* If there are active savepoints and any of them were created 
+-  ** since the most recent journal header was written, update the 
+-  ** PagerSavepoint.iHdrOffset fields now.
+-  */
+-  for(ii=0; ii<pPager->nSavepoint; ii++){
+-    if( pPager->aSavepoint[ii].iHdrOffset==0 ){
+-      pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
+-    }
+-  }
++static const unsigned char aJournalMagic[] = {
++  0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
++};
+ 
+-  pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
++/*
++** The size of the of each page record in the journal is given by
++** the following macro.
++*/
++#define JOURNAL_PG_SZ(pPager)  ((pPager->pageSize) + 8)
+ 
+-  /* 
+-  ** Write the nRec Field - the number of page records that follow this
+-  ** journal header. Normally, zero is written to this value at this time.
+-  ** After the records are added to the journal (and the journal synced, 
+-  ** if in full-sync mode), the zero is overwritten with the true number
+-  ** of records (see syncJournal()).
+-  **
+-  ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
+-  ** reading the journal this value tells SQLite to assume that the
+-  ** rest of the journal file contains valid page records. This assumption
+-  ** is dangerous, as if a failure occurred whilst writing to the journal
+-  ** file it may contain some garbage data. There are two scenarios
+-  ** where this risk can be ignored:
+-  **
+-  **   * When the pager is in no-sync mode. Corruption can follow a
+-  **     power failure in this case anyway.
+-  **
+-  **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
+-  **     that garbage data is never appended to the journal file.
+-  */
+-  assert( isOpen(pPager->fd) || pPager->noSync );
+-  if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
+-   || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 
+-  ){
+-    memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
+-    put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
+-  }else{
+-    memset(zHeader, 0, sizeof(aJournalMagic)+4);
+-  }
++/*
++** The journal header size for this pager. This is usually the same 
++** size as a single disk sector. See also setSectorSize().
++*/
++#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
+ 
+-  /* The random check-hash initializer */ 
+-  sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
+-  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
+-  /* The initial database size */
+-  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
+-  /* The assumed sector size for this process */
+-  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
++/*
++** The macro MEMDB is true if we are dealing with an in-memory database.
++** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
++** the value of MEMDB will be a constant and the compiler will optimize
++** out code that would never execute.
++*/
++#ifdef SQLITE_OMIT_MEMORYDB
++# define MEMDB 0
++#else
++# define MEMDB pPager->memDb
++#endif
+ 
+-  /* The page size */
+-  put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
++/*
++** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
++** interfaces to access the database using memory-mapped I/O.
++*/
++#if SQLITE_MAX_MMAP_SIZE>0
++# define USEFETCH(x) ((x)->bUseFetch)
++#else
++# define USEFETCH(x) 0
++#endif
+ 
+-  /* Initializing the tail of the buffer is not necessary.  Everything
+-  ** works find if the following memset() is omitted.  But initializing
+-  ** the memory prevents valgrind from complaining, so we are willing to
+-  ** take the performance hit.
+-  */
+-  memset(&zHeader[sizeof(aJournalMagic)+20], 0,
+-         nHeader-(sizeof(aJournalMagic)+20));
++/*
++** The maximum legal page number is (2^31 - 1).
++*/
++#define PAGER_MAX_PGNO 2147483647
+ 
+-  /* In theory, it is only necessary to write the 28 bytes that the 
+-  ** journal header consumes to the journal file here. Then increment the 
+-  ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next 
+-  ** record is written to the following sector (leaving a gap in the file
+-  ** that will be implicitly filled in by the OS).
+-  **
+-  ** However it has been discovered that on some systems this pattern can 
+-  ** be significantly slower than contiguously writing data to the file,
+-  ** even if that means explicitly writing data to the block of 
+-  ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
+-  ** is done. 
+-  **
+-  ** The loop is required here in case the sector-size is larger than the 
+-  ** database page size. Since the zHeader buffer is only Pager.pageSize
+-  ** bytes in size, more than one call to sqlite3OsWrite() may be required
+-  ** to populate the entire journal header sector.
+-  */ 
+-  for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
+-    IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
+-    rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
+-    assert( pPager->journalHdr <= pPager->journalOff );
+-    pPager->journalOff += nHeader;
+-  }
++/*
++** The argument to this macro is a file descriptor (type sqlite3_file*).
++** Return 0 if it is not open, or non-zero (but not 1) if it is.
++**
++** This is so that expressions can be written as:
++**
++**   if( isOpen(pPager->jfd) ){ ...
++**
++** instead of
++**
++**   if( pPager->jfd->pMethods ){ ...
++*/
++#define isOpen(pFd) ((pFd)->pMethods)
+ 
+-  return rc;
++/*
++** Return true if this pager uses a write-ahead log instead of the usual
++** rollback journal. Otherwise false.
++*/
++#ifndef SQLITE_OMIT_WAL
++static int pagerUseWal(Pager *pPager){
++  return (pPager->pWal!=0);
+ }
++#else
++# define pagerUseWal(x) 0
++# define pagerRollbackWal(x) 0
++# define pagerWalFrames(v,w,x,y) 0
++# define pagerOpenWalIfPresent(z) SQLITE_OK
++# define pagerBeginReadTransaction(z) SQLITE_OK
++#endif
+ 
++#ifndef NDEBUG 
+ /*
+-** The journal file must be open when this is called. A journal header file
+-** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
+-** file. The current location in the journal file is given by
+-** pPager->journalOff. See comments above function writeJournalHdr() for
+-** a description of the journal header format.
++** Usage:
+ **
+-** If the header is read successfully, *pNRec is set to the number of
+-** page records following this header and *pDbSize is set to the size of the
+-** database before the transaction began, in pages. Also, pPager->cksumInit
+-** is set to the value read from the journal header. SQLITE_OK is returned
+-** in this case.
++**   assert( assert_pager_state(pPager) );
+ **
+-** If the journal header file appears to be corrupted, SQLITE_DONE is
+-** returned and *pNRec and *PDbSize are undefined.  If JOURNAL_HDR_SZ bytes
+-** cannot be read from the journal file an error code is returned.
++** This function runs many asserts to try to find inconsistencies in
++** the internal state of the Pager object.
+ */
+-static int readJournalHdr(
+-  Pager *pPager,               /* Pager object */
+-  int isHot,
+-  i64 journalSize,             /* Size of the open journal file in bytes */
+-  u32 *pNRec,                  /* OUT: Value read from the nRec field */
+-  u32 *pDbSize                 /* OUT: Value of original database size field */
+-){
+-  int rc;                      /* Return code */
+-  unsigned char aMagic[8];     /* A buffer to hold the magic header */
+-  i64 iHdrOff;                 /* Offset of journal header being read */
++static int assert_pager_state(Pager *p){
++  Pager *pPager = p;
+ 
+-  assert( isOpen(pPager->jfd) );      /* Journal file must be open. */
++  /* State must be valid. */
++  assert( p->eState==PAGER_OPEN
++       || p->eState==PAGER_READER
++       || p->eState==PAGER_WRITER_LOCKED
++       || p->eState==PAGER_WRITER_CACHEMOD
++       || p->eState==PAGER_WRITER_DBMOD
++       || p->eState==PAGER_WRITER_FINISHED
++       || p->eState==PAGER_ERROR
++  );
+ 
+-  /* Advance Pager.journalOff to the start of the next sector. If the
+-  ** journal file is too small for there to be a header stored at this
+-  ** point, return SQLITE_DONE.
++  /* Regardless of the current state, a temp-file connection always behaves
++  ** as if it has an exclusive lock on the database file. It never updates
++  ** the change-counter field, so the changeCountDone flag is always set.
+   */
+-  pPager->journalOff = journalHdrOffset(pPager);
+-  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
+-    return SQLITE_DONE;
+-  }
+-  iHdrOff = pPager->journalOff;
++  assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
++  assert( p->tempFile==0 || pPager->changeCountDone );
+ 
+-  /* Read in the first 8 bytes of the journal header. If they do not match
+-  ** the  magic string found at the start of each journal header, return
+-  ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
+-  ** proceed.
++  /* If the useJournal flag is clear, the journal-mode must be "OFF". 
++  ** And if the journal-mode is "OFF", the journal file must not be open.
+   */
+-  if( isHot || iHdrOff!=pPager->journalHdr ){
+-    rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
+-    if( rc ){
+-      return rc;
+-    }
+-    if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
+-      return SQLITE_DONE;
+-    }
+-  }
++  assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
++  assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
+ 
+-  /* Read the first three 32-bit fields of the journal header: The nRec
+-  ** field, the checksum-initializer and the database size at the start
+-  ** of the transaction. Return an error code if anything goes wrong.
++  /* Check that MEMDB implies noSync. And an in-memory journal. Since 
++  ** this means an in-memory pager performs no IO at all, it cannot encounter 
++  ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing 
++  ** a journal file. (although the in-memory journal implementation may 
++  ** return SQLITE_IOERR_NOMEM while the journal file is being written). It 
++  ** is therefore not possible for an in-memory pager to enter the ERROR 
++  ** state.
+   */
+-  if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
+-   || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
+-   || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
+-  ){
+-    return rc;
+-  }
+-
+-  if( pPager->journalOff==0 ){
+-    u32 iPageSize;               /* Page-size field of journal header */
+-    u32 iSectorSize;             /* Sector-size field of journal header */
+-
+-    /* Read the page-size and sector-size journal header fields. */
+-    if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
+-     || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
+-    ){
+-      return rc;
+-    }
+-
+-    /* Versions of SQLite prior to 3.5.8 set the page-size field of the
+-    ** journal header to zero. In this case, assume that the Pager.pageSize
+-    ** variable is already set to the correct page size.
+-    */
+-    if( iPageSize==0 ){
+-      iPageSize = pPager->pageSize;
+-    }
+-
+-    /* Check that the values read from the page-size and sector-size fields
+-    ** are within range. To be 'in range', both values need to be a power
+-    ** of two greater than or equal to 512 or 32, and not greater than their 
+-    ** respective compile time maximum limits.
+-    */
+-    if( iPageSize<512                  || iSectorSize<32
+-     || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
+-     || ((iPageSize-1)&iPageSize)!=0   || ((iSectorSize-1)&iSectorSize)!=0 
+-    ){
+-      /* If the either the page-size or sector-size in the journal-header is 
+-      ** invalid, then the process that wrote the journal-header must have 
+-      ** crashed before the header was synced. In this case stop reading 
+-      ** the journal file here.
+-      */
+-      return SQLITE_DONE;
+-    }
+-
+-    /* Update the page-size to match the value read from the journal. 
+-    ** Use a testcase() macro to make sure that malloc failure within 
+-    ** PagerSetPagesize() is tested.
+-    */
+-    rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
+-    testcase( rc!=SQLITE_OK );
+-
+-    /* Update the assumed sector-size to match the value used by 
+-    ** the process that created this journal. If this journal was
+-    ** created by a process other than this one, then this routine
+-    ** is being called from within pager_playback(). The local value
+-    ** of Pager.sectorSize is restored at the end of that routine.
+-    */
+-    pPager->sectorSize = iSectorSize;
++  if( MEMDB ){
++    assert( p->noSync );
++    assert( p->journalMode==PAGER_JOURNALMODE_OFF 
++         || p->journalMode==PAGER_JOURNALMODE_MEMORY 
++    );
++    assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
++    assert( pagerUseWal(p)==0 );
+   }
+ 
+-  pPager->journalOff += JOURNAL_HDR_SZ(pPager);
+-  return rc;
+-}
++  /* If changeCountDone is set, a RESERVED lock or greater must be held
++  ** on the file.
++  */
++  assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
++  assert( p->eLock!=PENDING_LOCK );
+ 
++  switch( p->eState ){
++    case PAGER_OPEN:
++      assert( !MEMDB );
++      assert( pPager->errCode==SQLITE_OK );
++      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
++      break;
+ 
+-/*
+-** Write the supplied master journal name into the journal file for pager
+-** pPager at the current location. The master journal name must be the last
+-** thing written to a journal file. If the pager is in full-sync mode, the
+-** journal file descriptor is advanced to the next sector boundary before
+-** anything is written. The format is:
+-**
+-**   + 4 bytes: PAGER_MJ_PGNO.
+-**   + N bytes: Master journal filename in utf-8.
+-**   + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
+-**   + 4 bytes: Master journal name checksum.
+-**   + 8 bytes: aJournalMagic[].
+-**
+-** The master journal page checksum is the sum of the bytes in the master
+-** journal name, where each byte is interpreted as a signed 8-bit integer.
+-**
+-** If zMaster is a NULL pointer (occurs for a single database transaction), 
+-** this call is a no-op.
+-*/
+-static int writeMasterJournal(Pager *pPager, const char *zMaster){
+-  int rc;                          /* Return code */
+-  int nMaster;                     /* Length of string zMaster */
+-  i64 iHdrOff;                     /* Offset of header in journal file */
+-  i64 jrnlSize;                    /* Size of journal file on disk */
+-  u32 cksum = 0;                   /* Checksum of string zMaster */
++    case PAGER_READER:
++      assert( pPager->errCode==SQLITE_OK );
++      assert( p->eLock!=UNKNOWN_LOCK );
++      assert( p->eLock>=SHARED_LOCK );
++      break;
+ 
+-  assert( pPager->setMaster==0 );
+-  assert( !pagerUseWal(pPager) );
++    case PAGER_WRITER_LOCKED:
++      assert( p->eLock!=UNKNOWN_LOCK );
++      assert( pPager->errCode==SQLITE_OK );
++      if( !pagerUseWal(pPager) ){
++        assert( p->eLock>=RESERVED_LOCK );
++      }
++      assert( pPager->dbSize==pPager->dbOrigSize );
++      assert( pPager->dbOrigSize==pPager->dbFileSize );
++      assert( pPager->dbOrigSize==pPager->dbHintSize );
++      assert( pPager->setMaster==0 );
++      break;
+ 
+-  if( !zMaster 
+-   || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
+-   || pPager->journalMode==PAGER_JOURNALMODE_OFF 
+-  ){
+-    return SQLITE_OK;
+-  }
+-  pPager->setMaster = 1;
+-  assert( isOpen(pPager->jfd) );
+-  assert( pPager->journalHdr <= pPager->journalOff );
++    case PAGER_WRITER_CACHEMOD:
++      assert( p->eLock!=UNKNOWN_LOCK );
++      assert( pPager->errCode==SQLITE_OK );
++      if( !pagerUseWal(pPager) ){
++        /* It is possible that if journal_mode=wal here that neither the
++        ** journal file nor the WAL file are open. This happens during
++        ** a rollback transaction that switches from journal_mode=off
++        ** to journal_mode=wal.
++        */
++        assert( p->eLock>=RESERVED_LOCK );
++        assert( isOpen(p->jfd) 
++             || p->journalMode==PAGER_JOURNALMODE_OFF 
++             || p->journalMode==PAGER_JOURNALMODE_WAL 
++        );
++      }
++      assert( pPager->dbOrigSize==pPager->dbFileSize );
++      assert( pPager->dbOrigSize==pPager->dbHintSize );
++      break;
+ 
+-  /* Calculate the length in bytes and the checksum of zMaster */
+-  for(nMaster=0; zMaster[nMaster]; nMaster++){
+-    cksum += zMaster[nMaster];
+-  }
++    case PAGER_WRITER_DBMOD:
++      assert( p->eLock==EXCLUSIVE_LOCK );
++      assert( pPager->errCode==SQLITE_OK );
++      assert( !pagerUseWal(pPager) );
++      assert( p->eLock>=EXCLUSIVE_LOCK );
++      assert( isOpen(p->jfd) 
++           || p->journalMode==PAGER_JOURNALMODE_OFF 
++           || p->journalMode==PAGER_JOURNALMODE_WAL 
++      );
++      assert( pPager->dbOrigSize<=pPager->dbHintSize );
++      break;
+ 
+-  /* If in full-sync mode, advance to the next disk sector before writing
+-  ** the master journal name. This is in case the previous page written to
+-  ** the journal has already been synced.
+-  */
+-  if( pPager->fullSync ){
+-    pPager->journalOff = journalHdrOffset(pPager);
+-  }
+-  iHdrOff = pPager->journalOff;
++    case PAGER_WRITER_FINISHED:
++      assert( p->eLock==EXCLUSIVE_LOCK );
++      assert( pPager->errCode==SQLITE_OK );
++      assert( !pagerUseWal(pPager) );
++      assert( isOpen(p->jfd) 
++           || p->journalMode==PAGER_JOURNALMODE_OFF 
++           || p->journalMode==PAGER_JOURNALMODE_WAL 
++      );
++      break;
+ 
+-  /* Write the master journal data to the end of the journal file. If
+-  ** an error occurs, return the error code to the caller.
+-  */
+-  if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
+-   || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
+-   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
+-   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
+-   || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8)))
+-  ){
+-    return rc;
++    case PAGER_ERROR:
++      /* There must be at least one outstanding reference to the pager if
++      ** in ERROR state. Otherwise the pager should have already dropped
++      ** back to OPEN state.
++      */
++      assert( pPager->errCode!=SQLITE_OK );
++      assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
++      break;
+   }
+-  pPager->journalOff += (nMaster+20);
+ 
+-  /* If the pager is in peristent-journal mode, then the physical 
+-  ** journal-file may extend past the end of the master-journal name
+-  ** and 8 bytes of magic data just written to the file. This is 
+-  ** dangerous because the code to rollback a hot-journal file
+-  ** will not be able to find the master-journal name to determine 
+-  ** whether or not the journal is hot. 
+-  **
+-  ** Easiest thing to do in this scenario is to truncate the journal 
+-  ** file to the required size.
+-  */ 
+-  if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
+-   && jrnlSize>pPager->journalOff
+-  ){
+-    rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
+-  }
+-  return rc;
++  return 1;
+ }
++#endif /* ifndef NDEBUG */
+ 
++#ifdef SQLITE_DEBUG 
+ /*
+-** Find a page in the hash table given its page number. Return
+-** a pointer to the page or NULL if the requested page is not 
+-** already in memory.
++** Return a pointer to a human readable string in a static buffer
++** containing the state of the Pager object passed as an argument. This
++** is intended to be used within debuggers. For example, as an alternative
++** to "print *pPager" in gdb:
++**
++** (gdb) printf "%s", print_pager_state(pPager)
+ */
+-static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
+-  PgHdr *p;                         /* Return value */
++static char *print_pager_state(Pager *p){
++  static char zRet[1024];
+ 
+-  /* It is not possible for a call to PcacheFetch() with createFlag==0 to
+-  ** fail, since no attempt to allocate dynamic memory will be made.
+-  */
+-  (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
+-  return p;
++  sqlite3_snprintf(1024, zRet,
++      "Filename:      %s\n"
++      "State:         %s errCode=%d\n"
++      "Lock:          %s\n"
++      "Locking mode:  locking_mode=%s\n"
++      "Journal mode:  journal_mode=%s\n"
++      "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
++      "Journal:       journalOff=%lld journalHdr=%lld\n"
++      "Size:          dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
++      , p->zFilename
++      , p->eState==PAGER_OPEN            ? "OPEN" :
++        p->eState==PAGER_READER          ? "READER" :
++        p->eState==PAGER_WRITER_LOCKED   ? "WRITER_LOCKED" :
++        p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
++        p->eState==PAGER_WRITER_DBMOD    ? "WRITER_DBMOD" :
++        p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
++        p->eState==PAGER_ERROR           ? "ERROR" : "?error?"
++      , (int)p->errCode
++      , p->eLock==NO_LOCK         ? "NO_LOCK" :
++        p->eLock==RESERVED_LOCK   ? "RESERVED" :
++        p->eLock==EXCLUSIVE_LOCK  ? "EXCLUSIVE" :
++        p->eLock==SHARED_LOCK     ? "SHARED" :
++        p->eLock==UNKNOWN_LOCK    ? "UNKNOWN" : "?error?"
++      , p->exclusiveMode ? "exclusive" : "normal"
++      , p->journalMode==PAGER_JOURNALMODE_MEMORY   ? "memory" :
++        p->journalMode==PAGER_JOURNALMODE_OFF      ? "off" :
++        p->journalMode==PAGER_JOURNALMODE_DELETE   ? "delete" :
++        p->journalMode==PAGER_JOURNALMODE_PERSIST  ? "persist" :
++        p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
++        p->journalMode==PAGER_JOURNALMODE_WAL      ? "wal" : "?error?"
++      , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
++      , p->journalOff, p->journalHdr
++      , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
++  );
++
++  return zRet;
+ }
++#endif
+ 
+ /*
+-** Discard the entire contents of the in-memory page-cache.
++** Return true if it is necessary to write page *pPg into the sub-journal.
++** A page needs to be written into the sub-journal if there exists one
++** or more open savepoints for which:
++**
++**   * The page-number is less than or equal to PagerSavepoint.nOrig, and
++**   * The bit corresponding to the page-number is not set in
++**     PagerSavepoint.pInSavepoint.
+ */
+-static void pager_reset(Pager *pPager){
+-  sqlite3BackupRestart(pPager->pBackup);
+-  sqlite3PcacheClear(pPager->pPCache);
++static int subjRequiresPage(PgHdr *pPg){
++  Pgno pgno = pPg->pgno;
++  Pager *pPager = pPg->pPager;
++  int i;
++  for(i=0; i<pPager->nSavepoint; i++){
++    PagerSavepoint *p = &pPager->aSavepoint[i];
++    if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
++      return 1;
++    }
++  }
++  return 0;
+ }
+ 
+ /*
+-** Free all structures in the Pager.aSavepoint[] array and set both
+-** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
+-** if it is open and the pager is not in exclusive mode.
++** Return true if the page is already in the journal file.
+ */
+-static void releaseAllSavepoints(Pager *pPager){
+-  int ii;               /* Iterator for looping through Pager.aSavepoint */
+-  for(ii=0; ii<pPager->nSavepoint; ii++){
+-    sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
+-  }
+-  if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){
+-    sqlite3OsClose(pPager->sjfd);
+-  }
+-  sqlite3_free(pPager->aSavepoint);
+-  pPager->aSavepoint = 0;
+-  pPager->nSavepoint = 0;
+-  pPager->nSubRec = 0;
++static int pageInJournal(PgHdr *pPg){
++  return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
+ }
+ 
+ /*
+-** Set the bit number pgno in the PagerSavepoint.pInSavepoint 
+-** bitvecs of all open savepoints. Return SQLITE_OK if successful
+-** or SQLITE_NOMEM if a malloc failure occurs.
++** Read a 32-bit integer from the given file descriptor.  Store the integer
++** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
++** error code is something goes wrong.
++**
++** All values are stored on disk as big-endian.
+ */
+-static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
+-  int ii;                   /* Loop counter */
+-  int rc = SQLITE_OK;       /* Result code */
+-
+-  for(ii=0; ii<pPager->nSavepoint; ii++){
+-    PagerSavepoint *p = &pPager->aSavepoint[ii];
+-    if( pgno<=p->nOrig ){
+-      rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
+-      testcase( rc==SQLITE_NOMEM );
+-      assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+-    }
++static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
++  unsigned char ac[4];
++  int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
++  if( rc==SQLITE_OK ){
++    *pRes = sqlite3Get4byte(ac);
+   }
+   return rc;
+ }
+ 
+ /*
+-** This function is a no-op if the pager is in exclusive mode and not
+-** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
+-** state.
+-**
+-** If the pager is not in exclusive-access mode, the database file is
+-** completely unlocked. If the file is unlocked and the file-system does
+-** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
+-** closed (if it is open).
+-**
+-** If the pager is in ERROR state when this function is called, the 
+-** contents of the pager cache are discarded before switching back to 
+-** the OPEN state. Regardless of whether the pager is in exclusive-mode
+-** or not, any journal file left in the file-system will be treated
+-** as a hot-journal and rolled back the next time a read-transaction
+-** is opened (by this or by any other connection).
++** Write a 32-bit integer into a string buffer in big-endian byte order.
+ */
+-static void pager_unlock(Pager *pPager){
+-
+-  assert( pPager->eState==PAGER_READER 
+-       || pPager->eState==PAGER_OPEN 
+-       || pPager->eState==PAGER_ERROR 
+-  );
+-
+-  sqlite3BitvecDestroy(pPager->pInJournal);
+-  pPager->pInJournal = 0;
+-  releaseAllSavepoints(pPager);
+-
+-  if( pagerUseWal(pPager) ){
+-    assert( !isOpen(pPager->jfd) );
+-    sqlite3WalEndReadTransaction(pPager->pWal);
+-    pPager->eState = PAGER_OPEN;
+-  }else if( !pPager->exclusiveMode ){
+-    int rc;                       /* Error code returned by pagerUnlockDb() */
+-    int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
+-
+-    /* If the operating system support deletion of open files, then
+-    ** close the journal file when dropping the database lock.  Otherwise
+-    ** another connection with journal_mode=delete might delete the file
+-    ** out from under us.
+-    */
+-    assert( (PAGER_JOURNALMODE_MEMORY   & 5)!=1 );
+-    assert( (PAGER_JOURNALMODE_OFF      & 5)!=1 );
+-    assert( (PAGER_JOURNALMODE_WAL      & 5)!=1 );
+-    assert( (PAGER_JOURNALMODE_DELETE   & 5)!=1 );
+-    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
+-    assert( (PAGER_JOURNALMODE_PERSIST  & 5)==1 );
+-    if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
+-     || 1!=(pPager->journalMode & 5)
+-    ){
+-      sqlite3OsClose(pPager->jfd);
+-    }
+-
+-    /* If the pager is in the ERROR state and the call to unlock the database
+-    ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
+-    ** above the #define for UNKNOWN_LOCK for an explanation of why this
+-    ** is necessary.
+-    */
+-    rc = pagerUnlockDb(pPager, NO_LOCK);
+-    if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
+-      pPager->eLock = UNKNOWN_LOCK;
+-    }
+-
+-    /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
+-    ** without clearing the error code. This is intentional - the error
+-    ** code is cleared and the cache reset in the block below.
+-    */
+-    assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
+-    pPager->changeCountDone = 0;
+-    pPager->eState = PAGER_OPEN;
+-  }
++#define put32bits(A,B)  sqlite3Put4byte((u8*)A,B)
+ 
+-  /* If Pager.errCode is set, the contents of the pager cache cannot be
+-  ** trusted. Now that there are no outstanding references to the pager,
+-  ** it can safely move back to PAGER_OPEN state. This happens in both
+-  ** normal and exclusive-locking mode.
+-  */
+-  if( pPager->errCode ){
+-    assert( !MEMDB );
+-    pager_reset(pPager);
+-    pPager->changeCountDone = pPager->tempFile;
+-    pPager->eState = PAGER_OPEN;
+-    pPager->errCode = SQLITE_OK;
+-  }
+ 
+-  pPager->journalOff = 0;
+-  pPager->journalHdr = 0;
+-  pPager->setMaster = 0;
++/*
++** Write a 32-bit integer into the given file descriptor.  Return SQLITE_OK
++** on success or an error code is something goes wrong.
++*/
++static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
++  char ac[4];
++  put32bits(ac, val);
++  return sqlite3OsWrite(fd, ac, 4, offset);
+ }
+ 
+ /*
+-** This function is called whenever an IOERR or FULL error that requires
+-** the pager to transition into the ERROR state may ahve occurred.
+-** The first argument is a pointer to the pager structure, the second 
+-** the error-code about to be returned by a pager API function. The 
+-** value returned is a copy of the second argument to this function. 
+-**
+-** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
+-** IOERR sub-codes, the pager enters the ERROR state and the error code
+-** is stored in Pager.errCode. While the pager remains in the ERROR state,
+-** all major API calls on the Pager will immediately return Pager.errCode.
++** Unlock the database file to level eLock, which must be either NO_LOCK
++** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
++** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
+ **
+-** The ERROR state indicates that the contents of the pager-cache 
+-** cannot be trusted. This state can be cleared by completely discarding 
+-** the contents of the pager-cache. If a transaction was active when
+-** the persistent error occurred, then the rollback journal may need
+-** to be replayed to restore the contents of the database file (as if
+-** it were a hot-journal).
++** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
++** called, do not modify it. See the comment above the #define of 
++** UNKNOWN_LOCK for an explanation of this.
+ */
+-static int pager_error(Pager *pPager, int rc){
+-  int rc2 = rc & 0xff;
+-  assert( rc==SQLITE_OK || !MEMDB );
+-  assert(
+-       pPager->errCode==SQLITE_FULL ||
+-       pPager->errCode==SQLITE_OK ||
+-       (pPager->errCode & 0xff)==SQLITE_IOERR
+-  );
+-  if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
+-    pPager->errCode = rc;
+-    pPager->eState = PAGER_ERROR;
++static int pagerUnlockDb(Pager *pPager, int eLock){
++  int rc = SQLITE_OK;
++
++  assert( !pPager->exclusiveMode || pPager->eLock==eLock );
++  assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
++  assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
++  if( isOpen(pPager->fd) ){
++    assert( pPager->eLock>=eLock );
++    rc = sqlite3OsUnlock(pPager->fd, eLock);
++    if( pPager->eLock!=UNKNOWN_LOCK ){
++      pPager->eLock = (u8)eLock;
++    }
++    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
+   }
+   return rc;
+ }
+ 
+-static int pager_truncate(Pager *pPager, Pgno nPage);
+-
+ /*
+-** This routine ends a transaction. A transaction is usually ended by 
+-** either a COMMIT or a ROLLBACK operation. This routine may be called 
+-** after rollback of a hot-journal, or if an error occurs while opening
+-** the journal file or writing the very first journal-header of a
+-** database transaction.
+-** 
+-** This routine is never called in PAGER_ERROR state. If it is called
+-** in PAGER_NONE or PAGER_SHARED state and the lock held is less
+-** exclusive than a RESERVED lock, it is a no-op.
+-**
+-** Otherwise, any active savepoints are released.
+-**
+-** If the journal file is open, then it is "finalized". Once a journal 
+-** file has been finalized it is not possible to use it to roll back a 
+-** transaction. Nor will it be considered to be a hot-journal by this
+-** or any other database connection. Exactly how a journal is finalized
+-** depends on whether or not the pager is running in exclusive mode and
+-** the current journal-mode (Pager.journalMode value), as follows:
+-**
+-**   journalMode==MEMORY
+-**     Journal file descriptor is simply closed. This destroys an 
+-**     in-memory journal.
+-**
+-**   journalMode==TRUNCATE
+-**     Journal file is truncated to zero bytes in size.
+-**
+-**   journalMode==PERSIST
+-**     The first 28 bytes of the journal file are zeroed. This invalidates
+-**     the first journal header in the file, and hence the entire journal
+-**     file. An invalid journal file cannot be rolled back.
+-**
+-**   journalMode==DELETE
+-**     The journal file is closed and deleted using sqlite3OsDelete().
+-**
+-**     If the pager is running in exclusive mode, this method of finalizing
+-**     the journal file is never used. Instead, if the journalMode is
+-**     DELETE and the pager is in exclusive mode, the method described under
+-**     journalMode==PERSIST is used instead.
+-**
+-** After the journal is finalized, the pager moves to PAGER_READER state.
+-** If running in non-exclusive rollback mode, the lock on the file is 
+-** downgraded to a SHARED_LOCK.
++** Lock the database file to level eLock, which must be either SHARED_LOCK,
++** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
++** Pager.eLock variable to the new locking state. 
+ **
+-** SQLITE_OK is returned if no error occurs. If an error occurs during
+-** any of the IO operations to finalize the journal file or unlock the
+-** database then the IO error code is returned to the user. If the 
+-** operation to finalize the journal file fails, then the code still
+-** tries to unlock the database file if not in exclusive mode. If the
+-** unlock operation fails as well, then the first error code related
+-** to the first error encountered (the journal finalization one) is
+-** returned.
++** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is 
++** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. 
++** See the comment above the #define of UNKNOWN_LOCK for an explanation 
++** of this.
+ */
+-static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
+-  int rc = SQLITE_OK;      /* Error code from journal finalization operation */
+-  int rc2 = SQLITE_OK;     /* Error code from db file unlock operation */
+-
+-  /* Do nothing if the pager does not have an open write transaction
+-  ** or at least a RESERVED lock. This function may be called when there
+-  ** is no write-transaction active but a RESERVED or greater lock is
+-  ** held under two circumstances:
+-  **
+-  **   1. After a successful hot-journal rollback, it is called with
+-  **      eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
+-  **
+-  **   2. If a connection with locking_mode=exclusive holding an EXCLUSIVE 
+-  **      lock switches back to locking_mode=normal and then executes a
+-  **      read-transaction, this function is called with eState==PAGER_READER 
+-  **      and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
+-  */
+-  assert( assert_pager_state(pPager) );
+-  assert( pPager->eState!=PAGER_ERROR );
+-  if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
+-    return SQLITE_OK;
+-  }
+-
+-  releaseAllSavepoints(pPager);
+-  assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
+-  if( isOpen(pPager->jfd) ){
+-    assert( !pagerUseWal(pPager) );
+-
+-    /* Finalize the journal file. */
+-    if( sqlite3IsMemJournal(pPager->jfd) ){
+-      assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY );
+-      sqlite3OsClose(pPager->jfd);
+-    }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
+-      if( pPager->journalOff==0 ){
+-        rc = SQLITE_OK;
+-      }else{
+-        rc = sqlite3OsTruncate(pPager->jfd, 0);
+-      }
+-      pPager->journalOff = 0;
+-    }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+-      || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
+-    ){
+-      rc = zeroJournalHdr(pPager, hasMaster);
+-      pPager->journalOff = 0;
+-    }else{
+-      /* This branch may be executed with Pager.journalMode==MEMORY if
+-      ** a hot-journal was just rolled back. In this case the journal
+-      ** file should be closed and deleted. If this connection writes to
+-      ** the database file, it will do so using an in-memory journal. 
+-      */
+-      int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
+-      assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
+-           || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
+-           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
+-      );
+-      sqlite3OsClose(pPager->jfd);
+-      if( bDelete ){
+-        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+-      }
+-    }
+-  }
++static int pagerLockDb(Pager *pPager, int eLock){
++  int rc = SQLITE_OK;
+ 
+-#ifdef SQLITE_CHECK_PAGES
+-  sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
+-  if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
+-    PgHdr *p = pager_lookup(pPager, 1);
+-    if( p ){
+-      p->pageHash = 0;
+-      sqlite3PagerUnref(p);
++  assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
++  if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
++    rc = sqlite3OsLock(pPager->fd, eLock);
++    if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
++      pPager->eLock = (u8)eLock;
++      IOTRACE(("LOCK %p %d\n", pPager, eLock))
+     }
+   }
+-#endif
+-
+-  sqlite3BitvecDestroy(pPager->pInJournal);
+-  pPager->pInJournal = 0;
+-  pPager->nRec = 0;
+-  sqlite3PcacheCleanAll(pPager->pPCache);
+-  sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
+-
+-  if( pagerUseWal(pPager) ){
+-    /* Drop the WAL write-lock, if any. Also, if the connection was in 
+-    ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE 
+-    ** lock held on the database file.
+-    */
+-    rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
+-    assert( rc2==SQLITE_OK );
+-  }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
+-    /* This branch is taken when committing a transaction in rollback-journal
+-    ** mode if the database file on disk is larger than the database image.
+-    ** At this point the journal has been finalized and the transaction 
+-    ** successfully committed, but the EXCLUSIVE lock is still held on the
+-    ** file. So it is safe to truncate the database file to its minimum
+-    ** required size.  */
+-    assert( pPager->eLock==EXCLUSIVE_LOCK );
+-    rc = pager_truncate(pPager, pPager->dbSize);
+-  }
+-
+-  if( !pPager->exclusiveMode 
+-   && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
+-  ){
+-    rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
+-    pPager->changeCountDone = 0;
+-  }
+-  pPager->eState = PAGER_READER;
+-  pPager->setMaster = 0;
+-
+-  return (rc==SQLITE_OK?rc2:rc);
++  return rc;
+ }
+ 
+ /*
+-** Execute a rollback if a transaction is active and unlock the 
+-** database file. 
++** This function determines whether or not the atomic-write optimization
++** can be used with this pager. The optimization can be used if:
+ **
+-** If the pager has already entered the ERROR state, do not attempt 
+-** the rollback at this time. Instead, pager_unlock() is called. The
+-** call to pager_unlock() will discard all in-memory pages, unlock
+-** the database file and move the pager back to OPEN state. If this 
+-** means that there is a hot-journal left in the file-system, the next 
+-** connection to obtain a shared lock on the pager (which may be this one) 
+-** will roll it back.
++**  (a) the value returned by OsDeviceCharacteristics() indicates that
++**      a database page may be written atomically, and
++**  (b) the value returned by OsSectorSize() is less than or equal
++**      to the page size.
+ **
+-** If the pager has not already entered the ERROR state, but an IO or
+-** malloc error occurs during a rollback, then this will itself cause 
+-** the pager to enter the ERROR state. Which will be cleared by the
+-** call to pager_unlock(), as described above.
++** The optimization is also always enabled for temporary files. It is
++** an error to call this function if pPager is opened on an in-memory
++** database.
++**
++** If the optimization cannot be used, 0 is returned. If it can be used,
++** then the value returned is the size of the journal file when it
++** contains rollback data for exactly one page.
+ */
+-static void pagerUnlockAndRollback(Pager *pPager){
+-  if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
+-    assert( assert_pager_state(pPager) );
+-    if( pPager->eState>=PAGER_WRITER_LOCKED ){
+-      sqlite3BeginBenignMalloc();
+-      sqlite3PagerRollback(pPager);
+-      sqlite3EndBenignMalloc();
+-    }else if( !pPager->exclusiveMode ){
+-      assert( pPager->eState==PAGER_READER );
+-      pager_end_transaction(pPager, 0, 0);
++#ifdef SQLITE_ENABLE_ATOMIC_WRITE
++static int jrnlBufferSize(Pager *pPager){
++  assert( !MEMDB );
++  if( !pPager->tempFile ){
++    int dc;                           /* Device characteristics */
++    int nSector;                      /* Sector size */
++    int szPage;                       /* Page size */
++
++    assert( isOpen(pPager->fd) );
++    dc = sqlite3OsDeviceCharacteristics(pPager->fd);
++    nSector = pPager->sectorSize;
++    szPage = pPager->pageSize;
++
++    assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
++    assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
++    if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
++      return 0;
+     }
+   }
+-  pager_unlock(pPager);
++
++  return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
+ }
++#endif
+ 
+ /*
+-** Parameter aData must point to a buffer of pPager->pageSize bytes
+-** of data. Compute and return a checksum based ont the contents of the 
+-** page of data and the current value of pPager->cksumInit.
+-**
+-** This is not a real checksum. It is really just the sum of the 
+-** random initial value (pPager->cksumInit) and every 200th byte
+-** of the page data, starting with byte offset (pPager->pageSize%200).
+-** Each byte is interpreted as an 8-bit unsigned integer.
+-**
+-** Changing the formula used to compute this checksum results in an
+-** incompatible journal file format.
+-**
+-** If journal corruption occurs due to a power failure, the most likely 
+-** scenario is that one end or the other of the record will be changed. 
+-** It is much less likely that the two ends of the journal record will be
+-** correct and the middle be corrupt.  Thus, this "checksum" scheme,
+-** though fast and simple, catches the mostly likely kind of corruption.
++** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
++** on the cache using a hash function.  This is used for testing
++** and debugging only.
+ */
+-static u32 pager_cksum(Pager *pPager, const u8 *aData){
+-  u32 cksum = pPager->cksumInit;         /* Checksum value to return */
+-  int i = pPager->pageSize-200;          /* Loop counter */
+-  while( i>0 ){
+-    cksum += aData[i];
+-    i -= 200;
++#ifdef SQLITE_CHECK_PAGES
++/*
++** Return a 32-bit hash of the page data for pPage.
++*/
++static u32 pager_datahash(int nByte, unsigned char *pData){
++  u32 hash = 0;
++  int i;
++  for(i=0; i<nByte; i++){
++    hash = (hash*1039) + pData[i];
+   }
+-  return cksum;
++  return hash;
 +}
++static u32 pager_pagehash(PgHdr *pPage){
++  return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
++}
++static void pager_set_pagehash(PgHdr *pPage){
++  pPage->pageHash = pager_pagehash(pPage);
+ }
+ 
+ /*
+-** Report the current page size and number of reserved bytes back
+-** to the codec.
++** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
++** is defined, and NDEBUG is not defined, an assert() statement checks
++** that the page is either dirty or still matches the calculated page-hash.
+ */
+-#ifdef SQLITE_HAS_CODEC
+-static void pagerReportSize(Pager *pPager){
+-  if( pPager->xCodecSizeChng ){
+-    pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
+-                           (int)pPager->nReserve);
+-  }
++#define CHECK_PAGE(x) checkPage(x)
++static void checkPage(PgHdr *pPg){
++  Pager *pPager = pPg->pPager;
++  assert( pPager->eState!=PAGER_ERROR );
++  assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
+ }
 +
-+SQLITE_PRIVATE int sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno) {
-+  return (PAGER_MJ_PGNO(pPager) == pgno) ? 1 : 0;
+ #else
+-# define pagerReportSize(X)     /* No-op if we do not support a codec */
+-#endif
++#define pager_datahash(X,Y)  0
++#define pager_pagehash(X)  0
++#define pager_set_pagehash(X)
++#define CHECK_PAGE(x)
++#endif  /* SQLITE_CHECK_PAGES */
+ 
+ /*
+-** Read a single page from either the journal file (if isMainJrnl==1) or
+-** from the sub-journal (if isMainJrnl==0) and playback that page.
+-** The page begins at offset *pOffset into the file. The *pOffset
+-** value is increased to the start of the next page in the journal.
+-**
+-** The main rollback journal uses checksums - the statement journal does 
+-** not.
+-**
+-** If the page number of the page record read from the (sub-)journal file
+-** is greater than the current value of Pager.dbSize, then playback is
+-** skipped and SQLITE_OK is returned.
++** When this is called the journal file for pager pPager must be open.
++** This function attempts to read a master journal file name from the 
++** end of the file and, if successful, copies it into memory supplied 
++** by the caller. See comments above writeMasterJournal() for the format
++** used to store a master journal file name at the end of a journal file.
+ **
+-** If pDone is not NULL, then it is a record of pages that have already
+-** been played back.  If the page at *pOffset has already been played back
+-** (if the corresponding pDone bit is set) then skip the playback.
+-** Make sure the pDone bit corresponding to the *pOffset page is set
+-** prior to returning.
++** zMaster must point to a buffer of at least nMaster bytes allocated by
++** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
++** enough space to write the master journal name). If the master journal
++** name in the journal is longer than nMaster bytes (including a
++** nul-terminator), then this is handled as if no master journal name
++** were present in the journal.
+ **
+-** If the page record is successfully read from the (sub-)journal file
+-** and played back, then SQLITE_OK is returned. If an IO error occurs
+-** while reading the record from the (sub-)journal file or while writing
+-** to the database file, then the IO error code is returned. If data
+-** is successfully read from the (sub-)journal file but appears to be
+-** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
+-** two circumstances:
+-** 
+-**   * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
+-**   * If the record is being rolled back from the main journal file
+-**     and the checksum field does not match the record content.
++** If a master journal file name is present at the end of the journal
++** file, then it is copied into the buffer pointed to by zMaster. A
++** nul-terminator byte is appended to the buffer following the master
++** journal file name.
+ **
+-** Neither of these two scenarios are possible during a savepoint rollback.
++** If it is determined that no master journal file name is present 
++** zMaster[0] is set to 0 and SQLITE_OK returned.
+ **
+-** If this is a savepoint rollback, then memory may have to be dynamically
+-** allocated by this function. If this is the case and an allocation fails,
+-** SQLITE_NOMEM is returned.
++** If an error occurs while reading from the journal file, an SQLite
++** error code is returned.
+ */
+-static int pager_playback_one_page(
+-  Pager *pPager,                /* The pager being played back */
+-  i64 *pOffset,                 /* Offset of record to playback */
+-  Bitvec *pDone,                /* Bitvec of pages already played back */
+-  int isMainJrnl,               /* 1 -> main journal. 0 -> sub-journal. */
+-  int isSavepnt                 /* True for a savepoint rollback */
+-){
+-  int rc;
+-  PgHdr *pPg;                   /* An existing page in the cache */
+-  Pgno pgno;                    /* The page number of a page in journal */
+-  u32 cksum;                    /* Checksum used for sanity checking */
+-  char *aData;                  /* Temporary storage for the page */
+-  sqlite3_file *jfd;            /* The file descriptor for the journal file */
+-  int isSynced;                 /* True if journal page is synced */
+-
+-  assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
+-  assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
+-  assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
+-  assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */
+-
+-  aData = pPager->pTmpSpace;
+-  assert( aData );         /* Temp storage must have already been allocated */
+-  assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
+-
+-  /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction 
+-  ** or savepoint rollback done at the request of the caller) or this is
+-  ** a hot-journal rollback. If it is a hot-journal rollback, the pager
+-  ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
+-  ** only reads from the main journal, not the sub-journal.
+-  */
+-  assert( pPager->eState>=PAGER_WRITER_CACHEMOD
+-       || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
+-  );
+-  assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
+-
+-  /* Read the page number and page data from the journal or sub-journal
+-  ** file. Return an error code to the caller if an IO error occurs.
+-  */
+-  jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
+-  rc = read32bits(jfd, *pOffset, &pgno);
+-  if( rc!=SQLITE_OK ) return rc;
+-  rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
+-  if( rc!=SQLITE_OK ) return rc;
+-  *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
+-
+-  /* Sanity checking on the page.  This is more important that I originally
+-  ** thought.  If a power failure occurs while the journal is being written,
+-  ** it could cause invalid data to be written into the journal.  We need to
+-  ** detect this invalid data (with high probability) and ignore it.
+-  */
+-  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
+-    assert( !isSavepnt );
+-    return SQLITE_DONE;
+-  }
+-  if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
+-    return SQLITE_OK;
+-  }
+-  if( isMainJrnl ){
+-    rc = read32bits(jfd, (*pOffset)-4, &cksum);
+-    if( rc ) return rc;
+-    if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
+-      return SQLITE_DONE;
+-    }
+-  }
++static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
++  int rc;                    /* Return code */
++  u32 len;                   /* Length in bytes of master journal name */
++  i64 szJ;                   /* Total size in bytes of journal file pJrnl */
++  u32 cksum;                 /* MJ checksum value read from journal */
++  u32 u;                     /* Unsigned loop counter */
++  unsigned char aMagic[8];   /* A buffer to hold the magic header */
++  zMaster[0] = '\0';
+ 
+-  /* If this page has already been played by before during the current
+-  ** rollback, then don't bother to play it back again.
+-  */
+-  if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
++  if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
++   || szJ<16
++   || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
++   || len>=nMaster 
++   || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
++   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
++   || memcmp(aMagic, aJournalMagic, 8)
++   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
++  ){
+     return rc;
+   }
+ 
+-  /* When playing back page 1, restore the nReserve setting
+-  */
+-  if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
+-    pPager->nReserve = ((u8*)aData)[20];
+-    pagerReportSize(pPager);
+-  }
+-
+-  /* If the pager is in CACHEMOD state, then there must be a copy of this
+-  ** page in the pager cache. In this case just update the pager cache,
+-  ** not the database file. The page is left marked dirty in this case.
+-  **
+-  ** An exception to the above rule: If the database is in no-sync mode
+-  ** and a page is moved during an incremental vacuum then the page may
+-  ** not be in the pager cache. Later: if a malloc() or IO error occurs
+-  ** during a Movepage() call, then the page may not be in the cache
+-  ** either. So the condition described in the above paragraph is not
+-  ** assert()able.
+-  **
+-  ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
+-  ** pager cache if it exists and the main file. The page is then marked 
+-  ** not dirty. Since this code is only executed in PAGER_OPEN state for
+-  ** a hot-journal rollback, it is guaranteed that the page-cache is empty
+-  ** if the pager is in OPEN state.
+-  **
+-  ** Ticket #1171:  The statement journal might contain page content that is
+-  ** different from the page content at the start of the transaction.
+-  ** This occurs when a page is changed prior to the start of a statement
+-  ** then changed again within the statement.  When rolling back such a
+-  ** statement we must not write to the original database unless we know
+-  ** for certain that original page contents are synced into the main rollback
+-  ** journal.  Otherwise, a power loss might leave modified data in the
+-  ** database file without an entry in the rollback journal that can
+-  ** restore the database to its original form.  Two conditions must be
+-  ** met before writing to the database files. (1) the database must be
+-  ** locked.  (2) we know that the original page content is fully synced
+-  ** in the main journal either because the page is not in cache or else
+-  ** the page is marked as needSync==0.
+-  **
+-  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
+-  ** is possible to fail a statement on a database that does not yet exist.
+-  ** Do not attempt to write if database file has never been opened.
+-  */
+-  if( pagerUseWal(pPager) ){
+-    pPg = 0;
+-  }else{
+-    pPg = pager_lookup(pPager, pgno);
+-  }
+-  assert( pPg || !MEMDB );
+-  assert( pPager->eState!=PAGER_OPEN || pPg==0 );
+-  PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
+-           PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
+-           (isMainJrnl?"main-journal":"sub-journal")
+-  ));
+-  if( isMainJrnl ){
+-    isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
+-  }else{
+-    isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
+-  }
+-  if( isOpen(pPager->fd)
+-   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+-   && isSynced
+-  ){
+-    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
+-    testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
+-    assert( !pagerUseWal(pPager) );
+-    rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+-    if( pgno>pPager->dbFileSize ){
+-      pPager->dbFileSize = pgno;
+-    }
+-    if( pPager->pBackup ){
+-      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
+-      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
+-      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
+-    }
+-  }else if( !isMainJrnl && pPg==0 ){
+-    /* If this is a rollback of a savepoint and data was not written to
+-    ** the database and the page is not in-memory, there is a potential
+-    ** problem. When the page is next fetched by the b-tree layer, it 
+-    ** will be read from the database file, which may or may not be 
+-    ** current. 
+-    **
+-    ** There are a couple of different ways this can happen. All are quite
+-    ** obscure. When running in synchronous mode, this can only happen 
+-    ** if the page is on the free-list at the start of the transaction, then
+-    ** populated, then moved using sqlite3PagerMovepage().
+-    **
+-    ** The solution is to add an in-memory page to the cache containing
+-    ** the data just read from the sub-journal. Mark the page as dirty 
+-    ** and if the pager requires a journal-sync, then mark the page as 
+-    ** requiring a journal-sync before it is written.
+-    */
+-    assert( isSavepnt );
+-    assert( pPager->doNotSpill==0 );
+-    pPager->doNotSpill++;
+-    rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
+-    assert( pPager->doNotSpill==1 );
+-    pPager->doNotSpill--;
+-    if( rc!=SQLITE_OK ) return rc;
+-    pPg->flags &= ~PGHDR_NEED_READ;
+-    sqlite3PcacheMakeDirty(pPg);
++  /* See if the checksum matches the master journal name */
++  for(u=0; u<len; u++){
++    cksum -= zMaster[u];
+   }
+-  if( pPg ){
+-    /* No page should ever be explicitly rolled back that is in use, except
+-    ** for page 1 which is held in use in order to keep the lock on the
+-    ** database active. However such a page may be rolled back as a result
+-    ** of an internal error resulting in an automatic call to
+-    ** sqlite3PagerRollback().
++  if( cksum ){
++    /* If the checksum doesn't add up, then one or more of the disk sectors
++    ** containing the master journal filename is corrupted. This means
++    ** definitely roll back, so just return SQLITE_OK and report a (nul)
++    ** master-journal filename.
+     */
+-    void *pData;
+-    pData = pPg->pData;
+-    memcpy(pData, (u8*)aData, pPager->pageSize);
+-    pPager->xReiniter(pPg);
+-    if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
+-      /* If the contents of this page were just restored from the main 
+-      ** journal file, then its content must be as they were when the 
+-      ** transaction was first opened. In this case we can mark the page
+-      ** as clean, since there will be no need to write it out to the
+-      ** database.
+-      **
+-      ** There is one exception to this rule. If the page is being rolled
+-      ** back as part of a savepoint (or statement) rollback from an 
+-      ** unsynced portion of the main journal file, then it is not safe
+-      ** to mark the page as clean. This is because marking the page as
+-      ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
+-      ** already in the journal file (recorded in Pager.pInJournal) and
+-      ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
+-      ** again within this transaction, it will be marked as dirty but
+-      ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
+-      ** be written out into the database file before its journal file
+-      ** segment is synced. If a crash occurs during or following this,
+-      ** database corruption may ensue.
+-      */
+-      assert( !pagerUseWal(pPager) );
+-      sqlite3PcacheMakeClean(pPg);
+-    }
+-    pager_set_pagehash(pPg);
+-
+-    /* If this was page 1, then restore the value of Pager.dbFileVers.
+-    ** Do this before any decoding. */
+-    if( pgno==1 ){
+-      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
+-    }
+-
+-    /* Decode the page just read from disk */
+-    CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
+-    sqlite3PcacheRelease(pPg);
++    len = 0;
+   }
+-  return rc;
++  zMaster[len] = '\0';
++   
++  return SQLITE_OK;
+ }
+ 
+ /*
+-** Parameter zMaster is the name of a master journal file. A single journal
+-** file that referred to the master journal file has just been rolled back.
+-** This routine checks if it is possible to delete the master journal file,
+-** and does so if it is.
+-**
+-** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not 
+-** available for use within this function.
+-**
+-** When a master journal file is created, it is populated with the names 
+-** of all of its child journals, one after another, formatted as utf-8 
+-** encoded text. The end of each child journal file is marked with a 
+-** nul-terminator byte (0x00). i.e. the entire contents of a master journal
+-** file for a transaction involving two databases might be:
+-**
+-**   "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
+-**
+-** A master journal file may only be deleted once all of its child 
+-** journals have been rolled back.
+-**
+-** This function reads the contents of the master-journal file into 
+-** memory and loops through each of the child journal names. For
+-** each child journal, it checks if:
+-**
+-**   * if the child journal exists, and if so
+-**   * if the child journal contains a reference to master journal 
+-**     file zMaster
+-**
+-** If a child journal can be found that matches both of the criteria
+-** above, this function returns without doing anything. Otherwise, if
+-** no such child journal can be found, file zMaster is deleted from
+-** the file-system using sqlite3OsDelete().
++** Return the offset of the sector boundary at or immediately 
++** following the value in pPager->journalOff, assuming a sector 
++** size of pPager->sectorSize bytes.
+ **
+-** If an IO error within this function, an error code is returned. This
+-** function allocates memory by calling sqlite3Malloc(). If an allocation
+-** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors 
+-** occur, SQLITE_OK is returned.
++** i.e for a sector size of 512:
+ **
+-** TODO: This function allocates a single block of memory to load
+-** the entire contents of the master journal file. This could be
+-** a couple of kilobytes or so - potentially larger than the page 
+-** size.
++**   Pager.journalOff          Return value
++**   ---------------------------------------
++**   0                         0
++**   512                       512
++**   100                       512
++**   2000                      2048
++** 
+ */
+-static int pager_delmaster(Pager *pPager, const char *zMaster){
+-  sqlite3_vfs *pVfs = pPager->pVfs;
+-  int rc;                   /* Return code */
+-  sqlite3_file *pMaster;    /* Malloc'd master-journal file descriptor */
+-  sqlite3_file *pJournal;   /* Malloc'd child-journal file descriptor */
+-  char *zMasterJournal = 0; /* Contents of master journal file */
+-  i64 nMasterJournal;       /* Size of master journal file */
+-  char *zJournal;           /* Pointer to one journal within MJ file */
+-  char *zMasterPtr;         /* Space to hold MJ filename from a journal file */
+-  int nMasterPtr;           /* Amount of space allocated to zMasterPtr[] */
+-
+-  /* Allocate space for both the pJournal and pMaster file descriptors.
+-  ** If successful, open the master journal file for reading.
+-  */
+-  pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
+-  pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
+-  if( !pMaster ){
+-    rc = SQLITE_NOMEM;
+-  }else{
+-    const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
+-    rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
+-  }
+-  if( rc!=SQLITE_OK ) goto delmaster_out;
+-
+-  /* Load the entire master journal file into space obtained from
+-  ** sqlite3_malloc() and pointed to by zMasterJournal.   Also obtain
+-  ** sufficient space (in zMasterPtr) to hold the names of master
+-  ** journal files extracted from regular rollback-journals.
+-  */
+-  rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
+-  if( rc!=SQLITE_OK ) goto delmaster_out;
+-  nMasterPtr = pVfs->mxPathname+1;
+-  zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
+-  if( !zMasterJournal ){
+-    rc = SQLITE_NOMEM;
+-    goto delmaster_out;
+-  }
+-  zMasterPtr = &zMasterJournal[nMasterJournal+1];
+-  rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
+-  if( rc!=SQLITE_OK ) goto delmaster_out;
+-  zMasterJournal[nMasterJournal] = 0;
+-
+-  zJournal = zMasterJournal;
+-  while( (zJournal-zMasterJournal)<nMasterJournal ){
+-    int exists;
+-    rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
+-    if( rc!=SQLITE_OK ){
+-      goto delmaster_out;
+-    }
+-    if( exists ){
+-      /* One of the journals pointed to by the master journal exists.
+-      ** Open it and check if it points at the master journal. If
+-      ** so, return without deleting the master journal file.
+-      */
+-      int c;
+-      int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
+-      rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
+-      if( rc!=SQLITE_OK ){
+-        goto delmaster_out;
+-      }
+-
+-      rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
+-      sqlite3OsClose(pJournal);
+-      if( rc!=SQLITE_OK ){
+-        goto delmaster_out;
+-      }
+-
+-      c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
+-      if( c ){
+-        /* We have a match. Do not delete the master journal file. */
+-        goto delmaster_out;
+-      }
+-    }
+-    zJournal += (sqlite3Strlen30(zJournal)+1);
+-  }
+- 
+-  sqlite3OsClose(pMaster);
+-  rc = sqlite3OsDelete(pVfs, zMaster, 0);
+-
+-delmaster_out:
+-  sqlite3_free(zMasterJournal);
+-  if( pMaster ){
+-    sqlite3OsClose(pMaster);
+-    assert( !isOpen(pJournal) );
+-    sqlite3_free(pMaster);
++static i64 journalHdrOffset(Pager *pPager){
++  i64 offset = 0;
++  i64 c = pPager->journalOff;
++  if( c ){
++    offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
+   }
+-  return rc;
++  assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
++  assert( offset>=c );
++  assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
++  return offset;
+ }
+ 
+-
+ /*
+-** This function is used to change the actual size of the database 
+-** file in the file-system. This only happens when committing a transaction,
+-** or rolling back a transaction (including rolling back a hot-journal).
++** The journal file must be open when this function is called.
+ **
+-** If the main database file is not open, or the pager is not in either
+-** DBMOD or OPEN state, this function is a no-op. Otherwise, the size 
+-** of the file is changed to nPage pages (nPage*pPager->pageSize bytes). 
+-** If the file on disk is currently larger than nPage pages, then use the VFS
+-** xTruncate() method to truncate it.
++** This function is a no-op if the journal file has not been written to
++** within the current transaction (i.e. if Pager.journalOff==0).
+ **
+-** Or, it might might be the case that the file on disk is smaller than 
+-** nPage pages. Some operating system implementations can get confused if 
+-** you try to truncate a file to some size that is larger than it 
+-** currently is, so detect this case and write a single zero byte to 
+-** the end of the new file instead.
++** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
++** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
++** zero the 28-byte header at the start of the journal file. In either case, 
++** if the pager is not in no-sync mode, sync the journal file immediately 
++** after writing or truncating it.
+ **
+-** If successful, return SQLITE_OK. If an IO error occurs while modifying
+-** the database file, return the error code to the caller.
++** If Pager.journalSizeLimit is set to a positive, non-zero value, and
++** following the truncation or zeroing described above the size of the 
++** journal file in bytes is larger than this value, then truncate the
++** journal file to Pager.journalSizeLimit bytes. The journal file does
++** not need to be synced following this operation.
++**
++** If an IO error occurs, abandon processing and return the IO error code.
++** Otherwise, return SQLITE_OK.
+ */
+-static int pager_truncate(Pager *pPager, Pgno nPage){
+-  int rc = SQLITE_OK;
+-  assert( pPager->eState!=PAGER_ERROR );
+-  assert( pPager->eState!=PAGER_READER );
+-  
+-  if( isOpen(pPager->fd) 
+-   && (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 = szPage*(i64)nPage;
+-    if( rc==SQLITE_OK && currentSize!=newSize ){
+-      if( currentSize>newSize ){
+-        rc = sqlite3OsTruncate(pPager->fd, newSize);
+-      }else if( (currentSize+szPage)<=newSize ){
+-        char *pTmp = pPager->pTmpSpace;
+-        memset(pTmp, 0, szPage);
+-        testcase( (newSize-szPage) == currentSize );
+-        testcase( (newSize-szPage) >  currentSize );
+-        rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
+-      }
+-      if( rc==SQLITE_OK ){
+-        pPager->dbFileSize = nPage;
++static int zeroJournalHdr(Pager *pPager, int doTruncate){
++  int rc = SQLITE_OK;                               /* Return code */
++  assert( isOpen(pPager->jfd) );
++  if( pPager->journalOff ){
++    const i64 iLimit = pPager->journalSizeLimit;    /* Local cache of jsl */
++
++    IOTRACE(("JZEROHDR %p\n", pPager))
++    if( doTruncate || iLimit==0 ){
++      rc = sqlite3OsTruncate(pPager->jfd, 0);
++    }else{
++      static const char zeroHdr[28] = {0};
++      rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
++    }
++    if( rc==SQLITE_OK && !pPager->noSync ){
++      rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
++    }
++
++    /* At this point the transaction is committed but the write lock 
++    ** is still held on the file. If there is a size limit configured for 
++    ** the persistent journal and the journal file currently consumes more
++    ** space than that limit allows for, truncate it now. There is no need
++    ** to sync the file following this operation.
++    */
++    if( rc==SQLITE_OK && iLimit>0 ){
++      i64 sz;
++      rc = sqlite3OsFileSize(pPager->jfd, &sz);
++      if( rc==SQLITE_OK && sz>iLimit ){
++        rc = sqlite3OsTruncate(pPager->jfd, iLimit);
+       }
+     }
+   }
+@@ -40870,8409 +42646,8969 @@
+ }
+ 
+ /*
+-** Return a sanitized version of the sector-size of OS file pFile. The
+-** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
++** The journal file must be open when this routine is called. A journal
++** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
++** current location.
++**
++** The format for the journal header is as follows:
++** - 8 bytes: Magic identifying journal format.
++** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
++** - 4 bytes: Random number used for page hash.
++** - 4 bytes: Initial database page count.
++** - 4 bytes: Sector size used by the process that wrote this journal.
++** - 4 bytes: Database page size.
++** 
++** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
+ */
+-SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
+-  int iRet = sqlite3OsSectorSize(pFile);
+-  if( iRet<32 ){
+-    iRet = 512;
+-  }else if( iRet>MAX_SECTOR_SIZE ){
+-    assert( MAX_SECTOR_SIZE>=512 );
+-    iRet = MAX_SECTOR_SIZE;
++static int writeJournalHdr(Pager *pPager){
++  int rc = SQLITE_OK;                 /* Return code */
++  char *zHeader = pPager->pTmpSpace;  /* Temporary space used to build header */
++  u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
++  u32 nWrite;                         /* Bytes of header sector written */
++  int ii;                             /* Loop counter */
++
++  assert( isOpen(pPager->jfd) );      /* Journal file must be open. */
++
++  if( nHeader>JOURNAL_HDR_SZ(pPager) ){
++    nHeader = JOURNAL_HDR_SZ(pPager);
+   }
+-  return iRet;
+-}
+ 
+-/*
+-** Set the value of the Pager.sectorSize variable for the given
+-** pager based on the value returned by the xSectorSize method
+-** of the open database file. The sector size will be used used 
+-** to determine the size and alignment of journal header and 
+-** master journal pointers within created journal files.
+-**
+-** For temporary files the effective sector size is always 512 bytes.
+-**
+-** Otherwise, for non-temporary files, the effective sector size is
+-** the value returned by the xSectorSize() method rounded up to 32 if
+-** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
+-** is greater than MAX_SECTOR_SIZE.
+-**
+-** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
+-** the effective sector size to its minimum value (512).  The purpose of
+-** pPager->sectorSize is to define the "blast radius" of bytes that
+-** might change if a crash occurs while writing to a single byte in
+-** that range.  But with POWERSAFE_OVERWRITE, the blast radius is zero
+-** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
+-** size.  For backwards compatibility of the rollback journal file format,
+-** we cannot reduce the effective sector size below 512.
+-*/
+-static void setSectorSize(Pager *pPager){
+-  assert( isOpen(pPager->fd) || pPager->tempFile );
++  /* If there are active savepoints and any of them were created 
++  ** since the most recent journal header was written, update the 
++  ** PagerSavepoint.iHdrOffset fields now.
++  */
++  for(ii=0; ii<pPager->nSavepoint; ii++){
++    if( pPager->aSavepoint[ii].iHdrOffset==0 ){
++      pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
++    }
++  }
+ 
+-  if( pPager->tempFile
+-   || (sqlite3OsDeviceCharacteristics(pPager->fd) & 
+-              SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
++  pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
++
++  /* 
++  ** Write the nRec Field - the number of page records that follow this
++  ** journal header. Normally, zero is written to this value at this time.
++  ** After the records are added to the journal (and the journal synced, 
++  ** if in full-sync mode), the zero is overwritten with the true number
++  ** of records (see syncJournal()).
++  **
++  ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
++  ** reading the journal this value tells SQLite to assume that the
++  ** rest of the journal file contains valid page records. This assumption
++  ** is dangerous, as if a failure occurred whilst writing to the journal
++  ** file it may contain some garbage data. There are two scenarios
++  ** where this risk can be ignored:
++  **
++  **   * When the pager is in no-sync mode. Corruption can follow a
++  **     power failure in this case anyway.
++  **
++  **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
++  **     that garbage data is never appended to the journal file.
++  */
++  assert( isOpen(pPager->fd) || pPager->noSync );
++  if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
++   || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 
+   ){
+-    /* Sector size doesn't matter for temporary files. Also, the file
+-    ** may not have been opened yet, in which case the OsSectorSize()
+-    ** call will segfault. */
+-    pPager->sectorSize = 512;
++    memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
++    put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
+   }else{
+-    pPager->sectorSize = sqlite3SectorSize(pPager->fd);
++    memset(zHeader, 0, sizeof(aJournalMagic)+4);
++  }
++
++  /* The random check-hash initializer */ 
++  sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
++  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
++  /* The initial database size */
++  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
++  /* The assumed sector size for this process */
++  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
++
++  /* The page size */
++  put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
++
++  /* Initializing the tail of the buffer is not necessary.  Everything
++  ** works find if the following memset() is omitted.  But initializing
++  ** the memory prevents valgrind from complaining, so we are willing to
++  ** take the performance hit.
++  */
++  memset(&zHeader[sizeof(aJournalMagic)+20], 0,
++         nHeader-(sizeof(aJournalMagic)+20));
++
++  /* In theory, it is only necessary to write the 28 bytes that the 
++  ** journal header consumes to the journal file here. Then increment the 
++  ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next 
++  ** record is written to the following sector (leaving a gap in the file
++  ** that will be implicitly filled in by the OS).
++  **
++  ** However it has been discovered that on some systems this pattern can 
++  ** be significantly slower than contiguously writing data to the file,
++  ** even if that means explicitly writing data to the block of 
++  ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
++  ** is done. 
++  **
++  ** The loop is required here in case the sector-size is larger than the 
++  ** database page size. Since the zHeader buffer is only Pager.pageSize
++  ** bytes in size, more than one call to sqlite3OsWrite() may be required
++  ** to populate the entire journal header sector.
++  */ 
++  for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
++    IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
++    rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
++    assert( pPager->journalHdr <= pPager->journalOff );
++    pPager->journalOff += nHeader;
+   }
++
++  return rc;
+ }
+ 
+ /*
+-** Playback the journal and thus restore the database file to
+-** the state it was in before we started making changes.  
+-**
+-** The journal file format is as follows: 
+-**
+-**  (1)  8 byte prefix.  A copy of aJournalMagic[].
+-**  (2)  4 byte big-endian integer which is the number of valid page records
+-**       in the journal.  If this value is 0xffffffff, then compute the
+-**       number of page records from the journal size.
+-**  (3)  4 byte big-endian integer which is the initial value for the 
+-**       sanity checksum.
+-**  (4)  4 byte integer which is the number of pages to truncate the
+-**       database to during a rollback.
+-**  (5)  4 byte big-endian integer which is the sector size.  The header
+-**       is this many bytes in size.
+-**  (6)  4 byte big-endian integer which is the page size.
+-**  (7)  zero padding out to the next sector size.
+-**  (8)  Zero or more pages instances, each as follows:
+-**        +  4 byte page number.
+-**        +  pPager->pageSize bytes of data.
+-**        +  4 byte checksum
+-**
+-** When we speak of the journal header, we mean the first 7 items above.
+-** Each entry in the journal is an instance of the 8th item.
+-**
+-** Call the value from the second bullet "nRec".  nRec is the number of
+-** valid page entries in the journal.  In most cases, you can compute the
+-** value of nRec from the size of the journal file.  But if a power
+-** failure occurred while the journal was being written, it could be the
+-** case that the size of the journal file had already been increased but
+-** the extra entries had not yet made it safely to disk.  In such a case,
+-** the value of nRec computed from the file size would be too large.  For
+-** that reason, we always use the nRec value in the header.
+-**
+-** If the nRec value is 0xffffffff it means that nRec should be computed
+-** from the file size.  This value is used when the user selects the
+-** no-sync option for the journal.  A power failure could lead to corruption
+-** in this case.  But for things like temporary table (which will be
+-** deleted when the power is restored) we don't care.  
+-**
+-** If the file opened as the journal file is not a well-formed
+-** journal file then all pages up to the first corrupted page are rolled
+-** back (or no pages if the journal header is corrupted). The journal file
+-** is then deleted and SQLITE_OK returned, just as if no corruption had
+-** been encountered.
++** The journal file must be open when this is called. A journal header file
++** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
++** file. The current location in the journal file is given by
++** pPager->journalOff. See comments above function writeJournalHdr() for
++** a description of the journal header format.
+ **
+-** If an I/O or malloc() error occurs, the journal-file is not deleted
+-** and an error code is returned.
++** If the header is read successfully, *pNRec is set to the number of
++** page records following this header and *pDbSize is set to the size of the
++** database before the transaction began, in pages. Also, pPager->cksumInit
++** is set to the value read from the journal header. SQLITE_OK is returned
++** in this case.
+ **
+-** The isHot parameter indicates that we are trying to rollback a journal
+-** that might be a hot journal.  Or, it could be that the journal is 
+-** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
+-** If the journal really is hot, reset the pager cache prior rolling
+-** back any content.  If the journal is merely persistent, no reset is
+-** needed.
++** If the journal header file appears to be corrupted, SQLITE_DONE is
++** returned and *pNRec and *PDbSize are undefined.  If JOURNAL_HDR_SZ bytes
++** cannot be read from the journal file an error code is returned.
+ */
+-static int pager_playback(Pager *pPager, int isHot){
+-  sqlite3_vfs *pVfs = pPager->pVfs;
+-  i64 szJ;                 /* Size of the journal file in bytes */
+-  u32 nRec;                /* Number of Records in the journal */
+-  u32 u;                   /* Unsigned loop counter */
+-  Pgno mxPg = 0;           /* Size of the original file in pages */
+-  int rc;                  /* Result code of a subroutine */
+-  int res = 1;             /* Value returned by sqlite3OsAccess() */
+-  char *zMaster = 0;       /* Name of master journal file if any */
+-  int needPagerReset;      /* True to reset page prior to first page rollback */
+-  int nPlayback = 0;       /* Total number of pages restored from journal */
++static int readJournalHdr(
++  Pager *pPager,               /* Pager object */
++  int isHot,
++  i64 journalSize,             /* Size of the open journal file in bytes */
++  u32 *pNRec,                  /* OUT: Value read from the nRec field */
++  u32 *pDbSize                 /* OUT: Value of original database size field */
++){
++  int rc;                      /* Return code */
++  unsigned char aMagic[8];     /* A buffer to hold the magic header */
++  i64 iHdrOff;                 /* Offset of journal header being read */
+ 
+-  /* Figure out how many records are in the journal.  Abort early if
+-  ** the journal is empty.
++  assert( isOpen(pPager->jfd) );      /* Journal file must be open. */
++
++  /* Advance Pager.journalOff to the start of the next sector. If the
++  ** journal file is too small for there to be a header stored at this
++  ** point, return SQLITE_DONE.
+   */
+-  assert( isOpen(pPager->jfd) );
+-  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
+-  if( rc!=SQLITE_OK ){
+-    goto end_playback;
++  pPager->journalOff = journalHdrOffset(pPager);
++  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
++    return SQLITE_DONE;
+   }
++  iHdrOff = pPager->journalOff;
+ 
+-  /* Read the master journal name from the journal, if it is present.
+-  ** If a master journal file name is specified, but the file is not
+-  ** present on disk, then the journal is not hot and does not need to be
+-  ** played back.
+-  **
+-  ** TODO: Technically the following is an error because it assumes that
+-  ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
+-  ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
+-  **  mxPathname is 512, which is the same as the minimum allowable value
+-  ** for pageSize.
++  /* Read in the first 8 bytes of the journal header. If they do not match
++  ** the  magic string found at the start of each journal header, return
++  ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
++  ** proceed.
+   */
+-  zMaster = pPager->pTmpSpace;
+-  rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
+-  if( rc==SQLITE_OK && zMaster[0] ){
+-    rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
+-  }
+-  zMaster = 0;
+-  if( rc!=SQLITE_OK || !res ){
+-    goto end_playback;
++  if( isHot || iHdrOff!=pPager->journalHdr ){
++    rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
++    if( rc ){
++      return rc;
++    }
++    if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
++      return SQLITE_DONE;
++    }
+   }
+-  pPager->journalOff = 0;
+-  needPagerReset = isHot;
+ 
+-  /* This loop terminates either when a readJournalHdr() or 
+-  ** pager_playback_one_page() call returns SQLITE_DONE or an IO error 
+-  ** occurs. 
++  /* Read the first three 32-bit fields of the journal header: The nRec
++  ** field, the checksum-initializer and the database size at the start
++  ** of the transaction. Return an error code if anything goes wrong.
+   */
+-  while( 1 ){
+-    /* Read the next journal header from the journal file.  If there are
+-    ** not enough bytes left in the journal file for a complete header, or
+-    ** it is corrupted, then a process must have failed while writing it.
+-    ** This indicates nothing more needs to be rolled back.
+-    */
+-    rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
+-    if( rc!=SQLITE_OK ){ 
+-      if( rc==SQLITE_DONE ){
+-        rc = SQLITE_OK;
+-      }
+-      goto end_playback;
+-    }
++  if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
++   || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
++   || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
++  ){
++    return rc;
++  }
+ 
+-    /* If nRec is 0xffffffff, then this journal was created by a process
+-    ** working in no-sync mode. This means that the rest of the journal
+-    ** file consists of pages, there are no more journal headers. Compute
+-    ** the value of nRec based on this assumption.
+-    */
+-    if( nRec==0xffffffff ){
+-      assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
+-      nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
+-    }
++  if( pPager->journalOff==0 ){
++    u32 iPageSize;               /* Page-size field of journal header */
++    u32 iSectorSize;             /* Sector-size field of journal header */
+ 
+-    /* If nRec is 0 and this rollback is of a transaction created by this
+-    ** process and if this is the final header in the journal, then it means
+-    ** that this part of the journal was being filled but has not yet been
+-    ** synced to disk.  Compute the number of pages based on the remaining
+-    ** size of the file.
+-    **
+-    ** The third term of the test was added to fix ticket #2565.
+-    ** When rolling back a hot journal, nRec==0 always means that the next
+-    ** chunk of the journal contains zero pages to be rolled back.  But
+-    ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
+-    ** the journal, it means that the journal might contain additional
+-    ** pages that need to be rolled back and that the number of pages 
+-    ** should be computed based on the journal file size.
+-    */
+-    if( nRec==0 && !isHot &&
+-        pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
+-      nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
++    /* Read the page-size and sector-size journal header fields. */
++    if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
++     || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
++    ){
++      return rc;
+     }
+ 
+-    /* If this is the first header read from the journal, truncate the
+-    ** database file back to its original size.
++    /* Versions of SQLite prior to 3.5.8 set the page-size field of the
++    ** journal header to zero. In this case, assume that the Pager.pageSize
++    ** variable is already set to the correct page size.
+     */
+-    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
+-      rc = pager_truncate(pPager, mxPg);
+-      if( rc!=SQLITE_OK ){
+-        goto end_playback;
+-      }
+-      pPager->dbSize = mxPg;
++    if( iPageSize==0 ){
++      iPageSize = pPager->pageSize;
+     }
+ 
+-    /* Copy original pages out of the journal and back into the 
+-    ** database file and/or page cache.
++    /* Check that the values read from the page-size and sector-size fields
++    ** are within range. To be 'in range', both values need to be a power
++    ** of two greater than or equal to 512 or 32, and not greater than their 
++    ** respective compile time maximum limits.
+     */
+-    for(u=0; u<nRec; u++){
+-      if( needPagerReset ){
+-        pager_reset(pPager);
+-        needPagerReset = 0;
+-      }
+-      rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
+-      if( rc==SQLITE_OK ){
+-        nPlayback++;
+-      }else{
+-        if( rc==SQLITE_DONE ){
+-          pPager->journalOff = szJ;
+-          break;
+-        }else if( rc==SQLITE_IOERR_SHORT_READ ){
+-          /* If the journal has been truncated, simply stop reading and
+-          ** processing the journal. This might happen if the journal was
+-          ** not completely written and synced prior to a crash.  In that
+-          ** case, the database should have never been written in the
+-          ** first place so it is OK to simply abandon the rollback. */
+-          rc = SQLITE_OK;
+-          goto end_playback;
+-        }else{
+-          /* If we are unable to rollback, quit and return the error
+-          ** code.  This will cause the pager to enter the error state
+-          ** so that no further harm will be done.  Perhaps the next
+-          ** process to come along will be able to rollback the database.
+-          */
+-          goto end_playback;
+-        }
+-      }
+-    }
+-  }
+-  /*NOTREACHED*/
+-  assert( 0 );
+-
+-end_playback:
+-  /* Following a rollback, the database file should be back in its original
+-  ** state prior to the start of the transaction, so invoke the
+-  ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
+-  ** assertion that the transaction counter was modified.
+-  */
+-#ifdef SQLITE_DEBUG
+-  if( pPager->fd->pMethods ){
+-    sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
+-  }
+-#endif
+-
+-  /* If this playback is happening automatically as a result of an IO or 
+-  ** malloc error that occurred after the change-counter was updated but 
+-  ** before the transaction was committed, then the change-counter 
+-  ** modification may just have been reverted. If this happens in exclusive 
+-  ** mode, then subsequent transactions performed by the connection will not
+-  ** update the change-counter at all. This may lead to cache inconsistency
+-  ** problems for other processes at some point in the future. So, just
+-  ** in case this has happened, clear the changeCountDone flag now.
+-  */
+-  pPager->changeCountDone = pPager->tempFile;
++    if( iPageSize<512                  || iSectorSize<32
++     || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
++     || ((iPageSize-1)&iPageSize)!=0   || ((iSectorSize-1)&iSectorSize)!=0 
++    ){
++      /* If the either the page-size or sector-size in the journal-header is 
++      ** invalid, then the process that wrote the journal-header must have 
++      ** crashed before the header was synced. In this case stop reading 
++      ** the journal file here.
++      */
++      return SQLITE_DONE;
++    }
+ 
+-  if( rc==SQLITE_OK ){
+-    zMaster = pPager->pTmpSpace;
+-    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
+-    testcase( rc!=SQLITE_OK );
+-  }
+-  if( rc==SQLITE_OK
+-   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+-  ){
+-    rc = sqlite3PagerSync(pPager);
+-  }
+-  if( rc==SQLITE_OK ){
+-    rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
+-    testcase( rc!=SQLITE_OK );
+-  }
+-  if( rc==SQLITE_OK && zMaster[0] && res ){
+-    /* If there was a master journal and this routine will return success,
+-    ** see if it is possible to delete the master journal.
++    /* Update the page-size to match the value read from the journal. 
++    ** Use a testcase() macro to make sure that malloc failure within 
++    ** PagerSetPagesize() is tested.
+     */
+-    rc = pager_delmaster(pPager, zMaster);
++    rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
+     testcase( rc!=SQLITE_OK );
+-  }
+-  if( isHot && nPlayback ){
+-    sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
+-                nPlayback, pPager->zJournal);
++
++    /* Update the assumed sector-size to match the value used by 
++    ** the process that created this journal. If this journal was
++    ** created by a process other than this one, then this routine
++    ** is being called from within pager_playback(). The local value
++    ** of Pager.sectorSize is restored at the end of that routine.
++    */
++    pPager->sectorSize = iSectorSize;
+   }
+ 
+-  /* The Pager.sectorSize variable may have been updated while rolling
+-  ** back a journal created by a process with a different sector size
+-  ** value. Reset it to the correct value for this process.
+-  */
+-  setSectorSize(pPager);
++  pPager->journalOff += JOURNAL_HDR_SZ(pPager);
+   return rc;
+ }
+ 
+ 
+ /*
+-** Read the content for page pPg out of the database file and into 
+-** pPg->pData. A shared lock or greater must be held on the database
+-** file before this function is called.
++** Write the supplied master journal name into the journal file for pager
++** pPager at the current location. The master journal name must be the last
++** thing written to a journal file. If the pager is in full-sync mode, the
++** journal file descriptor is advanced to the next sector boundary before
++** anything is written. The format is:
+ **
+-** If page 1 is read, then the value of Pager.dbFileVers[] is set to
+-** the value read from the database file.
++**   + 4 bytes: PAGER_MJ_PGNO.
++**   + N bytes: Master journal filename in utf-8.
++**   + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
++**   + 4 bytes: Master journal name checksum.
++**   + 8 bytes: aJournalMagic[].
+ **
+-** If an IO error occurs, then the IO error is returned to the caller.
+-** Otherwise, SQLITE_OK is returned.
++** The master journal page checksum is the sum of the bytes in the master
++** journal name, where each byte is interpreted as a signed 8-bit integer.
++**
++** If zMaster is a NULL pointer (occurs for a single database transaction), 
++** this call is a no-op.
+ */
+-static int readDbPage(PgHdr *pPg, u32 iFrame){
+-  Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
+-  Pgno pgno = pPg->pgno;       /* Page number to read */
+-  int rc = SQLITE_OK;          /* Return code */
+-  int pgsz = pPager->pageSize; /* Number of bytes to read */
++static int writeMasterJournal(Pager *pPager, const char *zMaster){
++  int rc;                          /* Return code */
++  int nMaster;                     /* Length of string zMaster */
++  i64 iHdrOff;                     /* Offset of header in journal file */
++  i64 jrnlSize;                    /* Size of journal file on disk */
++  u32 cksum = 0;                   /* Checksum of string zMaster */
+ 
+-  assert( pPager->eState>=PAGER_READER && !MEMDB );
+-  assert( isOpen(pPager->fd) );
++  assert( pPager->setMaster==0 );
++  assert( !pagerUseWal(pPager) );
+ 
+-  if( NEVER(!isOpen(pPager->fd)) ){
+-    assert( pPager->tempFile );
+-    memset(pPg->pData, 0, pPager->pageSize);
++  if( !zMaster 
++   || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
++   || pPager->journalMode==PAGER_JOURNALMODE_OFF 
++  ){
+     return SQLITE_OK;
+   }
++  pPager->setMaster = 1;
++  assert( isOpen(pPager->jfd) );
++  assert( pPager->journalHdr <= pPager->journalOff );
+ 
+-#ifndef SQLITE_OMIT_WAL
+-  if( iFrame ){
+-    /* Try to pull the page from the write-ahead log. */
+-    rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
+-  }else
+-#endif
+-  {
+-    i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
+-    rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
+-    if( rc==SQLITE_IOERR_SHORT_READ ){
+-      rc = SQLITE_OK;
+-    }
++  /* Calculate the length in bytes and the checksum of zMaster */
++  for(nMaster=0; zMaster[nMaster]; nMaster++){
++    cksum += zMaster[nMaster];
+   }
+ 
+-  if( pgno==1 ){
+-    if( rc ){
+-      /* If the read is unsuccessful, set the dbFileVers[] to something
+-      ** that will never be a valid file version.  dbFileVers[] is a copy
+-      ** of bytes 24..39 of the database.  Bytes 28..31 should always be
+-      ** zero or the size of the database in page. Bytes 32..35 and 35..39
+-      ** should be page numbers which are never 0xffffffff.  So filling
+-      ** pPager->dbFileVers[] with all 0xff bytes should suffice.
+-      **
+-      ** For an encrypted database, the situation is more complex:  bytes
+-      ** 24..39 of the database are white noise.  But the probability of
+-      ** white noising equaling 16 bytes of 0xff is vanishingly small so
+-      ** we should still be ok.
+-      */
+-      memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
+-    }else{
+-      u8 *dbFileVers = &((u8*)pPg->pData)[24];
+-      memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
+-    }
++  /* If in full-sync mode, advance to the next disk sector before writing
++  ** the master journal name. This is in case the previous page written to
++  ** the journal has already been synced.
++  */
++  if( pPager->fullSync ){
++    pPager->journalOff = journalHdrOffset(pPager);
+   }
+-  CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
++  iHdrOff = pPager->journalOff;
+ 
+-  PAGER_INCR(sqlite3_pager_readdb_count);
+-  PAGER_INCR(pPager->nRead);
+-  IOTRACE(("PGIN %p %d\n", pPager, pgno));
+-  PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
+-               PAGERID(pPager), pgno, pager_pagehash(pPg)));
++  /* Write the master journal data to the end of the journal file. If
++  ** an error occurs, return the error code to the caller.
++  */
++  if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
++   || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
++   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
++   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
++   || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8)))
++  ){
++    return rc;
++  }
++  pPager->journalOff += (nMaster+20);
+ 
++  /* If the pager is in peristent-journal mode, then the physical 
++  ** journal-file may extend past the end of the master-journal name
++  ** and 8 bytes of magic data just written to the file. This is 
++  ** dangerous because the code to rollback a hot-journal file
++  ** will not be able to find the master-journal name to determine 
++  ** whether or not the journal is hot. 
++  **
++  ** Easiest thing to do in this scenario is to truncate the journal 
++  ** file to the required size.
++  */ 
++  if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
++   && jrnlSize>pPager->journalOff
++  ){
++    rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
++  }
+   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.
++** Find a page in the hash table given its page number. Return
++** a pointer to the page or NULL if the requested page is not 
++** already in memory.
+ */
+-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);
++static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
++  PgHdr *p;                         /* Return value */
+ 
+-  /* 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);
++  /* It is not possible for a call to PcacheFetch() with createFlag==0 to
++  ** fail, since no attempt to allocate dynamic memory will be made.
++  */
++  (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
++  return p;
+ }
+ 
+-#ifndef SQLITE_OMIT_WAL
+ /*
+-** This function is invoked once for each page that has already been 
+-** written into the log file when a WAL transaction is rolled back.
+-** Parameter iPg is the page number of said page. The pCtx argument 
+-** is actually a pointer to the Pager structure.
+-**
+-** If page iPg is present in the cache, and has no outstanding references,
+-** it is discarded. Otherwise, if there are one or more outstanding
+-** references, the page content is reloaded from the database. If the
+-** attempt to reload content from the database is required and fails, 
+-** return an SQLite error code. Otherwise, SQLITE_OK.
++** Discard the entire contents of the in-memory page-cache.
+ */
+-static int pagerUndoCallback(void *pCtx, Pgno iPg){
+-  int rc = SQLITE_OK;
+-  Pager *pPager = (Pager *)pCtx;
+-  PgHdr *pPg;
+-
+-  assert( pagerUseWal(pPager) );
+-  pPg = sqlite3PagerLookup(pPager, iPg);
+-  if( pPg ){
+-    if( sqlite3PcachePageRefcount(pPg)==1 ){
+-      sqlite3PcacheDrop(pPg);
+-    }else{
+-      u32 iFrame = 0;
+-      rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
+-      if( rc==SQLITE_OK ){
+-        rc = readDbPage(pPg, iFrame);
+-      }
+-      if( rc==SQLITE_OK ){
+-        pPager->xReiniter(pPg);
+-      }
+-      sqlite3PagerUnref(pPg);
+-    }
+-  }
+-
+-  /* Normally, if a transaction is rolled back, any backup processes are
+-  ** updated as data is copied out of the rollback journal and into the
+-  ** database. This is not generally possible with a WAL database, as
+-  ** rollback involves simply truncating the log file. Therefore, if one
+-  ** or more frames have already been written to the log (and therefore 
+-  ** also copied into the backup databases) as part of this transaction,
+-  ** the backups must be restarted.
+-  */
++static void pager_reset(Pager *pPager){
+   sqlite3BackupRestart(pPager->pBackup);
+-
+-  return rc;
++  sqlite3PcacheClear(pPager->pPCache);
+ }
+ 
+ /*
+-** This function is called to rollback a transaction on a WAL database.
++** Free all structures in the Pager.aSavepoint[] array and set both
++** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
++** if it is open and the pager is not in exclusive mode.
+ */
+-static int pagerRollbackWal(Pager *pPager){
+-  int rc;                         /* Return Code */
+-  PgHdr *pList;                   /* List of dirty pages to revert */
+-
+-  /* For all pages in the cache that are currently dirty or have already
+-  ** been written (but not committed) to the log file, do one of the 
+-  ** following:
+-  **
+-  **   + Discard the cached page (if refcount==0), or
+-  **   + Reload page content from the database (if refcount>0).
+-  */
+-  pPager->dbSize = pPager->dbOrigSize;
+-  rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
+-  pList = sqlite3PcacheDirtyList(pPager->pPCache);
+-  while( pList && rc==SQLITE_OK ){
+-    PgHdr *pNext = pList->pDirty;
+-    rc = pagerUndoCallback((void *)pPager, pList->pgno);
+-    pList = pNext;
++static void releaseAllSavepoints(Pager *pPager){
++  int ii;               /* Iterator for looping through Pager.aSavepoint */
++  for(ii=0; ii<pPager->nSavepoint; ii++){
++    sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
+   }
+-
+-  return rc;
++  if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){
++    sqlite3OsClose(pPager->sjfd);
++  }
++  sqlite3_free(pPager->aSavepoint);
++  pPager->aSavepoint = 0;
++  pPager->nSavepoint = 0;
++  pPager->nSubRec = 0;
+ }
+ 
+ /*
+-** 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. 
+-**
+-** 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 */
+-  PgHdr *pList,                   /* List of frames to log */
+-  Pgno nTruncate,                 /* Database size after this commit */
+-  int isCommit                    /* True if this is a commit */
+-){
+-  int rc;                         /* Return code */
+-  int nList;                      /* Number of pages in pList */
+-#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
+-  PgHdr *p;                       /* For looping over pages */
+-#endif
+-
+-  assert( pPager->pWal );
+-  assert( pList );
+-#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
+-
+-  assert( pList->pDirty==0 || isCommit );
+-  if( isCommit ){
+-    /* If a WAL transaction is being committed, there is no point in writing
+-    ** any pages with page numbers greater than nTruncate into the WAL file.
+-    ** They will never be read by any client. So remove them from the pDirty
+-    ** list here. */
+-    PgHdr *p;
+-    PgHdr **ppNext = &pList;
+-    nList = 0;
+-    for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
+-      if( p->pgno<=nTruncate ){
+-        ppNext = &p->pDirty;
+-        nList++;
+-      }
+-    }
+-    assert( pList );
+-  }else{
+-    nList = 1;
+-  }
+-  pPager->aStat[PAGER_STAT_WRITE] += nList;
++** Set the bit number pgno in the PagerSavepoint.pInSavepoint 
++** bitvecs of all open savepoints. Return SQLITE_OK if successful
++** or SQLITE_NOMEM if a malloc failure occurs.
++*/
++static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
++  int ii;                   /* Loop counter */
++  int rc = SQLITE_OK;       /* Result code */
+ 
+-  if( pList->pgno==1 ) pager_write_changecounter(pList);
+-  rc = sqlite3WalFrames(pPager->pWal, 
+-      pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
+-  );
+-  if( rc==SQLITE_OK && pPager->pBackup ){
+-    PgHdr *p;
+-    for(p=pList; p; p=p->pDirty){
+-      sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
++  for(ii=0; ii<pPager->nSavepoint; ii++){
++    PagerSavepoint *p = &pPager->aSavepoint[ii];
++    if( pgno<=p->nOrig ){
++      rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
++      testcase( rc==SQLITE_NOMEM );
++      assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+     }
+   }
+-
+-#ifdef SQLITE_CHECK_PAGES
+-  pList = sqlite3PcacheDirtyList(pPager->pPCache);
+-  for(p=pList; p; p=p->pDirty){
+-    pager_set_pagehash(p);
+-  }
+-#endif
+-
+   return rc;
+ }
+ 
+ /*
+-** Begin a read transaction on the WAL.
++** This function is a no-op if the pager is in exclusive mode and not
++** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
++** state.
+ **
+-** This routine used to be called "pagerOpenSnapshot()" because it essentially
+-** makes a snapshot of the database at the current point in time and preserves
+-** that snapshot for use by the reader in spite of concurrently changes by
+-** other writers or checkpointers.
++** If the pager is not in exclusive-access mode, the database file is
++** completely unlocked. If the file is unlocked and the file-system does
++** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
++** closed (if it is open).
++**
++** If the pager is in ERROR state when this function is called, the 
++** contents of the pager cache are discarded before switching back to 
++** the OPEN state. Regardless of whether the pager is in exclusive-mode
++** or not, any journal file left in the file-system will be treated
++** as a hot-journal and rolled back the next time a read-transaction
++** is opened (by this or by any other connection).
+ */
+-static int pagerBeginReadTransaction(Pager *pPager){
+-  int rc;                         /* Return code */
+-  int changed = 0;                /* True if cache must be reset */
+-
+-  assert( pagerUseWal(pPager) );
+-  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
+-
+-  /* sqlite3WalEndReadTransaction() was not called for the previous
+-  ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
+-  ** are in locking_mode=NORMAL and EndRead() was previously called,
+-  ** the duplicate call is harmless.
+-  */
+-  sqlite3WalEndReadTransaction(pPager->pWal);
++static void pager_unlock(Pager *pPager){
+ 
+-  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
+-  if( rc!=SQLITE_OK || changed ){
+-    pager_reset(pPager);
+-    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
+-  }
++  assert( pPager->eState==PAGER_READER 
++       || pPager->eState==PAGER_OPEN 
++       || pPager->eState==PAGER_ERROR 
++  );
+ 
+-  return rc;
+-}
+-#endif
++  sqlite3BitvecDestroy(pPager->pInJournal);
++  pPager->pInJournal = 0;
++  releaseAllSavepoints(pPager);
+ 
+-/*
+-** This function is called as part of the transition from PAGER_OPEN
+-** to PAGER_READER state to determine the size of the database file
+-** in pages (assuming the page size currently stored in Pager.pageSize).
+-**
+-** If no error occurs, SQLITE_OK is returned and the size of the database
+-** in pages is stored in *pnPage. Otherwise, an error code (perhaps
+-** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
+-*/
+-static int pagerPagecount(Pager *pPager, Pgno *pnPage){
+-  Pgno nPage;                     /* Value to return via *pnPage */
++  if( pagerUseWal(pPager) ){
++    assert( !isOpen(pPager->jfd) );
++    sqlite3WalEndReadTransaction(pPager->pWal);
++    pPager->eState = PAGER_OPEN;
++  }else if( !pPager->exclusiveMode ){
++    int rc;                       /* Error code returned by pagerUnlockDb() */
++    int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
+ 
+-  /* Query the WAL sub-system for the database size. The WalDbsize()
+-  ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
+-  ** if the database size is not available. The database size is not
+-  ** available from the WAL sub-system if the log file is empty or
+-  ** contains no valid committed transactions.
+-  */
+-  assert( pPager->eState==PAGER_OPEN );
+-  assert( pPager->eLock>=SHARED_LOCK );
+-  nPage = sqlite3WalDbsize(pPager->pWal);
++    /* If the operating system support deletion of open files, then
++    ** close the journal file when dropping the database lock.  Otherwise
++    ** another connection with journal_mode=delete might delete the file
++    ** out from under us.
++    */
++    assert( (PAGER_JOURNALMODE_MEMORY   & 5)!=1 );
++    assert( (PAGER_JOURNALMODE_OFF      & 5)!=1 );
++    assert( (PAGER_JOURNALMODE_WAL      & 5)!=1 );
++    assert( (PAGER_JOURNALMODE_DELETE   & 5)!=1 );
++    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
++    assert( (PAGER_JOURNALMODE_PERSIST  & 5)==1 );
++    if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
++     || 1!=(pPager->journalMode & 5)
++    ){
++      sqlite3OsClose(pPager->jfd);
++    }
+ 
+-  /* If the database size was not available from the WAL sub-system,
+-  ** determine it based on the size of the database file. If the size
+-  ** of the database file is not an integer multiple of the page-size,
+-  ** round down to the nearest page. Except, any file larger than 0
+-  ** bytes in size is considered to contain at least one page.
+-  */
+-  if( nPage==0 ){
+-    i64 n = 0;                    /* Size of db file in bytes */
+-    assert( isOpen(pPager->fd) || pPager->tempFile );
+-    if( isOpen(pPager->fd) ){
+-      int rc = sqlite3OsFileSize(pPager->fd, &n);
+-      if( rc!=SQLITE_OK ){
+-        return rc;
+-      }
++    /* If the pager is in the ERROR state and the call to unlock the database
++    ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
++    ** above the #define for UNKNOWN_LOCK for an explanation of why this
++    ** is necessary.
++    */
++    rc = pagerUnlockDb(pPager, NO_LOCK);
++    if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
++      pPager->eLock = UNKNOWN_LOCK;
+     }
+-    nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
++
++    /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
++    ** without clearing the error code. This is intentional - the error
++    ** code is cleared and the cache reset in the block below.
++    */
++    assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
++    pPager->changeCountDone = 0;
++    pPager->eState = PAGER_OPEN;
+   }
+ 
+-  /* If the current number of pages in the file is greater than the
+-  ** configured maximum pager number, increase the allowed limit so
+-  ** that the file can be read.
++  /* If Pager.errCode is set, the contents of the pager cache cannot be
++  ** trusted. Now that there are no outstanding references to the pager,
++  ** it can safely move back to PAGER_OPEN state. This happens in both
++  ** normal and exclusive-locking mode.
+   */
+-  if( nPage>pPager->mxPgno ){
+-    pPager->mxPgno = (Pgno)nPage;
++  if( pPager->errCode ){
++    assert( !MEMDB );
++    pager_reset(pPager);
++    pPager->changeCountDone = pPager->tempFile;
++    pPager->eState = PAGER_OPEN;
++    pPager->errCode = SQLITE_OK;
+   }
+ 
+-  *pnPage = nPage;
+-  return SQLITE_OK;
+-}
+-
+-#ifndef SQLITE_OMIT_WAL
+-/*
+-** Check if the *-wal file that corresponds to the database opened by pPager
+-** exists if the database is not empy, or verify that the *-wal file does
+-** not exist (by deleting it) if the database file is empty.
+-**
+-** If the database is not empty and the *-wal file exists, open the pager
+-** in WAL mode.  If the database is empty or if no *-wal file exists and
+-** if no error occurs, make sure Pager.journalMode is not set to
+-** PAGER_JOURNALMODE_WAL.
++  pPager->journalOff = 0;
++  pPager->journalHdr = 0;
++  pPager->setMaster = 0;
 +}
 +
-+SQLITE_PRIVATE sqlite3_file *sqlite3Pager_get_fd(Pager *pPager) {
-+  return (isOpen(pPager->fd)) ? pPager->fd : NULL;
++/*
++** This function is called whenever an IOERR or FULL error that requires
++** the pager to transition into the ERROR state may ahve occurred.
++** The first argument is a pointer to the pager structure, the second 
++** the error-code about to be returned by a pager API function. The 
++** value returned is a copy of the second argument to this function. 
+ **
+-** Return SQLITE_OK or an error code.
++** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
++** IOERR sub-codes, the pager enters the ERROR state and the error code
++** is stored in Pager.errCode. While the pager remains in the ERROR state,
++** all major API calls on the Pager will immediately return Pager.errCode.
+ **
+-** The caller must hold a SHARED lock on the database file to call this
+-** function. Because an EXCLUSIVE lock on the db file is required to delete 
+-** a WAL on a none-empty database, this ensures there is no race condition 
+-** between the xAccess() below and an xDelete() being executed by some 
+-** other connection.
++** The ERROR state indicates that the contents of the pager-cache 
++** cannot be trusted. This state can be cleared by completely discarding 
++** the contents of the pager-cache. If a transaction was active when
++** the persistent error occurred, then the rollback journal may need
++** to be replayed to restore the contents of the database file (as if
++** it were a hot-journal).
+ */
+-static int pagerOpenWalIfPresent(Pager *pPager){
+-  int rc = SQLITE_OK;
+-  assert( pPager->eState==PAGER_OPEN );
+-  assert( pPager->eLock>=SHARED_LOCK );
+-
+-  if( !pPager->tempFile ){
+-    int isWal;                    /* True if WAL file exists */
+-    Pgno nPage;                   /* Size of the database file */
+-
+-    rc = pagerPagecount(pPager, &nPage);
+-    if( rc ) return rc;
+-    if( nPage==0 ){
+-      rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+-      if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
+-      isWal = 0;
+-    }else{
+-      rc = sqlite3OsAccess(
+-          pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
+-      );
+-    }
+-    if( rc==SQLITE_OK ){
+-      if( isWal ){
+-        testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
+-        rc = sqlite3PagerOpenWal(pPager, 0);
+-      }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
+-        pPager->journalMode = PAGER_JOURNALMODE_DELETE;
+-      }
+-    }
++static int pager_error(Pager *pPager, int rc){
++  int rc2 = rc & 0xff;
++  assert( rc==SQLITE_OK || !MEMDB );
++  assert(
++       pPager->errCode==SQLITE_FULL ||
++       pPager->errCode==SQLITE_OK ||
++       (pPager->errCode & 0xff)==SQLITE_IOERR
++  );
++  if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
++    pPager->errCode = rc;
++    pPager->eState = PAGER_ERROR;
+   }
+   return rc;
+ }
+-#endif
++
++static int pager_truncate(Pager *pPager, Pgno nPage);
+ 
+ /*
+-** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
+-** the entire master journal file. The case pSavepoint==NULL occurs when 
+-** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction 
+-** savepoint.
++** This routine ends a transaction. A transaction is usually ended by 
++** either a COMMIT or a ROLLBACK operation. This routine may be called 
++** after rollback of a hot-journal, or if an error occurs while opening
++** the journal file or writing the very first journal-header of a
++** database transaction.
++** 
++** This routine is never called in PAGER_ERROR state. If it is called
++** in PAGER_NONE or PAGER_SHARED state and the lock held is less
++** exclusive than a RESERVED lock, it is a no-op.
+ **
+-** When pSavepoint is not NULL (meaning a non-transaction savepoint is 
+-** being rolled back), then the rollback consists of up to three stages,
+-** performed in the order specified:
++** Otherwise, any active savepoints are released.
+ **
+-**   * Pages are played back from the main journal starting at byte
+-**     offset PagerSavepoint.iOffset and continuing to 
+-**     PagerSavepoint.iHdrOffset, or to the end of the main journal
+-**     file if PagerSavepoint.iHdrOffset is zero.
++** If the journal file is open, then it is "finalized". Once a journal 
++** file has been finalized it is not possible to use it to roll back a 
++** transaction. Nor will it be considered to be a hot-journal by this
++** or any other database connection. Exactly how a journal is finalized
++** depends on whether or not the pager is running in exclusive mode and
++** the current journal-mode (Pager.journalMode value), as follows:
+ **
+-**   * If PagerSavepoint.iHdrOffset is not zero, then pages are played
+-**     back starting from the journal header immediately following 
+-**     PagerSavepoint.iHdrOffset to the end of the main journal file.
++**   journalMode==MEMORY
++**     Journal file descriptor is simply closed. This destroys an 
++**     in-memory journal.
+ **
+-**   * Pages are then played back from the sub-journal file, starting
+-**     with the PagerSavepoint.iSubRec and continuing to the end of
+-**     the journal file.
++**   journalMode==TRUNCATE
++**     Journal file is truncated to zero bytes in size.
+ **
+-** Throughout the rollback process, each time a page is rolled back, the
+-** corresponding bit is set in a bitvec structure (variable pDone in the
+-** implementation below). This is used to ensure that a page is only
+-** rolled back the first time it is encountered in either journal.
++**   journalMode==PERSIST
++**     The first 28 bytes of the journal file are zeroed. This invalidates
++**     the first journal header in the file, and hence the entire journal
++**     file. An invalid journal file cannot be rolled back.
+ **
+-** If pSavepoint is NULL, then pages are only played back from the main
+-** journal file. There is no need for a bitvec in this case.
++**   journalMode==DELETE
++**     The journal file is closed and deleted using sqlite3OsDelete().
+ **
+-** In either case, before playback commences the Pager.dbSize variable
+-** is reset to the value that it held at the start of the savepoint 
+-** (or transaction). No page with a page-number greater than this value
+-** is played back. If one is encountered it is simply skipped.
++**     If the pager is running in exclusive mode, this method of finalizing
++**     the journal file is never used. Instead, if the journalMode is
++**     DELETE and the pager is in exclusive mode, the method described under
++**     journalMode==PERSIST is used instead.
++**
++** After the journal is finalized, the pager moves to PAGER_READER state.
++** If running in non-exclusive rollback mode, the lock on the file is 
++** downgraded to a SHARED_LOCK.
++**
++** SQLITE_OK is returned if no error occurs. If an error occurs during
++** any of the IO operations to finalize the journal file or unlock the
++** database then the IO error code is returned to the user. If the 
++** operation to finalize the journal file fails, then the code still
++** tries to unlock the database file if not in exclusive mode. If the
++** unlock operation fails as well, then the first error code related
++** to the first error encountered (the journal finalization one) is
++** returned.
+ */
+-static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
+-  i64 szJ;                 /* Effective size of the main journal */
+-  i64 iHdrOff;             /* End of first segment of main-journal records */
+-  int rc = SQLITE_OK;      /* Return code */
+-  Bitvec *pDone = 0;       /* Bitvec to ensure pages played back only once */
+-
+-  assert( pPager->eState!=PAGER_ERROR );
+-  assert( pPager->eState>=PAGER_WRITER_LOCKED );
+-
+-  /* Allocate a bitvec to use to store the set of pages rolled back */
+-  if( pSavepoint ){
+-    pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
+-    if( !pDone ){
+-      return SQLITE_NOMEM;
+-    }
+-  }
++static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
++  int rc = SQLITE_OK;      /* Error code from journal finalization operation */
++  int rc2 = SQLITE_OK;     /* Error code from db file unlock operation */
+ 
+-  /* Set the database size back to the value it was before the savepoint 
+-  ** being reverted was opened.
++  /* Do nothing if the pager does not have an open write transaction
++  ** or at least a RESERVED lock. This function may be called when there
++  ** is no write-transaction active but a RESERVED or greater lock is
++  ** held under two circumstances:
++  **
++  **   1. After a successful hot-journal rollback, it is called with
++  **      eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
++  **
++  **   2. If a connection with locking_mode=exclusive holding an EXCLUSIVE 
++  **      lock switches back to locking_mode=normal and then executes a
++  **      read-transaction, this function is called with eState==PAGER_READER 
++  **      and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
+   */
+-  pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
+-  pPager->changeCountDone = pPager->tempFile;
+-
+-  if( !pSavepoint && pagerUseWal(pPager) ){
+-    return pagerRollbackWal(pPager);
++  assert( assert_pager_state(pPager) );
++  assert( pPager->eState!=PAGER_ERROR );
++  if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
++    return SQLITE_OK;
+   }
+ 
+-  /* Use pPager->journalOff as the effective size of the main rollback
+-  ** journal.  The actual file might be larger than this in
+-  ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST.  But anything
+-  ** past pPager->journalOff is off-limits to us.
+-  */
+-  szJ = pPager->journalOff;
+-  assert( pagerUseWal(pPager)==0 || szJ==0 );
++  releaseAllSavepoints(pPager);
++  assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
++  if( isOpen(pPager->jfd) ){
++    assert( !pagerUseWal(pPager) );
+ 
+-  /* Begin by rolling back records from the main journal starting at
+-  ** PagerSavepoint.iOffset and continuing to the next journal header.
+-  ** There might be records in the main journal that have a page number
+-  ** greater than the current database size (pPager->dbSize) but those
+-  ** will be skipped automatically.  Pages are added to pDone as they
+-  ** are played back.
+-  */
+-  if( pSavepoint && !pagerUseWal(pPager) ){
+-    iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
+-    pPager->journalOff = pSavepoint->iOffset;
+-    while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
+-      rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
++    /* Finalize the journal file. */
++    if( sqlite3IsMemJournal(pPager->jfd) ){
++      assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY );
++      sqlite3OsClose(pPager->jfd);
++    }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
++      if( pPager->journalOff==0 ){
++        rc = SQLITE_OK;
++      }else{
++        rc = sqlite3OsTruncate(pPager->jfd, 0);
++      }
++      pPager->journalOff = 0;
++    }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
++      || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
++    ){
++      rc = zeroJournalHdr(pPager, hasMaster);
++      pPager->journalOff = 0;
++    }else{
++      /* This branch may be executed with Pager.journalMode==MEMORY if
++      ** a hot-journal was just rolled back. In this case the journal
++      ** file should be closed and deleted. If this connection writes to
++      ** the database file, it will do so using an in-memory journal. 
++      */
++      int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
++      assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
++           || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
++           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
++      );
++      sqlite3OsClose(pPager->jfd);
++      if( bDelete ){
++        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
++      }
+     }
+-    assert( rc!=SQLITE_DONE );
+-  }else{
+-    pPager->journalOff = 0;
+   }
+ 
+-  /* Continue rolling back records out of the main journal starting at
+-  ** the first journal header seen and continuing until the effective end
+-  ** of the main journal file.  Continue to skip out-of-range pages and
+-  ** continue adding pages rolled back to pDone.
+-  */
+-  while( rc==SQLITE_OK && pPager->journalOff<szJ ){
+-    u32 ii;            /* Loop counter */
+-    u32 nJRec = 0;     /* Number of Journal Records */
+-    u32 dummy;
+-    rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
+-    assert( rc!=SQLITE_DONE );
+-
+-    /*
+-    ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
+-    ** test is related to ticket #2565.  See the discussion in the
+-    ** pager_playback() function for additional information.
+-    */
+-    if( nJRec==0 
+-     && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
+-    ){
+-      nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
+-    }
+-    for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
+-      rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
++#ifdef SQLITE_CHECK_PAGES
++  sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
++  if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
++    PgHdr *p = pager_lookup(pPager, 1);
++    if( p ){
++      p->pageHash = 0;
++      sqlite3PagerUnref(p);
+     }
+-    assert( rc!=SQLITE_DONE );
+   }
+-  assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
++#endif
+ 
+-  /* Finally,  rollback pages from the sub-journal.  Page that were
+-  ** previously rolled back out of the main journal (and are hence in pDone)
+-  ** will be skipped.  Out-of-range pages are also skipped.
+-  */
+-  if( pSavepoint ){
+-    u32 ii;            /* Loop counter */
+-    i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
++  sqlite3BitvecDestroy(pPager->pInJournal);
++  pPager->pInJournal = 0;
++  pPager->nRec = 0;
++  sqlite3PcacheCleanAll(pPager->pPCache);
++  sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
+ 
+-    if( pagerUseWal(pPager) ){
+-      rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
+-    }
+-    for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
+-      assert( offset==(i64)ii*(4+pPager->pageSize) );
+-      rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
+-    }
+-    assert( rc!=SQLITE_DONE );
++  if( pagerUseWal(pPager) ){
++    /* Drop the WAL write-lock, if any. Also, if the connection was in 
++    ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE 
++    ** lock held on the database file.
++    */
++    rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
++    assert( rc2==SQLITE_OK );
++  }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
++    /* This branch is taken when committing a transaction in rollback-journal
++    ** mode if the database file on disk is larger than the database image.
++    ** At this point the journal has been finalized and the transaction 
++    ** successfully committed, but the EXCLUSIVE lock is still held on the
++    ** file. So it is safe to truncate the database file to its minimum
++    ** required size.  */
++    assert( pPager->eLock==EXCLUSIVE_LOCK );
++    rc = pager_truncate(pPager, pPager->dbSize);
+   }
+ 
+-  sqlite3BitvecDestroy(pDone);
+-  if( rc==SQLITE_OK ){
+-    pPager->journalOff = szJ;
++  if( !pPager->exclusiveMode 
++   && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
++  ){
++    rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
++    pPager->changeCountDone = 0;
+   }
++  pPager->eState = PAGER_READER;
++  pPager->setMaster = 0;
+ 
+-  return rc;
+-}
+-
+-/*
+-** Change the maximum number of in-memory pages that are allowed.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
+-  sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
++  return (rc==SQLITE_OK?rc2:rc);
+ }
+ 
+ /*
+-** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
++** Execute a rollback if a transaction is active and unlock the 
++** database file. 
++**
++** If the pager has already entered the ERROR state, do not attempt 
++** the rollback at this time. Instead, pager_unlock() is called. The
++** call to pager_unlock() will discard all in-memory pages, unlock
++** the database file and move the pager back to OPEN state. If this 
++** means that there is a hot-journal left in the file-system, the next 
++** connection to obtain a shared lock on the pager (which may be this one) 
++** will roll it back.
++**
++** If the pager has not already entered the ERROR state, but an IO or
++** malloc error occurs during a rollback, then this will itself cause 
++** the pager to enter the ERROR state. Which will be cleared by the
++** call to pager_unlock(), as described above.
+ */
+-static void pagerFixMaplimit(Pager *pPager){
+-#if SQLITE_MAX_MMAP_SIZE>0
+-  sqlite3_file *fd = pPager->fd;
+-  if( isOpen(fd) ){
+-    sqlite3_int64 sz;
+-    pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
+-    sz = pPager->szMmap;
+-    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
++static void pagerUnlockAndRollback(Pager *pPager){
++  if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
++    assert( assert_pager_state(pPager) );
++    if( pPager->eState>=PAGER_WRITER_LOCKED ){
++      sqlite3BeginBenignMalloc();
++      sqlite3PagerRollback(pPager);
++      sqlite3EndBenignMalloc();
++    }else if( !pPager->exclusiveMode ){
++      assert( pPager->eState==PAGER_READER );
++      pager_end_transaction(pPager, 0, 0);
++    }
+   }
+-#endif
+-}
+-
+-/*
+-** Change the maximum size of any memory mapping made of the database file.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
+-  pPager->szMmap = szMmap;
+-  pagerFixMaplimit(pPager);
+-}
+-
+-/*
+-** Free as much memory as possible from the pager.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
+-  sqlite3PcacheShrink(pPager->pPCache);
++  pager_unlock(pPager);
+ }
+ 
+ /*
+-** Adjust the robustness of the database to damage due to OS crashes
+-** or power failures by changing the number of syncs()s when writing
+-** the rollback journal.  There are three levels:
+-**
+-**    OFF       sqlite3OsSync() is never called.  This is the default
+-**              for temporary and transient files.
+-**
+-**    NORMAL    The journal is synced once before writes begin on the
+-**              database.  This is normally adequate protection, but
+-**              it is theoretically possible, though very unlikely,
+-**              that an inopertune power failure could leave the journal
+-**              in a state which would cause damage to the database
+-**              when it is rolled back.
+-**
+-**    FULL      The journal is synced twice before writes begin on the
+-**              database (with some additional information - the nRec field
+-**              of the journal header - being written in between the two
+-**              syncs).  If we assume that writing a
+-**              single disk sector is atomic, then this mode provides
+-**              assurance that the journal will not be corrupted to the
+-**              point of causing damage to the database during rollback.
++** Parameter aData must point to a buffer of pPager->pageSize bytes
++** of data. Compute and return a checksum based ont the contents of the 
++** page of data and the current value of pPager->cksumInit.
+ **
+-** The above is for a rollback-journal mode.  For WAL mode, OFF continues
+-** to mean that no syncs ever occur.  NORMAL means that the WAL is synced
+-** prior to the start of checkpoint and that the database file is synced
+-** at the conclusion of the checkpoint if the entire content of the WAL
+-** was written back into the database.  But no sync operations occur for
+-** an ordinary commit in NORMAL mode with WAL.  FULL means that the WAL
+-** file is synced following each commit operation, in addition to the
+-** syncs associated with NORMAL.
++** This is not a real checksum. It is really just the sum of the 
++** random initial value (pPager->cksumInit) and every 200th byte
++** of the page data, starting with byte offset (pPager->pageSize%200).
++** Each byte is interpreted as an 8-bit unsigned integer.
+ **
+-** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL.  The
+-** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
+-** using fcntl(F_FULLFSYNC).  SQLITE_SYNC_NORMAL means to do an
+-** ordinary fsync() call.  There is no difference between SQLITE_SYNC_FULL
+-** and SQLITE_SYNC_NORMAL on platforms other than MacOSX.  But the
+-** synchronous=FULL versus synchronous=NORMAL setting determines when
+-** the xSync primitive is called and is relevant to all platforms.
++** Changing the formula used to compute this checksum results in an
++** incompatible journal file format.
+ **
+-** Numeric values associated with these states are OFF==1, NORMAL=2,
+-** and FULL=3.
++** If journal corruption occurs due to a power failure, the most likely 
++** scenario is that one end or the other of the record will be changed. 
++** It is much less likely that the two ends of the journal record will be
++** correct and the middle be corrupt.  Thus, this "checksum" scheme,
++** though fast and simple, catches the mostly likely kind of corruption.
+ */
+-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
+-  Pager *pPager,        /* The pager to set safety level for */
+-  int level,            /* PRAGMA synchronous.  1=OFF, 2=NORMAL, 3=FULL */  
+-  int bFullFsync,       /* PRAGMA fullfsync */
+-  int bCkptFullFsync    /* PRAGMA checkpoint_fullfsync */
+-){
+-  assert( level>=1 && level<=3 );
+-  pPager->noSync =  (level==1 || pPager->tempFile) ?1:0;
+-  pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
+-  if( pPager->noSync ){
+-    pPager->syncFlags = 0;
+-    pPager->ckptSyncFlags = 0;
+-  }else if( bFullFsync ){
+-    pPager->syncFlags = SQLITE_SYNC_FULL;
+-    pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
+-  }else if( bCkptFullFsync ){
+-    pPager->syncFlags = SQLITE_SYNC_NORMAL;
+-    pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
+-  }else{
+-    pPager->syncFlags = SQLITE_SYNC_NORMAL;
+-    pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+-  }
+-  pPager->walSyncFlags = pPager->syncFlags;
+-  if( pPager->fullSync ){
+-    pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
++static u32 pager_cksum(Pager *pPager, const u8 *aData){
++  u32 cksum = pPager->cksumInit;         /* Checksum value to return */
++  int i = pPager->pageSize-200;          /* Loop counter */
++  while( i>0 ){
++    cksum += aData[i];
++    i -= 200;
+   }
++  return cksum;
+ }
+-#endif
+ 
+ /*
+-** The following global variable is incremented whenever the library
+-** attempts to open a temporary file.  This information is used for
+-** testing and analysis only.  
++** Report the current page size and number of reserved bytes back
++** to the codec.
+ */
+-#ifdef SQLITE_TEST
+-SQLITE_API int sqlite3_opentemp_count = 0;
++#ifdef SQLITE_HAS_CODEC
++static void pagerReportSize(Pager *pPager){
++  if( pPager->xCodecSizeChng ){
++    pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
++                           (int)pPager->nReserve);
++  }
 +}
++#else
++# define pagerReportSize(X)     /* No-op if we do not support a codec */
+ #endif
+ 
+ /*
+-** Open a temporary file.
++** Read a single page from either the journal file (if isMainJrnl==1) or
++** from the sub-journal (if isMainJrnl==0) and playback that page.
++** The page begins at offset *pOffset into the file. The *pOffset
++** value is increased to the start of the next page in the journal.
+ **
+-** Write the file descriptor into *pFile. Return SQLITE_OK on success 
+-** or some other error code if we fail. The OS will automatically 
+-** delete the temporary file when it is closed.
++** The main rollback journal uses checksums - the statement journal does 
++** not.
++**
++** If the page number of the page record read from the (sub-)journal file
++** is greater than the current value of Pager.dbSize, then playback is
++** skipped and SQLITE_OK is returned.
++**
++** If pDone is not NULL, then it is a record of pages that have already
++** been played back.  If the page at *pOffset has already been played back
++** (if the corresponding pDone bit is set) then skip the playback.
++** Make sure the pDone bit corresponding to the *pOffset page is set
++** prior to returning.
++**
++** If the page record is successfully read from the (sub-)journal file
++** and played back, then SQLITE_OK is returned. If an IO error occurs
++** while reading the record from the (sub-)journal file or while writing
++** to the database file, then the IO error code is returned. If data
++** is successfully read from the (sub-)journal file but appears to be
++** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
++** two circumstances:
++** 
++**   * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
++**   * If the record is being rolled back from the main journal file
++**     and the checksum field does not match the record content.
+ **
+-** The flags passed to the VFS layer xOpen() call are those specified
+-** by parameter vfsFlags ORed with the following:
++** Neither of these two scenarios are possible during a savepoint rollback.
+ **
+-**     SQLITE_OPEN_READWRITE
+-**     SQLITE_OPEN_CREATE
+-**     SQLITE_OPEN_EXCLUSIVE
+-**     SQLITE_OPEN_DELETEONCLOSE
++** If this is a savepoint rollback, then memory may have to be dynamically
++** allocated by this function. If this is the case and an allocation fails,
++** SQLITE_NOMEM is returned.
+ */
+-static int pagerOpentemp(
+-  Pager *pPager,        /* The pager object */
+-  sqlite3_file *pFile,  /* Write the file descriptor here */
+-  int vfsFlags          /* Flags passed through to the VFS */
++static int pager_playback_one_page(
++  Pager *pPager,                /* The pager being played back */
++  i64 *pOffset,                 /* Offset of record to playback */
++  Bitvec *pDone,                /* Bitvec of pages already played back */
++  int isMainJrnl,               /* 1 -> main journal. 0 -> sub-journal. */
++  int isSavepnt                 /* True for a savepoint rollback */
+ ){
+-  int rc;               /* Return code */
++  int rc;
++  PgHdr *pPg;                   /* An existing page in the cache */
++  Pgno pgno;                    /* The page number of a page in journal */
++  u32 cksum;                    /* Checksum used for sanity checking */
++  char *aData;                  /* Temporary storage for the page */
++  sqlite3_file *jfd;            /* The file descriptor for the journal file */
++  int isSynced;                 /* True if journal page is synced */
+ 
+-#ifdef SQLITE_TEST
+-  sqlite3_opentemp_count++;  /* Used for testing and analysis only */
+-#endif
++  assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
++  assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
++  assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
++  assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */
+ 
+-  vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+-            SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
+-  rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
+-  assert( rc!=SQLITE_OK || isOpen(pFile) );
+-  return rc;
+-}
++  aData = pPager->pTmpSpace;
++  assert( aData );         /* Temp storage must have already been allocated */
++  assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
+ 
+-/*
+-** Set the busy handler function.
+-**
+-** The pager invokes the busy-handler if sqlite3OsLock() returns 
+-** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
+-** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE 
+-** lock. It does *not* invoke the busy handler when upgrading from
+-** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
+-** (which occurs during hot-journal rollback). Summary:
+-**
+-**   Transition                        | Invokes xBusyHandler
+-**   --------------------------------------------------------
+-**   NO_LOCK       -> SHARED_LOCK      | Yes
+-**   SHARED_LOCK   -> RESERVED_LOCK    | No
+-**   SHARED_LOCK   -> EXCLUSIVE_LOCK   | No
+-**   RESERVED_LOCK -> EXCLUSIVE_LOCK   | Yes
+-**
+-** If the busy-handler callback returns non-zero, the lock is 
+-** retried. If it returns zero, then the SQLITE_BUSY error is
+-** returned to the caller of the pager API function.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
+-  Pager *pPager,                       /* Pager object */
+-  int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
+-  void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
+-){
+-  pPager->xBusyHandler = xBusyHandler;
+-  pPager->pBusyHandlerArg = pBusyHandlerArg;
++  /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction 
++  ** or savepoint rollback done at the request of the caller) or this is
++  ** a hot-journal rollback. If it is a hot-journal rollback, the pager
++  ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
++  ** only reads from the main journal, not the sub-journal.
++  */
++  assert( pPager->eState>=PAGER_WRITER_CACHEMOD
++       || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
++  );
++  assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
+ 
+-  if( isOpen(pPager->fd) ){
+-    void **ap = (void **)&pPager->xBusyHandler;
+-    assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+-    assert( ap[1]==pBusyHandlerArg );
+-    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
++  /* Read the page number and page data from the journal or sub-journal
++  ** file. Return an error code to the caller if an IO error occurs.
++  */
++  jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
++  rc = read32bits(jfd, *pOffset, &pgno);
++  if( rc!=SQLITE_OK ) return rc;
++  rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
++  if( rc!=SQLITE_OK ) return rc;
++  *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
 +
-+SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetCodec(
-+  Pager *pPager,
-+  void *(*xCodec)(void*,void*,Pgno,int),
-+  void (*xCodecSizeChng)(void*,int,int),
-+  void (*xCodecFree)(void*),
-+  void *pCodec
++  /* Sanity checking on the page.  This is more important that I originally
++  ** thought.  If a power failure occurs while the journal is being written,
++  ** it could cause invalid data to be written into the journal.  We need to
++  ** detect this invalid data (with high probability) and ignore it.
++  */
++  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
++    assert( !isSavepnt );
++    return SQLITE_DONE;
++  }
++  if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
++    return SQLITE_OK;
++  }
++  if( isMainJrnl ){
++    rc = read32bits(jfd, (*pOffset)-4, &cksum);
++    if( rc ) return rc;
++    if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
++      return SQLITE_DONE;
++    }
++  }
++
++  /* If this page has already been played by before during the current
++  ** rollback, then don't bother to play it back again.
++  */
++  if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
++    return rc;
++  }
++
++  /* When playing back page 1, restore the nReserve setting
++  */
++  if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
++    pPager->nReserve = ((u8*)aData)[20];
++    pagerReportSize(pPager);
++  }
++
++  /* If the pager is in CACHEMOD state, then there must be a copy of this
++  ** page in the pager cache. In this case just update the pager cache,
++  ** not the database file. The page is left marked dirty in this case.
++  **
++  ** An exception to the above rule: If the database is in no-sync mode
++  ** and a page is moved during an incremental vacuum then the page may
++  ** not be in the pager cache. Later: if a malloc() or IO error occurs
++  ** during a Movepage() call, then the page may not be in the cache
++  ** either. So the condition described in the above paragraph is not
++  ** assert()able.
++  **
++  ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
++  ** pager cache if it exists and the main file. The page is then marked 
++  ** not dirty. Since this code is only executed in PAGER_OPEN state for
++  ** a hot-journal rollback, it is guaranteed that the page-cache is empty
++  ** if the pager is in OPEN state.
++  **
++  ** Ticket #1171:  The statement journal might contain page content that is
++  ** different from the page content at the start of the transaction.
++  ** This occurs when a page is changed prior to the start of a statement
++  ** then changed again within the statement.  When rolling back such a
++  ** statement we must not write to the original database unless we know
++  ** for certain that original page contents are synced into the main rollback
++  ** journal.  Otherwise, a power loss might leave modified data in the
++  ** database file without an entry in the rollback journal that can
++  ** restore the database to its original form.  Two conditions must be
++  ** met before writing to the database files. (1) the database must be
++  ** locked.  (2) we know that the original page content is fully synced
++  ** in the main journal either because the page is not in cache or else
++  ** the page is marked as needSync==0.
++  **
++  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
++  ** is possible to fail a statement on a database that does not yet exist.
++  ** Do not attempt to write if database file has never been opened.
++  */
++  if( pagerUseWal(pPager) ){
++    pPg = 0;
++  }else{
++    pPg = pager_lookup(pPager, pgno);
++  }
++  assert( pPg || !MEMDB );
++  assert( pPager->eState!=PAGER_OPEN || pPg==0 );
++  PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
++           PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
++           (isMainJrnl?"main-journal":"sub-journal")
++  ));
++  if( isMainJrnl ){
++    isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
++  }else{
++    isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
++  }
++  if( isOpen(pPager->fd)
++   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
++   && isSynced
++  ){
++    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
++    testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
++    assert( !pagerUseWal(pPager) );
++    rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
++    if( pgno>pPager->dbFileSize ){
++      pPager->dbFileSize = pgno;
++    }
++    if( pPager->pBackup ){
++      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
++      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
++      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
++    }
++  }else if( !isMainJrnl && pPg==0 ){
++    /* If this is a rollback of a savepoint and data was not written to
++    ** the database and the page is not in-memory, there is a potential
++    ** problem. When the page is next fetched by the b-tree layer, it 
++    ** will be read from the database file, which may or may not be 
++    ** current. 
++    **
++    ** There are a couple of different ways this can happen. All are quite
++    ** obscure. When running in synchronous mode, this can only happen 
++    ** if the page is on the free-list at the start of the transaction, then
++    ** populated, then moved using sqlite3PagerMovepage().
++    **
++    ** The solution is to add an in-memory page to the cache containing
++    ** the data just read from the sub-journal. Mark the page as dirty 
++    ** and if the pager requires a journal-sync, then mark the page as 
++    ** requiring a journal-sync before it is written.
++    */
++    assert( isSavepnt );
++    assert( pPager->doNotSpill==0 );
++    pPager->doNotSpill++;
++    rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
++    assert( pPager->doNotSpill==1 );
++    pPager->doNotSpill--;
++    if( rc!=SQLITE_OK ) return rc;
++    pPg->flags &= ~PGHDR_NEED_READ;
++    sqlite3PcacheMakeDirty(pPg);
++  }
++  if( pPg ){
++    /* No page should ever be explicitly rolled back that is in use, except
++    ** for page 1 which is held in use in order to keep the lock on the
++    ** database active. However such a page may be rolled back as a result
++    ** of an internal error resulting in an automatic call to
++    ** sqlite3PagerRollback().
++    */
++    void *pData;
++    pData = pPg->pData;
++    memcpy(pData, (u8*)aData, pPager->pageSize);
++    pPager->xReiniter(pPg);
++    if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
++      /* If the contents of this page were just restored from the main 
++      ** journal file, then its content must be as they were when the 
++      ** transaction was first opened. In this case we can mark the page
++      ** as clean, since there will be no need to write it out to the
++      ** database.
++      **
++      ** There is one exception to this rule. If the page is being rolled
++      ** back as part of a savepoint (or statement) rollback from an 
++      ** unsynced portion of the main journal file, then it is not safe
++      ** to mark the page as clean. This is because marking the page as
++      ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
++      ** already in the journal file (recorded in Pager.pInJournal) and
++      ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
++      ** again within this transaction, it will be marked as dirty but
++      ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
++      ** be written out into the database file before its journal file
++      ** segment is synced. If a crash occurs during or following this,
++      ** database corruption may ensue.
++      */
++      assert( !pagerUseWal(pPager) );
++      sqlite3PcacheMakeClean(pPg);
++    }
++    pager_set_pagehash(pPg);
++
++    /* If this was page 1, then restore the value of Pager.dbFileVers.
++    ** Do this before any decoding. */
++    if( pgno==1 ){
++      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
++    }
++
++    /* Decode the page just read from disk */
++    CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
++    sqlite3PcacheRelease(pPg);
+   }
++  return rc;
+ }
+ 
+ /*
+-** Change the page size used by the Pager object. The new page size 
+-** is passed in *pPageSize.
++** Parameter zMaster is the name of a master journal file. A single journal
++** file that referred to the master journal file has just been rolled back.
++** This routine checks if it is possible to delete the master journal file,
++** and does so if it is.
+ **
+-** If the pager is in the error state when this function is called, it
+-** is a no-op. The value returned is the error state error code (i.e. 
+-** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
++** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not 
++** available for use within this function.
+ **
+-** Otherwise, if all of the following are true:
++** When a master journal file is created, it is populated with the names 
++** of all of its child journals, one after another, formatted as utf-8 
++** encoded text. The end of each child journal file is marked with a 
++** nul-terminator byte (0x00). i.e. the entire contents of a master journal
++** file for a transaction involving two databases might be:
+ **
+-**   * the new page size (value of *pPageSize) is valid (a power 
+-**     of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
++**   "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
+ **
+-**   * there are no outstanding page references, and
++** A master journal file may only be deleted once all of its child 
++** journals have been rolled back.
+ **
+-**   * the database is either not an in-memory database or it is
+-**     an in-memory database that currently consists of zero pages.
++** This function reads the contents of the master-journal file into 
++** memory and loops through each of the child journal names. For
++** each child journal, it checks if:
+ **
+-** then the pager object page size is set to *pPageSize.
++**   * if the child journal exists, and if so
++**   * if the child journal contains a reference to master journal 
++**     file zMaster
+ **
+-** If the page size is changed, then this function uses sqlite3PagerMalloc() 
+-** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt 
+-** fails, SQLITE_NOMEM is returned and the page size remains unchanged. 
+-** In all other cases, SQLITE_OK is returned.
++** If a child journal can be found that matches both of the criteria
++** above, this function returns without doing anything. Otherwise, if
++** no such child journal can be found, file zMaster is deleted from
++** the file-system using sqlite3OsDelete().
+ **
+-** If the page size is not changed, either because one of the enumerated
+-** conditions above is not true, the pager was in error state when this
+-** function was called, or because the memory allocation attempt failed, 
+-** then *pPageSize is set to the old, retained page size before returning.
++** If an IO error within this function, an error code is returned. This
++** function allocates memory by calling sqlite3Malloc(). If an allocation
++** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors 
++** occur, SQLITE_OK is returned.
++**
++** TODO: This function allocates a single block of memory to load
++** the entire contents of the master journal file. This could be
++** a couple of kilobytes or so - potentially larger than the page 
++** size.
+ */
+-SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
+-  int rc = SQLITE_OK;
++static int pager_delmaster(Pager *pPager, const char *zMaster){
++  sqlite3_vfs *pVfs = pPager->pVfs;
++  int rc;                   /* Return code */
++  sqlite3_file *pMaster;    /* Malloc'd master-journal file descriptor */
++  sqlite3_file *pJournal;   /* Malloc'd child-journal file descriptor */
++  char *zMasterJournal = 0; /* Contents of master journal file */
++  i64 nMasterJournal;       /* Size of master journal file */
++  char *zJournal;           /* Pointer to one journal within MJ file */
++  char *zMasterPtr;         /* Space to hold MJ filename from a journal file */
++  int nMasterPtr;           /* Amount of space allocated to zMasterPtr[] */
+ 
+-  /* It is not possible to do a full assert_pager_state() here, as this
+-  ** function may be called from within PagerOpen(), before the state
+-  ** of the Pager object is internally consistent.
+-  **
+-  ** At one point this function returned an error if the pager was in 
+-  ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
+-  ** there is at least one outstanding page reference, this function
+-  ** is a no-op for that case anyhow.
++  /* Allocate space for both the pJournal and pMaster file descriptors.
++  ** If successful, open the master journal file for reading.
+   */
++  pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
++  pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
++  if( !pMaster ){
++    rc = SQLITE_NOMEM;
++  }else{
++    const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
++    rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
++  }
++  if( rc!=SQLITE_OK ) goto delmaster_out;
+ 
+-  u32 pageSize = *pPageSize;
+-  assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
+-  if( (pPager->memDb==0 || pPager->dbSize==0)
+-   && sqlite3PcacheRefCount(pPager->pPCache)==0 
+-   && pageSize && pageSize!=(u32)pPager->pageSize 
+-  ){
+-    char *pNew = NULL;             /* New temp space */
+-    i64 nByte = 0;
++  /* Load the entire master journal file into space obtained from
++  ** sqlite3_malloc() and pointed to by zMasterJournal.   Also obtain
++  ** sufficient space (in zMasterPtr) to hold the names of master
++  ** journal files extracted from regular rollback-journals.
++  */
++  rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
++  if( rc!=SQLITE_OK ) goto delmaster_out;
++  nMasterPtr = pVfs->mxPathname+1;
++  zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
++  if( !zMasterJournal ){
++    rc = SQLITE_NOMEM;
++    goto delmaster_out;
++  }
++  zMasterPtr = &zMasterJournal[nMasterJournal+1];
++  rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
++  if( rc!=SQLITE_OK ) goto delmaster_out;
++  zMasterJournal[nMasterJournal] = 0;
+ 
+-    if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
+-      rc = sqlite3OsFileSize(pPager->fd, &nByte);
+-    }
+-    if( rc==SQLITE_OK ){
+-      pNew = (char *)sqlite3PageMalloc(pageSize);
+-      if( !pNew ) rc = SQLITE_NOMEM;
++  zJournal = zMasterJournal;
++  while( (zJournal-zMasterJournal)<nMasterJournal ){
++    int exists;
++    rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
++    if( rc!=SQLITE_OK ){
++      goto delmaster_out;
+     }
++    if( exists ){
++      /* One of the journals pointed to by the master journal exists.
++      ** Open it and check if it points at the master journal. If
++      ** so, return without deleting the master journal file.
++      */
++      int c;
++      int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
++      rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
++      if( rc!=SQLITE_OK ){
++        goto delmaster_out;
++      }
+ 
+-    if( rc==SQLITE_OK ){
+-      pager_reset(pPager);
+-      pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
+-      pPager->pageSize = pageSize;
+-      sqlite3PageFree(pPager->pTmpSpace);
+-      pPager->pTmpSpace = pNew;
+-      sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
++      rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
++      sqlite3OsClose(pJournal);
++      if( rc!=SQLITE_OK ){
++        goto delmaster_out;
++      }
++
++      c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
++      if( c ){
++        /* We have a match. Do not delete the master journal file. */
++        goto delmaster_out;
++      }
+     }
++    zJournal += (sqlite3Strlen30(zJournal)+1);
+   }
++ 
++  sqlite3OsClose(pMaster);
++  rc = sqlite3OsDelete(pVfs, zMaster, 0);
+ 
+-  *pPageSize = pPager->pageSize;
+-  if( rc==SQLITE_OK ){
+-    if( nReserve<0 ) nReserve = pPager->nReserve;
+-    assert( nReserve>=0 && nReserve<1000 );
+-    pPager->nReserve = (i16)nReserve;
+-    pagerReportSize(pPager);
+-    pagerFixMaplimit(pPager);
++delmaster_out:
++  sqlite3_free(zMasterJournal);
++  if( pMaster ){
++    sqlite3OsClose(pMaster);
++    assert( !isOpen(pJournal) );
++    sqlite3_free(pMaster);
+   }
+   return rc;
+ }
+ 
+-/*
+-** Return a pointer to the "temporary page" buffer held internally
+-** by the pager.  This is a buffer that is big enough to hold the
+-** entire content of a database page.  This buffer is used internally
+-** during rollback and will be overwritten whenever a rollback
+-** occurs.  But other modules are free to use it too, as long as
+-** no rollbacks are happening.
+-*/
+-SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
+-  return pPager->pTmpSpace;
+-}
+-
+-/*
+-** Attempt to set the maximum database page count if mxPage is positive. 
+-** Make no changes if mxPage is zero or negative.  And never reduce the
+-** maximum page count below the current size of the database.
+-**
+-** Regardless of mxPage, return the current maximum page count.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
+-  if( mxPage>0 ){
+-    pPager->mxPgno = mxPage;
+-  }
+-  assert( pPager->eState!=PAGER_OPEN );      /* Called only by OP_MaxPgcnt */
+-  assert( pPager->mxPgno>=pPager->dbSize );  /* OP_MaxPgcnt enforces this */
+-  return pPager->mxPgno;
+-}
+ 
+ /*
+-** The following set of routines are used to disable the simulated
+-** I/O error mechanism.  These routines are used to avoid simulated
+-** errors in places where we do not care about errors.
++** This function is used to change the actual size of the database 
++** file in the file-system. This only happens when committing a transaction,
++** or rolling back a transaction (including rolling back a hot-journal).
+ **
+-** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
+-** and generate no code.
+-*/
+-#ifdef SQLITE_TEST
+-SQLITE_API extern int sqlite3_io_error_pending;
+-SQLITE_API extern int sqlite3_io_error_hit;
+-static int saved_cnt;
+-void disable_simulated_io_errors(void){
+-  saved_cnt = sqlite3_io_error_pending;
+-  sqlite3_io_error_pending = -1;
+-}
+-void enable_simulated_io_errors(void){
+-  sqlite3_io_error_pending = saved_cnt;
+-}
+-#else
+-# define disable_simulated_io_errors()
+-# define enable_simulated_io_errors()
+-#endif
+-
+-/*
+-** Read the first N bytes from the beginning of the file into memory
+-** that pDest points to. 
++** If the main database file is not open, or the pager is not in either
++** DBMOD or OPEN state, this function is a no-op. Otherwise, the size 
++** of the file is changed to nPage pages (nPage*pPager->pageSize bytes). 
++** If the file on disk is currently larger than nPage pages, then use the VFS
++** xTruncate() method to truncate it.
+ **
+-** If the pager was opened on a transient file (zFilename==""), or
+-** opened on a file less than N bytes in size, the output buffer is
+-** zeroed and SQLITE_OK returned. The rationale for this is that this 
+-** function is used to read database headers, and a new transient or
+-** zero sized database has a header than consists entirely of zeroes.
++** Or, it might might be the case that the file on disk is smaller than 
++** nPage pages. Some operating system implementations can get confused if 
++** you try to truncate a file to some size that is larger than it 
++** currently is, so detect this case and write a single zero byte to 
++** the end of the new file instead.
+ **
+-** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
+-** the error code is returned to the caller and the contents of the
+-** output buffer undefined.
++** If successful, return SQLITE_OK. If an IO error occurs while modifying
++** the database file, return the error code to the caller.
+ */
+-SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
++static int pager_truncate(Pager *pPager, Pgno nPage){
+   int rc = SQLITE_OK;
+-  memset(pDest, 0, N);
+-  assert( isOpen(pPager->fd) || pPager->tempFile );
+-
+-  /* This routine is only called by btree immediately after creating
+-  ** the Pager object.  There has not been an opportunity to transition
+-  ** to WAL mode yet.
+-  */
+-  assert( !pagerUseWal(pPager) );
+-
+-  if( isOpen(pPager->fd) ){
+-    IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
+-    rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
+-    if( rc==SQLITE_IOERR_SHORT_READ ){
+-      rc = SQLITE_OK;
++  assert( pPager->eState!=PAGER_ERROR );
++  assert( pPager->eState!=PAGER_READER );
++  
++  if( isOpen(pPager->fd) 
++   && (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 = szPage*(i64)nPage;
++    if( rc==SQLITE_OK && currentSize!=newSize ){
++      if( currentSize>newSize ){
++        rc = sqlite3OsTruncate(pPager->fd, newSize);
++      }else if( (currentSize+szPage)<=newSize ){
++        char *pTmp = pPager->pTmpSpace;
++        memset(pTmp, 0, szPage);
++        testcase( (newSize-szPage) == currentSize );
++        testcase( (newSize-szPage) >  currentSize );
++        rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
++      }
++      if( rc==SQLITE_OK ){
++        pPager->dbFileSize = nPage;
++      }
+     }
+   }
+   return rc;
+ }
+ 
+ /*
+-** This function may only be called when a read-transaction is open on
+-** the pager. It returns the total number of pages in the database.
+-**
+-** However, if the file is between 1 and <page-size> bytes in size, then 
+-** this is considered a 1 page file.
++** Return a sanitized version of the sector-size of OS file pFile. The
++** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
+ */
+-SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
+-  assert( pPager->eState>=PAGER_READER );
+-  assert( pPager->eState!=PAGER_WRITER_FINISHED );
+-  *pnPage = (int)pPager->dbSize;
++SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
++  int iRet = sqlite3OsSectorSize(pFile);
++  if( iRet<32 ){
++    iRet = 512;
++  }else if( iRet>MAX_SECTOR_SIZE ){
++    assert( MAX_SECTOR_SIZE>=512 );
++    iRet = MAX_SECTOR_SIZE;
++  }
++  return iRet;
+ }
+ 
+-
+ /*
+-** Try to obtain a lock of type locktype on the database file. If
+-** a similar or greater lock is already held, this function is a no-op
+-** (returning SQLITE_OK immediately).
++** Set the value of the Pager.sectorSize variable for the given
++** pager based on the value returned by the xSectorSize method
++** of the open database file. The sector size will be used used 
++** to determine the size and alignment of journal header and 
++** master journal pointers within created journal files.
+ **
+-** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke 
+-** the busy callback if the lock is currently not available. Repeat 
+-** until the busy callback returns false or until the attempt to 
+-** obtain the lock succeeds.
++** For temporary files the effective sector size is always 512 bytes.
+ **
+-** Return SQLITE_OK on success and an error code if we cannot obtain
+-** the lock. If the lock is obtained successfully, set the Pager.state 
+-** variable to locktype before returning.
++** Otherwise, for non-temporary files, the effective sector size is
++** the value returned by the xSectorSize() method rounded up to 32 if
++** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
++** is greater than MAX_SECTOR_SIZE.
++**
++** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
++** the effective sector size to its minimum value (512).  The purpose of
++** pPager->sectorSize is to define the "blast radius" of bytes that
++** might change if a crash occurs while writing to a single byte in
++** that range.  But with POWERSAFE_OVERWRITE, the blast radius is zero
++** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
++** size.  For backwards compatibility of the rollback journal file format,
++** we cannot reduce the effective sector size below 512.
+ */
+-static int pager_wait_on_lock(Pager *pPager, int locktype){
+-  int rc;                              /* Return code */
+-
+-  /* Check that this is either a no-op (because the requested lock is 
+-  ** already held, or one of the transistions that the busy-handler
+-  ** may be invoked during, according to the comment above
+-  ** sqlite3PagerSetBusyhandler().
+-  */
+-  assert( (pPager->eLock>=locktype)
+-       || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
+-       || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
+-  );
++static void setSectorSize(Pager *pPager){
++  assert( isOpen(pPager->fd) || pPager->tempFile );
+ 
+-  do {
+-    rc = pagerLockDb(pPager, locktype);
+-  }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
+-  return rc;
++  if( pPager->tempFile
++   || (sqlite3OsDeviceCharacteristics(pPager->fd) & 
++              SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
++  ){
++    /* Sector size doesn't matter for temporary files. Also, the file
++    ** may not have been opened yet, in which case the OsSectorSize()
++    ** call will segfault. */
++    pPager->sectorSize = 512;
++  }else{
++    pPager->sectorSize = sqlite3SectorSize(pPager->fd);
++  }
+ }
+ 
+ /*
+-** Function assertTruncateConstraint(pPager) checks that one of the 
+-** following is true for all dirty pages currently in the page-cache:
++** Playback the journal and thus restore the database file to
++** the state it was in before we started making changes.  
+ **
+-**   a) The page number is less than or equal to the size of the 
+-**      current database image, in pages, OR
++** The journal file format is as follows: 
+ **
+-**   b) if the page content were written at this time, it would not
+-**      be necessary to write the current content out to the sub-journal
+-**      (as determined by function subjRequiresPage()).
++**  (1)  8 byte prefix.  A copy of aJournalMagic[].
++**  (2)  4 byte big-endian integer which is the number of valid page records
++**       in the journal.  If this value is 0xffffffff, then compute the
++**       number of page records from the journal size.
++**  (3)  4 byte big-endian integer which is the initial value for the 
++**       sanity checksum.
++**  (4)  4 byte integer which is the number of pages to truncate the
++**       database to during a rollback.
++**  (5)  4 byte big-endian integer which is the sector size.  The header
++**       is this many bytes in size.
++**  (6)  4 byte big-endian integer which is the page size.
++**  (7)  zero padding out to the next sector size.
++**  (8)  Zero or more pages instances, each as follows:
++**        +  4 byte page number.
++**        +  pPager->pageSize bytes of data.
++**        +  4 byte checksum
+ **
+-** If the condition asserted by this function were not true, and the
+-** dirty page were to be discarded from the cache via the pagerStress()
+-** routine, pagerStress() would not write the current page content to
+-** the database file. If a savepoint transaction were rolled back after
+-** this happened, the correct behavior would be to restore the current
+-** content of the page. However, since this content is not present in either
+-** the database file or the portion of the rollback journal and 
+-** sub-journal rolled back the content could not be restored and the
+-** database image would become corrupt. It is therefore fortunate that 
+-** this circumstance cannot arise.
+-*/
+-#if defined(SQLITE_DEBUG)
+-static void assertTruncateConstraintCb(PgHdr *pPg){
+-  assert( pPg->flags&PGHDR_DIRTY );
+-  assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
+-}
+-static void assertTruncateConstraint(Pager *pPager){
+-  sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
+-}
+-#else
+-# define assertTruncateConstraint(pPager)
+-#endif
+-
+-/*
+-** Truncate the in-memory database file image to nPage pages. This 
+-** function does not actually modify the database file on disk. It 
+-** just sets the internal state of the pager object so that the 
+-** truncation will be done when the current transaction is committed.
++** When we speak of the journal header, we mean the first 7 items above.
++** Each entry in the journal is an instance of the 8th item.
+ **
+-** This function is only called right before committing a transaction.
+-** Once this function has been called, the transaction must either be
+-** rolled back or committed. It is not safe to call this function and
+-** then continue writing to the database.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
+-  assert( pPager->dbSize>=nPage );
+-  assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
+-  pPager->dbSize = nPage;
+-
+-  /* At one point the code here called assertTruncateConstraint() to
+-  ** ensure that all pages being truncated away by this operation are,
+-  ** if one or more savepoints are open, present in the savepoint 
+-  ** journal so that they can be restored if the savepoint is rolled
+-  ** back. This is no longer necessary as this function is now only
+-  ** called right before committing a transaction. So although the 
+-  ** Pager object may still have open savepoints (Pager.nSavepoint!=0), 
+-  ** they cannot be rolled back. So the assertTruncateConstraint() call
+-  ** is no longer correct. */
+-}
+-
+-
+-/*
+-** This function is called before attempting a hot-journal rollback. It
+-** syncs the journal file to disk, then sets pPager->journalHdr to the
+-** size of the journal file so that the pager_playback() routine knows
+-** that the entire journal file has been synced.
++** Call the value from the second bullet "nRec".  nRec is the number of
++** valid page entries in the journal.  In most cases, you can compute the
++** value of nRec from the size of the journal file.  But if a power
++** failure occurred while the journal was being written, it could be the
++** case that the size of the journal file had already been increased but
++** the extra entries had not yet made it safely to disk.  In such a case,
++** the value of nRec computed from the file size would be too large.  For
++** that reason, we always use the nRec value in the header.
+ **
+-** Syncing a hot-journal to disk before attempting to roll it back ensures 
+-** that if a power-failure occurs during the rollback, the process that
+-** attempts rollback following system recovery sees the same journal
+-** content as this process.
++** If the nRec value is 0xffffffff it means that nRec should be computed
++** from the file size.  This value is used when the user selects the
++** no-sync option for the journal.  A power failure could lead to corruption
++** in this case.  But for things like temporary table (which will be
++** deleted when the power is restored) we don't care.  
+ **
+-** If everything goes as planned, SQLITE_OK is returned. Otherwise, 
+-** an SQLite error code.
++** If the file opened as the journal file is not a well-formed
++** journal file then all pages up to the first corrupted page are rolled
++** back (or no pages if the journal header is corrupted). The journal file
++** is then deleted and SQLITE_OK returned, just as if no corruption had
++** been encountered.
++**
++** If an I/O or malloc() error occurs, the journal-file is not deleted
++** and an error code is returned.
++**
++** The isHot parameter indicates that we are trying to rollback a journal
++** that might be a hot journal.  Or, it could be that the journal is 
++** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
++** If the journal really is hot, reset the pager cache prior rolling
++** back any content.  If the journal is merely persistent, no reset is
++** needed.
+ */
+-static int pagerSyncHotJournal(Pager *pPager){
+-  int rc = SQLITE_OK;
+-  if( !pPager->noSync ){
+-    rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
++static int pager_playback(Pager *pPager, int isHot){
++  sqlite3_vfs *pVfs = pPager->pVfs;
++  i64 szJ;                 /* Size of the journal file in bytes */
++  u32 nRec;                /* Number of Records in the journal */
++  u32 u;                   /* Unsigned loop counter */
++  Pgno mxPg = 0;           /* Size of the original file in pages */
++  int rc;                  /* Result code of a subroutine */
++  int res = 1;             /* Value returned by sqlite3OsAccess() */
++  char *zMaster = 0;       /* Name of master journal file if any */
++  int needPagerReset;      /* True to reset page prior to first page rollback */
++  int nPlayback = 0;       /* Total number of pages restored from journal */
++
++  /* Figure out how many records are in the journal.  Abort early if
++  ** the journal is empty.
++  */
++  assert( isOpen(pPager->jfd) );
++  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
++  if( rc!=SQLITE_OK ){
++    goto end_playback;
+   }
+-  if( rc==SQLITE_OK ){
+-    rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
++
++  /* Read the master journal name from the journal, if it is present.
++  ** If a master journal file name is specified, but the file is not
++  ** present on disk, then the journal is not hot and does not need to be
++  ** played back.
++  **
++  ** TODO: Technically the following is an error because it assumes that
++  ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
++  ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
++  **  mxPathname is 512, which is the same as the minimum allowable value
++  ** for pageSize.
++  */
++  zMaster = pPager->pTmpSpace;
++  rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
++  if( rc==SQLITE_OK && zMaster[0] ){
++    rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
+   }
+-  return rc;
+-}
++  zMaster = 0;
++  if( rc!=SQLITE_OK || !res ){
++    goto end_playback;
++  }
++  pPager->journalOff = 0;
++  needPagerReset = isHot;
+ 
+-/*
+-** Obtain a reference to a memory mapped page object for page number pgno. 
+-** The new object will use the pointer pData, obtained from xFetch().
+-** If successful, set *ppPage to point to the new page reference
+-** and return SQLITE_OK. Otherwise, return an SQLite error code and set
+-** *ppPage to zero.
+-**
+-** Page references obtained by calling this function should be released
+-** by calling pagerReleaseMapPage().
+-*/
+-static int pagerAcquireMapPage(
+-  Pager *pPager,                  /* Pager object */
+-  Pgno pgno,                      /* Page number */
+-  void *pData,                    /* xFetch()'d data for this page */
+-  PgHdr **ppPage                  /* OUT: Acquired page object */
+-){
+-  PgHdr *p;                       /* Memory mapped page to return */
++  /* This loop terminates either when a readJournalHdr() or 
++  ** pager_playback_one_page() call returns SQLITE_DONE or an IO error 
++  ** occurs. 
++  */
++  while( 1 ){
++    /* Read the next journal header from the journal file.  If there are
++    ** not enough bytes left in the journal file for a complete header, or
++    ** it is corrupted, then a process must have failed while writing it.
++    ** This indicates nothing more needs to be rolled back.
++    */
++    rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
++    if( rc!=SQLITE_OK ){ 
++      if( rc==SQLITE_DONE ){
++        rc = SQLITE_OK;
++      }
++      goto end_playback;
++    }
+ 
+-  if( pPager->pMmapFreelist ){
+-    *ppPage = p = pPager->pMmapFreelist;
+-    pPager->pMmapFreelist = p->pDirty;
+-    p->pDirty = 0;
+-    memset(p->pExtra, 0, pPager->nExtra);
+-  }else{
+-    *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
+-    if( p==0 ){
+-      sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
+-      return SQLITE_NOMEM;
++    /* If nRec is 0xffffffff, then this journal was created by a process
++    ** working in no-sync mode. This means that the rest of the journal
++    ** file consists of pages, there are no more journal headers. Compute
++    ** the value of nRec based on this assumption.
++    */
++    if( nRec==0xffffffff ){
++      assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
++      nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
+     }
+-    p->pExtra = (void *)&p[1];
+-    p->flags = PGHDR_MMAP;
+-    p->nRef = 1;
+-    p->pPager = pPager;
+-  }
+ 
+-  assert( p->pExtra==(void *)&p[1] );
+-  assert( p->pPage==0 );
+-  assert( p->flags==PGHDR_MMAP );
+-  assert( p->pPager==pPager );
+-  assert( p->nRef==1 );
++    /* If nRec is 0 and this rollback is of a transaction created by this
++    ** process and if this is the final header in the journal, then it means
++    ** that this part of the journal was being filled but has not yet been
++    ** synced to disk.  Compute the number of pages based on the remaining
++    ** size of the file.
++    **
++    ** The third term of the test was added to fix ticket #2565.
++    ** When rolling back a hot journal, nRec==0 always means that the next
++    ** chunk of the journal contains zero pages to be rolled back.  But
++    ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
++    ** the journal, it means that the journal might contain additional
++    ** pages that need to be rolled back and that the number of pages 
++    ** should be computed based on the journal file size.
++    */
++    if( nRec==0 && !isHot &&
++        pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
++      nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
++    }
+ 
+-  p->pgno = pgno;
+-  p->pData = pData;
+-  pPager->nMmapOut++;
++    /* If this is the first header read from the journal, truncate the
++    ** database file back to its original size.
++    */
++    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
++      rc = pager_truncate(pPager, mxPg);
++      if( rc!=SQLITE_OK ){
++        goto end_playback;
++      }
++      pPager->dbSize = mxPg;
++    }
+ 
+-  return SQLITE_OK;
+-}
++    /* Copy original pages out of the journal and back into the 
++    ** database file and/or page cache.
++    */
++    for(u=0; u<nRec; u++){
++      if( needPagerReset ){
++        pager_reset(pPager);
++        needPagerReset = 0;
++      }
++      rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
++      if( rc==SQLITE_OK ){
++        nPlayback++;
++      }else{
++        if( rc==SQLITE_DONE ){
++          pPager->journalOff = szJ;
++          break;
++        }else if( rc==SQLITE_IOERR_SHORT_READ ){
++          /* If the journal has been truncated, simply stop reading and
++          ** processing the journal. This might happen if the journal was
++          ** not completely written and synced prior to a crash.  In that
++          ** case, the database should have never been written in the
++          ** first place so it is OK to simply abandon the rollback. */
++          rc = SQLITE_OK;
++          goto end_playback;
++        }else{
++          /* If we are unable to rollback, quit and return the error
++          ** code.  This will cause the pager to enter the error state
++          ** so that no further harm will be done.  Perhaps the next
++          ** process to come along will be able to rollback the database.
++          */
++          goto end_playback;
++        }
++      }
++    }
++  }
++  /*NOTREACHED*/
++  assert( 0 );
+ 
+-/*
+-** Release a reference to page pPg. pPg must have been returned by an 
+-** earlier call to pagerAcquireMapPage().
+-*/
+-static void pagerReleaseMapPage(PgHdr *pPg){
+-  Pager *pPager = pPg->pPager;
+-  pPager->nMmapOut--;
+-  pPg->pDirty = pPager->pMmapFreelist;
+-  pPager->pMmapFreelist = pPg;
++end_playback:
++  /* Following a rollback, the database file should be back in its original
++  ** state prior to the start of the transaction, so invoke the
++  ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
++  ** assertion that the transaction counter was modified.
++  */
++#ifdef SQLITE_DEBUG
++  if( pPager->fd->pMethods ){
++    sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
++  }
++#endif
+ 
+-  assert( pPager->fd->pMethods->iVersion>=3 );
+-  sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
+-}
++  /* If this playback is happening automatically as a result of an IO or 
++  ** malloc error that occurred after the change-counter was updated but 
++  ** before the transaction was committed, then the change-counter 
++  ** modification may just have been reverted. If this happens in exclusive 
++  ** mode, then subsequent transactions performed by the connection will not
++  ** update the change-counter at all. This may lead to cache inconsistency
++  ** problems for other processes at some point in the future. So, just
++  ** in case this has happened, clear the changeCountDone flag now.
++  */
++  pPager->changeCountDone = pPager->tempFile;
+ 
+-/*
+-** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
+-*/
+-static void pagerFreeMapHdrs(Pager *pPager){
+-  PgHdr *p;
+-  PgHdr *pNext;
+-  for(p=pPager->pMmapFreelist; p; p=pNext){
+-    pNext = p->pDirty;
+-    sqlite3_free(p);
++  if( rc==SQLITE_OK ){
++    zMaster = pPager->pTmpSpace;
++    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
++    testcase( rc!=SQLITE_OK );
++  }
++  if( rc==SQLITE_OK
++   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
++  ){
++    rc = sqlite3PagerSync(pPager);
++  }
++  if( rc==SQLITE_OK ){
++    rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
++    testcase( rc!=SQLITE_OK );
++  }
++  if( rc==SQLITE_OK && zMaster[0] && res ){
++    /* If there was a master journal and this routine will return success,
++    ** see if it is possible to delete the master journal.
++    */
++    rc = pager_delmaster(pPager, zMaster);
++    testcase( rc!=SQLITE_OK );
+   }
++  if( isHot && nPlayback ){
++    sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
++                nPlayback, pPager->zJournal);
++  }
++
++  /* The Pager.sectorSize variable may have been updated while rolling
++  ** back a journal created by a process with a different sector size
++  ** value. Reset it to the correct value for this process.
++  */
++  setSectorSize(pPager);
++  return rc;
+ }
+ 
+ 
+ /*
+-** Shutdown the page cache.  Free all memory and close all files.
++** Read the content for page pPg out of the database file and into 
++** pPg->pData. A shared lock or greater must be held on the database
++** file before this function is called.
+ **
+-** If a transaction was in progress when this routine is called, that
+-** transaction is rolled back.  All outstanding pages are invalidated
+-** and their memory is freed.  Any attempt to use a page associated
+-** with this page cache after this function returns will likely
+-** result in a coredump.
++** If page 1 is read, then the value of Pager.dbFileVers[] is set to
++** the value read from the database file.
+ **
+-** This function always succeeds. If a transaction is active an attempt
+-** is made to roll it back. If an error occurs during the rollback 
+-** a hot journal may be left in the filesystem but no error is returned
+-** to the caller.
++** If an IO error occurs, then the IO error is returned to the caller.
++** Otherwise, SQLITE_OK is returned.
+ */
+-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
+-  u8 *pTmp = (u8 *)pPager->pTmpSpace;
++static int readDbPage(PgHdr *pPg, u32 iFrame){
++  Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
++  Pgno pgno = pPg->pgno;       /* Page number to read */
++  int rc = SQLITE_OK;          /* Return code */
++  int pgsz = pPager->pageSize; /* Number of bytes to read */
++
++  assert( pPager->eState>=PAGER_READER && !MEMDB );
++  assert( isOpen(pPager->fd) );
++
++  if( NEVER(!isOpen(pPager->fd)) ){
++    assert( pPager->tempFile );
++    memset(pPg->pData, 0, pPager->pageSize);
++    return SQLITE_OK;
++  }
+ 
+-  assert( assert_pager_state(pPager) );
+-  disable_simulated_io_errors();
+-  sqlite3BeginBenignMalloc();
+-  pagerFreeMapHdrs(pPager);
+-  /* pPager->errCode = 0; */
+-  pPager->exclusiveMode = 0;
+ #ifndef SQLITE_OMIT_WAL
+-  sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
+-  pPager->pWal = 0;
++  if( iFrame ){
++    /* Try to pull the page from the write-ahead log. */
++    rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
++  }else
+ #endif
+-  pager_reset(pPager);
+-  if( MEMDB ){
+-    pager_unlock(pPager);
+-  }else{
+-    /* If it is open, sync the journal file before calling UnlockAndRollback.
+-    ** If this is not done, then an unsynced portion of the open journal 
+-    ** file may be played back into the database. If a power failure occurs 
+-    ** while this is happening, the database could become corrupt.
+-    **
+-    ** If an error occurs while trying to sync the journal, shift the pager
+-    ** into the ERROR state. This causes UnlockAndRollback to unlock the
+-    ** database and close the journal file without attempting to roll it
+-    ** back or finalize it. The next database user will have to do hot-journal
+-    ** rollback before accessing the database file.
+-    */
+-    if( isOpen(pPager->jfd) ){
+-      pager_error(pPager, pagerSyncHotJournal(pPager));
++  {
++    i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
++    rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
++    if( rc==SQLITE_IOERR_SHORT_READ ){
++      rc = SQLITE_OK;
+     }
+-    pagerUnlockAndRollback(pPager);
+   }
+-  sqlite3EndBenignMalloc();
+-  enable_simulated_io_errors();
+-  PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
+-  IOTRACE(("CLOSE %p\n", pPager))
+-  sqlite3OsClose(pPager->jfd);
+-  sqlite3OsClose(pPager->fd);
+-  sqlite3PageFree(pTmp);
+-  sqlite3PcacheClose(pPager->pPCache);
+ 
+-#ifdef SQLITE_HAS_CODEC
+-  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+-#endif
++  if( pgno==1 ){
++    if( rc ){
++      /* If the read is unsuccessful, set the dbFileVers[] to something
++      ** that will never be a valid file version.  dbFileVers[] is a copy
++      ** of bytes 24..39 of the database.  Bytes 28..31 should always be
++      ** zero or the size of the database in page. Bytes 32..35 and 35..39
++      ** should be page numbers which are never 0xffffffff.  So filling
++      ** pPager->dbFileVers[] with all 0xff bytes should suffice.
++      **
++      ** For an encrypted database, the situation is more complex:  bytes
++      ** 24..39 of the database are white noise.  But the probability of
++      ** white noising equaling 16 bytes of 0xff is vanishingly small so
++      ** we should still be ok.
++      */
++      memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
++    }else{
++      u8 *dbFileVers = &((u8*)pPg->pData)[24];
++      memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
++    }
++  }
++  CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
+ 
+-  assert( !pPager->aSavepoint && !pPager->pInJournal );
+-  assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
++  PAGER_INCR(sqlite3_pager_readdb_count);
++  PAGER_INCR(pPager->nRead);
++  IOTRACE(("PGIN %p %d\n", pPager, pgno));
++  PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
++               PAGERID(pPager), pgno, pager_pagehash(pPg)));
+ 
+-  sqlite3_free(pPager);
+-  return SQLITE_OK;
++  return rc;
+ }
+ 
+-#if !defined(NDEBUG) || defined(SQLITE_TEST)
+ /*
+-** Return the page number for page pPg.
++** 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.
+ */
+-SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){
+-  return pPg->pgno;
+-}
+-#endif
++static void pager_write_changecounter(PgHdr *pPg){
++  u32 change_counter;
+ 
+-/*
+-** Increment the reference count for page pPg.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
+-  sqlite3PcacheRef(pPg);
++  /* 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);
+ }
+ 
++#ifndef SQLITE_OMIT_WAL
+ /*
+-** Sync the journal. In other words, make sure all the pages that have
+-** been written to the journal have actually reached the surface of the
+-** disk and can be restored in the event of a hot-journal rollback.
+-**
+-** If the Pager.noSync flag is set, then this function is a no-op.
+-** Otherwise, the actions required depend on the journal-mode and the 
+-** device characteristics of the file-system, as follows:
+-**
+-**   * If the journal file is an in-memory journal file, no action need
+-**     be taken.
+-**
+-**   * Otherwise, if the device does not support the SAFE_APPEND property,
+-**     then the nRec field of the most recently written journal header
+-**     is updated to contain the number of journal records that have
+-**     been written following it. If the pager is operating in full-sync
+-**     mode, then the journal file is synced before this field is updated.
+-**
+-**   * If the device does not support the SEQUENTIAL property, then 
+-**     journal file is synced.
+-**
+-** Or, in pseudo-code:
+-**
+-**   if( NOT <in-memory journal> ){
+-**     if( NOT SAFE_APPEND ){
+-**       if( <full-sync mode> ) xSync(<journal file>);
+-**       <update nRec field>
+-**     } 
+-**     if( NOT SEQUENTIAL ) xSync(<journal file>);
+-**   }
++** This function is invoked once for each page that has already been 
++** written into the log file when a WAL transaction is rolled back.
++** Parameter iPg is the page number of said page. The pCtx argument 
++** is actually a pointer to the Pager structure.
+ **
+-** If successful, this routine clears the PGHDR_NEED_SYNC flag of every 
+-** page currently held in memory before returning SQLITE_OK. If an IO
+-** error is encountered, then the IO error code is returned to the caller.
++** If page iPg is present in the cache, and has no outstanding references,
++** it is discarded. Otherwise, if there are one or more outstanding
++** references, the page content is reloaded from the database. If the
++** attempt to reload content from the database is required and fails, 
++** return an SQLite error code. Otherwise, SQLITE_OK.
+ */
+-static int syncJournal(Pager *pPager, int newHdr){
+-  int rc;                         /* Return code */
+-
+-  assert( pPager->eState==PAGER_WRITER_CACHEMOD
+-       || pPager->eState==PAGER_WRITER_DBMOD
+-  );
+-  assert( assert_pager_state(pPager) );
+-  assert( !pagerUseWal(pPager) );
+-
+-  rc = sqlite3PagerExclusiveLock(pPager);
+-  if( rc!=SQLITE_OK ) return rc;
+-
+-  if( !pPager->noSync ){
+-    assert( !pPager->tempFile );
+-    if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
+-      const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+-      assert( isOpen(pPager->jfd) );
+-
+-      if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
+-        /* This block deals with an obscure problem. If the last connection
+-        ** that wrote to this database was operating in persistent-journal
+-        ** mode, then the journal file may at this point actually be larger
+-        ** than Pager.journalOff bytes. If the next thing in the journal
+-        ** file happens to be a journal-header (written as part of the
+-        ** previous connection's transaction), and a crash or power-failure 
+-        ** occurs after nRec is updated but before this connection writes 
+-        ** anything else to the journal file (or commits/rolls back its 
+-        ** transaction), then SQLite may become confused when doing the 
+-        ** hot-journal rollback following recovery. It may roll back all
+-        ** of this connections data, then proceed to rolling back the old,
+-        ** out-of-date data that follows it. Database corruption.
+-        **
+-        ** To work around this, if the journal file does appear to contain
+-        ** a valid header following Pager.journalOff, then write a 0x00
+-        ** byte to the start of it to prevent it from being recognized.
+-        **
+-        ** Variable iNextHdrOffset is set to the offset at which this
+-        ** problematic header will occur, if it exists. aMagic is used 
+-        ** as a temporary buffer to inspect the first couple of bytes of
+-        ** the potential journal header.
+-        */
+-        i64 iNextHdrOffset;
+-        u8 aMagic[8];
+-        u8 zHeader[sizeof(aJournalMagic)+4];
+-
+-        memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
+-        put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
+-
+-        iNextHdrOffset = journalHdrOffset(pPager);
+-        rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
+-        if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
+-          static const u8 zerobyte = 0;
+-          rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
+-        }
+-        if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
+-          return rc;
+-        }
++static int pagerUndoCallback(void *pCtx, Pgno iPg){
++  int rc = SQLITE_OK;
++  Pager *pPager = (Pager *)pCtx;
++  PgHdr *pPg;
+ 
+-        /* Write the nRec value into the journal file header. If in
+-        ** full-synchronous mode, sync the journal first. This ensures that
+-        ** all data has really hit the disk before nRec is updated to mark
+-        ** it as a candidate for rollback.
+-        **
+-        ** This is not required if the persistent media supports the
+-        ** SAFE_APPEND property. Because in this case it is not possible 
+-        ** for garbage data to be appended to the file, the nRec field
+-        ** is populated with 0xFFFFFFFF when the journal header is written
+-        ** and never needs to be updated.
+-        */
+-        if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+-          PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
+-          IOTRACE(("JSYNC %p\n", pPager))
+-          rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
+-          if( rc!=SQLITE_OK ) return rc;
+-        }
+-        IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
+-        rc = sqlite3OsWrite(
+-            pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
+-        );
+-        if( rc!=SQLITE_OK ) return rc;
+-      }
+-      if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+-        PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
+-        IOTRACE(("JSYNC %p\n", pPager))
+-        rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| 
+-          (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
+-        );
+-        if( rc!=SQLITE_OK ) return rc;
++  assert( pagerUseWal(pPager) );
++  pPg = sqlite3PagerLookup(pPager, iPg);
++  if( pPg ){
++    if( sqlite3PcachePageRefcount(pPg)==1 ){
++      sqlite3PcacheDrop(pPg);
++    }else{
++      u32 iFrame = 0;
++      rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
++      if( rc==SQLITE_OK ){
++        rc = readDbPage(pPg, iFrame);
+       }
+-
+-      pPager->journalHdr = pPager->journalOff;
+-      if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
+-        pPager->nRec = 0;
+-        rc = writeJournalHdr(pPager);
+-        if( rc!=SQLITE_OK ) return rc;
++      if( rc==SQLITE_OK ){
++        pPager->xReiniter(pPg);
+       }
+-    }else{
+-      pPager->journalHdr = pPager->journalOff;
++      sqlite3PagerUnref(pPg);
+     }
+   }
+ 
+-  /* Unless the pager is in noSync mode, the journal file was just 
+-  ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on 
+-  ** all pages.
++  /* Normally, if a transaction is rolled back, any backup processes are
++  ** updated as data is copied out of the rollback journal and into the
++  ** database. This is not generally possible with a WAL database, as
++  ** rollback involves simply truncating the log file. Therefore, if one
++  ** or more frames have already been written to the log (and therefore 
++  ** also copied into the backup databases) as part of this transaction,
++  ** the backups must be restarted.
+   */
+-  sqlite3PcacheClearSyncFlags(pPager->pPCache);
+-  pPager->eState = PAGER_WRITER_DBMOD;
+-  assert( assert_pager_state(pPager) );
+-  return SQLITE_OK;
++  sqlite3BackupRestart(pPager->pBackup);
++
++  return rc;
+ }
+ 
+ /*
+-** The argument is the first in a linked list of dirty pages connected
+-** by the PgHdr.pDirty pointer. This function writes each one of the
+-** in-memory pages in the list to the database file. The argument may
+-** be NULL, representing an empty list. In this case this function is
+-** a no-op.
+-**
+-** The pager must hold at least a RESERVED lock when this function
+-** is called. Before writing anything to the database file, this lock
+-** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
+-** SQLITE_BUSY is returned and no data is written to the database file.
+-** 
+-** If the pager is a temp-file pager and the actual file-system file
+-** is not yet open, it is created and opened before any data is 
+-** written out.
+-**
+-** Once the lock has been upgraded and, if necessary, the file opened,
+-** the pages are written out to the database file in list order. Writing
+-** a page is skipped if it meets either of the following criteria:
+-**
+-**   * The page number is greater than Pager.dbSize, or
+-**   * The PGHDR_DONT_WRITE flag is set on the page.
+-**
+-** If writing out a page causes the database file to grow, Pager.dbFileSize
+-** is updated accordingly. If page 1 is written out, then the value cached
+-** in Pager.dbFileVers[] is updated to match the new value stored in
+-** the database file.
+-**
+-** If everything is successful, SQLITE_OK is returned. If an IO error 
+-** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
+-** be obtained, SQLITE_BUSY is returned.
++** This function is called to rollback a transaction on a WAL database.
+ */
+-static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
+-  int rc = SQLITE_OK;                  /* Return code */
+-
+-  /* This function is only called for rollback pagers in WRITER_DBMOD state. */
+-  assert( !pagerUseWal(pPager) );
+-  assert( pPager->eState==PAGER_WRITER_DBMOD );
+-  assert( pPager->eLock==EXCLUSIVE_LOCK );
+-
+-  /* If the file is a temp-file has not yet been opened, open it now. It
+-  ** is not possible for rc to be other than SQLITE_OK if this branch
+-  ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
+-  */
+-  if( !isOpen(pPager->fd) ){
+-    assert( pPager->tempFile && rc==SQLITE_OK );
+-    rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
+-  }
++static int pagerRollbackWal(Pager *pPager){
++  int rc;                         /* Return Code */
++  PgHdr *pList;                   /* List of dirty pages to revert */
+ 
+-  /* Before the first write, give the VFS a hint of what the final
+-  ** file size will be.
++  /* For all pages in the cache that are currently dirty or have already
++  ** been written (but not committed) to the log file, do one of the 
++  ** following:
++  **
++  **   + Discard the cached page (if refcount==0), or
++  **   + Reload page content from the database (if refcount>0).
+   */
+-  assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
+-  if( rc==SQLITE_OK 
+-   && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize 
+-  ){
+-    sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
+-    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
+-    pPager->dbHintSize = pPager->dbSize;
++  pPager->dbSize = pPager->dbOrigSize;
++  rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
++  pList = sqlite3PcacheDirtyList(pPager->pPCache);
++  while( pList && rc==SQLITE_OK ){
++    PgHdr *pNext = pList->pDirty;
++    rc = pagerUndoCallback((void *)pPager, pList->pgno);
++    pList = pNext;
+   }
+ 
+-  while( rc==SQLITE_OK && pList ){
+-    Pgno pgno = pList->pgno;
+-
+-    /* If there are dirty pages in the page cache with page numbers greater
+-    ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
+-    ** make the file smaller (presumably by auto-vacuum code). Do not write
+-    ** any such pages to the file.
+-    **
+-    ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
+-    ** set (set by sqlite3PagerDontWrite()).
+-    */
+-    if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
+-      i64 offset = (pgno-1)*(i64)pPager->pageSize;   /* Offset to write */
+-      char *pData;                                   /* Data to write */    
+-
+-      assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
+-      if( pList->pgno==1 ) pager_write_changecounter(pList);
++  return rc;
++}
+ 
+-      /* Encode the database */
+-      CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
++/*
++** 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. 
++**
++** 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 */
++  PgHdr *pList,                   /* List of frames to log */
++  Pgno nTruncate,                 /* Database size after this commit */
++  int isCommit                    /* True if this is a commit */
 +){
-+  sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec); 
++  int rc;                         /* Return code */
++  int nList;                      /* Number of pages in pList */
++#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
++  PgHdr *p;                       /* For looping over pages */
++#endif
+ 
+-      /* Write out the page data. */
+-      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
++  assert( pPager->pWal );
++  assert( pList );
++#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 page 1 was just written, update Pager.dbFileVers to match
+-      ** the value now stored in the database file. If writing this 
+-      ** page caused the database file to grow, update dbFileSize. 
+-      */
+-      if( pgno==1 ){
+-        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
+-      }
+-      if( pgno>pPager->dbFileSize ){
+-        pPager->dbFileSize = pgno;
++  assert( pList->pDirty==0 || isCommit );
++  if( isCommit ){
++    /* If a WAL transaction is being committed, there is no point in writing
++    ** any pages with page numbers greater than nTruncate into the WAL file.
++    ** They will never be read by any client. So remove them from the pDirty
++    ** list here. */
++    PgHdr *p;
++    PgHdr **ppNext = &pList;
++    nList = 0;
++    for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
++      if( p->pgno<=nTruncate ){
++        ppNext = &p->pDirty;
++        nList++;
+       }
+-      pPager->aStat[PAGER_STAT_WRITE]++;
+-
+-      /* Update any backup objects copying the contents of this pager. */
+-      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
++    }
++    assert( pList );
++  }else{
++    nList = 1;
++  }
++  pPager->aStat[PAGER_STAT_WRITE] += nList;
+ 
+-      PAGERTRACE(("STORE %d page %d hash(%08x)\n",
+-                   PAGERID(pPager), pgno, pager_pagehash(pList)));
+-      IOTRACE(("PGOUT %p %d\n", pPager, pgno));
+-      PAGER_INCR(sqlite3_pager_writedb_count);
+-    }else{
+-      PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
++  if( pList->pgno==1 ) pager_write_changecounter(pList);
++  rc = sqlite3WalFrames(pPager->pWal, 
++      pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
++  );
++  if( rc==SQLITE_OK && pPager->pBackup ){
++    PgHdr *p;
++    for(p=pList; p; p=p->pDirty){
++      sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
+     }
+-    pager_set_pagehash(pList);
+-    pList = pList->pDirty;
+   }
+ 
++#ifdef SQLITE_CHECK_PAGES
++  pList = sqlite3PcacheDirtyList(pPager->pPCache);
++  for(p=pList; p; p=p->pDirty){
++    pager_set_pagehash(p);
++  }
++#endif
++
+   return rc;
+ }
+ 
+ /*
+-** Ensure that the sub-journal file is open. If it is already open, this 
+-** function is a no-op.
++** Begin a read transaction on the WAL.
+ **
+-** SQLITE_OK is returned if everything goes according to plan. An 
+-** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() 
+-** fails.
++** This routine used to be called "pagerOpenSnapshot()" because it essentially
++** makes a snapshot of the database at the current point in time and preserves
++** that snapshot for use by the reader in spite of concurrently changes by
++** other writers or checkpointers.
+ */
+-static int openSubJournal(Pager *pPager){
+-  int rc = SQLITE_OK;
+-  if( !isOpen(pPager->sjfd) ){
+-    if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
+-      sqlite3MemJournalOpen(pPager->sjfd);
+-    }else{
+-      rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL);
+-    }
++static int pagerBeginReadTransaction(Pager *pPager){
++  int rc;                         /* Return code */
++  int changed = 0;                /* True if cache must be reset */
++
++  assert( pagerUseWal(pPager) );
++  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
++
++  /* sqlite3WalEndReadTransaction() was not called for the previous
++  ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
++  ** are in locking_mode=NORMAL and EndRead() was previously called,
++  ** the duplicate call is harmless.
++  */
++  sqlite3WalEndReadTransaction(pPager->pWal);
++
++  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
++  if( rc!=SQLITE_OK || changed ){
++    pager_reset(pPager);
++    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
+   }
++
+   return rc;
+ }
++#endif
+ 
+ /*
+-** Append a record of the current state of page pPg to the sub-journal. 
+-** It is the callers responsibility to use subjRequiresPage() to check 
+-** that it is really required before calling this function.
+-**
+-** If successful, set the bit corresponding to pPg->pgno in the bitvecs
+-** for all open savepoints before returning.
++** This function is called as part of the transition from PAGER_OPEN
++** to PAGER_READER state to determine the size of the database file
++** in pages (assuming the page size currently stored in Pager.pageSize).
+ **
+-** This function returns SQLITE_OK if everything is successful, an IO
+-** error code if the attempt to write to the sub-journal fails, or 
+-** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
+-** bitvec.
++** If no error occurs, SQLITE_OK is returned and the size of the database
++** in pages is stored in *pnPage. Otherwise, an error code (perhaps
++** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
+ */
+-static int subjournalPage(PgHdr *pPg){
+-  int rc = SQLITE_OK;
+-  Pager *pPager = pPg->pPager;
+-  if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
++static int pagerPagecount(Pager *pPager, Pgno *pnPage){
++  Pgno nPage;                     /* Value to return via *pnPage */
+ 
+-    /* Open the sub-journal, if it has not already been opened */
+-    assert( pPager->useJournal );
+-    assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
+-    assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
+-    assert( pagerUseWal(pPager) 
+-         || pageInJournal(pPg) 
+-         || pPg->pgno>pPager->dbOrigSize 
+-    );
+-    rc = openSubJournal(pPager);
++  /* Query the WAL sub-system for the database size. The WalDbsize()
++  ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
++  ** if the database size is not available. The database size is not
++  ** available from the WAL sub-system if the log file is empty or
++  ** contains no valid committed transactions.
++  */
++  assert( pPager->eState==PAGER_OPEN );
++  assert( pPager->eLock>=SHARED_LOCK );
++  nPage = sqlite3WalDbsize(pPager->pWal);
+ 
+-    /* If the sub-journal was opened successfully (or was already open),
+-    ** write the journal record into the file.  */
+-    if( rc==SQLITE_OK ){
+-      void *pData = pPg->pData;
+-      i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
+-      char *pData2;
+-  
+-      CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
+-      PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
+-      rc = write32bits(pPager->sjfd, offset, pPg->pgno);
+-      if( rc==SQLITE_OK ){
+-        rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
++  /* If the database size was not available from the WAL sub-system,
++  ** determine it based on the size of the database file. If the size
++  ** of the database file is not an integer multiple of the page-size,
++  ** round down to the nearest page. Except, any file larger than 0
++  ** bytes in size is considered to contain at least one page.
++  */
++  if( nPage==0 ){
++    i64 n = 0;                    /* Size of db file in bytes */
++    assert( isOpen(pPager->fd) || pPager->tempFile );
++    if( isOpen(pPager->fd) ){
++      int rc = sqlite3OsFileSize(pPager->fd, &n);
++      if( rc!=SQLITE_OK ){
++        return rc;
+       }
+     }
++    nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
+   }
+-  if( rc==SQLITE_OK ){
+-    pPager->nSubRec++;
+-    assert( pPager->nSavepoint>0 );
+-    rc = addToSavepointBitvecs(pPager, pPg->pgno);
++
++  /* If the current number of pages in the file is greater than the
++  ** configured maximum pager number, increase the allowed limit so
++  ** that the file can be read.
++  */
++  if( nPage>pPager->mxPgno ){
++    pPager->mxPgno = (Pgno)nPage;
+   }
+-  return rc;
++
++  *pnPage = nPage;
++  return SQLITE_OK;
+ }
+ 
++#ifndef SQLITE_OMIT_WAL
+ /*
+-** This function is called by the pcache layer when it has reached some
+-** soft memory limit. The first argument is a pointer to a Pager object
+-** (cast as a void*). The pager is always 'purgeable' (not an in-memory
+-** database). The second argument is a reference to a page that is 
+-** currently dirty but has no outstanding references. The page
+-** is always associated with the Pager object passed as the first 
+-** argument.
++** Check if the *-wal file that corresponds to the database opened by pPager
++** exists if the database is not empy, or verify that the *-wal file does
++** not exist (by deleting it) if the database file is empty.
+ **
+-** The job of this function is to make pPg clean by writing its contents
+-** out to the database file, if possible. This may involve syncing the
+-** journal file. 
++** If the database is not empty and the *-wal file exists, open the pager
++** in WAL mode.  If the database is empty or if no *-wal file exists and
++** if no error occurs, make sure Pager.journalMode is not set to
++** PAGER_JOURNALMODE_WAL.
+ **
+-** If successful, sqlite3PcacheMakeClean() is called on the page and
+-** SQLITE_OK returned. If an IO error occurs while trying to make the
+-** page clean, the IO error code is returned. If the page cannot be
+-** made clean for some other reason, but no error occurs, then SQLITE_OK
+-** is returned by sqlite3PcacheMakeClean() is not called.
++** Return SQLITE_OK or an error code.
++**
++** The caller must hold a SHARED lock on the database file to call this
++** function. Because an EXCLUSIVE lock on the db file is required to delete 
++** a WAL on a none-empty database, this ensures there is no race condition 
++** between the xAccess() below and an xDelete() being executed by some 
++** other connection.
+ */
+-static int pagerStress(void *p, PgHdr *pPg){
+-  Pager *pPager = (Pager *)p;
++static int pagerOpenWalIfPresent(Pager *pPager){
+   int rc = SQLITE_OK;
++  assert( pPager->eState==PAGER_OPEN );
++  assert( pPager->eLock>=SHARED_LOCK );
+ 
+-  assert( pPg->pPager==pPager );
+-  assert( pPg->flags&PGHDR_DIRTY );
+-
+-  /* The doNotSyncSpill flag is set during times when doing a sync of
+-  ** journal (and adding a new header) is not allowed.  This occurs
+-  ** during calls to sqlite3PagerWrite() while trying to journal multiple
+-  ** pages belonging to the same sector.
+-  **
+-  ** The doNotSpill flag inhibits all cache spilling regardless of whether
+-  ** or not a sync is required.  This is set during a rollback.
+-  **
+-  ** Spilling is also prohibited when in an error state since that could
+-  ** lead to database corruption.   In the current implementaton it 
+-  ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
+-  ** while in the error state, hence it is impossible for this routine to
+-  ** be called in the error state.  Nevertheless, we include a NEVER()
+-  ** test for the error state as a safeguard against future changes.
+-  */
+-  if( NEVER(pPager->errCode) ) return SQLITE_OK;
+-  if( pPager->doNotSpill ) return SQLITE_OK;
+-  if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
+-    return SQLITE_OK;
+-  }
++  if( !pPager->tempFile ){
++    int isWal;                    /* True if WAL file exists */
++    Pgno nPage;                   /* Size of the database file */
+ 
+-  pPg->pDirty = 0;
+-  if( pagerUseWal(pPager) ){
+-    /* Write a single frame for this page to the log. */
+-    if( subjRequiresPage(pPg) ){ 
+-      rc = subjournalPage(pPg); 
+-    }
+-    if( rc==SQLITE_OK ){
+-      rc = pagerWalFrames(pPager, pPg, 0, 0);
+-    }
+-  }else{
+-  
+-    /* Sync the journal file if required. */
+-    if( pPg->flags&PGHDR_NEED_SYNC 
+-     || pPager->eState==PAGER_WRITER_CACHEMOD
+-    ){
+-      rc = syncJournal(pPager, 1);
+-    }
+-  
+-    /* If the page number of this page is larger than the current size of
+-    ** the database image, it may need to be written to the sub-journal.
+-    ** This is because the call to pager_write_pagelist() below will not
+-    ** actually write data to the file in this case.
+-    **
+-    ** Consider the following sequence of events:
+-    **
+-    **   BEGIN;
+-    **     <journal page X>
+-    **     <modify page X>
+-    **     SAVEPOINT sp;
+-    **       <shrink database file to Y pages>
+-    **       pagerStress(page X)
+-    **     ROLLBACK TO sp;
+-    **
+-    ** If (X>Y), then when pagerStress is called page X will not be written
+-    ** out to the database file, but will be dropped from the cache. Then,
+-    ** following the "ROLLBACK TO sp" statement, reading page X will read
+-    ** data from the database file. This will be the copy of page X as it
+-    ** was when the transaction started, not as it was when "SAVEPOINT sp"
+-    ** was executed.
+-    **
+-    ** The solution is to write the current data for page X into the 
+-    ** sub-journal file now (if it is not already there), so that it will
+-    ** be restored to its current value when the "ROLLBACK TO sp" is 
+-    ** executed.
+-    */
+-    if( NEVER(
+-        rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg)
+-    ) ){
+-      rc = subjournalPage(pPg);
++    rc = pagerPagecount(pPager, &nPage);
++    if( rc ) return rc;
++    if( nPage==0 ){
++      rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
++      if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
++      isWal = 0;
++    }else{
++      rc = sqlite3OsAccess(
++          pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
++      );
+     }
+-  
+-    /* Write the contents of the page out to the database file. */
+     if( rc==SQLITE_OK ){
+-      assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
+-      rc = pager_write_pagelist(pPager, pPg);
++      if( isWal ){
++        testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
++        rc = sqlite3PagerOpenWal(pPager, 0);
++      }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
++        pPager->journalMode = PAGER_JOURNALMODE_DELETE;
++      }
+     }
+   }
+-
+-  /* Mark the page as clean. */
+-  if( rc==SQLITE_OK ){
+-    PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
+-    sqlite3PcacheMakeClean(pPg);
+-  }
+-
+-  return pager_error(pPager, rc); 
++  return rc;
+ }
+-
++#endif
+ 
+ /*
+-** Allocate and initialize a new Pager object and put a pointer to it
+-** in *ppPager. The pager should eventually be freed by passing it
+-** to sqlite3PagerClose().
++** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
++** the entire master journal file. The case pSavepoint==NULL occurs when 
++** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction 
++** savepoint.
+ **
+-** The zFilename argument is the path to the database file to open.
+-** If zFilename is NULL then a randomly-named temporary file is created
+-** and used as the file to be cached. Temporary files are be deleted
+-** automatically when they are closed. If zFilename is ":memory:" then 
+-** all information is held in cache. It is never written to disk. 
+-** This can be used to implement an in-memory database.
++** When pSavepoint is not NULL (meaning a non-transaction savepoint is 
++** being rolled back), then the rollback consists of up to three stages,
++** performed in the order specified:
+ **
+-** The nExtra parameter specifies the number of bytes of space allocated
+-** along with each page reference. This space is available to the user
+-** via the sqlite3PagerGetExtra() API.
++**   * Pages are played back from the main journal starting at byte
++**     offset PagerSavepoint.iOffset and continuing to 
++**     PagerSavepoint.iHdrOffset, or to the end of the main journal
++**     file if PagerSavepoint.iHdrOffset is zero.
+ **
+-** The flags argument is used to specify properties that affect the
+-** operation of the pager. It should be passed some bitwise combination
+-** of the PAGER_* flags.
++**   * If PagerSavepoint.iHdrOffset is not zero, then pages are played
++**     back starting from the journal header immediately following 
++**     PagerSavepoint.iHdrOffset to the end of the main journal file.
+ **
+-** The vfsFlags parameter is a bitmask to pass to the flags parameter
+-** of the xOpen() method of the supplied VFS when opening files. 
++**   * Pages are then played back from the sub-journal file, starting
++**     with the PagerSavepoint.iSubRec and continuing to the end of
++**     the journal file.
+ **
+-** If the pager object is allocated and the specified file opened 
+-** successfully, SQLITE_OK is returned and *ppPager set to point to
+-** the new pager object. If an error occurs, *ppPager is set to NULL
+-** and error code returned. This function may return SQLITE_NOMEM
+-** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or 
+-** various SQLITE_IO_XXX errors.
++** Throughout the rollback process, each time a page is rolled back, the
++** corresponding bit is set in a bitvec structure (variable pDone in the
++** implementation below). This is used to ensure that a page is only
++** rolled back the first time it is encountered in either journal.
++**
++** If pSavepoint is NULL, then pages are only played back from the main
++** journal file. There is no need for a bitvec in this case.
++**
++** In either case, before playback commences the Pager.dbSize variable
++** is reset to the value that it held at the start of the savepoint 
++** (or transaction). No page with a page-number greater than this value
++** is played back. If one is encountered it is simply skipped.
+ */
+-SQLITE_PRIVATE int sqlite3PagerOpen(
+-  sqlite3_vfs *pVfs,       /* The virtual file system to use */
+-  Pager **ppPager,         /* OUT: Return the Pager structure here */
+-  const char *zFilename,   /* Name of the database file to open */
+-  int nExtra,              /* Extra bytes append to each in-memory page */
+-  int flags,               /* flags controlling this file */
+-  int vfsFlags,            /* flags passed through to sqlite3_vfs.xOpen() */
+-  void (*xReinit)(DbPage*) /* Function to reinitialize pages */
+-){
+-  u8 *pPtr;
+-  Pager *pPager = 0;       /* Pager object to allocate and return */
++static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
++  i64 szJ;                 /* Effective size of the main journal */
++  i64 iHdrOff;             /* End of first segment of main-journal records */
+   int rc = SQLITE_OK;      /* Return code */
+-  int tempFile = 0;        /* True for temp files (incl. in-memory files) */
+-  int memDb = 0;           /* True if this is an in-memory file */
+-  int readOnly = 0;        /* True if this is a read-only file */
+-  int journalFileSize;     /* Bytes to allocate for each journal fd */
+-  char *zPathname = 0;     /* Full path to database file */
+-  int nPathname = 0;       /* Number of bytes in zPathname */
+-  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
+-  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
+-  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
+-  const char *zUri = 0;    /* URI args to copy */
+-  int nUri = 0;            /* Number of bytes of URI args at *zUri */
++  Bitvec *pDone = 0;       /* Bitvec to ensure pages played back only once */
+ 
+-  /* Figure out how much space is required for each journal file-handle
+-  ** (there are two of them, the main journal and the sub-journal). This
+-  ** is the maximum space required for an in-memory journal file handle 
+-  ** and a regular journal file-handle. Note that a "regular journal-handle"
+-  ** may be a wrapper capable of caching the first portion of the journal
+-  ** file in memory to implement the atomic-write optimization (see 
+-  ** source file journal.c).
+-  */
+-  if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
+-    journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
+-  }else{
+-    journalFileSize = ROUND8(sqlite3MemJournalSize());
++  assert( pPager->eState!=PAGER_ERROR );
++  assert( pPager->eState>=PAGER_WRITER_LOCKED );
++
++  /* Allocate a bitvec to use to store the set of pages rolled back */
++  if( pSavepoint ){
++    pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
++    if( !pDone ){
++      return SQLITE_NOMEM;
++    }
+   }
+ 
+-  /* Set the output variable to NULL in case an error occurs. */
+-  *ppPager = 0;
++  /* Set the database size back to the value it was before the savepoint 
++  ** being reverted was opened.
++  */
++  pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
++  pPager->changeCountDone = pPager->tempFile;
+ 
+-#ifndef SQLITE_OMIT_MEMORYDB
+-  if( flags & PAGER_MEMORY ){
+-    memDb = 1;
+-    if( zFilename && zFilename[0] ){
+-      zPathname = sqlite3DbStrDup(0, zFilename);
+-      if( zPathname==0  ) return SQLITE_NOMEM;
+-      nPathname = sqlite3Strlen30(zPathname);
+-      zFilename = 0;
+-    }
++  if( !pSavepoint && pagerUseWal(pPager) ){
++    return pagerRollbackWal(pPager);
+   }
+-#endif
+ 
+-  /* Compute and store the full pathname in an allocated buffer pointed
+-  ** to by zPathname, length nPathname. Or, if this is a temporary file,
+-  ** leave both nPathname and zPathname set to 0.
++  /* Use pPager->journalOff as the effective size of the main rollback
++  ** journal.  The actual file might be larger than this in
++  ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST.  But anything
++  ** past pPager->journalOff is off-limits to us.
+   */
+-  if( zFilename && zFilename[0] ){
+-    const char *z;
+-    nPathname = pVfs->mxPathname+1;
+-    zPathname = sqlite3DbMallocRaw(0, nPathname*2);
+-    if( zPathname==0 ){
+-      return SQLITE_NOMEM;
+-    }
+-    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
+-    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
+-    nPathname = sqlite3Strlen30(zPathname);
+-    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
+-    while( *z ){
+-      z += sqlite3Strlen30(z)+1;
+-      z += sqlite3Strlen30(z)+1;
+-    }
+-    nUri = (int)(&z[1] - zUri);
+-    assert( nUri>=0 );
+-    if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
+-      /* This branch is taken when the journal path required by
+-      ** the database being opened will be more than pVfs->mxPathname
+-      ** bytes in length. This means the database cannot be opened,
+-      ** as it will not be possible to open the journal file or even
+-      ** check for a hot-journal before reading.
+-      */
+-      rc = SQLITE_CANTOPEN_BKPT;
+-    }
+-    if( rc!=SQLITE_OK ){
+-      sqlite3DbFree(0, zPathname);
+-      return rc;
++  szJ = pPager->journalOff;
++  assert( pagerUseWal(pPager)==0 || szJ==0 );
++
++  /* Begin by rolling back records from the main journal starting at
++  ** PagerSavepoint.iOffset and continuing to the next journal header.
++  ** There might be records in the main journal that have a page number
++  ** greater than the current database size (pPager->dbSize) but those
++  ** will be skipped automatically.  Pages are added to pDone as they
++  ** are played back.
++  */
++  if( pSavepoint && !pagerUseWal(pPager) ){
++    iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
++    pPager->journalOff = pSavepoint->iOffset;
++    while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
++      rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
+     }
++    assert( rc!=SQLITE_DONE );
++  }else{
++    pPager->journalOff = 0;
+   }
+ 
+-  /* Allocate memory for the Pager structure, PCache object, the
+-  ** three file descriptors, the database file name and the journal 
+-  ** file name. The layout in memory is as follows:
+-  **
+-  **     Pager object                    (sizeof(Pager) bytes)
+-  **     PCache object                   (sqlite3PcacheSize() bytes)
+-  **     Database file handle            (pVfs->szOsFile bytes)
+-  **     Sub-journal file handle         (journalFileSize bytes)
+-  **     Main journal file handle        (journalFileSize bytes)
+-  **     Database file name              (nPathname+1 bytes)
+-  **     Journal file name               (nPathname+8+1 bytes)
++  /* Continue rolling back records out of the main journal starting at
++  ** the first journal header seen and continuing until the effective end
++  ** of the main journal file.  Continue to skip out-of-range pages and
++  ** continue adding pages rolled back to pDone.
+   */
+-  pPtr = (u8 *)sqlite3MallocZero(
+-    ROUND8(sizeof(*pPager)) +      /* Pager structure */
+-    ROUND8(pcacheSize) +           /* PCache object */
+-    ROUND8(pVfs->szOsFile) +       /* The main db file */
+-    journalFileSize * 2 +          /* The two journal files */ 
+-    nPathname + 1 + nUri +         /* zFilename */
+-    nPathname + 8 + 2              /* zJournal */
+-#ifndef SQLITE_OMIT_WAL
+-    + nPathname + 4 + 2            /* zWal */
+-#endif
+-  );
+-  assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
+-  if( !pPtr ){
+-    sqlite3DbFree(0, zPathname);
+-    return SQLITE_NOMEM;
+-  }
+-  pPager =              (Pager*)(pPtr);
+-  pPager->pPCache =    (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
+-  pPager->fd =   (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
+-  pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
+-  pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
+-  pPager->zFilename =    (char*)(pPtr += journalFileSize);
+-  assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
++  while( rc==SQLITE_OK && pPager->journalOff<szJ ){
++    u32 ii;            /* Loop counter */
++    u32 nJRec = 0;     /* Number of Journal Records */
++    u32 dummy;
++    rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
++    assert( rc!=SQLITE_DONE );
+ 
+-  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
+-  if( zPathname ){
+-    assert( nPathname>0 );
+-    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
+-    memcpy(pPager->zFilename, zPathname, nPathname);
+-    if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
+-    memcpy(pPager->zJournal, zPathname, nPathname);
+-    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
+-    sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
+-#ifndef SQLITE_OMIT_WAL
+-    pPager->zWal = &pPager->zJournal[nPathname+8+1];
+-    memcpy(pPager->zWal, zPathname, nPathname);
+-    memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
+-    sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
+-#endif
+-    sqlite3DbFree(0, zPathname);
++    /*
++    ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
++    ** test is related to ticket #2565.  See the discussion in the
++    ** pager_playback() function for additional information.
++    */
++    if( nJRec==0 
++     && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
++    ){
++      nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
++    }
++    for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
++      rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
++    }
++    assert( rc!=SQLITE_DONE );
+   }
+-  pPager->pVfs = pVfs;
+-  pPager->vfsFlags = vfsFlags;
++  assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
+ 
+-  /* Open the pager file.
++  /* Finally,  rollback pages from the sub-journal.  Page that were
++  ** previously rolled back out of the main journal (and are hence in pDone)
++  ** will be skipped.  Out-of-range pages are also skipped.
+   */
+-  if( zFilename && zFilename[0] ){
+-    int fout = 0;                    /* VFS flags returned by xOpen() */
+-    rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
+-    assert( !memDb );
+-    readOnly = (fout&SQLITE_OPEN_READONLY);
++  if( pSavepoint ){
++    u32 ii;            /* Loop counter */
++    i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
+ 
+-    /* If the file was successfully opened for read/write access,
+-    ** choose a default page size in case we have to create the
+-    ** database file. The default page size is the maximum of:
+-    **
+-    **    + SQLITE_DEFAULT_PAGE_SIZE,
+-    **    + The value returned by sqlite3OsSectorSize()
+-    **    + The largest page size that can be written atomically.
+-    */
+-    if( rc==SQLITE_OK && !readOnly ){
+-      setSectorSize(pPager);
+-      assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
+-      if( szPageDflt<pPager->sectorSize ){
+-        if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
+-          szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
+-        }else{
+-          szPageDflt = (u32)pPager->sectorSize;
+-        }
+-      }
+-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+-      {
+-        int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+-        int ii;
+-        assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
+-        assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+-        assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
+-        for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
+-          if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
+-            szPageDflt = ii;
+-          }
+-        }
+-      }
+-#endif
++    if( pagerUseWal(pPager) ){
++      rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
++    }
++    for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
++      assert( offset==(i64)ii*(4+pPager->pageSize) );
++      rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
+     }
+-  }else{
+-    /* If a temporary file is requested, it is not opened immediately.
+-    ** In this case we accept the default page size and delay actually
+-    ** opening the file until the first call to OsWrite().
+-    **
+-    ** This branch is also run for an in-memory database. An in-memory
+-    ** database is the same as a temp-file that is never written out to
+-    ** disk and uses an in-memory rollback journal.
+-    */ 
+-    tempFile = 1;
+-    pPager->eState = PAGER_READER;
+-    pPager->eLock = EXCLUSIVE_LOCK;
+-    readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
++    assert( rc!=SQLITE_DONE );
+   }
+ 
+-  /* The following call to PagerSetPagesize() serves to set the value of 
+-  ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
+-  */
++  sqlite3BitvecDestroy(pDone);
+   if( rc==SQLITE_OK ){
+-    assert( pPager->memDb==0 );
+-    rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
+-    testcase( rc!=SQLITE_OK );
++    pPager->journalOff = szJ;
+   }
+ 
+-  /* If an error occurred in either of the blocks above, free the 
+-  ** Pager structure and close the file.
+-  */
+-  if( rc!=SQLITE_OK ){
+-    assert( !pPager->pTmpSpace );
+-    sqlite3OsClose(pPager->fd);
+-    sqlite3_free(pPager);
+-    return rc;
++  return rc;
 +}
 +
-+SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetError( Pager *pPager, int error) {
-+  pPager->errCode = error;
++/*
++** Change the maximum number of in-memory pages that are allowed.
++*/
++SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
++  sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
++}
++
++/*
++** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
++*/
++static void pagerFixMaplimit(Pager *pPager){
++#if SQLITE_MAX_MMAP_SIZE>0
++  sqlite3_file *fd = pPager->fd;
++  if( isOpen(fd) ){
++    sqlite3_int64 sz;
++    pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
++    sz = pPager->szMmap;
++    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
+   }
++#endif
++}
+ 
+-  /* Initialize the PCache object. */
+-  assert( nExtra<1000 );
+-  nExtra = ROUND8(nExtra);
+-  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
+-                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
++/*
++** Change the maximum size of any memory mapping made of the database file.
++*/
++SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
++  pPager->szMmap = szMmap;
++  pagerFixMaplimit(pPager);
++}
+ 
+-  PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
+-  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
++/*
++** Free as much memory as possible from the pager.
++*/
++SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
++  sqlite3PcacheShrink(pPager->pPCache);
++}
+ 
+-  pPager->useJournal = (u8)useJournal;
+-  /* pPager->stmtOpen = 0; */
+-  /* pPager->stmtInUse = 0; */
+-  /* pPager->nRef = 0; */
+-  /* pPager->stmtSize = 0; */
+-  /* pPager->stmtJSize = 0; */
+-  /* pPager->nPage = 0; */
+-  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
+-  /* pPager->state = PAGER_UNLOCK; */
+-#if 0
+-  assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
+-#endif
+-  /* pPager->errMask = 0; */
+-  pPager->tempFile = (u8)tempFile;
+-  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
+-          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
+-  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
+-  pPager->exclusiveMode = (u8)tempFile; 
+-  pPager->changeCountDone = pPager->tempFile;
+-  pPager->memDb = (u8)memDb;
+-  pPager->readOnly = (u8)readOnly;
+-  assert( useJournal || pPager->tempFile );
+-  pPager->noSync = pPager->tempFile;
++/*
++** Adjust the robustness of the database to damage due to OS crashes
++** or power failures by changing the number of syncs()s when writing
++** the rollback journal.  There are three levels:
++**
++**    OFF       sqlite3OsSync() is never called.  This is the default
++**              for temporary and transient files.
++**
++**    NORMAL    The journal is synced once before writes begin on the
++**              database.  This is normally adequate protection, but
++**              it is theoretically possible, though very unlikely,
++**              that an inopertune power failure could leave the journal
++**              in a state which would cause damage to the database
++**              when it is rolled back.
++**
++**    FULL      The journal is synced twice before writes begin on the
++**              database (with some additional information - the nRec field
++**              of the journal header - being written in between the two
++**              syncs).  If we assume that writing a
++**              single disk sector is atomic, then this mode provides
++**              assurance that the journal will not be corrupted to the
++**              point of causing damage to the database during rollback.
++**
++** The above is for a rollback-journal mode.  For WAL mode, OFF continues
++** to mean that no syncs ever occur.  NORMAL means that the WAL is synced
++** prior to the start of checkpoint and that the database file is synced
++** at the conclusion of the checkpoint if the entire content of the WAL
++** was written back into the database.  But no sync operations occur for
++** an ordinary commit in NORMAL mode with WAL.  FULL means that the WAL
++** file is synced following each commit operation, in addition to the
++** syncs associated with NORMAL.
++**
++** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL.  The
++** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
++** using fcntl(F_FULLFSYNC).  SQLITE_SYNC_NORMAL means to do an
++** ordinary fsync() call.  There is no difference between SQLITE_SYNC_FULL
++** and SQLITE_SYNC_NORMAL on platforms other than MacOSX.  But the
++** synchronous=FULL versus synchronous=NORMAL setting determines when
++** the xSync primitive is called and is relevant to all platforms.
++**
++** Numeric values associated with these states are OFF==1, NORMAL=2,
++** and FULL=3.
++*/
++#ifndef SQLITE_OMIT_PAGER_PRAGMAS
++SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
++  Pager *pPager,        /* The pager to set safety level for */
++  int level,            /* PRAGMA synchronous.  1=OFF, 2=NORMAL, 3=FULL */  
++  int bFullFsync,       /* PRAGMA fullfsync */
++  int bCkptFullFsync    /* PRAGMA checkpoint_fullfsync */
++){
++  assert( level>=1 && level<=3 );
++  pPager->noSync =  (level==1 || pPager->tempFile) ?1:0;
++  pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
+   if( pPager->noSync ){
+-    assert( pPager->fullSync==0 );
+-    assert( pPager->syncFlags==0 );
+-    assert( pPager->walSyncFlags==0 );
+-    assert( pPager->ckptSyncFlags==0 );
++    pPager->syncFlags = 0;
++    pPager->ckptSyncFlags = 0;
++  }else if( bFullFsync ){
++    pPager->syncFlags = SQLITE_SYNC_FULL;
++    pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
++  }else if( bCkptFullFsync ){
++    pPager->syncFlags = SQLITE_SYNC_NORMAL;
++    pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
+   }else{
+-    pPager->fullSync = 1;
+     pPager->syncFlags = SQLITE_SYNC_NORMAL;
+-    pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
+     pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+   }
+-  /* pPager->pFirst = 0; */
+-  /* pPager->pFirstSynced = 0; */
+-  /* pPager->pLast = 0; */
+-  pPager->nExtra = (u16)nExtra;
+-  pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
+-  assert( isOpen(pPager->fd) || tempFile );
+-  setSectorSize(pPager);
+-  if( !useJournal ){
+-    pPager->journalMode = PAGER_JOURNALMODE_OFF;
+-  }else if( memDb ){
+-    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
++  pPager->walSyncFlags = pPager->syncFlags;
++  if( pPager->fullSync ){
++    pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
+   }
+-  /* pPager->xBusyHandler = 0; */
+-  /* pPager->pBusyHandlerArg = 0; */
+-  pPager->xReiniter = xReinit;
+-  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
+-  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
++}
++#endif
+ 
+-  *ppPager = pPager;
+-  return SQLITE_OK;
++/*
++** The following global variable is incremented whenever the library
++** attempts to open a temporary file.  This information is used for
++** testing and analysis only.  
++*/
++#ifdef SQLITE_TEST
++SQLITE_API int sqlite3_opentemp_count = 0;
++#endif
++
++/*
++** Open a temporary file.
++**
++** Write the file descriptor into *pFile. Return SQLITE_OK on success 
++** or some other error code if we fail. The OS will automatically 
++** delete the temporary file when it is closed.
++**
++** The flags passed to the VFS layer xOpen() call are those specified
++** by parameter vfsFlags ORed with the following:
++**
++**     SQLITE_OPEN_READWRITE
++**     SQLITE_OPEN_CREATE
++**     SQLITE_OPEN_EXCLUSIVE
++**     SQLITE_OPEN_DELETEONCLOSE
++*/
++static int pagerOpentemp(
++  Pager *pPager,        /* The pager object */
++  sqlite3_file *pFile,  /* Write the file descriptor here */
++  int vfsFlags          /* Flags passed through to the VFS */
++){
++  int rc;               /* Return code */
++
++#ifdef SQLITE_TEST
++  sqlite3_opentemp_count++;  /* Used for testing and analysis only */
++#endif
++
++  vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
++            SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
++  rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
++  assert( rc!=SQLITE_OK || isOpen(pFile) );
++  return rc;
+ }
+ 
++/*
++** Set the busy handler function.
++**
++** The pager invokes the busy-handler if sqlite3OsLock() returns 
++** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
++** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE 
++** lock. It does *not* invoke the busy handler when upgrading from
++** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
++** (which occurs during hot-journal rollback). Summary:
++**
++**   Transition                        | Invokes xBusyHandler
++**   --------------------------------------------------------
++**   NO_LOCK       -> SHARED_LOCK      | Yes
++**   SHARED_LOCK   -> RESERVED_LOCK    | No
++**   SHARED_LOCK   -> EXCLUSIVE_LOCK   | No
++**   RESERVED_LOCK -> EXCLUSIVE_LOCK   | Yes
++**
++** If the busy-handler callback returns non-zero, the lock is 
++** retried. If it returns zero, then the SQLITE_BUSY error is
++** returned to the caller of the pager API function.
++*/
++SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
++  Pager *pPager,                       /* Pager object */
++  int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
++  void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
++){
++  pPager->xBusyHandler = xBusyHandler;
++  pPager->pBusyHandlerArg = pBusyHandlerArg;
+ 
++  if( isOpen(pPager->fd) ){
++    void **ap = (void **)&pPager->xBusyHandler;
++    assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
++    assert( ap[1]==pBusyHandlerArg );
++    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
++  }
++}
+ 
+ /*
+-** This function is called after transitioning from PAGER_UNLOCK to
+-** PAGER_SHARED state. It tests if there is a hot journal present in
+-** the file-system for the given pager. A hot journal is one that 
+-** needs to be played back. According to this function, a hot-journal
+-** file exists if the following criteria are met:
++** Change the page size used by the Pager object. The new page size 
++** is passed in *pPageSize.
+ **
+-**   * The journal file exists in the file system, and
+-**   * No process holds a RESERVED or greater lock on the database file, and
+-**   * The database file itself is greater than 0 bytes in size, and
+-**   * The first byte of the journal file exists and is not 0x00.
++** If the pager is in the error state when this function is called, it
++** is a no-op. The value returned is the error state error code (i.e. 
++** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
+ **
+-** If the current size of the database file is 0 but a journal file
+-** exists, that is probably an old journal left over from a prior
+-** database with the same name. In this case the journal file is
+-** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
+-** is returned.
++** Otherwise, if all of the following are true:
+ **
+-** This routine does not check if there is a master journal filename
+-** at the end of the file. If there is, and that master journal file
+-** does not exist, then the journal file is not really hot. In this
+-** case this routine will return a false-positive. The pager_playback()
+-** routine will discover that the journal file is not really hot and 
+-** will not roll it back. 
++**   * the new page size (value of *pPageSize) is valid (a power 
++**     of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
+ **
+-** If a hot-journal file is found to exist, *pExists is set to 1 and 
+-** SQLITE_OK returned. If no hot-journal file is present, *pExists is
+-** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
+-** to determine whether or not a hot-journal file exists, the IO error
+-** code is returned and the value of *pExists is undefined.
++**   * there are no outstanding page references, and
++**
++**   * the database is either not an in-memory database or it is
++**     an in-memory database that currently consists of zero pages.
++**
++** then the pager object page size is set to *pPageSize.
++**
++** If the page size is changed, then this function uses sqlite3PagerMalloc() 
++** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt 
++** fails, SQLITE_NOMEM is returned and the page size remains unchanged. 
++** In all other cases, SQLITE_OK is returned.
++**
++** If the page size is not changed, either because one of the enumerated
++** conditions above is not true, the pager was in error state when this
++** function was called, or because the memory allocation attempt failed, 
++** then *pPageSize is set to the old, retained page size before returning.
+ */
+-static int hasHotJournal(Pager *pPager, int *pExists){
+-  sqlite3_vfs * const pVfs = pPager->pVfs;
+-  int rc = SQLITE_OK;           /* Return code */
+-  int exists = 1;               /* True if a journal file is present */
+-  int jrnlOpen = !!isOpen(pPager->jfd);
++SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
++  int rc = SQLITE_OK;
+ 
+-  assert( pPager->useJournal );
+-  assert( isOpen(pPager->fd) );
+-  assert( pPager->eState==PAGER_OPEN );
++  /* It is not possible to do a full assert_pager_state() here, as this
++  ** function may be called from within PagerOpen(), before the state
++  ** of the Pager object is internally consistent.
++  **
++  ** At one point this function returned an error if the pager was in 
++  ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
++  ** there is at least one outstanding page reference, this function
++  ** is a no-op for that case anyhow.
++  */
+ 
+-  assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
+-    SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+-  ));
++  u32 pageSize = *pPageSize;
++  assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
++  if( (pPager->memDb==0 || pPager->dbSize==0)
++   && sqlite3PcacheRefCount(pPager->pPCache)==0 
++   && pageSize && pageSize!=(u32)pPager->pageSize 
++  ){
++    char *pNew = NULL;             /* New temp space */
++    i64 nByte = 0;
+ 
+-  *pExists = 0;
+-  if( !jrnlOpen ){
+-    rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
++    if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
++      rc = sqlite3OsFileSize(pPager->fd, &nByte);
++    }
++    if( rc==SQLITE_OK ){
++      pNew = (char *)sqlite3PageMalloc(pageSize);
++      if( !pNew ) rc = SQLITE_NOMEM;
++    }
++
++    if( rc==SQLITE_OK ){
++      pager_reset(pPager);
++      pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
++      pPager->pageSize = pageSize;
++      sqlite3PageFree(pPager->pTmpSpace);
++      pPager->pTmpSpace = pNew;
++      sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
++    }
+   }
+-  if( rc==SQLITE_OK && exists ){
+-    int locked = 0;             /* True if some process holds a RESERVED lock */
+ 
+-    /* Race condition here:  Another process might have been holding the
+-    ** the RESERVED lock and have a journal open at the sqlite3OsAccess() 
+-    ** call above, but then delete the journal and drop the lock before
+-    ** we get to the following sqlite3OsCheckReservedLock() call.  If that
+-    ** is the case, this routine might think there is a hot journal when
+-    ** in fact there is none.  This results in a false-positive which will
+-    ** be dealt with by the playback routine.  Ticket #3883.
+-    */
+-    rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
+-    if( rc==SQLITE_OK && !locked ){
+-      Pgno nPage;                 /* Number of pages in database file */
++  *pPageSize = pPager->pageSize;
++  if( rc==SQLITE_OK ){
++    if( nReserve<0 ) nReserve = pPager->nReserve;
++    assert( nReserve>=0 && nReserve<1000 );
++    pPager->nReserve = (i16)nReserve;
++    pagerReportSize(pPager);
++    pagerFixMaplimit(pPager);
++  }
++  return rc;
++}
+ 
+-      /* Check the size of the database file. If it consists of 0 pages,
+-      ** then delete the journal file. See the header comment above for 
+-      ** the reasoning here.  Delete the obsolete journal file under
+-      ** a RESERVED lock to avoid race conditions and to avoid violating
+-      ** [H33020].
+-      */
+-      rc = pagerPagecount(pPager, &nPage);
+-      if( rc==SQLITE_OK ){
+-        if( nPage==0 ){
+-          sqlite3BeginBenignMalloc();
+-          if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
+-            sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+-            if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
+-          }
+-          sqlite3EndBenignMalloc();
+-        }else{
+-          /* The journal file exists and no other connection has a reserved
+-          ** or greater lock on the database file. Now check that there is
+-          ** at least one non-zero bytes at the start of the journal file.
+-          ** If there is, then we consider this journal to be hot. If not, 
+-          ** it can be ignored.
+-          */
+-          if( !jrnlOpen ){
+-            int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
+-            rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
+-          }
+-          if( rc==SQLITE_OK ){
+-            u8 first = 0;
+-            rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
+-            if( rc==SQLITE_IOERR_SHORT_READ ){
+-              rc = SQLITE_OK;
+-            }
+-            if( !jrnlOpen ){
+-              sqlite3OsClose(pPager->jfd);
+-            }
+-            *pExists = (first!=0);
+-          }else if( rc==SQLITE_CANTOPEN ){
+-            /* If we cannot open the rollback journal file in order to see if
+-            ** its has a zero header, that might be due to an I/O error, or
+-            ** it might be due to the race condition described above and in
+-            ** ticket #3883.  Either way, assume that the journal is hot.
+-            ** This might be a false positive.  But if it is, then the
+-            ** automatic journal playback and recovery mechanism will deal
+-            ** with it under an EXCLUSIVE lock where we do not need to
+-            ** worry so much with race conditions.
+-            */
+-            *pExists = 1;
+-            rc = SQLITE_OK;
+-          }
+-        }
+-      }
++/*
++** Return a pointer to the "temporary page" buffer held internally
++** by the pager.  This is a buffer that is big enough to hold the
++** entire content of a database page.  This buffer is used internally
++** during rollback and will be overwritten whenever a rollback
++** occurs.  But other modules are free to use it too, as long as
++** no rollbacks are happening.
++*/
++SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
++  return pPager->pTmpSpace;
++}
++
++/*
++** Attempt to set the maximum database page count if mxPage is positive. 
++** Make no changes if mxPage is zero or negative.  And never reduce the
++** maximum page count below the current size of the database.
++**
++** Regardless of mxPage, return the current maximum page count.
++*/
++SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
++  if( mxPage>0 ){
++    pPager->mxPgno = mxPage;
++  }
++  assert( pPager->eState!=PAGER_OPEN );      /* Called only by OP_MaxPgcnt */
++  assert( pPager->mxPgno>=pPager->dbSize );  /* OP_MaxPgcnt enforces this */
++  return pPager->mxPgno;
++}
++
++/*
++** The following set of routines are used to disable the simulated
++** I/O error mechanism.  These routines are used to avoid simulated
++** errors in places where we do not care about errors.
++**
++** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
++** and generate no code.
++*/
++#ifdef SQLITE_TEST
++SQLITE_API extern int sqlite3_io_error_pending;
++SQLITE_API extern int sqlite3_io_error_hit;
++static int saved_cnt;
++void disable_simulated_io_errors(void){
++  saved_cnt = sqlite3_io_error_pending;
++  sqlite3_io_error_pending = -1;
++}
++void enable_simulated_io_errors(void){
++  sqlite3_io_error_pending = saved_cnt;
++}
++#else
++# define disable_simulated_io_errors()
++# define enable_simulated_io_errors()
++#endif
++
++/*
++** Read the first N bytes from the beginning of the file into memory
++** that pDest points to. 
++**
++** If the pager was opened on a transient file (zFilename==""), or
++** opened on a file less than N bytes in size, the output buffer is
++** zeroed and SQLITE_OK returned. The rationale for this is that this 
++** function is used to read database headers, and a new transient or
++** zero sized database has a header than consists entirely of zeroes.
++**
++** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
++** the error code is returned to the caller and the contents of the
++** output buffer undefined.
++*/
++SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
++  int rc = SQLITE_OK;
++  memset(pDest, 0, N);
++  assert( isOpen(pPager->fd) || pPager->tempFile );
++
++  /* This routine is only called by btree immediately after creating
++  ** the Pager object.  There has not been an opportunity to transition
++  ** to WAL mode yet.
++  */
++  assert( !pagerUseWal(pPager) );
++
++  if( isOpen(pPager->fd) ){
++    IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
++    rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
++    if( rc==SQLITE_IOERR_SHORT_READ ){
++      rc = SQLITE_OK;
+     }
+   }
+-
+   return rc;
+ }
+ 
+ /*
+-** This function is called to obtain a shared lock on the database file.
+-** It is illegal to call sqlite3PagerAcquire() until after this function
+-** has been successfully called. If a shared-lock is already held when
+-** this function is called, it is a no-op.
+-**
+-** The following operations are also performed by this function.
++** This function may only be called when a read-transaction is open on
++** the pager. It returns the total number of pages in the database.
+ **
+-**   1) If the pager is currently in PAGER_OPEN state (no lock held
+-**      on the database file), then an attempt is made to obtain a
+-**      SHARED lock on the database file. Immediately after obtaining
+-**      the SHARED lock, the file-system is checked for a hot-journal,
+-**      which is played back if present. Following any hot-journal 
+-**      rollback, the contents of the cache are validated by checking
+-**      the 'change-counter' field of the database file header and
+-**      discarded if they are found to be invalid.
++** However, if the file is between 1 and <page-size> bytes in size, then 
++** this is considered a 1 page file.
++*/
++SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
++  assert( pPager->eState>=PAGER_READER );
++  assert( pPager->eState!=PAGER_WRITER_FINISHED );
++  *pnPage = (int)pPager->dbSize;
++}
++
++
++/*
++** Try to obtain a lock of type locktype on the database file. If
++** a similar or greater lock is already held, this function is a no-op
++** (returning SQLITE_OK immediately).
+ **
+-**   2) If the pager is running in exclusive-mode, and there are currently
+-**      no outstanding references to any pages, and is in the error state,
+-**      then an attempt is made to clear the error state by discarding
+-**      the contents of the page cache and rolling back any open journal
+-**      file.
++** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke 
++** the busy callback if the lock is currently not available. Repeat 
++** until the busy callback returns false or until the attempt to 
++** obtain the lock succeeds.
+ **
+-** If everything is successful, SQLITE_OK is returned. If an IO error 
+-** occurs while locking the database, checking for a hot-journal file or 
+-** rolling back a journal file, the IO error code is returned.
++** Return SQLITE_OK on success and an error code if we cannot obtain
++** the lock. If the lock is obtained successfully, set the Pager.state 
++** variable to locktype before returning.
+ */
+-SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
+-  int rc = SQLITE_OK;                /* Return code */
++static int pager_wait_on_lock(Pager *pPager, int locktype){
++  int rc;                              /* Return code */
+ 
+-  /* This routine is only called from b-tree and only when there are no
+-  ** outstanding pages. This implies that the pager state should either
+-  ** be OPEN or READER. READER is only possible if the pager is or was in 
+-  ** exclusive access mode.
++  /* Check that this is either a no-op (because the requested lock is 
++  ** already held, or one of the transistions that the busy-handler
++  ** may be invoked during, according to the comment above
++  ** sqlite3PagerSetBusyhandler().
+   */
+-  assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
+-  assert( assert_pager_state(pPager) );
+-  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
+-  if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
++  assert( (pPager->eLock>=locktype)
++       || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
++       || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
++  );
+ 
+-  if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
+-    int bHotJournal = 1;          /* True if there exists a hot journal-file */
++  do {
++    rc = pagerLockDb(pPager, locktype);
++  }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
++  return rc;
++}
+ 
+-    assert( !MEMDB );
++/*
++** Function assertTruncateConstraint(pPager) checks that one of the 
++** following is true for all dirty pages currently in the page-cache:
++**
++**   a) The page number is less than or equal to the size of the 
++**      current database image, in pages, OR
++**
++**   b) if the page content were written at this time, it would not
++**      be necessary to write the current content out to the sub-journal
++**      (as determined by function subjRequiresPage()).
++**
++** If the condition asserted by this function were not true, and the
++** dirty page were to be discarded from the cache via the pagerStress()
++** routine, pagerStress() would not write the current page content to
++** the database file. If a savepoint transaction were rolled back after
++** this happened, the correct behavior would be to restore the current
++** content of the page. However, since this content is not present in either
++** the database file or the portion of the rollback journal and 
++** sub-journal rolled back the content could not be restored and the
++** database image would become corrupt. It is therefore fortunate that 
++** this circumstance cannot arise.
++*/
++#if defined(SQLITE_DEBUG)
++static void assertTruncateConstraintCb(PgHdr *pPg){
++  assert( pPg->flags&PGHDR_DIRTY );
++  assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
++}
++static void assertTruncateConstraint(Pager *pPager){
++  sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
++}
++#else
++# define assertTruncateConstraint(pPager)
++#endif
+ 
+-    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+-    if( rc!=SQLITE_OK ){
+-      assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
+-      goto failed;
+-    }
++/*
++** Truncate the in-memory database file image to nPage pages. This 
++** function does not actually modify the database file on disk. It 
++** just sets the internal state of the pager object so that the 
++** truncation will be done when the current transaction is committed.
++**
++** This function is only called right before committing a transaction.
++** Once this function has been called, the transaction must either be
++** rolled back or committed. It is not safe to call this function and
++** then continue writing to the database.
++*/
++SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
++  assert( pPager->dbSize>=nPage );
++  assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
++  pPager->dbSize = nPage;
+ 
+-    /* If a journal file exists, and there is no RESERVED lock on the
+-    ** database file, then it either needs to be played back or deleted.
+-    */
+-    if( pPager->eLock<=SHARED_LOCK ){
+-      rc = hasHotJournal(pPager, &bHotJournal);
+-    }
+-    if( rc!=SQLITE_OK ){
+-      goto failed;
+-    }
+-    if( bHotJournal ){
+-      if( pPager->readOnly ){
+-        rc = SQLITE_READONLY_ROLLBACK;
+-        goto failed;
+-      }
++  /* At one point the code here called assertTruncateConstraint() to
++  ** ensure that all pages being truncated away by this operation are,
++  ** if one or more savepoints are open, present in the savepoint 
++  ** journal so that they can be restored if the savepoint is rolled
++  ** back. This is no longer necessary as this function is now only
++  ** called right before committing a transaction. So although the 
++  ** Pager object may still have open savepoints (Pager.nSavepoint!=0), 
++  ** they cannot be rolled back. So the assertTruncateConstraint() call
++  ** is no longer correct. */
++}
+ 
+-      /* Get an EXCLUSIVE lock on the database file. At this point it is
+-      ** important that a RESERVED lock is not obtained on the way to the
+-      ** EXCLUSIVE lock. If it were, another process might open the
+-      ** database file, detect the RESERVED lock, and conclude that the
+-      ** database is safe to read while this process is still rolling the 
+-      ** hot-journal back.
+-      ** 
+-      ** Because the intermediate RESERVED lock is not requested, any
+-      ** other process attempting to access the database file will get to 
+-      ** this point in the code and fail to obtain its own EXCLUSIVE lock 
+-      ** on the database file.
+-      **
+-      ** Unless the pager is in locking_mode=exclusive mode, the lock is
+-      ** downgraded to SHARED_LOCK before this function returns.
+-      */
+-      rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+-      if( rc!=SQLITE_OK ){
+-        goto failed;
+-      }
+- 
+-      /* If it is not already open and the file exists on disk, open the 
+-      ** journal for read/write access. Write access is required because 
+-      ** in exclusive-access mode the file descriptor will be kept open 
+-      ** and possibly used for a transaction later on. Also, write-access 
+-      ** is usually required to finalize the journal in journal_mode=persist 
+-      ** mode (and also for journal_mode=truncate on some systems).
+-      **
+-      ** If the journal does not exist, it usually means that some 
+-      ** other connection managed to get in and roll it back before 
+-      ** this connection obtained the exclusive lock above. Or, it 
+-      ** may mean that the pager was in the error-state when this
+-      ** function was called and the journal file does not exist.
+-      */
+-      if( !isOpen(pPager->jfd) ){
+-        sqlite3_vfs * const pVfs = pPager->pVfs;
+-        int bExists;              /* True if journal file exists */
+-        rc = sqlite3OsAccess(
+-            pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
+-        if( rc==SQLITE_OK && bExists ){
+-          int fout = 0;
+-          int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
+-          assert( !pPager->tempFile );
+-          rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
+-          assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
+-          if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
+-            rc = SQLITE_CANTOPEN_BKPT;
+-            sqlite3OsClose(pPager->jfd);
+-          }
+-        }
+-      }
+- 
+-      /* Playback and delete the journal.  Drop the database write
+-      ** lock and reacquire the read lock. Purge the cache before
+-      ** playing back the hot-journal so that we don't end up with
+-      ** an inconsistent cache.  Sync the hot journal before playing
+-      ** it back since the process that crashed and left the hot journal
+-      ** probably did not sync it and we are required to always sync
+-      ** the journal before playing it back.
+-      */
+-      if( isOpen(pPager->jfd) ){
+-        assert( rc==SQLITE_OK );
+-        rc = pagerSyncHotJournal(pPager);
+-        if( rc==SQLITE_OK ){
+-          rc = pager_playback(pPager, 1);
+-          pPager->eState = PAGER_OPEN;
+-        }
+-      }else if( !pPager->exclusiveMode ){
+-        pagerUnlockDb(pPager, SHARED_LOCK);
+-      }
+ 
+-      if( rc!=SQLITE_OK ){
+-        /* This branch is taken if an error occurs while trying to open
+-        ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
+-        ** pager_unlock() routine will be called before returning to unlock
+-        ** the file. If the unlock attempt fails, then Pager.eLock must be
+-        ** set to UNKNOWN_LOCK (see the comment above the #define for 
+-        ** UNKNOWN_LOCK above for an explanation). 
+-        **
+-        ** In order to get pager_unlock() to do this, set Pager.eState to
+-        ** PAGER_ERROR now. This is not actually counted as a transition
+-        ** to ERROR state in the state diagram at the top of this file,
+-        ** since we know that the same call to pager_unlock() will very
+-        ** shortly transition the pager object to the OPEN state. Calling
+-        ** assert_pager_state() would fail now, as it should not be possible
+-        ** to be in ERROR state when there are zero outstanding page 
+-        ** references.
+-        */
+-        pager_error(pPager, rc);
+-        goto failed;
+-      }
++/*
++** This function is called before attempting a hot-journal rollback. It
++** syncs the journal file to disk, then sets pPager->journalHdr to the
++** size of the journal file so that the pager_playback() routine knows
++** that the entire journal file has been synced.
++**
++** Syncing a hot-journal to disk before attempting to roll it back ensures 
++** that if a power-failure occurs during the rollback, the process that
++** attempts rollback following system recovery sees the same journal
++** content as this process.
++**
++** If everything goes as planned, SQLITE_OK is returned. Otherwise, 
++** an SQLite error code.
++*/
++static int pagerSyncHotJournal(Pager *pPager){
++  int rc = SQLITE_OK;
++  if( !pPager->noSync ){
++    rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
++  }
++  if( rc==SQLITE_OK ){
++    rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
++  }
++  return rc;
++}
+ 
+-      assert( pPager->eState==PAGER_OPEN );
+-      assert( (pPager->eLock==SHARED_LOCK)
+-           || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
+-      );
++/*
++** Obtain a reference to a memory mapped page object for page number pgno. 
++** The new object will use the pointer pData, obtained from xFetch().
++** If successful, set *ppPage to point to the new page reference
++** and return SQLITE_OK. Otherwise, return an SQLite error code and set
++** *ppPage to zero.
++**
++** Page references obtained by calling this function should be released
++** by calling pagerReleaseMapPage().
++*/
++static int pagerAcquireMapPage(
++  Pager *pPager,                  /* Pager object */
++  Pgno pgno,                      /* Page number */
++  void *pData,                    /* xFetch()'d data for this page */
++  PgHdr **ppPage                  /* OUT: Acquired page object */
++){
++  PgHdr *p;                       /* Memory mapped page to return */
++
++  if( pPager->pMmapFreelist ){
++    *ppPage = p = pPager->pMmapFreelist;
++    pPager->pMmapFreelist = p->pDirty;
++    p->pDirty = 0;
++    memset(p->pExtra, 0, pPager->nExtra);
++  }else{
++    *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
++    if( p==0 ){
++      sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
++      return SQLITE_NOMEM;
+     }
++    p->pExtra = (void *)&p[1];
++    p->flags = PGHDR_MMAP;
++    p->nRef = 1;
++    p->pPager = pPager;
++  }
+ 
+-    if( !pPager->tempFile && (
+-        pPager->pBackup 
+-     || sqlite3PcachePagecount(pPager->pPCache)>0 
+-     || USEFETCH(pPager)
+-    )){
+-      /* The shared-lock has just been acquired on the database file
+-      ** and there are already pages in the cache (from a previous
+-      ** read or write transaction).  Check to see if the database
+-      ** has been modified.  If the database has changed, flush the
+-      ** cache.
+-      **
+-      ** Database changes is detected by looking at 15 bytes beginning
+-      ** at offset 24 into the file.  The first 4 of these 16 bytes are
+-      ** a 32-bit counter that is incremented with each change.  The
+-      ** other bytes change randomly with each file change when
+-      ** a codec is in use.
+-      ** 
+-      ** There is a vanishingly small chance that a change will not be 
+-      ** detected.  The chance of an undetected change is so small that
+-      ** it can be neglected.
+-      */
+-      Pgno nPage = 0;
+-      char dbFileVers[sizeof(pPager->dbFileVers)];
++  assert( p->pExtra==(void *)&p[1] );
++  assert( p->pPage==0 );
++  assert( p->flags==PGHDR_MMAP );
++  assert( p->pPager==pPager );
++  assert( p->nRef==1 );
+ 
+-      rc = pagerPagecount(pPager, &nPage);
+-      if( rc ) goto failed;
++  p->pgno = pgno;
++  p->pData = pData;
++  pPager->nMmapOut++;
+ 
+-      if( nPage>0 ){
+-        IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+-        rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+-        if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
+-          goto failed;
+-        }
+-      }else{
+-        memset(dbFileVers, 0, sizeof(dbFileVers));
+-      }
++  return SQLITE_OK;
++}
+ 
+-      if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
+-        pager_reset(pPager);
++/*
++** Release a reference to page pPg. pPg must have been returned by an 
++** earlier call to pagerAcquireMapPage().
++*/
++static void pagerReleaseMapPage(PgHdr *pPg){
++  Pager *pPager = pPg->pPager;
++  pPager->nMmapOut--;
++  pPg->pDirty = pPager->pMmapFreelist;
++  pPager->pMmapFreelist = pPg;
+ 
+-        /* Unmap the database file. It is possible that external processes
+-        ** may have truncated the database file and then extended it back
+-        ** to its original size while this process was not holding a lock.
+-        ** In this case there may exist a Pager.pMap mapping that appears
+-        ** to be the right size but is not actually valid. Avoid this
+-        ** possibility by unmapping the db here. */
+-        if( USEFETCH(pPager) ){
+-          sqlite3OsUnfetch(pPager->fd, 0, 0);
+-        }
+-      }
+-    }
++  assert( pPager->fd->pMethods->iVersion>=3 );
++  sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
++}
+ 
+-    /* If there is a WAL file in the file-system, open this database in WAL
+-    ** mode. Otherwise, the following function call is a no-op.
+-    */
+-    rc = pagerOpenWalIfPresent(pPager);
+-#ifndef SQLITE_OMIT_WAL
+-    assert( pPager->pWal==0 || rc==SQLITE_OK );
+-#endif
++/*
++** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
++*/
++static void pagerFreeMapHdrs(Pager *pPager){
++  PgHdr *p;
++  PgHdr *pNext;
++  for(p=pPager->pMmapFreelist; p; p=pNext){
++    pNext = p->pDirty;
++    sqlite3_free(p);
+   }
++}
+ 
+-  if( pagerUseWal(pPager) ){
+-    assert( rc==SQLITE_OK );
+-    rc = pagerBeginReadTransaction(pPager);
+-  }
+ 
+-  if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
+-    rc = pagerPagecount(pPager, &pPager->dbSize);
+-  }
++/*
++** Shutdown the page cache.  Free all memory and close all files.
++**
++** If a transaction was in progress when this routine is called, that
++** transaction is rolled back.  All outstanding pages are invalidated
++** and their memory is freed.  Any attempt to use a page associated
++** with this page cache after this function returns will likely
++** result in a coredump.
++**
++** This function always succeeds. If a transaction is active an attempt
++** is made to roll it back. If an error occurs during the rollback 
++** a hot journal may be left in the filesystem but no error is returned
++** to the caller.
++*/
++SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
++  u8 *pTmp = (u8 *)pPager->pTmpSpace;
+ 
+- failed:
+-  if( rc!=SQLITE_OK ){
+-    assert( !MEMDB );
++  assert( assert_pager_state(pPager) );
++  disable_simulated_io_errors();
++  sqlite3BeginBenignMalloc();
++  pagerFreeMapHdrs(pPager);
++  /* pPager->errCode = 0; */
++  pPager->exclusiveMode = 0;
++#ifndef SQLITE_OMIT_WAL
++  sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
++  pPager->pWal = 0;
++#endif
++  pager_reset(pPager);
++  if( MEMDB ){
+     pager_unlock(pPager);
+-    assert( pPager->eState==PAGER_OPEN );
+   }else{
+-    pPager->eState = PAGER_READER;
++    /* If it is open, sync the journal file before calling UnlockAndRollback.
++    ** If this is not done, then an unsynced portion of the open journal 
++    ** file may be played back into the database. If a power failure occurs 
++    ** while this is happening, the database could become corrupt.
++    **
++    ** If an error occurs while trying to sync the journal, shift the pager
++    ** into the ERROR state. This causes UnlockAndRollback to unlock the
++    ** database and close the journal file without attempting to roll it
++    ** back or finalize it. The next database user will have to do hot-journal
++    ** rollback before accessing the database file.
++    */
++    if( isOpen(pPager->jfd) ){
++      pager_error(pPager, pagerSyncHotJournal(pPager));
++    }
++    pagerUnlockAndRollback(pPager);
+   }
+-  return rc;
++  sqlite3EndBenignMalloc();
++  enable_simulated_io_errors();
++  PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
++  IOTRACE(("CLOSE %p\n", pPager))
++  sqlite3OsClose(pPager->jfd);
++  sqlite3OsClose(pPager->fd);
++  sqlite3PageFree(pTmp);
++  sqlite3PcacheClose(pPager->pPCache);
++
++#ifdef SQLITE_HAS_CODEC
++  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
++#endif
++
++  assert( !pPager->aSavepoint && !pPager->pInJournal );
++  assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
++
++  sqlite3_free(pPager);
++  return SQLITE_OK;
+ }
+ 
++#if !defined(NDEBUG) || defined(SQLITE_TEST)
+ /*
+-** If the reference count has reached zero, rollback any active
+-** transaction and unlock the pager.
+-**
+-** Except, in locking_mode=EXCLUSIVE when there is nothing to in
+-** the rollback journal, the unlock is not performed and there is
+-** nothing to rollback, so this routine is a no-op.
+-*/ 
+-static void pagerUnlockIfUnused(Pager *pPager){
+-  if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
+-    pagerUnlockAndRollback(pPager);
+-  }
++** Return the page number for page pPg.
++*/
++SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){
++  return pPg->pgno;
+ }
++#endif
+ 
+ /*
+-** Acquire a reference to page number pgno in pager pPager (a page
+-** reference has type DbPage*). If the requested reference is 
+-** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
+-**
+-** If the requested page is already in the cache, it is returned. 
+-** Otherwise, a new page object is allocated and populated with data
+-** read from the database file. In some cases, the pcache module may
+-** choose not to allocate a new page object and may reuse an existing
+-** object with no outstanding references.
+-**
+-** The extra data appended to a page is always initialized to zeros the 
+-** first time a page is loaded into memory. If the page requested is 
+-** already in the cache when this function is called, then the extra
+-** data is left as it was when the page object was last used.
+-**
+-** If the database image is smaller than the requested page or if a 
+-** non-zero value is passed as the noContent parameter and the 
+-** requested page is not already stored in the cache, then no 
+-** actual disk read occurs. In this case the memory image of the 
+-** page is initialized to all zeros. 
++** Increment the reference count for page pPg.
++*/
++SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
++  sqlite3PcacheRef(pPg);
++}
++
++/*
++** Sync the journal. In other words, make sure all the pages that have
++** been written to the journal have actually reached the surface of the
++** disk and can be restored in the event of a hot-journal rollback.
+ **
+-** If noContent is true, it means that we do not care about the contents
+-** of the page. This occurs in two seperate scenarios:
++** If the Pager.noSync flag is set, then this function is a no-op.
++** Otherwise, the actions required depend on the journal-mode and the 
++** device characteristics of the file-system, as follows:
+ **
+-**   a) When reading a free-list leaf page from the database, and
++**   * If the journal file is an in-memory journal file, no action need
++**     be taken.
+ **
+-**   b) When a savepoint is being rolled back and we need to load
+-**      a new page into the cache to be filled with the data read
+-**      from the savepoint journal.
++**   * Otherwise, if the device does not support the SAFE_APPEND property,
++**     then the nRec field of the most recently written journal header
++**     is updated to contain the number of journal records that have
++**     been written following it. If the pager is operating in full-sync
++**     mode, then the journal file is synced before this field is updated.
+ **
+-** If noContent is true, then the data returned is zeroed instead of
+-** being read from the database. Additionally, the bits corresponding
+-** to pgno in Pager.pInJournal (bitvec of pages already written to the
+-** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
+-** savepoints are set. This means if the page is made writable at any
+-** point in the future, using a call to sqlite3PagerWrite(), its contents
+-** will not be journaled. This saves IO.
++**   * If the device does not support the SEQUENTIAL property, then 
++**     journal file is synced.
+ **
+-** The acquisition might fail for several reasons.  In all cases,
+-** an appropriate error code is returned and *ppPage is set to NULL.
++** Or, in pseudo-code:
+ **
+-** See also sqlite3PagerLookup().  Both this routine and Lookup() attempt
+-** to find a page in the in-memory cache first.  If the page is not already
+-** in memory, this routine goes to disk to read it in whereas Lookup()
+-** just returns 0.  This routine acquires a read-lock the first time it
+-** has to go to disk, and could also playback an old journal if necessary.
+-** Since Lookup() never goes to disk, it never has to deal with locks
+-** or journal files.
++**   if( NOT <in-memory journal> ){
++**     if( NOT SAFE_APPEND ){
++**       if( <full-sync mode> ) xSync(<journal file>);
++**       <update nRec field>
++**     } 
++**     if( NOT SEQUENTIAL ) xSync(<journal file>);
++**   }
++**
++** If successful, this routine clears the PGHDR_NEED_SYNC flag of every 
++** page currently held in memory before returning SQLITE_OK. If an IO
++** error is encountered, then the IO error code is returned to the caller.
+ */
+-SQLITE_PRIVATE int sqlite3PagerAcquire(
+-  Pager *pPager,      /* The pager open on the database file */
+-  Pgno pgno,          /* Page number to fetch */
+-  DbPage **ppPage,    /* Write a pointer to the page here */
+-  int flags           /* PAGER_ACQUIRE_XXX flags */
+-){
+-  int rc = SQLITE_OK;
+-  PgHdr *pPg = 0;
+-  u32 iFrame = 0;                 /* Frame to read from WAL file */
+-  const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
++static int syncJournal(Pager *pPager, int newHdr){
++  int rc;                         /* Return code */
+ 
+-  /* It is acceptable to use a read-only (mmap) page for any page except
+-  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
+-  ** flag was specified by the caller. And so long as the db is not a 
+-  ** temporary or in-memory database.  */
+-  const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
+-   && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
+-#ifdef SQLITE_HAS_CODEC
+-   && pPager->xCodec==0
+-#endif
++  assert( pPager->eState==PAGER_WRITER_CACHEMOD
++       || pPager->eState==PAGER_WRITER_DBMOD
+   );
+-
+-  assert( pPager->eState>=PAGER_READER );
+   assert( assert_pager_state(pPager) );
+-  assert( noContent==0 || bMmapOk==0 );
+-
+-  if( pgno==0 ){
+-    return SQLITE_CORRUPT_BKPT;
+-  }
++  assert( !pagerUseWal(pPager) );
+ 
+-  /* If the pager is in the error state, return an error immediately. 
+-  ** Otherwise, request the page from the PCache layer. */
+-  if( pPager->errCode!=SQLITE_OK ){
+-    rc = pPager->errCode;
+-  }else{
++  rc = sqlite3PagerExclusiveLock(pPager);
++  if( rc!=SQLITE_OK ) return rc;
+ 
+-    if( bMmapOk && pagerUseWal(pPager) ){
+-      rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
+-      if( rc!=SQLITE_OK ) goto pager_acquire_err;
+-    }
++  if( !pPager->noSync ){
++    assert( !pPager->tempFile );
++    if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
++      const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
++      assert( isOpen(pPager->jfd) );
+ 
+-    if( iFrame==0 && bMmapOk ){
+-      void *pData = 0;
++      if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
++        /* This block deals with an obscure problem. If the last connection
++        ** that wrote to this database was operating in persistent-journal
++        ** mode, then the journal file may at this point actually be larger
++        ** than Pager.journalOff bytes. If the next thing in the journal
++        ** file happens to be a journal-header (written as part of the
++        ** previous connection's transaction), and a crash or power-failure 
++        ** occurs after nRec is updated but before this connection writes 
++        ** anything else to the journal file (or commits/rolls back its 
++        ** transaction), then SQLite may become confused when doing the 
++        ** hot-journal rollback following recovery. It may roll back all
++        ** of this connections data, then proceed to rolling back the old,
++        ** out-of-date data that follows it. Database corruption.
++        **
++        ** To work around this, if the journal file does appear to contain
++        ** a valid header following Pager.journalOff, then write a 0x00
++        ** byte to the start of it to prevent it from being recognized.
++        **
++        ** Variable iNextHdrOffset is set to the offset at which this
++        ** problematic header will occur, if it exists. aMagic is used 
++        ** as a temporary buffer to inspect the first couple of bytes of
++        ** the potential journal header.
++        */
++        i64 iNextHdrOffset;
++        u8 aMagic[8];
++        u8 zHeader[sizeof(aJournalMagic)+4];
+ 
+-      rc = sqlite3OsFetch(pPager->fd, 
+-          (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
+-      );
++        memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
++        put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
+ 
+-      if( rc==SQLITE_OK && pData ){
+-        if( pPager->eState>PAGER_READER ){
+-          (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
++        iNextHdrOffset = journalHdrOffset(pPager);
++        rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
++        if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
++          static const u8 zerobyte = 0;
++          rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
+         }
+-        if( pPg==0 ){
+-          rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
+-        }else{
+-          sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
++        if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
++          return rc;
+         }
+-        if( pPg ){
+-          assert( rc==SQLITE_OK );
+-          *ppPage = pPg;
+-          return SQLITE_OK;
++
++        /* Write the nRec value into the journal file header. If in
++        ** full-synchronous mode, sync the journal first. This ensures that
++        ** all data has really hit the disk before nRec is updated to mark
++        ** it as a candidate for rollback.
++        **
++        ** This is not required if the persistent media supports the
++        ** SAFE_APPEND property. Because in this case it is not possible 
++        ** for garbage data to be appended to the file, the nRec field
++        ** is populated with 0xFFFFFFFF when the journal header is written
++        ** and never needs to be updated.
++        */
++        if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
++          PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
++          IOTRACE(("JSYNC %p\n", pPager))
++          rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
++          if( rc!=SQLITE_OK ) return rc;
+         }
++        IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
++        rc = sqlite3OsWrite(
++            pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
++        );
++        if( rc!=SQLITE_OK ) return rc;
+       }
+-      if( rc!=SQLITE_OK ){
+-        goto pager_acquire_err;
++      if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
++        PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
++        IOTRACE(("JSYNC %p\n", pPager))
++        rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| 
++          (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
++        );
++        if( rc!=SQLITE_OK ) return rc;
++      }
++
++      pPager->journalHdr = pPager->journalOff;
++      if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
++        pPager->nRec = 0;
++        rc = writeJournalHdr(pPager);
++        if( rc!=SQLITE_OK ) return rc;
+       }
++    }else{
++      pPager->journalHdr = pPager->journalOff;
+     }
++  }
+ 
+-    rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
++  /* Unless the pager is in noSync mode, the journal file was just 
++  ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on 
++  ** all pages.
++  */
++  sqlite3PcacheClearSyncFlags(pPager->pPCache);
++  pPager->eState = PAGER_WRITER_DBMOD;
++  assert( assert_pager_state(pPager) );
++  return SQLITE_OK;
 +}
 +
++/*
++** The argument is the first in a linked list of dirty pages connected
++** by the PgHdr.pDirty pointer. This function writes each one of the
++** in-memory pages in the list to the database file. The argument may
++** be NULL, representing an empty list. In this case this function is
++** a no-op.
++**
++** The pager must hold at least a RESERVED lock when this function
++** is called. Before writing anything to the database file, this lock
++** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
++** SQLITE_BUSY is returned and no data is written to the database file.
++** 
++** If the pager is a temp-file pager and the actual file-system file
++** is not yet open, it is created and opened before any data is 
++** written out.
++**
++** Once the lock has been upgraded and, if necessary, the file opened,
++** the pages are written out to the database file in list order. Writing
++** a page is skipped if it meets either of the following criteria:
++**
++**   * The page number is greater than Pager.dbSize, or
++**   * The PGHDR_DONT_WRITE flag is set on the page.
++**
++** If writing out a page causes the database file to grow, Pager.dbFileSize
++** is updated accordingly. If page 1 is written out, then the value cached
++** in Pager.dbFileVers[] is updated to match the new value stored in
++** the database file.
++**
++** If everything is successful, SQLITE_OK is returned. If an IO error 
++** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
++** be obtained, SQLITE_BUSY is returned.
++*/
++static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
++  int rc = SQLITE_OK;                  /* Return code */
++
++  /* This function is only called for rollback pagers in WRITER_DBMOD state. */
++  assert( !pagerUseWal(pPager) );
++  assert( pPager->eState==PAGER_WRITER_DBMOD );
++  assert( pPager->eLock==EXCLUSIVE_LOCK );
++
++  /* If the file is a temp-file has not yet been opened, open it now. It
++  ** is not possible for rc to be other than SQLITE_OK if this branch
++  ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
++  */
++  if( !isOpen(pPager->fd) ){
++    assert( pPager->tempFile && rc==SQLITE_OK );
++    rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
+   }
+ 
+-  if( rc!=SQLITE_OK ){
+-    /* Either the call to sqlite3PcacheFetch() returned an error or the
+-    ** pager was already in the error-state when this function was called.
+-    ** Set pPg to 0 and jump to the exception handler.  */
+-    pPg = 0;
+-    goto pager_acquire_err;
++  /* Before the first write, give the VFS a hint of what the final
++  ** file size will be.
++  */
++  assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
++  if( rc==SQLITE_OK 
++   && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize 
++  ){
++    sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
++    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
++    pPager->dbHintSize = pPager->dbSize;
+   }
+-  assert( (*ppPage)->pgno==pgno );
+-  assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
+ 
+-  if( (*ppPage)->pPager && !noContent ){
+-    /* In this case the pcache already contains an initialized copy of
+-    ** the page. Return without further ado.  */
+-    assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
+-    pPager->aStat[PAGER_STAT_HIT]++;
+-    return SQLITE_OK;
++  while( rc==SQLITE_OK && pList ){
++    Pgno pgno = pList->pgno;
+ 
+-  }else{
+-    /* The pager cache has created a new page. Its content needs to 
+-    ** be initialized.  */
++    /* If there are dirty pages in the page cache with page numbers greater
++    ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
++    ** make the file smaller (presumably by auto-vacuum code). Do not write
++    ** any such pages to the file.
++    **
++    ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
++    ** set (set by sqlite3PagerDontWrite()).
++    */
++    if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
++      i64 offset = (pgno-1)*(i64)pPager->pageSize;   /* Offset to write */
++      char *pData;                                   /* Data to write */    
+ 
+-    pPg = *ppPage;
+-    pPg->pPager = pPager;
++      assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
++      if( pList->pgno==1 ) pager_write_changecounter(pList);
+ 
+-    /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
+-    ** number greater than this, or the unused locking-page, is requested. */
+-    if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
+-      rc = SQLITE_CORRUPT_BKPT;
+-      goto pager_acquire_err;
+-    }
++      /* Encode the database */
++      CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
+ 
+-    if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
+-      if( pgno>pPager->mxPgno ){
+-        rc = SQLITE_FULL;
+-        goto pager_acquire_err;
+-      }
+-      if( noContent ){
+-        /* Failure to set the bits in the InJournal bit-vectors is benign.
+-        ** It merely means that we might do some extra work to journal a 
+-        ** page that does not need to be journaled.  Nevertheless, be sure 
+-        ** to test the case where a malloc error occurs while trying to set 
+-        ** a bit in a bit vector.
+-        */
+-        sqlite3BeginBenignMalloc();
+-        if( pgno<=pPager->dbOrigSize ){
+-          TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
+-          testcase( rc==SQLITE_NOMEM );
+-        }
+-        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
+-        testcase( rc==SQLITE_NOMEM );
+-        sqlite3EndBenignMalloc();
+-      }
+-      memset(pPg->pData, 0, pPager->pageSize);
+-      IOTRACE(("ZERO %p %d\n", pPager, pgno));
+-    }else{
+-      if( pagerUseWal(pPager) && bMmapOk==0 ){
+-        rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
+-        if( rc!=SQLITE_OK ) goto pager_acquire_err;
++      /* Write out the page data. */
++      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
++
++      /* If page 1 was just written, update Pager.dbFileVers to match
++      ** the value now stored in the database file. If writing this 
++      ** page caused the database file to grow, update dbFileSize. 
++      */
++      if( pgno==1 ){
++        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
+       }
+-      assert( pPg->pPager==pPager );
+-      pPager->aStat[PAGER_STAT_MISS]++;
+-      rc = readDbPage(pPg, iFrame);
+-      if( rc!=SQLITE_OK ){
+-        goto pager_acquire_err;
++      if( pgno>pPager->dbFileSize ){
++        pPager->dbFileSize = pgno;
+       }
+-    }
+-    pager_set_pagehash(pPg);
+-  }
++      pPager->aStat[PAGER_STAT_WRITE]++;
+ 
+-  return SQLITE_OK;
++      /* Update any backup objects copying the contents of this pager. */
++      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
+ 
+-pager_acquire_err:
+-  assert( rc!=SQLITE_OK );
+-  if( pPg ){
+-    sqlite3PcacheDrop(pPg);
++      PAGERTRACE(("STORE %d page %d hash(%08x)\n",
++                   PAGERID(pPager), pgno, pager_pagehash(pList)));
++      IOTRACE(("PGOUT %p %d\n", pPager, pgno));
++      PAGER_INCR(sqlite3_pager_writedb_count);
++    }else{
++      PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
++    }
++    pager_set_pagehash(pList);
++    pList = pList->pDirty;
+   }
+-  pagerUnlockIfUnused(pPager);
+ 
+-  *ppPage = 0;
+   return rc;
+ }
+ 
+ /*
+-** Acquire a page if it is already in the in-memory cache.  Do
+-** not read the page from disk.  Return a pointer to the page,
+-** or 0 if the page is not in cache. 
+-**
+-** See also sqlite3PagerGet().  The difference between this routine
+-** and sqlite3PagerGet() is that _get() will go to the disk and read
+-** in the page if the page is not already in cache.  This routine
+-** returns NULL if the page is not in cache or if a disk I/O error 
+-** has ever happened.
+-*/
+-SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
+-  PgHdr *pPg = 0;
+-  assert( pPager!=0 );
+-  assert( pgno!=0 );
+-  assert( pPager->pPCache!=0 );
+-  assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR );
+-  sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
+-  return pPg;
+-}
+-
+-/*
+-** Release a page reference.
++** Ensure that the sub-journal file is open. If it is already open, this 
++** function is a no-op.
+ **
+-** If the number of references to the page drop to zero, then the
+-** page is added to the LRU list.  When all references to all pages
+-** are released, a rollback occurs and the lock on the database is
+-** removed.
++** SQLITE_OK is returned if everything goes according to plan. An 
++** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() 
++** fails.
+ */
+-SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
+-  if( pPg ){
+-    Pager *pPager = pPg->pPager;
+-    if( pPg->flags & PGHDR_MMAP ){
+-      pagerReleaseMapPage(pPg);
++static int openSubJournal(Pager *pPager){
++  int rc = SQLITE_OK;
++  if( !isOpen(pPager->sjfd) ){
++    if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
++      sqlite3MemJournalOpen(pPager->sjfd);
+     }else{
+-      sqlite3PcacheRelease(pPg);
++      rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL);
+     }
+-    pagerUnlockIfUnused(pPager);
+   }
++  return rc;
+ }
+ 
+ /*
+-** This function is called at the start of every write transaction.
+-** There must already be a RESERVED or EXCLUSIVE lock on the database 
+-** file when this routine is called.
+-**
+-** Open the journal file for pager pPager and write a journal header
+-** to the start of it. If there are active savepoints, open the sub-journal
+-** as well. This function is only used when the journal file is being 
+-** opened to write a rollback log for a transaction. It is not used 
+-** when opening a hot journal file to roll it back.
+-**
+-** If the journal file is already open (as it may be in exclusive mode),
+-** then this function just writes a journal header to the start of the
+-** already open file. 
++** Append a record of the current state of page pPg to the sub-journal. 
++** It is the callers responsibility to use subjRequiresPage() to check 
++** that it is really required before calling this function.
+ **
+-** Whether or not the journal file is opened by this function, the
+-** Pager.pInJournal bitvec structure is allocated.
++** If successful, set the bit corresponding to pPg->pgno in the bitvecs
++** for all open savepoints before returning.
+ **
+-** Return SQLITE_OK if everything is successful. Otherwise, return 
+-** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or 
+-** an IO error code if opening or writing the journal file fails.
++** This function returns SQLITE_OK if everything is successful, an IO
++** error code if the attempt to write to the sub-journal fails, or 
++** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
++** bitvec.
+ */
+-static int pager_open_journal(Pager *pPager){
+-  int rc = SQLITE_OK;                        /* Return code */
+-  sqlite3_vfs * const pVfs = pPager->pVfs;   /* Local cache of vfs pointer */
++static int subjournalPage(PgHdr *pPg){
++  int rc = SQLITE_OK;
++  Pager *pPager = pPg->pPager;
++  if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+ 
+-  assert( pPager->eState==PAGER_WRITER_LOCKED );
+-  assert( assert_pager_state(pPager) );
+-  assert( pPager->pInJournal==0 );
+-  
+-  /* If already in the error state, this function is a no-op.  But on
+-  ** the other hand, this routine is never called if we are already in
+-  ** an error state. */
+-  if( NEVER(pPager->errCode) ) return pPager->errCode;
++    /* Open the sub-journal, if it has not already been opened */
++    assert( pPager->useJournal );
++    assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
++    assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
++    assert( pagerUseWal(pPager) 
++         || pageInJournal(pPg) 
++         || pPg->pgno>pPager->dbOrigSize 
++    );
++    rc = openSubJournal(pPager);
+ 
+-  if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+-    pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
+-    if( pPager->pInJournal==0 ){
+-      return SQLITE_NOMEM;
+-    }
++    /* If the sub-journal was opened successfully (or was already open),
++    ** write the journal record into the file.  */
++    if( rc==SQLITE_OK ){
++      void *pData = pPg->pData;
++      i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
++      char *pData2;
+   
+-    /* Open the journal file if it is not already open. */
+-    if( !isOpen(pPager->jfd) ){
+-      if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
+-        sqlite3MemJournalOpen(pPager->jfd);
+-      }else{
+-        const int flags =                   /* VFS flags to open journal file */
+-          SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
+-          (pPager->tempFile ? 
+-            (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
+-            (SQLITE_OPEN_MAIN_JOURNAL)
+-          );
+-  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
+-        rc = sqlite3JournalOpen(
+-            pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+-        );
+-  #else
+-        rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+-  #endif
++      CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
++      PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
++      rc = write32bits(pPager->sjfd, offset, pPg->pgno);
++      if( rc==SQLITE_OK ){
++        rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
+       }
+-      assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
+-    }
+-  
+-  
+-    /* Write the first journal header to the journal file and open 
+-    ** the sub-journal if necessary.
+-    */
+-    if( rc==SQLITE_OK ){
+-      /* TODO: Check if all of these are really required. */
+-      pPager->nRec = 0;
+-      pPager->journalOff = 0;
+-      pPager->setMaster = 0;
+-      pPager->journalHdr = 0;
+-      rc = writeJournalHdr(pPager);
+     }
+   }
+-
+-  if( rc!=SQLITE_OK ){
+-    sqlite3BitvecDestroy(pPager->pInJournal);
+-    pPager->pInJournal = 0;
+-  }else{
+-    assert( pPager->eState==PAGER_WRITER_LOCKED );
+-    pPager->eState = PAGER_WRITER_CACHEMOD;
+-  }
+-
++  if( rc==SQLITE_OK ){
++    pPager->nSubRec++;
++    assert( pPager->nSavepoint>0 );
++    rc = addToSavepointBitvecs(pPager, pPg->pgno);
++  }
+   return rc;
+ }
+ 
+ /*
+-** Begin a write-transaction on the specified pager object. If a 
+-** write-transaction has already been opened, this function is a no-op.
++** This function is called by the pcache layer when it has reached some
++** soft memory limit. The first argument is a pointer to a Pager object
++** (cast as a void*). The pager is always 'purgeable' (not an in-memory
++** database). The second argument is a reference to a page that is 
++** currently dirty but has no outstanding references. The page
++** is always associated with the Pager object passed as the first 
++** argument.
+ **
+-** If the exFlag argument is false, then acquire at least a RESERVED
+-** lock on the database file. If exFlag is true, then acquire at least
+-** an EXCLUSIVE lock. If such a lock is already held, no locking 
+-** functions need be called.
++** The job of this function is to make pPg clean by writing its contents
++** out to the database file, if possible. This may involve syncing the
++** journal file. 
+ **
+-** If the subjInMemory argument is non-zero, then any sub-journal opened
+-** within this transaction will be opened as an in-memory file. This
+-** has no effect if the sub-journal is already opened (as it may be when
+-** running in exclusive mode) or if the transaction does not require a
+-** sub-journal. If the subjInMemory argument is zero, then any required
+-** sub-journal is implemented in-memory if pPager is an in-memory database, 
+-** or using a temporary file otherwise.
++** If successful, sqlite3PcacheMakeClean() is called on the page and
++** SQLITE_OK returned. If an IO error occurs while trying to make the
++** page clean, the IO error code is returned. If the page cannot be
++** made clean for some other reason, but no error occurs, then SQLITE_OK
++** is returned by sqlite3PcacheMakeClean() is not called.
+ */
+-SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
++static int pagerStress(void *p, PgHdr *pPg){
++  Pager *pPager = (Pager *)p;
+   int rc = SQLITE_OK;
+ 
+-  if( pPager->errCode ) return pPager->errCode;
+-  assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
+-  pPager->subjInMemory = (u8)subjInMemory;
+-
+-  if( ALWAYS(pPager->eState==PAGER_READER) ){
+-    assert( pPager->pInJournal==0 );
++  assert( pPg->pPager==pPager );
++  assert( pPg->flags&PGHDR_DIRTY );
+ 
+-    if( pagerUseWal(pPager) ){
+-      /* If the pager is configured to use locking_mode=exclusive, and an
+-      ** exclusive lock on the database is not already held, obtain it now.
+-      */
+-      if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
+-        rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+-        if( rc!=SQLITE_OK ){
+-          return rc;
+-        }
+-        sqlite3WalExclusiveMode(pPager->pWal, 1);
+-      }
++  /* The doNotSyncSpill flag is set during times when doing a sync of
++  ** journal (and adding a new header) is not allowed.  This occurs
++  ** during calls to sqlite3PagerWrite() while trying to journal multiple
++  ** pages belonging to the same sector.
++  **
++  ** The doNotSpill flag inhibits all cache spilling regardless of whether
++  ** or not a sync is required.  This is set during a rollback.
++  **
++  ** Spilling is also prohibited when in an error state since that could
++  ** lead to database corruption.   In the current implementaton it 
++  ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
++  ** while in the error state, hence it is impossible for this routine to
++  ** be called in the error state.  Nevertheless, we include a NEVER()
++  ** test for the error state as a safeguard against future changes.
++  */
++  if( NEVER(pPager->errCode) ) return SQLITE_OK;
++  if( pPager->doNotSpill ) return SQLITE_OK;
++  if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
++    return SQLITE_OK;
++  }
+ 
+-      /* Grab the write lock on the log file. If successful, upgrade to
+-      ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
+-      ** The busy-handler is not invoked if another connection already
+-      ** holds the write-lock. If possible, the upper layer will call it.
+-      */
+-      rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
+-    }else{
+-      /* Obtain a RESERVED lock on the database file. If the exFlag parameter
+-      ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
+-      ** busy-handler callback can be used when upgrading to the EXCLUSIVE
+-      ** lock, but not when obtaining the RESERVED lock.
+-      */
+-      rc = pagerLockDb(pPager, RESERVED_LOCK);
+-      if( rc==SQLITE_OK && exFlag ){
+-        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+-      }
++  pPg->pDirty = 0;
++  if( pagerUseWal(pPager) ){
++    /* Write a single frame for this page to the log. */
++    if( subjRequiresPage(pPg) ){ 
++      rc = subjournalPage(pPg); 
+     }
+-
+     if( rc==SQLITE_OK ){
+-      /* Change to WRITER_LOCKED state.
+-      **
+-      ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
+-      ** when it has an open transaction, but never to DBMOD or FINISHED.
+-      ** This is because in those states the code to roll back savepoint 
+-      ** transactions may copy data from the sub-journal into the database 
+-      ** file as well as into the page cache. Which would be incorrect in 
+-      ** WAL mode.
+-      */
+-      pPager->eState = PAGER_WRITER_LOCKED;
+-      pPager->dbHintSize = pPager->dbSize;
+-      pPager->dbFileSize = pPager->dbSize;
+-      pPager->dbOrigSize = pPager->dbSize;
+-      pPager->journalOff = 0;
++      rc = pagerWalFrames(pPager, pPg, 0, 0);
++    }
++  }else{
++  
++    /* Sync the journal file if required. */
++    if( pPg->flags&PGHDR_NEED_SYNC 
++     || pPager->eState==PAGER_WRITER_CACHEMOD
++    ){
++      rc = syncJournal(pPager, 1);
++    }
++  
++    /* If the page number of this page is larger than the current size of
++    ** the database image, it may need to be written to the sub-journal.
++    ** This is because the call to pager_write_pagelist() below will not
++    ** actually write data to the file in this case.
++    **
++    ** Consider the following sequence of events:
++    **
++    **   BEGIN;
++    **     <journal page X>
++    **     <modify page X>
++    **     SAVEPOINT sp;
++    **       <shrink database file to Y pages>
++    **       pagerStress(page X)
++    **     ROLLBACK TO sp;
++    **
++    ** If (X>Y), then when pagerStress is called page X will not be written
++    ** out to the database file, but will be dropped from the cache. Then,
++    ** following the "ROLLBACK TO sp" statement, reading page X will read
++    ** data from the database file. This will be the copy of page X as it
++    ** was when the transaction started, not as it was when "SAVEPOINT sp"
++    ** was executed.
++    **
++    ** The solution is to write the current data for page X into the 
++    ** sub-journal file now (if it is not already there), so that it will
++    ** be restored to its current value when the "ROLLBACK TO sp" is 
++    ** executed.
++    */
++    if( NEVER(
++        rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg)
++    ) ){
++      rc = subjournalPage(pPg);
++    }
++  
++    /* Write the contents of the page out to the database file. */
++    if( rc==SQLITE_OK ){
++      assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
++      rc = pager_write_pagelist(pPager, pPg);
+     }
++  }
+ 
+-    assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
+-    assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
+-    assert( assert_pager_state(pPager) );
++  /* Mark the page as clean. */
++  if( rc==SQLITE_OK ){
++    PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
++    sqlite3PcacheMakeClean(pPg);
+   }
+ 
+-  PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
+-  return rc;
++  return pager_error(pPager, rc); 
+ }
+ 
++
+ /*
+-** Mark a single data page as writeable. The page is written into the 
+-** main journal or sub-journal as required. If the page is written into
+-** one of the journals, the corresponding bit is set in the 
+-** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
+-** of any open savepoints as appropriate.
++** Allocate and initialize a new Pager object and put a pointer to it
++** in *ppPager. The pager should eventually be freed by passing it
++** to sqlite3PagerClose().
++**
++** The zFilename argument is the path to the database file to open.
++** If zFilename is NULL then a randomly-named temporary file is created
++** and used as the file to be cached. Temporary files are be deleted
++** automatically when they are closed. If zFilename is ":memory:" then 
++** all information is held in cache. It is never written to disk. 
++** This can be used to implement an in-memory database.
++**
++** The nExtra parameter specifies the number of bytes of space allocated
++** along with each page reference. This space is available to the user
++** via the sqlite3PagerGetExtra() API.
++**
++** The flags argument is used to specify properties that affect the
++** operation of the pager. It should be passed some bitwise combination
++** of the PAGER_* flags.
++**
++** The vfsFlags parameter is a bitmask to pass to the flags parameter
++** of the xOpen() method of the supplied VFS when opening files. 
++**
++** If the pager object is allocated and the specified file opened 
++** successfully, SQLITE_OK is returned and *ppPager set to point to
++** the new pager object. If an error occurs, *ppPager is set to NULL
++** and error code returned. This function may return SQLITE_NOMEM
++** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or 
++** various SQLITE_IO_XXX errors.
+ */
+-static int pager_write(PgHdr *pPg){
+-  void *pData = pPg->pData;
+-  Pager *pPager = pPg->pPager;
+-  int rc = SQLITE_OK;
++SQLITE_PRIVATE int sqlite3PagerOpen(
++  sqlite3_vfs *pVfs,       /* The virtual file system to use */
++  Pager **ppPager,         /* OUT: Return the Pager structure here */
++  const char *zFilename,   /* Name of the database file to open */
++  int nExtra,              /* Extra bytes append to each in-memory page */
++  int flags,               /* flags controlling this file */
++  int vfsFlags,            /* flags passed through to sqlite3_vfs.xOpen() */
++  void (*xReinit)(DbPage*) /* Function to reinitialize pages */
++){
++  u8 *pPtr;
++  Pager *pPager = 0;       /* Pager object to allocate and return */
++  int rc = SQLITE_OK;      /* Return code */
++  int tempFile = 0;        /* True for temp files (incl. in-memory files) */
++  int memDb = 0;           /* True if this is an in-memory file */
++  int readOnly = 0;        /* True if this is a read-only file */
++  int journalFileSize;     /* Bytes to allocate for each journal fd */
++  char *zPathname = 0;     /* Full path to database file */
++  int nPathname = 0;       /* Number of bytes in zPathname */
++  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
++  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
++  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
++  const char *zUri = 0;    /* URI args to copy */
++  int nUri = 0;            /* Number of bytes of URI args at *zUri */
+ 
+-  /* This routine is not called unless a write-transaction has already 
+-  ** been started. The journal file may or may not be open at this point.
+-  ** It is never called in the ERROR state.
++  /* Figure out how much space is required for each journal file-handle
++  ** (there are two of them, the main journal and the sub-journal). This
++  ** is the maximum space required for an in-memory journal file handle 
++  ** and a regular journal file-handle. Note that a "regular journal-handle"
++  ** may be a wrapper capable of caching the first portion of the journal
++  ** file in memory to implement the atomic-write optimization (see 
++  ** source file journal.c).
+   */
+-  assert( pPager->eState==PAGER_WRITER_LOCKED
+-       || pPager->eState==PAGER_WRITER_CACHEMOD
+-       || pPager->eState==PAGER_WRITER_DBMOD
+-  );
+-  assert( assert_pager_state(pPager) );
+-
+-  /* If an error has been previously detected, report the same error
+-  ** again. This should not happen, but the check provides robustness. */
+-  if( NEVER(pPager->errCode) )  return pPager->errCode;
++  if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
++    journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
++  }else{
++    journalFileSize = ROUND8(sqlite3MemJournalSize());
++  }
+ 
+-  /* Higher-level routines never call this function if database is not
+-  ** writable.  But check anyway, just for robustness. */
+-  if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
++  /* Set the output variable to NULL in case an error occurs. */
++  *ppPager = 0;
+ 
+-  CHECK_PAGE(pPg);
++#ifndef SQLITE_OMIT_MEMORYDB
++  if( flags & PAGER_MEMORY ){
++    memDb = 1;
++    if( zFilename && zFilename[0] ){
++      zPathname = sqlite3DbStrDup(0, zFilename);
++      if( zPathname==0  ) return SQLITE_NOMEM;
++      nPathname = sqlite3Strlen30(zPathname);
++      zFilename = 0;
++    }
++  }
++#endif
+ 
+-  /* The journal file needs to be opened. Higher level routines have already
+-  ** obtained the necessary locks to begin the write-transaction, but the
+-  ** rollback journal might not yet be open. Open it now if this is the case.
+-  **
+-  ** This is done before calling sqlite3PcacheMakeDirty() on the page. 
+-  ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
+-  ** an error might occur and the pager would end up in WRITER_LOCKED state
+-  ** with pages marked as dirty in the cache.
++  /* Compute and store the full pathname in an allocated buffer pointed
++  ** to by zPathname, length nPathname. Or, if this is a temporary file,
++  ** leave both nPathname and zPathname set to 0.
+   */
+-  if( pPager->eState==PAGER_WRITER_LOCKED ){
+-    rc = pager_open_journal(pPager);
+-    if( rc!=SQLITE_OK ) return rc;
++  if( zFilename && zFilename[0] ){
++    const char *z;
++    nPathname = pVfs->mxPathname+1;
++    zPathname = sqlite3DbMallocRaw(0, nPathname*2);
++    if( zPathname==0 ){
++      return SQLITE_NOMEM;
++    }
++    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
++    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
++    nPathname = sqlite3Strlen30(zPathname);
++    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
++    while( *z ){
++      z += sqlite3Strlen30(z)+1;
++      z += sqlite3Strlen30(z)+1;
++    }
++    nUri = (int)(&z[1] - zUri);
++    assert( nUri>=0 );
++    if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
++      /* This branch is taken when the journal path required by
++      ** the database being opened will be more than pVfs->mxPathname
++      ** bytes in length. This means the database cannot be opened,
++      ** as it will not be possible to open the journal file or even
++      ** check for a hot-journal before reading.
++      */
++      rc = SQLITE_CANTOPEN_BKPT;
++    }
++    if( rc!=SQLITE_OK ){
++      sqlite3DbFree(0, zPathname);
++      return rc;
++    }
+   }
+-  assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
+-  assert( assert_pager_state(pPager) );
+ 
+-  /* Mark the page as dirty.  If the page has already been written
+-  ** to the journal then we can return right away.
++  /* Allocate memory for the Pager structure, PCache object, the
++  ** three file descriptors, the database file name and the journal 
++  ** file name. The layout in memory is as follows:
++  **
++  **     Pager object                    (sizeof(Pager) bytes)
++  **     PCache object                   (sqlite3PcacheSize() bytes)
++  **     Database file handle            (pVfs->szOsFile bytes)
++  **     Sub-journal file handle         (journalFileSize bytes)
++  **     Main journal file handle        (journalFileSize bytes)
++  **     Database file name              (nPathname+1 bytes)
++  **     Journal file name               (nPathname+8+1 bytes)
+   */
+-  sqlite3PcacheMakeDirty(pPg);
+-  if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
+-    assert( !pagerUseWal(pPager) );
+-  }else{
+-  
+-    /* The transaction journal now exists and we have a RESERVED or an
+-    ** EXCLUSIVE lock on the main database file.  Write the current page to
+-    ** the transaction journal if it is not there already.
+-    */
+-    if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
+-      assert( pagerUseWal(pPager)==0 );
+-      if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
+-        u32 cksum;
+-        char *pData2;
+-        i64 iOff = pPager->journalOff;
+-
+-        /* We should never write to the journal file the page that
+-        ** contains the database locks.  The following assert verifies
+-        ** that we do not. */
+-        assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
+-
+-        assert( pPager->journalHdr<=pPager->journalOff );
+-        CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
+-        cksum = pager_cksum(pPager, (u8*)pData2);
+-
+-        /* Even if an IO or diskfull error occurs while journalling the
+-        ** page in the block above, set the need-sync flag for the page.
+-        ** Otherwise, when the transaction is rolled back, the logic in
+-        ** playback_one_page() will think that the page needs to be restored
+-        ** in the database file. And if an IO error occurs while doing so,
+-        ** then corruption may follow.
+-        */
+-        pPg->flags |= PGHDR_NEED_SYNC;
++  pPtr = (u8 *)sqlite3MallocZero(
++    ROUND8(sizeof(*pPager)) +      /* Pager structure */
++    ROUND8(pcacheSize) +           /* PCache object */
++    ROUND8(pVfs->szOsFile) +       /* The main db file */
++    journalFileSize * 2 +          /* The two journal files */ 
++    nPathname + 1 + nUri +         /* zFilename */
++    nPathname + 8 + 2              /* zJournal */
++#ifndef SQLITE_OMIT_WAL
++    + nPathname + 4 + 2            /* zWal */
++#endif
++  );
++  assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
++  if( !pPtr ){
++    sqlite3DbFree(0, zPathname);
++    return SQLITE_NOMEM;
++  }
++  pPager =              (Pager*)(pPtr);
++  pPager->pPCache =    (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
++  pPager->fd =   (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
++  pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
++  pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
++  pPager->zFilename =    (char*)(pPtr += journalFileSize);
++  assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
+ 
+-        rc = write32bits(pPager->jfd, iOff, pPg->pgno);
+-        if( rc!=SQLITE_OK ) return rc;
+-        rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
+-        if( rc!=SQLITE_OK ) return rc;
+-        rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
+-        if( rc!=SQLITE_OK ) return rc;
++  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
++  if( zPathname ){
++    assert( nPathname>0 );
++    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
++    memcpy(pPager->zFilename, zPathname, nPathname);
++    if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
++    memcpy(pPager->zJournal, zPathname, nPathname);
++    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
++    sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
++#ifndef SQLITE_OMIT_WAL
++    pPager->zWal = &pPager->zJournal[nPathname+8+1];
++    memcpy(pPager->zWal, zPathname, nPathname);
++    memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
++    sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
++#endif
++    sqlite3DbFree(0, zPathname);
++  }
++  pPager->pVfs = pVfs;
++  pPager->vfsFlags = vfsFlags;
+ 
+-        IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 
+-                 pPager->journalOff, pPager->pageSize));
+-        PAGER_INCR(sqlite3_pager_writej_count);
+-        PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
+-             PAGERID(pPager), pPg->pgno, 
+-             ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
++  /* Open the pager file.
++  */
++  if( zFilename && zFilename[0] ){
++    int fout = 0;                    /* VFS flags returned by xOpen() */
++    rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
++    assert( !memDb );
++    readOnly = (fout&SQLITE_OPEN_READONLY);
+ 
+-        pPager->journalOff += 8 + pPager->pageSize;
+-        pPager->nRec++;
+-        assert( pPager->pInJournal!=0 );
+-        rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
+-        testcase( rc==SQLITE_NOMEM );
+-        assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+-        rc |= addToSavepointBitvecs(pPager, pPg->pgno);
+-        if( rc!=SQLITE_OK ){
+-          assert( rc==SQLITE_NOMEM );
+-          return rc;
++    /* If the file was successfully opened for read/write access,
++    ** choose a default page size in case we have to create the
++    ** database file. The default page size is the maximum of:
++    **
++    **    + SQLITE_DEFAULT_PAGE_SIZE,
++    **    + The value returned by sqlite3OsSectorSize()
++    **    + The largest page size that can be written atomically.
++    */
++    if( rc==SQLITE_OK && !readOnly ){
++      setSectorSize(pPager);
++      assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
++      if( szPageDflt<pPager->sectorSize ){
++        if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
++          szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
++        }else{
++          szPageDflt = (u32)pPager->sectorSize;
+         }
+-      }else{
+-        if( pPager->eState!=PAGER_WRITER_DBMOD ){
+-          pPg->flags |= PGHDR_NEED_SYNC;
++      }
++#ifdef SQLITE_ENABLE_ATOMIC_WRITE
++      {
++        int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
++        int ii;
++        assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
++        assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
++        assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
++        for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
++          if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
++            szPageDflt = ii;
++          }
+         }
+-        PAGERTRACE(("APPEND %d page %d needSync=%d\n",
+-                PAGERID(pPager), pPg->pgno,
+-               ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
+       }
++#endif
+     }
+-  
+-    /* If the statement journal is open and the page is not in it,
+-    ** then write the current page to the statement journal.  Note that
+-    ** the statement journal format differs from the standard journal format
+-    ** in that it omits the checksums and the header.
+-    */
+-    if( subjRequiresPage(pPg) ){
+-      rc = subjournalPage(pPg);
+-    }
++  }else{
++    /* If a temporary file is requested, it is not opened immediately.
++    ** In this case we accept the default page size and delay actually
++    ** opening the file until the first call to OsWrite().
++    **
++    ** This branch is also run for an in-memory database. An in-memory
++    ** database is the same as a temp-file that is never written out to
++    ** disk and uses an in-memory rollback journal.
++    */ 
++    tempFile = 1;
++    pPager->eState = PAGER_READER;
++    pPager->eLock = EXCLUSIVE_LOCK;
++    readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
++  }
++
++  /* The following call to PagerSetPagesize() serves to set the value of 
++  ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
++  */
++  if( rc==SQLITE_OK ){
++    assert( pPager->memDb==0 );
++    rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
++    testcase( rc!=SQLITE_OK );
++  }
++
++  /* If an error occurred in either of the blocks above, free the 
++  ** Pager structure and close the file.
++  */
++  if( rc!=SQLITE_OK ){
++    assert( !pPager->pTmpSpace );
++    sqlite3OsClose(pPager->fd);
++    sqlite3_free(pPager);
++    return rc;
+   }
+ 
+-  /* Update the database size and return.
+-  */
+-  if( pPager->dbSize<pPg->pgno ){
+-    pPager->dbSize = pPg->pgno;
++  /* Initialize the PCache object. */
++  assert( nExtra<1000 );
++  nExtra = ROUND8(nExtra);
++  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
++                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
++
++  PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
++  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
++
++  pPager->useJournal = (u8)useJournal;
++  /* pPager->stmtOpen = 0; */
++  /* pPager->stmtInUse = 0; */
++  /* pPager->nRef = 0; */
++  /* pPager->stmtSize = 0; */
++  /* pPager->stmtJSize = 0; */
++  /* pPager->nPage = 0; */
++  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
++  /* pPager->state = PAGER_UNLOCK; */
++#if 0
++  assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
++#endif
++  /* pPager->errMask = 0; */
++  pPager->tempFile = (u8)tempFile;
++  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
++          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
++  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
++  pPager->exclusiveMode = (u8)tempFile; 
++  pPager->changeCountDone = pPager->tempFile;
++  pPager->memDb = (u8)memDb;
++  pPager->readOnly = (u8)readOnly;
++  assert( useJournal || pPager->tempFile );
++  pPager->noSync = pPager->tempFile;
++  if( pPager->noSync ){
++    assert( pPager->fullSync==0 );
++    assert( pPager->syncFlags==0 );
++    assert( pPager->walSyncFlags==0 );
++    assert( pPager->ckptSyncFlags==0 );
++  }else{
++    pPager->fullSync = 1;
++    pPager->syncFlags = SQLITE_SYNC_NORMAL;
++    pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
++    pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+   }
+-  return rc;
++  /* pPager->pFirst = 0; */
++  /* pPager->pFirstSynced = 0; */
++  /* pPager->pLast = 0; */
++  pPager->nExtra = (u16)nExtra;
++  pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
++  assert( isOpen(pPager->fd) || tempFile );
++  setSectorSize(pPager);
++  if( !useJournal ){
++    pPager->journalMode = PAGER_JOURNALMODE_OFF;
++  }else if( memDb ){
++    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
++  }
++  /* pPager->xBusyHandler = 0; */
++  /* pPager->pBusyHandlerArg = 0; */
++  pPager->xReiniter = xReinit;
++  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
++  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
++
++  *ppPager = pPager;
++  return SQLITE_OK;
+ }
+ 
++
++
+ /*
+-** Mark a data page as writeable. This routine must be called before 
+-** making changes to a page. The caller must check the return value 
+-** of this function and be careful not to change any page data unless 
+-** this routine returns SQLITE_OK.
++** This function is called after transitioning from PAGER_UNLOCK to
++** PAGER_SHARED state. It tests if there is a hot journal present in
++** the file-system for the given pager. A hot journal is one that 
++** needs to be played back. According to this function, a hot-journal
++** file exists if the following criteria are met:
+ **
+-** The difference between this function and pager_write() is that this
+-** function also deals with the special case where 2 or more pages
+-** fit on a single disk sector. In this case all co-resident pages
+-** must have been written to the journal file before returning.
++**   * The journal file exists in the file system, and
++**   * No process holds a RESERVED or greater lock on the database file, and
++**   * The database file itself is greater than 0 bytes in size, and
++**   * The first byte of the journal file exists and is not 0x00.
+ **
+-** If an error occurs, SQLITE_NOMEM or an IO error code is returned
+-** as appropriate. Otherwise, SQLITE_OK.
++** If the current size of the database file is 0 but a journal file
++** exists, that is probably an old journal left over from a prior
++** database with the same name. In this case the journal file is
++** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
++** is returned.
++**
++** This routine does not check if there is a master journal filename
++** at the end of the file. If there is, and that master journal file
++** does not exist, then the journal file is not really hot. In this
++** case this routine will return a false-positive. The pager_playback()
++** routine will discover that the journal file is not really hot and 
++** will not roll it back. 
++**
++** If a hot-journal file is found to exist, *pExists is set to 1 and 
++** SQLITE_OK returned. If no hot-journal file is present, *pExists is
++** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
++** to determine whether or not a hot-journal file exists, the IO error
++** code is returned and the value of *pExists is undefined.
+ */
+-SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
+-  int rc = SQLITE_OK;
+-
+-  PgHdr *pPg = pDbPage;
+-  Pager *pPager = pPg->pPager;
+-  Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
++static int hasHotJournal(Pager *pPager, int *pExists){
++  sqlite3_vfs * const pVfs = pPager->pVfs;
++  int rc = SQLITE_OK;           /* Return code */
++  int exists = 1;               /* True if a journal file is present */
++  int jrnlOpen = !!isOpen(pPager->jfd);
+ 
+-  assert( (pPg->flags & PGHDR_MMAP)==0 );
+-  assert( pPager->eState>=PAGER_WRITER_LOCKED );
+-  assert( pPager->eState!=PAGER_ERROR );
+-  assert( assert_pager_state(pPager) );
++  assert( pPager->useJournal );
++  assert( isOpen(pPager->fd) );
++  assert( pPager->eState==PAGER_OPEN );
+ 
+-  if( nPagePerSector>1 ){
+-    Pgno nPageCount;          /* Total number of pages in database file */
+-    Pgno pg1;                 /* First page of the sector pPg is located on. */
+-    int nPage = 0;            /* Number of pages starting at pg1 to journal */
+-    int ii;                   /* Loop counter */
+-    int needSync = 0;         /* True if any page has PGHDR_NEED_SYNC */
++  assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
++    SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
++  ));
+ 
+-    /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
+-    ** a journal header to be written between the pages journaled by
+-    ** this function.
+-    */
+-    assert( !MEMDB );
+-    assert( pPager->doNotSyncSpill==0 );
+-    pPager->doNotSyncSpill++;
++  *pExists = 0;
++  if( !jrnlOpen ){
++    rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
++  }
++  if( rc==SQLITE_OK && exists ){
++    int locked = 0;             /* True if some process holds a RESERVED lock */
+ 
+-    /* This trick assumes that both the page-size and sector-size are
+-    ** an integer power of 2. It sets variable pg1 to the identifier
+-    ** of the first page of the sector pPg is located on.
++    /* Race condition here:  Another process might have been holding the
++    ** the RESERVED lock and have a journal open at the sqlite3OsAccess() 
++    ** call above, but then delete the journal and drop the lock before
++    ** we get to the following sqlite3OsCheckReservedLock() call.  If that
++    ** is the case, this routine might think there is a hot journal when
++    ** in fact there is none.  This results in a false-positive which will
++    ** be dealt with by the playback routine.  Ticket #3883.
+     */
+-    pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
+-
+-    nPageCount = pPager->dbSize;
+-    if( pPg->pgno>nPageCount ){
+-      nPage = (pPg->pgno - pg1)+1;
+-    }else if( (pg1+nPagePerSector-1)>nPageCount ){
+-      nPage = nPageCount+1-pg1;
+-    }else{
+-      nPage = nPagePerSector;
+-    }
+-    assert(nPage>0);
+-    assert(pg1<=pPg->pgno);
+-    assert((pg1+nPage)>pPg->pgno);
++    rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
++    if( rc==SQLITE_OK && !locked ){
++      Pgno nPage;                 /* Number of pages in database file */
+ 
+-    for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
+-      Pgno pg = pg1+ii;
+-      PgHdr *pPage;
+-      if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
+-        if( pg!=PAGER_MJ_PGNO(pPager) ){
+-          rc = sqlite3PagerGet(pPager, pg, &pPage);
++      /* Check the size of the database file. If it consists of 0 pages,
++      ** then delete the journal file. See the header comment above for 
++      ** the reasoning here.  Delete the obsolete journal file under
++      ** a RESERVED lock to avoid race conditions and to avoid violating
++      ** [H33020].
++      */
++      rc = pagerPagecount(pPager, &nPage);
++      if( rc==SQLITE_OK ){
++        if( nPage==0 ){
++          sqlite3BeginBenignMalloc();
++          if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
++            sqlite3OsDelete(pVfs, pPager->zJournal, 0);
++            if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
++          }
++          sqlite3EndBenignMalloc();
++        }else{
++          /* The journal file exists and no other connection has a reserved
++          ** or greater lock on the database file. Now check that there is
++          ** at least one non-zero bytes at the start of the journal file.
++          ** If there is, then we consider this journal to be hot. If not, 
++          ** it can be ignored.
++          */
++          if( !jrnlOpen ){
++            int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
++            rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
++          }
+           if( rc==SQLITE_OK ){
+-            rc = pager_write(pPage);
+-            if( pPage->flags&PGHDR_NEED_SYNC ){
+-              needSync = 1;
++            u8 first = 0;
++            rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
++            if( rc==SQLITE_IOERR_SHORT_READ ){
++              rc = SQLITE_OK;
+             }
+-            sqlite3PagerUnref(pPage);
++            if( !jrnlOpen ){
++              sqlite3OsClose(pPager->jfd);
++            }
++            *pExists = (first!=0);
++          }else if( rc==SQLITE_CANTOPEN ){
++            /* If we cannot open the rollback journal file in order to see if
++            ** its has a zero header, that might be due to an I/O error, or
++            ** it might be due to the race condition described above and in
++            ** ticket #3883.  Either way, assume that the journal is hot.
++            ** This might be a false positive.  But if it is, then the
++            ** automatic journal playback and recovery mechanism will deal
++            ** with it under an EXCLUSIVE lock where we do not need to
++            ** worry so much with race conditions.
++            */
++            *pExists = 1;
++            rc = SQLITE_OK;
+           }
+         }
+-      }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
+-        if( pPage->flags&PGHDR_NEED_SYNC ){
+-          needSync = 1;
+-        }
+-        sqlite3PagerUnref(pPage);
+-      }
+-    }
+-
+-    /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages 
+-    ** starting at pg1, then it needs to be set for all of them. Because
+-    ** writing to any of these nPage pages may damage the others, the
+-    ** journal file must contain sync()ed copies of all of them
+-    ** before any of them can be written out to the database file.
+-    */
+-    if( rc==SQLITE_OK && needSync ){
+-      assert( !MEMDB );
+-      for(ii=0; ii<nPage; ii++){
+-        PgHdr *pPage = pager_lookup(pPager, pg1+ii);
+-        if( pPage ){
+-          pPage->flags |= PGHDR_NEED_SYNC;
+-          sqlite3PagerUnref(pPage);
+-        }
+       }
+     }
+-
+-    assert( pPager->doNotSyncSpill==1 );
+-    pPager->doNotSyncSpill--;
+-  }else{
+-    rc = pager_write(pDbPage);
+   }
+-  return rc;
+-}
+ 
+-/*
+-** Return TRUE if the page given in the argument was previously passed
+-** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
+-** to change the content of the page.
+-*/
+-#ifndef NDEBUG
+-SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
+-  return pPg->flags&PGHDR_DIRTY;
++  return rc;
+ }
+-#endif
+ 
+ /*
+-** A call to this routine tells the pager that it is not necessary to
+-** write the information on page pPg back to the disk, even though
+-** that page might be marked as dirty.  This happens, for example, when
+-** the page has been added as a leaf of the freelist and so its
+-** content no longer matters.
+-**
+-** The overlying software layer calls this routine when all of the data
+-** on the given page is unused. The pager marks the page as clean so
+-** that it does not get written to disk.
++** This function is called to obtain a shared lock on the database file.
++** It is illegal to call sqlite3PagerAcquire() until after this function
++** has been successfully called. If a shared-lock is already held when
++** this function is called, it is a no-op.
+ **
+-** Tests show that this optimization can quadruple the speed of large 
+-** DELETE operations.
+-*/
+-SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
+-  Pager *pPager = pPg->pPager;
+-  if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
+-    PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
+-    IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
+-    pPg->flags |= PGHDR_DONT_WRITE;
+-    pager_set_pagehash(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.  The secondary change counter at
+-** 92 is also updated, as is the SQLite version number at offset 96.
++** The following operations are also performed by this function.
+ **
+-** 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.
++**   1) If the pager is currently in PAGER_OPEN state (no lock held
++**      on the database file), then an attempt is made to obtain a
++**      SHARED lock on the database file. Immediately after obtaining
++**      the SHARED lock, the file-system is checked for a hot-journal,
++**      which is played back if present. Following any hot-journal 
++**      rollback, the contents of the cache are validated by checking
++**      the 'change-counter' field of the database file header and
++**      discarded if they are found to be invalid.
+ **
+-** If the isDirectMode flag is zero, then this is done by calling 
+-** sqlite3PagerWrite() on page 1, then modifying the contents of the
+-** page data. In this case the file will be updated when the current
+-** transaction is committed.
++**   2) If the pager is running in exclusive-mode, and there are currently
++**      no outstanding references to any pages, and is in the error state,
++**      then an attempt is made to clear the error state by discarding
++**      the contents of the page cache and rolling back any open journal
++**      file.
+ **
+-** The isDirectMode flag may only be non-zero if the library was compiled
+-** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
+-** if isDirect is non-zero, then the database file is updated directly
+-** by writing an updated version of page 1 using a call to the 
+-** sqlite3OsWrite() function.
++** If everything is successful, SQLITE_OK is returned. If an IO error 
++** occurs while locking the database, checking for a hot-journal file or 
++** rolling back a journal file, the IO error code is returned.
+ */
+-static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
+-  int rc = SQLITE_OK;
+-
+-  assert( pPager->eState==PAGER_WRITER_CACHEMOD
+-       || pPager->eState==PAGER_WRITER_DBMOD
+-  );
+-  assert( assert_pager_state(pPager) );
++SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
++  int rc = SQLITE_OK;                /* Return code */
+ 
+-  /* Declare and initialize constant integer 'isDirect'. If the
+-  ** atomic-write optimization is enabled in this build, then isDirect
+-  ** is initialized to the value passed as the isDirectMode parameter
+-  ** to this function. Otherwise, it is always set to zero.
+-  **
+-  ** The idea is that if the atomic-write optimization is not
+-  ** enabled at compile time, the compiler can omit the tests of
+-  ** 'isDirect' below, as well as the block enclosed in the
+-  ** "if( isDirect )" condition.
++  /* This routine is only called from b-tree and only when there are no
++  ** outstanding pages. This implies that the pager state should either
++  ** be OPEN or READER. READER is only possible if the pager is or was in 
++  ** exclusive access mode.
+   */
+-#ifndef SQLITE_ENABLE_ATOMIC_WRITE
+-# define DIRECT_MODE 0
+-  assert( isDirectMode==0 );
+-  UNUSED_PARAMETER(isDirectMode);
+-#else
+-# define DIRECT_MODE isDirectMode
+-#endif
++  assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
++  assert( assert_pager_state(pPager) );
++  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
++  if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
+ 
+-  if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
+-    PgHdr *pPgHdr;                /* Reference to page 1 */
++  if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
++    int bHotJournal = 1;          /* True if there exists a hot journal-file */
+ 
+-    assert( !pPager->tempFile && isOpen(pPager->fd) );
++    assert( !MEMDB );
+ 
+-    /* Open page 1 of the file for writing. */
+-    rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
+-    assert( pPgHdr==0 || rc==SQLITE_OK );
++    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
++    if( rc!=SQLITE_OK ){
++      assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
++      goto failed;
++    }
+ 
+-    /* If page one was fetched successfully, and this function is not
+-    ** operating in direct-mode, make page 1 writable.  When not in 
+-    ** direct mode, page 1 is always held in cache and hence the PagerGet()
+-    ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
++    /* If a journal file exists, and there is no RESERVED lock on the
++    ** database file, then it either needs to be played back or deleted.
+     */
+-    if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
+-      rc = sqlite3PagerWrite(pPgHdr);
++    if( pPager->eLock<=SHARED_LOCK ){
++      rc = hasHotJournal(pPager, &bHotJournal);
++    }
++    if( rc!=SQLITE_OK ){
++      goto failed;
++    }
++    if( bHotJournal ){
++      if( pPager->readOnly ){
++        rc = SQLITE_READONLY_ROLLBACK;
++        goto failed;
++      }
++
++      /* Get an EXCLUSIVE lock on the database file. At this point it is
++      ** important that a RESERVED lock is not obtained on the way to the
++      ** EXCLUSIVE lock. If it were, another process might open the
++      ** database file, detect the RESERVED lock, and conclude that the
++      ** database is safe to read while this process is still rolling the 
++      ** hot-journal back.
++      ** 
++      ** Because the intermediate RESERVED lock is not requested, any
++      ** other process attempting to access the database file will get to 
++      ** this point in the code and fail to obtain its own EXCLUSIVE lock 
++      ** on the database file.
++      **
++      ** Unless the pager is in locking_mode=exclusive mode, the lock is
++      ** downgraded to SHARED_LOCK before this function returns.
++      */
++      rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
++      if( rc!=SQLITE_OK ){
++        goto failed;
++      }
++ 
++      /* If it is not already open and the file exists on disk, open the 
++      ** journal for read/write access. Write access is required because 
++      ** in exclusive-access mode the file descriptor will be kept open 
++      ** and possibly used for a transaction later on. Also, write-access 
++      ** is usually required to finalize the journal in journal_mode=persist 
++      ** mode (and also for journal_mode=truncate on some systems).
++      **
++      ** If the journal does not exist, it usually means that some 
++      ** other connection managed to get in and roll it back before 
++      ** this connection obtained the exclusive lock above. Or, it 
++      ** may mean that the pager was in the error-state when this
++      ** function was called and the journal file does not exist.
++      */
++      if( !isOpen(pPager->jfd) ){
++        sqlite3_vfs * const pVfs = pPager->pVfs;
++        int bExists;              /* True if journal file exists */
++        rc = sqlite3OsAccess(
++            pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
++        if( rc==SQLITE_OK && bExists ){
++          int fout = 0;
++          int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
++          assert( !pPager->tempFile );
++          rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
++          assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
++          if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
++            rc = SQLITE_CANTOPEN_BKPT;
++            sqlite3OsClose(pPager->jfd);
++          }
++        }
++      }
++ 
++      /* Playback and delete the journal.  Drop the database write
++      ** lock and reacquire the read lock. Purge the cache before
++      ** playing back the hot-journal so that we don't end up with
++      ** an inconsistent cache.  Sync the hot journal before playing
++      ** it back since the process that crashed and left the hot journal
++      ** probably did not sync it and we are required to always sync
++      ** the journal before playing it back.
++      */
++      if( isOpen(pPager->jfd) ){
++        assert( rc==SQLITE_OK );
++        rc = pagerSyncHotJournal(pPager);
++        if( rc==SQLITE_OK ){
++          rc = pager_playback(pPager, 1);
++          pPager->eState = PAGER_OPEN;
++        }
++      }else if( !pPager->exclusiveMode ){
++        pagerUnlockDb(pPager, SHARED_LOCK);
++      }
++
++      if( rc!=SQLITE_OK ){
++        /* This branch is taken if an error occurs while trying to open
++        ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
++        ** pager_unlock() routine will be called before returning to unlock
++        ** the file. If the unlock attempt fails, then Pager.eLock must be
++        ** set to UNKNOWN_LOCK (see the comment above the #define for 
++        ** UNKNOWN_LOCK above for an explanation). 
++        **
++        ** In order to get pager_unlock() to do this, set Pager.eState to
++        ** PAGER_ERROR now. This is not actually counted as a transition
++        ** to ERROR state in the state diagram at the top of this file,
++        ** since we know that the same call to pager_unlock() will very
++        ** shortly transition the pager object to the OPEN state. Calling
++        ** assert_pager_state() would fail now, as it should not be possible
++        ** to be in ERROR state when there are zero outstanding page 
++        ** references.
++        */
++        pager_error(pPager, rc);
++        goto failed;
++      }
++
++      assert( pPager->eState==PAGER_OPEN );
++      assert( (pPager->eLock==SHARED_LOCK)
++           || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
++      );
+     }
+ 
+-    if( rc==SQLITE_OK ){
+-      /* Actually do the update of the change counter */
+-      pager_write_changecounter(pPgHdr);
++    if( !pPager->tempFile && (
++        pPager->pBackup 
++     || sqlite3PcachePagecount(pPager->pPCache)>0 
++     || USEFETCH(pPager)
++    )){
++      /* The shared-lock has just been acquired on the database file
++      ** and there are already pages in the cache (from a previous
++      ** read or write transaction).  Check to see if the database
++      ** has been modified.  If the database has changed, flush the
++      ** cache.
++      **
++      ** Database changes is detected by looking at 15 bytes beginning
++      ** at offset 24 into the file.  The first 4 of these 16 bytes are
++      ** a 32-bit counter that is incremented with each change.  The
++      ** other bytes change randomly with each file change when
++      ** a codec is in use.
++      ** 
++      ** There is a vanishingly small chance that a change will not be 
++      ** detected.  The chance of an undetected change is so small that
++      ** it can be neglected.
++      */
++      Pgno nPage = 0;
++      char dbFileVers[sizeof(pPager->dbFileVers)];
++
++      rc = pagerPagecount(pPager, &nPage);
++      if( rc ) goto failed;
+ 
+-      /* If running in direct mode, write the contents of page 1 to the file. */
+-      if( DIRECT_MODE ){
+-        const void *zBuf;
+-        assert( pPager->dbFileSize>0 );
+-        CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
+-        if( rc==SQLITE_OK ){
+-          rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
+-          pPager->aStat[PAGER_STAT_WRITE]++;
+-        }
+-        if( rc==SQLITE_OK ){
+-          /* Update the pager's copy of the change-counter. Otherwise, the
+-          ** next time a read transaction is opened the cache will be
+-          ** flushed (as the change-counter values will not match).  */
+-          const void *pCopy = (const void *)&((const char *)zBuf)[24];
+-          memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
+-          pPager->changeCountDone = 1;
++      if( nPage>0 ){
++        IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
++        rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
++        if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
++          goto failed;
+         }
+       }else{
+-        pPager->changeCountDone = 1;
++        memset(dbFileVers, 0, sizeof(dbFileVers));
++      }
++
++      if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
++        pager_reset(pPager);
++
++        /* Unmap the database file. It is possible that external processes
++        ** may have truncated the database file and then extended it back
++        ** to its original size while this process was not holding a lock.
++        ** In this case there may exist a Pager.pMap mapping that appears
++        ** to be the right size but is not actually valid. Avoid this
++        ** possibility by unmapping the db here. */
++        if( USEFETCH(pPager) ){
++          sqlite3OsUnfetch(pPager->fd, 0, 0);
++        }
+       }
+     }
+ 
+-    /* Release the page reference. */
+-    sqlite3PagerUnref(pPgHdr);
++    /* If there is a WAL file in the file-system, open this database in WAL
++    ** mode. Otherwise, the following function call is a no-op.
++    */
++    rc = pagerOpenWalIfPresent(pPager);
++#ifndef SQLITE_OMIT_WAL
++    assert( pPager->pWal==0 || rc==SQLITE_OK );
 +#endif
-+/* END CRYPTO */
+   }
+-  return rc;
+-}
+ 
+-/*
+-** Sync the database file to disk. This is a no-op for in-memory databases
+-** or pages with the Pager.noSync flag set.
+-**
+-** If successful, or if called on a pager for which it is a no-op, this
+-** function returns SQLITE_OK. Otherwise, an IO error code is returned.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
+-  int rc = SQLITE_OK;
+-  if( !pPager->noSync ){
+-    assert( !MEMDB );
+-    rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
+-  }else if( isOpen(pPager->fd) ){
++  if( pagerUseWal(pPager) ){
++    assert( rc==SQLITE_OK );
++    rc = pagerBeginReadTransaction(pPager);
++  }
++
++  if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
++    rc = pagerPagecount(pPager, &pPager->dbSize);
++  }
++
++ failed:
++  if( rc!=SQLITE_OK ){
+     assert( !MEMDB );
+-    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
+-    if( rc==SQLITE_NOTFOUND ){
+-      rc = SQLITE_OK;
+-    }
++    pager_unlock(pPager);
++    assert( pPager->eState==PAGER_OPEN );
++  }else{
++    pPager->eState = PAGER_READER;
+   }
+   return rc;
+ }
+ 
+ /*
+-** This function may only be called while a write-transaction is active in
+-** rollback. If the connection is in WAL mode, this call is a no-op. 
+-** Otherwise, if the connection does not already have an EXCLUSIVE lock on 
+-** the database file, an attempt is made to obtain one.
++** If the reference count has reached zero, rollback any active
++** transaction and unlock the pager.
+ **
+-** If the EXCLUSIVE lock is already held or the attempt to obtain it is
+-** successful, or the connection is in WAL mode, SQLITE_OK is returned.
+-** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is 
+-** returned.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
+-  int rc = SQLITE_OK;
+-  assert( pPager->eState==PAGER_WRITER_CACHEMOD 
+-       || pPager->eState==PAGER_WRITER_DBMOD 
+-       || pPager->eState==PAGER_WRITER_LOCKED 
+-  );
+-  assert( assert_pager_state(pPager) );
+-  if( 0==pagerUseWal(pPager) ){
+-    rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
++** Except, in locking_mode=EXCLUSIVE when there is nothing to in
++** the rollback journal, the unlock is not performed and there is
++** nothing to rollback, so this routine is a no-op.
++*/ 
++static void pagerUnlockIfUnused(Pager *pPager){
++  if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
++    pagerUnlockAndRollback(pPager);
+   }
+-  return rc;
+ }
+ 
+ /*
+-** Sync the database file for the pager pPager. zMaster points to the name
+-** of a master journal file that should be written into the individual
+-** journal file. zMaster may be NULL, which is interpreted as no master
+-** journal (a single database transaction).
++** Acquire a reference to page number pgno in pager pPager (a page
++** reference has type DbPage*). If the requested reference is 
++** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
+ **
+-** This routine ensures that:
++** If the requested page is already in the cache, it is returned. 
++** Otherwise, a new page object is allocated and populated with data
++** read from the database file. In some cases, the pcache module may
++** choose not to allocate a new page object and may reuse an existing
++** object with no outstanding references.
+ **
+-**   * The database file change-counter is updated,
+-**   * the journal is synced (unless the atomic-write optimization is used),
+-**   * all dirty pages are written to the database file, 
+-**   * the database file is truncated (if required), and
+-**   * the database file synced. 
++** The extra data appended to a page is always initialized to zeros the 
++** first time a page is loaded into memory. If the page requested is 
++** already in the cache when this function is called, then the extra
++** data is left as it was when the page object was last used.
+ **
+-** The only thing that remains to commit the transaction is to finalize 
+-** (delete, truncate or zero the first part of) the journal file (or 
+-** delete the master journal file if specified).
++** If the database image is smaller than the requested page or if a 
++** non-zero value is passed as the noContent parameter and the 
++** requested page is not already stored in the cache, then no 
++** actual disk read occurs. In this case the memory image of the 
++** page is initialized to all zeros. 
+ **
+-** Note that if zMaster==NULL, this does not overwrite a previous value
+-** passed to an sqlite3PagerCommitPhaseOne() call.
++** If noContent is true, it means that we do not care about the contents
++** of the page. This occurs in two seperate scenarios:
+ **
+-** If the final parameter - noSync - is true, then the database file itself
+-** is not synced. The caller must call sqlite3PagerSync() directly to
+-** sync the database file before calling CommitPhaseTwo() to delete the
+-** journal file in this case.
++**   a) When reading a free-list leaf page from the database, and
++**
++**   b) When a savepoint is being rolled back and we need to load
++**      a new page into the cache to be filled with the data read
++**      from the savepoint journal.
++**
++** If noContent is true, then the data returned is zeroed instead of
++** being read from the database. Additionally, the bits corresponding
++** to pgno in Pager.pInJournal (bitvec of pages already written to the
++** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
++** savepoints are set. This means if the page is made writable at any
++** point in the future, using a call to sqlite3PagerWrite(), its contents
++** will not be journaled. This saves IO.
++**
++** The acquisition might fail for several reasons.  In all cases,
++** an appropriate error code is returned and *ppPage is set to NULL.
++**
++** See also sqlite3PagerLookup().  Both this routine and Lookup() attempt
++** to find a page in the in-memory cache first.  If the page is not already
++** in memory, this routine goes to disk to read it in whereas Lookup()
++** just returns 0.  This routine acquires a read-lock the first time it
++** has to go to disk, and could also playback an old journal if necessary.
++** Since Lookup() never goes to disk, it never has to deal with locks
++** or journal files.
+ */
+-SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
+-  Pager *pPager,                  /* Pager object */
+-  const char *zMaster,            /* If not NULL, the master journal name */
+-  int noSync                      /* True to omit the xSync on the db file */
++SQLITE_PRIVATE int sqlite3PagerAcquire(
++  Pager *pPager,      /* The pager open on the database file */
++  Pgno pgno,          /* Page number to fetch */
++  DbPage **ppPage,    /* Write a pointer to the page here */
++  int flags           /* PAGER_ACQUIRE_XXX flags */
+ ){
+-  int rc = SQLITE_OK;             /* Return code */
++  int rc = SQLITE_OK;
++  PgHdr *pPg = 0;
++  u32 iFrame = 0;                 /* Frame to read from WAL file */
++  const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
+ 
+-  assert( pPager->eState==PAGER_WRITER_LOCKED
+-       || pPager->eState==PAGER_WRITER_CACHEMOD
+-       || pPager->eState==PAGER_WRITER_DBMOD
+-       || pPager->eState==PAGER_ERROR
++  /* It is acceptable to use a read-only (mmap) page for any page except
++  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
++  ** flag was specified by the caller. And so long as the db is not a 
++  ** temporary or in-memory database.  */
++  const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
++   && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
++#ifdef SQLITE_HAS_CODEC
++   && pPager->xCodec==0
++#endif
+   );
++
++  assert( pPager->eState>=PAGER_READER );
+   assert( assert_pager_state(pPager) );
++  assert( noContent==0 || bMmapOk==0 );
+ 
+-  /* If a prior error occurred, report that error again. */
+-  if( NEVER(pPager->errCode) ) return pPager->errCode;
++  if( pgno==0 ){
++    return SQLITE_CORRUPT_BKPT;
++  }
+ 
+-  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
+-      pPager->zFilename, zMaster, pPager->dbSize));
++  /* If the pager is in the error state, return an error immediately. 
++  ** Otherwise, request the page from the PCache layer. */
++  if( pPager->errCode!=SQLITE_OK ){
++    rc = pPager->errCode;
++  }else{
+ 
+-  /* If no database changes have been made, return early. */
+-  if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
++    if( bMmapOk && pagerUseWal(pPager) ){
++      rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
++      if( rc!=SQLITE_OK ) goto pager_acquire_err;
++    }
+ 
+-  if( MEMDB ){
+-    /* If this is an in-memory db, or no pages have been written to, or this
+-    ** function has already been called, it is mostly a no-op.  However, any
+-    ** backup in progress needs to be restarted.
+-    */
+-    sqlite3BackupRestart(pPager->pBackup);
+-  }else{
+-    if( pagerUseWal(pPager) ){
+-      PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
+-      PgHdr *pPageOne = 0;
+-      if( pList==0 ){
+-        /* Must have at least one page for the WAL commit flag.
+-        ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
+-        rc = sqlite3PagerGet(pPager, 1, &pPageOne);
+-        pList = pPageOne;
+-        pList->pDirty = 0;
+-      }
+-      assert( rc==SQLITE_OK );
+-      if( ALWAYS(pList) ){
+-        rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
+-      }
+-      sqlite3PagerUnref(pPageOne);
+-      if( rc==SQLITE_OK ){
+-        sqlite3PcacheCleanAll(pPager->pPCache);
+-      }
+-    }else{
+-      /* The following block updates the change-counter. Exactly how it
+-      ** does this depends on whether or not the atomic-update optimization
+-      ** was enabled at compile time, and if this transaction meets the 
+-      ** runtime criteria to use the operation: 
+-      **
+-      **    * The file-system supports the atomic-write property for
+-      **      blocks of size page-size, and 
+-      **    * This commit is not part of a multi-file transaction, and
+-      **    * Exactly one page has been modified and store in the journal file.
+-      **
+-      ** If the optimization was not enabled at compile time, then the
+-      ** pager_incr_changecounter() function is called to update the change
+-      ** counter in 'indirect-mode'. If the optimization is compiled in but
+-      ** is not applicable to this transaction, call sqlite3JournalCreate()
+-      ** to make sure the journal file has actually been created, then call
+-      ** pager_incr_changecounter() to update the change-counter in indirect
+-      ** mode. 
+-      **
+-      ** Otherwise, if the optimization is both enabled and applicable,
+-      ** then call pager_incr_changecounter() to update the change-counter
+-      ** in 'direct' mode. In this case the journal file will never be
+-      ** created for this transaction.
+-      */
+-  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
+-      PgHdr *pPg;
+-      assert( isOpen(pPager->jfd) 
+-           || pPager->journalMode==PAGER_JOURNALMODE_OFF 
+-           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
++    if( iFrame==0 && bMmapOk ){
++      void *pData = 0;
 +
++      rc = sqlite3OsFetch(pPager->fd, 
++          (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
+       );
+-      if( !zMaster && isOpen(pPager->jfd) 
+-       && pPager->journalOff==jrnlBufferSize(pPager) 
+-       && pPager->dbSize>=pPager->dbOrigSize
+-       && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
+-      ){
+-        /* Update the db file change counter via the direct-write method. The 
+-        ** following call will modify the in-memory representation of page 1 
+-        ** to include the updated change counter and then write page 1 
+-        ** directly to the database file. Because of the atomic-write 
+-        ** property of the host file-system, this is safe.
+-        */
+-        rc = pager_incr_changecounter(pPager, 1);
+-      }else{
+-        rc = sqlite3JournalCreate(pPager->jfd);
+-        if( rc==SQLITE_OK ){
+-          rc = pager_incr_changecounter(pPager, 0);
 +
- /************** End of pager.c ***********************************************/
- /************** Begin file wal.c *********************************************/
++      if( rc==SQLITE_OK && pData ){
++        if( pPager->eState>PAGER_READER ){
++          (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
++        }
++        if( pPg==0 ){
++          rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
++        }else{
++          sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
++        }
++        if( pPg ){
++          assert( rc==SQLITE_OK );
++          *ppPage = pPg;
++          return SQLITE_OK;
+         }
+       }
+-  #else
+-      rc = pager_incr_changecounter(pPager, 0);
+-  #endif
+-      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+-  
+-      /* Write the master journal name into the journal file. If a master 
+-      ** journal file name has already been written to the journal file, 
+-      ** or if zMaster is NULL (no master journal), then this call is a no-op.
+-      */
+-      rc = writeMasterJournal(pPager, zMaster);
+-      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+-  
+-      /* Sync the journal file and write all dirty pages to the database.
+-      ** If the atomic-update optimization is being used, this sync will not 
+-      ** create the journal file or perform any real IO.
+-      **
+-      ** Because the change-counter page was just modified, unless the
+-      ** atomic-update optimization is used it is almost certain that the
+-      ** journal requires a sync here. However, in locking_mode=exclusive
+-      ** on a system under memory pressure it is just possible that this is 
+-      ** not the case. In this case it is likely enough that the redundant
+-      ** xSync() call will be changed to a no-op by the OS anyhow. 
+-      */
+-      rc = syncJournal(pPager, 0);
+-      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+-  
+-      rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
+       if( rc!=SQLITE_OK ){
+-        assert( rc!=SQLITE_IOERR_BLOCKED );
+-        goto commit_phase_one_exit;
++        goto pager_acquire_err;
+       }
+-      sqlite3PcacheCleanAll(pPager->pPCache);
++    }
+ 
+-      /* If the file on disk is smaller than the database image, use 
+-      ** pager_truncate to grow the file here. This can happen if the database
+-      ** image was extended as part of the current transaction and then the
+-      ** last page in the db image moved to the free-list. In this case the
+-      ** last page is never written out to disk, leaving the database file
+-      ** undersized. Fix this now if it is the case.  */
+-      if( pPager->dbSize>pPager->dbFileSize ){
+-        Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
+-        assert( pPager->eState==PAGER_WRITER_DBMOD );
+-        rc = pager_truncate(pPager, nNew);
+-        if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
++    rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
++  }
++
++  if( rc!=SQLITE_OK ){
++    /* Either the call to sqlite3PcacheFetch() returned an error or the
++    ** pager was already in the error-state when this function was called.
++    ** Set pPg to 0 and jump to the exception handler.  */
++    pPg = 0;
++    goto pager_acquire_err;
++  }
++  assert( (*ppPage)->pgno==pgno );
++  assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
++
++  if( (*ppPage)->pPager && !noContent ){
++    /* In this case the pcache already contains an initialized copy of
++    ** the page. Return without further ado.  */
++    assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
++    pPager->aStat[PAGER_STAT_HIT]++;
++    return SQLITE_OK;
++
++  }else{
++    /* The pager cache has created a new page. Its content needs to 
++    ** be initialized.  */
++
++    pPg = *ppPage;
++    pPg->pPager = pPager;
++
++    /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
++    ** number greater than this, or the unused locking-page, is requested. */
++    if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
++      rc = SQLITE_CORRUPT_BKPT;
++      goto pager_acquire_err;
++    }
++
++    if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
++      if( pgno>pPager->mxPgno ){
++        rc = SQLITE_FULL;
++        goto pager_acquire_err;
+       }
+-  
+-      /* Finally, sync the database file. */
+-      if( !noSync ){
+-        rc = sqlite3PagerSync(pPager);
++      if( noContent ){
++        /* Failure to set the bits in the InJournal bit-vectors is benign.
++        ** It merely means that we might do some extra work to journal a 
++        ** page that does not need to be journaled.  Nevertheless, be sure 
++        ** to test the case where a malloc error occurs while trying to set 
++        ** a bit in a bit vector.
++        */
++        sqlite3BeginBenignMalloc();
++        if( pgno<=pPager->dbOrigSize ){
++          TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
++          testcase( rc==SQLITE_NOMEM );
++        }
++        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
++        testcase( rc==SQLITE_NOMEM );
++        sqlite3EndBenignMalloc();
++      }
++      memset(pPg->pData, 0, pPager->pageSize);
++      IOTRACE(("ZERO %p %d\n", pPager, pgno));
++    }else{
++      if( pagerUseWal(pPager) && bMmapOk==0 ){
++        rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
++        if( rc!=SQLITE_OK ) goto pager_acquire_err;
++      }
++      assert( pPg->pPager==pPager );
++      pPager->aStat[PAGER_STAT_MISS]++;
++      rc = readDbPage(pPg, iFrame);
++      if( rc!=SQLITE_OK ){
++        goto pager_acquire_err;
+       }
+-      IOTRACE(("DBSYNC %p\n", pPager))
+     }
++    pager_set_pagehash(pPg);
+   }
+ 
+-commit_phase_one_exit:
+-  if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
+-    pPager->eState = PAGER_WRITER_FINISHED;
++  return SQLITE_OK;
++
++pager_acquire_err:
++  assert( rc!=SQLITE_OK );
++  if( pPg ){
++    sqlite3PcacheDrop(pPg);
+   }
++  pagerUnlockIfUnused(pPager);
++
++  *ppPage = 0;
+   return rc;
+ }
+ 
+-
+ /*
+-** When this function is called, the database file has been completely
+-** updated to reflect the changes made by the current transaction and
+-** synced to disk. The journal file still exists in the file-system 
+-** though, and if a failure occurs at this point it will eventually
+-** be used as a hot-journal and the current transaction rolled back.
+-**
+-** This function finalizes the journal file, either by deleting, 
+-** truncating or partially zeroing it, so that it cannot be used 
+-** for hot-journal rollback. Once this is done the transaction is
+-** irrevocably committed.
++** Acquire a page if it is already in the in-memory cache.  Do
++** not read the page from disk.  Return a pointer to the page,
++** or 0 if the page is not in cache. 
+ **
+-** If an error occurs, an IO error code is returned and the pager
+-** moves into the error state. Otherwise, SQLITE_OK is returned.
++** See also sqlite3PagerGet().  The difference between this routine
++** and sqlite3PagerGet() is that _get() will go to the disk and read
++** in the page if the page is not already in cache.  This routine
++** returns NULL if the page is not in cache or if a disk I/O error 
++** has ever happened.
+ */
+-SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
+-  int rc = SQLITE_OK;                  /* Return code */
+-
+-  /* This routine should not be called if a prior error has occurred.
+-  ** But if (due to a coding error elsewhere in the system) it does get
+-  ** called, just return the same error code without doing anything. */
+-  if( NEVER(pPager->errCode) ) return pPager->errCode;
+-
+-  assert( pPager->eState==PAGER_WRITER_LOCKED
+-       || pPager->eState==PAGER_WRITER_FINISHED
+-       || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
+-  );
+-  assert( assert_pager_state(pPager) );
++SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
++  PgHdr *pPg = 0;
++  assert( pPager!=0 );
++  assert( pgno!=0 );
++  assert( pPager->pPCache!=0 );
++  assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR );
++  sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
++  return pPg;
++}
+ 
+-  /* An optimization. If the database was not actually modified during
+-  ** this transaction, the pager is running in exclusive-mode and is
+-  ** using persistent journals, then this function is a no-op.
+-  **
+-  ** The start of the journal file currently contains a single journal 
+-  ** header with the nRec field set to 0. If such a journal is used as
+-  ** a hot-journal during hot-journal rollback, 0 changes will be made
+-  ** to the database file. So there is no need to zero the journal 
+-  ** header. Since the pager is in exclusive mode, there is no need
+-  ** to drop any locks either.
+-  */
+-  if( pPager->eState==PAGER_WRITER_LOCKED 
+-   && pPager->exclusiveMode 
+-   && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+-  ){
+-    assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
+-    pPager->eState = PAGER_READER;
+-    return SQLITE_OK;
++/*
++** Release a page reference.
++**
++** If the number of references to the page drop to zero, then the
++** page is added to the LRU list.  When all references to all pages
++** are released, a rollback occurs and the lock on the database is
++** removed.
++*/
++SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
++  if( pPg ){
++    Pager *pPager = pPg->pPager;
++    if( pPg->flags & PGHDR_MMAP ){
++      pagerReleaseMapPage(pPg);
++    }else{
++      sqlite3PcacheRelease(pPg);
++    }
++    pagerUnlockIfUnused(pPager);
+   }
+-
+-  PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
+-  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
+-  return pager_error(pPager, rc);
+ }
+ 
  /*
-@@ -44127,3533 +46473,2869 @@
- ** that correspond to frames greater than the new K value are removed
- ** from the hash table at this point.
+-** If a write transaction is open, then all changes made within the 
+-** transaction are reverted and the current write-transaction is closed.
+-** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
+-** state if an error occurs.
+-**
+-** If the pager is already in PAGER_ERROR state when this function is called,
+-** it returns Pager.errCode immediately. No work is performed in this case.
+-**
+-** Otherwise, in rollback mode, this function performs two functions:
++** This function is called at the start of every write transaction.
++** There must already be a RESERVED or EXCLUSIVE lock on the database 
++** file when this routine is called.
+ **
+-**   1) It rolls back the journal file, restoring all database file and 
+-**      in-memory cache pages to the state they were in when the transaction
+-**      was opened, and
++** Open the journal file for pager pPager and write a journal header
++** to the start of it. If there are active savepoints, open the sub-journal
++** as well. This function is only used when the journal file is being 
++** opened to write a rollback log for a transaction. It is not used 
++** when opening a hot journal file to roll it back.
+ **
+-**   2) It finalizes the journal file, so that it is not used for hot
+-**      rollback at any point in the future.
++** If the journal file is already open (as it may be in exclusive mode),
++** then this function just writes a journal header to the start of the
++** already open file. 
+ **
+-** Finalization of the journal file (task 2) is only performed if the 
+-** rollback is successful.
++** Whether or not the journal file is opened by this function, the
++** Pager.pInJournal bitvec structure is allocated.
+ **
+-** In WAL mode, all cache-entries containing data modified within the
+-** current transaction are either expelled from the cache or reverted to
+-** their pre-transaction state by re-reading data from the database or
+-** WAL files. The WAL transaction is then closed.
++** Return SQLITE_OK if everything is successful. Otherwise, return 
++** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or 
++** an IO error code if opening or writing the journal file fails.
  */
+-SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
+-  int rc = SQLITE_OK;                  /* Return code */
+-  PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
++static int pager_open_journal(Pager *pPager){
++  int rc = SQLITE_OK;                        /* Return code */
++  sqlite3_vfs * const pVfs = pPager->pVfs;   /* Local cache of vfs pointer */
+ 
+-  /* PagerRollback() is a no-op if called in READER or OPEN state. If
+-  ** the pager is already in the ERROR state, the rollback is not 
+-  ** attempted here. Instead, the error code is returned to the caller.
+-  */
++  assert( pPager->eState==PAGER_WRITER_LOCKED );
+   assert( assert_pager_state(pPager) );
+-  if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
+-  if( pPager->eState<=PAGER_READER ) return SQLITE_OK;
++  assert( pPager->pInJournal==0 );
++  
++  /* If already in the error state, this function is a no-op.  But on
++  ** the other hand, this routine is never called if we are already in
++  ** an error state. */
++  if( NEVER(pPager->errCode) ) return pPager->errCode;
+ 
+-  if( pagerUseWal(pPager) ){
+-    int rc2;
+-    rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
+-    rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
+-    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, 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;
++  if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
++    pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
++    if( pPager->pInJournal==0 ){
++      return SQLITE_NOMEM;
++    }
++  
++    /* Open the journal file if it is not already open. */
++    if( !isOpen(pPager->jfd) ){
++      if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
++        sqlite3MemJournalOpen(pPager->jfd);
++      }else{
++        const int flags =                   /* VFS flags to open journal file */
++          SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
++          (pPager->tempFile ? 
++            (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
++            (SQLITE_OPEN_MAIN_JOURNAL)
++          );
++  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
++        rc = sqlite3JournalOpen(
++            pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
++        );
++  #else
++        rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
++  #endif
++      }
++      assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
++    }
++  
++  
++    /* Write the first journal header to the journal file and open 
++    ** the sub-journal if necessary.
++    */
++    if( rc==SQLITE_OK ){
++      /* TODO: Check if all of these are really required. */
++      pPager->nRec = 0;
++      pPager->journalOff = 0;
++      pPager->setMaster = 0;
++      pPager->journalHdr = 0;
++      rc = writeJournalHdr(pPager);
+     }
+-  }else{
+-    rc = pager_playback(pPager, 0);
+   }
+ 
+-  assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
+-  assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
+-          || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
++  if( rc!=SQLITE_OK ){
++    sqlite3BitvecDestroy(pPager->pInJournal);
++    pPager->pInJournal = 0;
++  }else{
++    assert( pPager->eState==PAGER_WRITER_LOCKED );
++    pPager->eState = PAGER_WRITER_CACHEMOD;
++  }
+ 
+-  /* If an error occurs during a ROLLBACK, we can no longer trust the pager
+-  ** cache. So call pager_error() on the way out to make any error persistent.
+-  */
+-  return pager_error(pPager, rc);
++  return rc;
+ }
+ 
+ /*
+-** Return TRUE if the database file is opened read-only.  Return FALSE
+-** if the database is (in theory) writable.
++** Begin a write-transaction on the specified pager object. If a 
++** write-transaction has already been opened, this function is a no-op.
++**
++** If the exFlag argument is false, then acquire at least a RESERVED
++** lock on the database file. If exFlag is true, then acquire at least
++** an EXCLUSIVE lock. If such a lock is already held, no locking 
++** functions need be called.
++**
++** If the subjInMemory argument is non-zero, then any sub-journal opened
++** within this transaction will be opened as an in-memory file. This
++** has no effect if the sub-journal is already opened (as it may be when
++** running in exclusive mode) or if the transaction does not require a
++** sub-journal. If the subjInMemory argument is zero, then any required
++** sub-journal is implemented in-memory if pPager is an in-memory database, 
++** or using a temporary file otherwise.
+ */
+-SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){
+-  return pPager->readOnly;
+-}
++SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
++  int rc = SQLITE_OK;
+ 
+-/*
+-** Return the number of references to the pager.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
+-  return sqlite3PcacheRefCount(pPager->pPCache);
+-}
++  if( pPager->errCode ) return pPager->errCode;
++  assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
++  pPager->subjInMemory = (u8)subjInMemory;
+ 
+-/*
+-** Return the approximate number of bytes of memory currently
+-** used by the pager and its associated cache.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){
+-  int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
+-                                     + 5*sizeof(void*);
+-  return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
+-           + sqlite3MallocSize(pPager)
+-           + pPager->pageSize;
+-}
++  if( ALWAYS(pPager->eState==PAGER_READER) ){
++    assert( pPager->pInJournal==0 );
+ 
+-/*
+-** Return the number of references to the specified page.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
+-  return sqlite3PcachePageRefcount(pPage);
+-}
++    if( pagerUseWal(pPager) ){
++      /* If the pager is configured to use locking_mode=exclusive, and an
++      ** exclusive lock on the database is not already held, obtain it now.
++      */
++      if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
++        rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
++        if( rc!=SQLITE_OK ){
++          return rc;
++        }
++        sqlite3WalExclusiveMode(pPager->pWal, 1);
++      }
+ 
+-#ifdef SQLITE_TEST
+-/*
+-** This routine is used for testing and analysis only.
+-*/
+-SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
+-  static int a[11];
+-  a[0] = sqlite3PcacheRefCount(pPager->pPCache);
+-  a[1] = sqlite3PcachePagecount(pPager->pPCache);
+-  a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
+-  a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
+-  a[4] = pPager->eState;
+-  a[5] = pPager->errCode;
+-  a[6] = pPager->aStat[PAGER_STAT_HIT];
+-  a[7] = pPager->aStat[PAGER_STAT_MISS];
+-  a[8] = 0;  /* Used to be pPager->nOvfl */
+-  a[9] = pPager->nRead;
+-  a[10] = pPager->aStat[PAGER_STAT_WRITE];
+-  return a;
++      /* Grab the write lock on the log file. If successful, upgrade to
++      ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
++      ** The busy-handler is not invoked if another connection already
++      ** holds the write-lock. If possible, the upper layer will call it.
++      */
++      rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
++    }else{
++      /* Obtain a RESERVED lock on the database file. If the exFlag parameter
++      ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
++      ** busy-handler callback can be used when upgrading to the EXCLUSIVE
++      ** lock, but not when obtaining the RESERVED lock.
++      */
++      rc = pagerLockDb(pPager, RESERVED_LOCK);
++      if( rc==SQLITE_OK && exFlag ){
++        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
++      }
++    }
++
++    if( rc==SQLITE_OK ){
++      /* Change to WRITER_LOCKED state.
++      **
++      ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
++      ** when it has an open transaction, but never to DBMOD or FINISHED.
++      ** This is because in those states the code to roll back savepoint 
++      ** transactions may copy data from the sub-journal into the database 
++      ** file as well as into the page cache. Which would be incorrect in 
++      ** WAL mode.
++      */
++      pPager->eState = PAGER_WRITER_LOCKED;
++      pPager->dbHintSize = pPager->dbSize;
++      pPager->dbFileSize = pPager->dbSize;
++      pPager->dbOrigSize = pPager->dbSize;
++      pPager->journalOff = 0;
++    }
++
++    assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
++    assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
++    assert( assert_pager_state(pPager) );
++  }
++
++  PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
++  return rc;
+ }
+-#endif
+ 
+ /*
+-** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
+-** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
+-** current cache hit or miss count, according to the value of eStat. If the 
+-** reset parameter is non-zero, the cache hit or miss count is zeroed before 
+-** returning.
++** Mark a single data page as writeable. The page is written into the 
++** main journal or sub-journal as required. If the page is written into
++** one of the journals, the corresponding bit is set in the 
++** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
++** of any open savepoints as appropriate.
+ */
+-SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
++static int pager_write(PgHdr *pPg){
++  void *pData = pPg->pData;
++  Pager *pPager = pPg->pPager;
++  int rc = SQLITE_OK;
+ 
+-  assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
+-       || eStat==SQLITE_DBSTATUS_CACHE_MISS
+-       || eStat==SQLITE_DBSTATUS_CACHE_WRITE
++  /* This routine is not called unless a write-transaction has already 
++  ** been started. The journal file may or may not be open at this point.
++  ** It is never called in the ERROR state.
++  */
++  assert( pPager->eState==PAGER_WRITER_LOCKED
++       || pPager->eState==PAGER_WRITER_CACHEMOD
++       || pPager->eState==PAGER_WRITER_DBMOD
+   );
++  assert( assert_pager_state(pPager) );
+ 
+-  assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
+-  assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
+-  assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
++  /* If an error has been previously detected, report the same error
++  ** again. This should not happen, but the check provides robustness. */
++  if( NEVER(pPager->errCode) )  return pPager->errCode;
+ 
+-  *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
+-  if( reset ){
+-    pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
++  /* Higher-level routines never call this function if database is not
++  ** writable.  But check anyway, just for robustness. */
++  if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
++
++  CHECK_PAGE(pPg);
++
++  /* The journal file needs to be opened. Higher level routines have already
++  ** obtained the necessary locks to begin the write-transaction, but the
++  ** rollback journal might not yet be open. Open it now if this is the case.
++  **
++  ** This is done before calling sqlite3PcacheMakeDirty() on the page. 
++  ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
++  ** an error might occur and the pager would end up in WRITER_LOCKED state
++  ** with pages marked as dirty in the cache.
++  */
++  if( pPager->eState==PAGER_WRITER_LOCKED ){
++    rc = pager_open_journal(pPager);
++    if( rc!=SQLITE_OK ) return rc;
+   }
+-}
++  assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
++  assert( assert_pager_state(pPager) );
+ 
+-/*
+-** Return true if this is an in-memory pager.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
+-  return MEMDB;
+-}
++  /* Mark the page as dirty.  If the page has already been written
++  ** to the journal then we can return right away.
++  */
++  sqlite3PcacheMakeDirty(pPg);
++  if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
++    assert( !pagerUseWal(pPager) );
++  }else{
++  
++    /* The transaction journal now exists and we have a RESERVED or an
++    ** EXCLUSIVE lock on the main database file.  Write the current page to
++    ** the transaction journal if it is not there already.
++    */
++    if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
++      assert( pagerUseWal(pPager)==0 );
++      if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
++        u32 cksum;
++        char *pData2;
++        i64 iOff = pPager->journalOff;
+ 
+-/*
+-** Check that there are at least nSavepoint savepoints open. If there are
+-** currently less than nSavepoints open, then open one or more savepoints
+-** to make up the difference. If the number of savepoints is already
+-** equal to nSavepoint, then this function is a no-op.
+-**
+-** If a memory allocation fails, SQLITE_NOMEM is returned. If an error 
+-** occurs while opening the sub-journal file, then an IO error code is
+-** returned. Otherwise, SQLITE_OK.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
+-  int rc = SQLITE_OK;                       /* Return code */
+-  int nCurrent = pPager->nSavepoint;        /* Current number of savepoints */
++        /* We should never write to the journal file the page that
++        ** contains the database locks.  The following assert verifies
++        ** that we do not. */
++        assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
+ 
+-  assert( pPager->eState>=PAGER_WRITER_LOCKED );
+-  assert( assert_pager_state(pPager) );
++        assert( pPager->journalHdr<=pPager->journalOff );
++        CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
++        cksum = pager_cksum(pPager, (u8*)pData2);
+ 
+-  if( nSavepoint>nCurrent && pPager->useJournal ){
+-    int ii;                                 /* Iterator variable */
+-    PagerSavepoint *aNew;                   /* New Pager.aSavepoint array */
++        /* Even if an IO or diskfull error occurs while journalling the
++        ** page in the block above, set the need-sync flag for the page.
++        ** Otherwise, when the transaction is rolled back, the logic in
++        ** playback_one_page() will think that the page needs to be restored
++        ** in the database file. And if an IO error occurs while doing so,
++        ** then corruption may follow.
++        */
++        pPg->flags |= PGHDR_NEED_SYNC;
+ 
+-    /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
+-    ** if the allocation fails. Otherwise, zero the new portion in case a 
+-    ** malloc failure occurs while populating it in the for(...) loop below.
+-    */
+-    aNew = (PagerSavepoint *)sqlite3Realloc(
+-        pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
+-    );
+-    if( !aNew ){
+-      return SQLITE_NOMEM;
+-    }
+-    memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
+-    pPager->aSavepoint = aNew;
++        rc = write32bits(pPager->jfd, iOff, pPg->pgno);
++        if( rc!=SQLITE_OK ) return rc;
++        rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
++        if( rc!=SQLITE_OK ) return rc;
++        rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
++        if( rc!=SQLITE_OK ) return rc;
+ 
+-    /* Populate the PagerSavepoint structures just allocated. */
+-    for(ii=nCurrent; ii<nSavepoint; ii++){
+-      aNew[ii].nOrig = pPager->dbSize;
+-      if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
+-        aNew[ii].iOffset = pPager->journalOff;
++        IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 
++                 pPager->journalOff, pPager->pageSize));
++        PAGER_INCR(sqlite3_pager_writej_count);
++        PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
++             PAGERID(pPager), pPg->pgno, 
++             ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
++
++        pPager->journalOff += 8 + pPager->pageSize;
++        pPager->nRec++;
++        assert( pPager->pInJournal!=0 );
++        rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
++        testcase( rc==SQLITE_NOMEM );
++        assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
++        rc |= addToSavepointBitvecs(pPager, pPg->pgno);
++        if( rc!=SQLITE_OK ){
++          assert( rc==SQLITE_NOMEM );
++          return rc;
++        }
+       }else{
+-        aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
+-      }
+-      aNew[ii].iSubRec = pPager->nSubRec;
+-      aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
+-      if( !aNew[ii].pInSavepoint ){
+-        return SQLITE_NOMEM;
+-      }
+-      if( pagerUseWal(pPager) ){
+-        sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
++        if( pPager->eState!=PAGER_WRITER_DBMOD ){
++          pPg->flags |= PGHDR_NEED_SYNC;
++        }
++        PAGERTRACE(("APPEND %d page %d needSync=%d\n",
++                PAGERID(pPager), pPg->pgno,
++               ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
+       }
+-      pPager->nSavepoint = ii+1;
+     }
+-    assert( pPager->nSavepoint==nSavepoint );
+-    assertTruncateConstraint(pPager);
++  
++    /* If the statement journal is open and the page is not in it,
++    ** then write the current page to the statement journal.  Note that
++    ** the statement journal format differs from the standard journal format
++    ** in that it omits the checksums and the header.
++    */
++    if( subjRequiresPage(pPg) ){
++      rc = subjournalPage(pPg);
++    }
+   }
+ 
++  /* Update the database size and return.
++  */
++  if( pPager->dbSize<pPg->pgno ){
++    pPager->dbSize = pPg->pgno;
++  }
+   return rc;
+ }
+ 
+ /*
+-** This function is called to rollback or release (commit) a savepoint.
+-** The savepoint to release or rollback need not be the most recently 
+-** created savepoint.
+-**
+-** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
+-** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
+-** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
+-** that have occurred since the specified savepoint was created.
+-**
+-** The savepoint to rollback or release is identified by parameter 
+-** iSavepoint. A value of 0 means to operate on the outermost savepoint
+-** (the first created). A value of (Pager.nSavepoint-1) means operate
+-** on the most recently created savepoint. If iSavepoint is greater than
+-** (Pager.nSavepoint-1), then this function is a no-op.
+-**
+-** If a negative value is passed to this function, then the current
+-** transaction is rolled back. This is different to calling 
+-** sqlite3PagerRollback() because this function does not terminate
+-** the transaction or unlock the database, it just restores the 
+-** contents of the database to its original state. 
++** Mark a data page as writeable. This routine must be called before 
++** making changes to a page. The caller must check the return value 
++** of this function and be careful not to change any page data unless 
++** this routine returns SQLITE_OK.
+ **
+-** In any case, all savepoints with an index greater than iSavepoint 
+-** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
+-** then savepoint iSavepoint is also destroyed.
++** The difference between this function and pager_write() is that this
++** function also deals with the special case where 2 or more pages
++** fit on a single disk sector. In this case all co-resident pages
++** must have been written to the journal file before returning.
+ **
+-** This function may return SQLITE_NOMEM if a memory allocation fails,
+-** or an IO error code if an IO error occurs while rolling back a 
+-** savepoint. If no errors occur, SQLITE_OK is returned.
+-*/ 
+-SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
+-  int rc = pPager->errCode;       /* Return code */
++** If an error occurs, SQLITE_NOMEM or an IO error code is returned
++** as appropriate. Otherwise, SQLITE_OK.
++*/
++SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
++  int rc = SQLITE_OK;
+ 
+-  assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
+-  assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
++  PgHdr *pPg = pDbPage;
++  Pager *pPager = pPg->pPager;
++  Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
+ 
+-  if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
+-    int ii;            /* Iterator variable */
+-    int nNew;          /* Number of remaining savepoints after this op. */
++  assert( (pPg->flags & PGHDR_MMAP)==0 );
++  assert( pPager->eState>=PAGER_WRITER_LOCKED );
++  assert( pPager->eState!=PAGER_ERROR );
++  assert( assert_pager_state(pPager) );
++
++  if( nPagePerSector>1 ){
++    Pgno nPageCount;          /* Total number of pages in database file */
++    Pgno pg1;                 /* First page of the sector pPg is located on. */
++    int nPage = 0;            /* Number of pages starting at pg1 to journal */
++    int ii;                   /* Loop counter */
++    int needSync = 0;         /* True if any page has PGHDR_NEED_SYNC */
++
++    /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
++    ** a journal header to be written between the pages journaled by
++    ** this function.
++    */
++    assert( !MEMDB );
++    assert( pPager->doNotSyncSpill==0 );
++    pPager->doNotSyncSpill++;
+ 
+-    /* Figure out how many savepoints will still be active after this
+-    ** operation. Store this value in nNew. Then free resources associated 
+-    ** with any savepoints that are destroyed by this operation.
++    /* This trick assumes that both the page-size and sector-size are
++    ** an integer power of 2. It sets variable pg1 to the identifier
++    ** of the first page of the sector pPg is located on.
+     */
+-    nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
+-    for(ii=nNew; ii<pPager->nSavepoint; ii++){
+-      sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
++    pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
++
++    nPageCount = pPager->dbSize;
++    if( pPg->pgno>nPageCount ){
++      nPage = (pPg->pgno - pg1)+1;
++    }else if( (pg1+nPagePerSector-1)>nPageCount ){
++      nPage = nPageCount+1-pg1;
++    }else{
++      nPage = nPagePerSector;
+     }
+-    pPager->nSavepoint = nNew;
++    assert(nPage>0);
++    assert(pg1<=pPg->pgno);
++    assert((pg1+nPage)>pPg->pgno);
+ 
+-    /* If this is a release of the outermost savepoint, truncate 
+-    ** the sub-journal to zero bytes in size. */
+-    if( op==SAVEPOINT_RELEASE ){
+-      if( nNew==0 && isOpen(pPager->sjfd) ){
+-        /* Only truncate if it is an in-memory sub-journal. */
+-        if( sqlite3IsMemJournal(pPager->sjfd) ){
+-          rc = sqlite3OsTruncate(pPager->sjfd, 0);
+-          assert( rc==SQLITE_OK );
++    for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
++      Pgno pg = pg1+ii;
++      PgHdr *pPage;
++      if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
++        if( pg!=PAGER_MJ_PGNO(pPager) ){
++          rc = sqlite3PagerGet(pPager, pg, &pPage);
++          if( rc==SQLITE_OK ){
++            rc = pager_write(pPage);
++            if( pPage->flags&PGHDR_NEED_SYNC ){
++              needSync = 1;
++            }
++            sqlite3PagerUnref(pPage);
++          }
+         }
+-        pPager->nSubRec = 0;
++      }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
++        if( pPage->flags&PGHDR_NEED_SYNC ){
++          needSync = 1;
++        }
++        sqlite3PagerUnref(pPage);
+       }
+     }
+-    /* Else this is a rollback operation, playback the specified savepoint.
+-    ** If this is a temp-file, it is possible that the journal file has
+-    ** not yet been opened. In this case there have been no changes to
+-    ** the database file, so the playback operation can be skipped.
++
++    /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages 
++    ** starting at pg1, then it needs to be set for all of them. Because
++    ** writing to any of these nPage pages may damage the others, the
++    ** journal file must contain sync()ed copies of all of them
++    ** before any of them can be written out to the database file.
+     */
+-    else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
+-      PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
+-      rc = pagerPlaybackSavepoint(pPager, pSavepoint);
+-      assert(rc!=SQLITE_DONE);
++    if( rc==SQLITE_OK && needSync ){
++      assert( !MEMDB );
++      for(ii=0; ii<nPage; ii++){
++        PgHdr *pPage = pager_lookup(pPager, pg1+ii);
++        if( pPage ){
++          pPage->flags |= PGHDR_NEED_SYNC;
++          sqlite3PagerUnref(pPage);
++        }
++      }
+     }
+-  }
+ 
++    assert( pPager->doNotSyncSpill==1 );
++    pPager->doNotSyncSpill--;
++  }else{
++    rc = pager_write(pDbPage);
++  }
+   return rc;
+ }
+ 
+ /*
+-** Return the full pathname of the database file.
+-**
+-** Except, if the pager is in-memory only, then return an empty string if
+-** nullIfMemDb is true.  This routine is called with nullIfMemDb==1 when
+-** used to report the filename to the user, for compatibility with legacy
+-** behavior.  But when the Btree needs to know the filename for matching to
+-** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
+-** participate in shared-cache.
++** Return TRUE if the page given in the argument was previously passed
++** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
++** to change the content of the page.
+ */
+-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
+-  return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
++#ifndef NDEBUG
++SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
++  return pPg->flags&PGHDR_DIRTY;
+ }
++#endif
+ 
+ /*
+-** Return the VFS structure for the pager.
++** A call to this routine tells the pager that it is not necessary to
++** write the information on page pPg back to the disk, even though
++** that page might be marked as dirty.  This happens, for example, when
++** the page has been added as a leaf of the freelist and so its
++** content no longer matters.
++**
++** The overlying software layer calls this routine when all of the data
++** on the given page is unused. The pager marks the page as clean so
++** that it does not get written to disk.
++**
++** Tests show that this optimization can quadruple the speed of large 
++** DELETE operations.
+ */
+-SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
+-  return pPager->pVfs;
++SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
++  Pager *pPager = pPg->pPager;
++  if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
++    PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
++    IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
++    pPg->flags |= PGHDR_DONT_WRITE;
++    pager_set_pagehash(pPg);
++  }
+ }
+ 
+ /*
+-** Return the file handle for the database file associated
+-** with the pager.  This might return NULL if the file has
+-** not yet been opened.
++** 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.  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
++** page data. In this case the file will be updated when the current
++** transaction is committed.
++**
++** The isDirectMode flag may only be non-zero if the library was compiled
++** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
++** if isDirect is non-zero, then the database file is updated directly
++** by writing an updated version of page 1 using a call to the 
++** sqlite3OsWrite() function.
+ */
+-SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
+-  return pPager->fd;
+-}
++static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
++  int rc = SQLITE_OK;
+ 
+-/*
+-** Return the full pathname of the journal file.
+-*/
+-SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
+-  return pPager->zJournal;
++  assert( pPager->eState==PAGER_WRITER_CACHEMOD
++       || pPager->eState==PAGER_WRITER_DBMOD
++  );
++  assert( assert_pager_state(pPager) );
++
++  /* Declare and initialize constant integer 'isDirect'. If the
++  ** atomic-write optimization is enabled in this build, then isDirect
++  ** is initialized to the value passed as the isDirectMode parameter
++  ** to this function. Otherwise, it is always set to zero.
++  **
++  ** The idea is that if the atomic-write optimization is not
++  ** enabled at compile time, the compiler can omit the tests of
++  ** 'isDirect' below, as well as the block enclosed in the
++  ** "if( isDirect )" condition.
++  */
++#ifndef SQLITE_ENABLE_ATOMIC_WRITE
++# define DIRECT_MODE 0
++  assert( isDirectMode==0 );
++  UNUSED_PARAMETER(isDirectMode);
++#else
++# define DIRECT_MODE isDirectMode
++#endif
++
++  if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
++    PgHdr *pPgHdr;                /* Reference to page 1 */
++
++    assert( !pPager->tempFile && isOpen(pPager->fd) );
++
++    /* Open page 1 of the file for writing. */
++    rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
++    assert( pPgHdr==0 || rc==SQLITE_OK );
++
++    /* If page one was fetched successfully, and this function is not
++    ** operating in direct-mode, make page 1 writable.  When not in 
++    ** direct mode, page 1 is always held in cache and hence the PagerGet()
++    ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
++    */
++    if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
++      rc = sqlite3PagerWrite(pPgHdr);
++    }
++
++    if( rc==SQLITE_OK ){
++      /* 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 ){
++        const void *zBuf;
++        assert( pPager->dbFileSize>0 );
++        CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
++        if( rc==SQLITE_OK ){
++          rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
++          pPager->aStat[PAGER_STAT_WRITE]++;
++        }
++        if( rc==SQLITE_OK ){
++          /* Update the pager's copy of the change-counter. Otherwise, the
++          ** next time a read transaction is opened the cache will be
++          ** flushed (as the change-counter values will not match).  */
++          const void *pCopy = (const void *)&((const char *)zBuf)[24];
++          memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
++          pPager->changeCountDone = 1;
++        }
++      }else{
++        pPager->changeCountDone = 1;
++      }
++    }
++
++    /* Release the page reference. */
++    sqlite3PagerUnref(pPgHdr);
++  }
++  return rc;
+ }
+ 
+ /*
+-** Return true if fsync() calls are disabled for this pager.  Return FALSE
+-** if fsync()s are executed normally.
++** Sync the database file to disk. This is a no-op for in-memory databases
++** or pages with the Pager.noSync flag set.
++**
++** If successful, or if called on a pager for which it is a no-op, this
++** function returns SQLITE_OK. Otherwise, an IO error code is returned.
+ */
+-SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
+-  return pPager->noSync;
++SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
++  int rc = SQLITE_OK;
++  if( !pPager->noSync ){
++    assert( !MEMDB );
++    rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
++  }else if( isOpen(pPager->fd) ){
++    assert( !MEMDB );
++    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
++    if( rc==SQLITE_NOTFOUND ){
++      rc = SQLITE_OK;
++    }
++  }
++  return rc;
+ }
+ 
+-#ifdef SQLITE_HAS_CODEC
+ /*
+-** Set or retrieve the codec for this pager
++** This function may only be called while a write-transaction is active in
++** rollback. If the connection is in WAL mode, this call is a no-op. 
++** Otherwise, if the connection does not already have an EXCLUSIVE lock on 
++** the database file, an attempt is made to obtain one.
++**
++** If the EXCLUSIVE lock is already held or the attempt to obtain it is
++** successful, or the connection is in WAL mode, SQLITE_OK is returned.
++** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is 
++** returned.
+ */
+-SQLITE_PRIVATE void sqlite3PagerSetCodec(
+-  Pager *pPager,
+-  void *(*xCodec)(void*,void*,Pgno,int),
+-  void (*xCodecSizeChng)(void*,int,int),
+-  void (*xCodecFree)(void*),
+-  void *pCodec
+-){
+-  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+-  pPager->xCodec = pPager->memDb ? 0 : xCodec;
+-  pPager->xCodecSizeChng = xCodecSizeChng;
+-  pPager->xCodecFree = xCodecFree;
+-  pPager->pCodec = pCodec;
+-  pagerReportSize(pPager);
+-}
+-SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
+-  return pPager->pCodec;
++SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
++  int rc = SQLITE_OK;
++  assert( pPager->eState==PAGER_WRITER_CACHEMOD 
++       || pPager->eState==PAGER_WRITER_DBMOD 
++       || pPager->eState==PAGER_WRITER_LOCKED 
++  );
++  assert( assert_pager_state(pPager) );
++  if( 0==pagerUseWal(pPager) ){
++    rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
++  }
++  return rc;
+ }
+-#endif
+ 
+-#ifndef SQLITE_OMIT_AUTOVACUUM
+ /*
+-** Move the page pPg to location pgno in the file.
++** Sync the database file for the pager pPager. zMaster points to the name
++** of a master journal file that should be written into the individual
++** journal file. zMaster may be NULL, which is interpreted as no master
++** journal (a single database transaction).
+ **
+-** There must be no references to the page previously located at
+-** pgno (which we call pPgOld) though that page is allowed to be
+-** in cache.  If the page previously located at pgno is not already
+-** in the rollback journal, it is not put there by by this routine.
++** This routine ensures that:
+ **
+-** References to the page pPg remain valid. Updating any
+-** meta-data associated with pPg (i.e. data stored in the nExtra bytes
+-** allocated along with the page) is the responsibility of the caller.
++**   * The database file change-counter is updated,
++**   * the journal is synced (unless the atomic-write optimization is used),
++**   * all dirty pages are written to the database file, 
++**   * the database file is truncated (if required), and
++**   * the database file synced. 
+ **
+-** A transaction must be active when this routine is called. It used to be
+-** required that a statement transaction was not active, but this restriction
+-** has been removed (CREATE INDEX needs to move a page when a statement
+-** transaction is active).
++** The only thing that remains to commit the transaction is to finalize 
++** (delete, truncate or zero the first part of) the journal file (or 
++** delete the master journal file if specified).
+ **
+-** If the fourth argument, isCommit, is non-zero, then this page is being
+-** moved as part of a database reorganization just before the transaction 
+-** is being committed. In this case, it is guaranteed that the database page 
+-** pPg refers to will not be written to again within this transaction.
++** Note that if zMaster==NULL, this does not overwrite a previous value
++** passed to an sqlite3PagerCommitPhaseOne() call.
+ **
+-** This function may return SQLITE_NOMEM or an IO error code if an error
+-** occurs. Otherwise, it returns SQLITE_OK.
++** If the final parameter - noSync - is true, then the database file itself
++** is not synced. The caller must call sqlite3PagerSync() directly to
++** sync the database file before calling CommitPhaseTwo() to delete the
++** journal file in this case.
+ */
+-SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
+-  PgHdr *pPgOld;               /* The page being overwritten. */
+-  Pgno needSyncPgno = 0;       /* Old value of pPg->pgno, if sync is required */
+-  int rc;                      /* Return code */
+-  Pgno origPgno;               /* The original page number */
++SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
++  Pager *pPager,                  /* Pager object */
++  const char *zMaster,            /* If not NULL, the master journal name */
++  int noSync                      /* True to omit the xSync on the db file */
++){
++  int rc = SQLITE_OK;             /* Return code */
+ 
+-  assert( pPg->nRef>0 );
+-  assert( pPager->eState==PAGER_WRITER_CACHEMOD
++  assert( pPager->eState==PAGER_WRITER_LOCKED
++       || pPager->eState==PAGER_WRITER_CACHEMOD
+        || pPager->eState==PAGER_WRITER_DBMOD
++       || pPager->eState==PAGER_ERROR
+   );
+   assert( assert_pager_state(pPager) );
+ 
+-  /* In order to be able to rollback, an in-memory database must journal
+-  ** the page we are moving from.
+-  */
+-  if( MEMDB ){
+-    rc = sqlite3PagerWrite(pPg);
+-    if( rc ) return rc;
+-  }
+-
+-  /* If the page being moved is dirty and has not been saved by the latest
+-  ** savepoint, then save the current contents of the page into the 
+-  ** sub-journal now. This is required to handle the following scenario:
+-  **
+-  **   BEGIN;
+-  **     <journal page X, then modify it in memory>
+-  **     SAVEPOINT one;
+-  **       <Move page X to location Y>
+-  **     ROLLBACK TO one;
+-  **
+-  ** If page X were not written to the sub-journal here, it would not
+-  ** be possible to restore its contents when the "ROLLBACK TO one"
+-  ** statement were is processed.
+-  **
+-  ** subjournalPage() may need to allocate space to store pPg->pgno into
+-  ** one or more savepoint bitvecs. This is the reason this function
+-  ** may return SQLITE_NOMEM.
+-  */
+-  if( pPg->flags&PGHDR_DIRTY
+-   && subjRequiresPage(pPg)
+-   && SQLITE_OK!=(rc = subjournalPage(pPg))
+-  ){
+-    return rc;
+-  }
+-
+-  PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", 
+-      PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
+-  IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
+-
+-  /* If the journal needs to be sync()ed before page pPg->pgno can
+-  ** be written to, store pPg->pgno in local variable needSyncPgno.
+-  **
+-  ** If the isCommit flag is set, there is no need to remember that
+-  ** the journal needs to be sync()ed before database page pPg->pgno 
+-  ** can be written to. The caller has already promised not to write to it.
+-  */
+-  if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
+-    needSyncPgno = pPg->pgno;
+-    assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
+-            pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+-    assert( pPg->flags&PGHDR_DIRTY );
+-  }
++  /* If a prior error occurred, report that error again. */
++  if( NEVER(pPager->errCode) ) return pPager->errCode;
+ 
+-  /* If the cache contains a page with page-number pgno, remove it
+-  ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for 
+-  ** page pgno before the 'move' operation, it needs to be retained 
+-  ** for the page moved there.
+-  */
+-  pPg->flags &= ~PGHDR_NEED_SYNC;
+-  pPgOld = pager_lookup(pPager, pgno);
+-  assert( !pPgOld || pPgOld->nRef==1 );
+-  if( pPgOld ){
+-    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+-    if( MEMDB ){
+-      /* Do not discard pages from an in-memory database since we might
+-      ** need to rollback later.  Just move the page out of the way. */
+-      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
+-    }else{
+-      sqlite3PcacheDrop(pPgOld);
+-    }
+-  }
++  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
++      pPager->zFilename, zMaster, pPager->dbSize));
+ 
+-  origPgno = pPg->pgno;
+-  sqlite3PcacheMove(pPg, pgno);
+-  sqlite3PcacheMakeDirty(pPg);
++  /* If no database changes have been made, return early. */
++  if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
+ 
+-  /* For an in-memory database, make sure the original page continues
+-  ** to exist, in case the transaction needs to roll back.  Use pPgOld
+-  ** as the original page since it has already been allocated.
+-  */
+   if( MEMDB ){
+-    assert( pPgOld );
+-    sqlite3PcacheMove(pPgOld, origPgno);
+-    sqlite3PagerUnref(pPgOld);
+-  }
++    /* If this is an in-memory db, or no pages have been written to, or this
++    ** function has already been called, it is mostly a no-op.  However, any
++    ** backup in progress needs to be restarted.
++    */
++    sqlite3BackupRestart(pPager->pBackup);
++  }else{
++    if( pagerUseWal(pPager) ){
++      PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
++      PgHdr *pPageOne = 0;
++      if( pList==0 ){
++        /* Must have at least one page for the WAL commit flag.
++        ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
++        rc = sqlite3PagerGet(pPager, 1, &pPageOne);
++        pList = pPageOne;
++        pList->pDirty = 0;
++      }
++      assert( rc==SQLITE_OK );
++      if( ALWAYS(pList) ){
++        rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
++      }
++      sqlite3PagerUnref(pPageOne);
++      if( rc==SQLITE_OK ){
++        sqlite3PcacheCleanAll(pPager->pPCache);
++      }
++    }else{
++      /* The following block updates the change-counter. Exactly how it
++      ** does this depends on whether or not the atomic-update optimization
++      ** was enabled at compile time, and if this transaction meets the 
++      ** runtime criteria to use the operation: 
++      **
++      **    * The file-system supports the atomic-write property for
++      **      blocks of size page-size, and 
++      **    * This commit is not part of a multi-file transaction, and
++      **    * Exactly one page has been modified and store in the journal file.
++      **
++      ** If the optimization was not enabled at compile time, then the
++      ** pager_incr_changecounter() function is called to update the change
++      ** counter in 'indirect-mode'. If the optimization is compiled in but
++      ** is not applicable to this transaction, call sqlite3JournalCreate()
++      ** to make sure the journal file has actually been created, then call
++      ** pager_incr_changecounter() to update the change-counter in indirect
++      ** mode. 
++      **
++      ** Otherwise, if the optimization is both enabled and applicable,
++      ** then call pager_incr_changecounter() to update the change-counter
++      ** in 'direct' mode. In this case the journal file will never be
++      ** created for this transaction.
++      */
++  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
++      PgHdr *pPg;
++      assert( isOpen(pPager->jfd) 
++           || pPager->journalMode==PAGER_JOURNALMODE_OFF 
++           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
++      );
++      if( !zMaster && isOpen(pPager->jfd) 
++       && pPager->journalOff==jrnlBufferSize(pPager) 
++       && pPager->dbSize>=pPager->dbOrigSize
++       && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
++      ){
++        /* Update the db file change counter via the direct-write method. The 
++        ** following call will modify the in-memory representation of page 1 
++        ** to include the updated change counter and then write page 1 
++        ** directly to the database file. Because of the atomic-write 
++        ** property of the host file-system, this is safe.
++        */
++        rc = pager_incr_changecounter(pPager, 1);
++      }else{
++        rc = sqlite3JournalCreate(pPager->jfd);
++        if( rc==SQLITE_OK ){
++          rc = pager_incr_changecounter(pPager, 0);
++        }
++      }
++  #else
++      rc = pager_incr_changecounter(pPager, 0);
++  #endif
++      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
++  
++      /* Write the master journal name into the journal file. If a master 
++      ** journal file name has already been written to the journal file, 
++      ** or if zMaster is NULL (no master journal), then this call is a no-op.
++      */
++      rc = writeMasterJournal(pPager, zMaster);
++      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
++  
++      /* Sync the journal file and write all dirty pages to the database.
++      ** If the atomic-update optimization is being used, this sync will not 
++      ** create the journal file or perform any real IO.
++      **
++      ** Because the change-counter page was just modified, unless the
++      ** atomic-update optimization is used it is almost certain that the
++      ** journal requires a sync here. However, in locking_mode=exclusive
++      ** on a system under memory pressure it is just possible that this is 
++      ** not the case. In this case it is likely enough that the redundant
++      ** xSync() call will be changed to a no-op by the OS anyhow. 
++      */
++      rc = syncJournal(pPager, 0);
++      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
++  
++      rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
++      if( rc!=SQLITE_OK ){
++        assert( rc!=SQLITE_IOERR_BLOCKED );
++        goto commit_phase_one_exit;
++      }
++      sqlite3PcacheCleanAll(pPager->pPCache);
+ 
+-  if( needSyncPgno ){
+-    /* If needSyncPgno is non-zero, then the journal file needs to be 
+-    ** sync()ed before any data is written to database file page needSyncPgno.
+-    ** Currently, no such page exists in the page-cache and the 
+-    ** "is journaled" bitvec flag has been set. This needs to be remedied by
+-    ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
+-    ** flag.
+-    **
+-    ** If the attempt to load the page into the page-cache fails, (due
+-    ** to a malloc() or IO failure), clear the bit in the pInJournal[]
+-    ** array. Otherwise, if the page is loaded and written again in
+-    ** this transaction, it may be written to the database file before
+-    ** it is synced into the journal file. This way, it may end up in
+-    ** the journal file twice, but that is not a problem.
+-    */
+-    PgHdr *pPgHdr;
+-    rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
+-    if( rc!=SQLITE_OK ){
+-      if( needSyncPgno<=pPager->dbOrigSize ){
+-        assert( pPager->pTmpSpace!=0 );
+-        sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
++      /* If the file on disk is smaller than the database image, use 
++      ** pager_truncate to grow the file here. This can happen if the database
++      ** image was extended as part of the current transaction and then the
++      ** last page in the db image moved to the free-list. In this case the
++      ** last page is never written out to disk, leaving the database file
++      ** undersized. Fix this now if it is the case.  */
++      if( pPager->dbSize>pPager->dbFileSize ){
++        Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
++        assert( pPager->eState==PAGER_WRITER_DBMOD );
++        rc = pager_truncate(pPager, nNew);
++        if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+       }
+-      return rc;
++  
++      /* Finally, sync the database file. */
++      if( !noSync ){
++        rc = sqlite3PagerSync(pPager);
++      }
++      IOTRACE(("DBSYNC %p\n", pPager))
+     }
+-    pPgHdr->flags |= PGHDR_NEED_SYNC;
+-    sqlite3PcacheMakeDirty(pPgHdr);
+-    sqlite3PagerUnref(pPgHdr);
+   }
+ 
+-  return SQLITE_OK;
+-}
+-#endif
+-
+-/*
+-** Return a pointer to the data for the specified page.
+-*/
+-SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
+-  assert( pPg->nRef>0 || pPg->pPager->memDb );
+-  return pPg->pData;
++commit_phase_one_exit:
++  if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
++    pPager->eState = PAGER_WRITER_FINISHED;
++  }
++  return rc;
+ }
+ 
+-/*
+-** Return a pointer to the Pager.nExtra bytes of "extra" space 
+-** allocated along with the specified page.
+-*/
+-SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
+-  return pPg->pExtra;
+-}
+ 
+ /*
+-** Get/set the locking-mode for this pager. Parameter eMode must be one
+-** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or 
+-** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
+-** the locking-mode is set to the value specified.
++** When this function is called, the database file has been completely
++** updated to reflect the changes made by the current transaction and
++** synced to disk. The journal file still exists in the file-system 
++** though, and if a failure occurs at this point it will eventually
++** be used as a hot-journal and the current transaction rolled back.
+ **
+-** The returned value is either PAGER_LOCKINGMODE_NORMAL or
+-** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
+-** locking-mode.
++** This function finalizes the journal file, either by deleting, 
++** truncating or partially zeroing it, so that it cannot be used 
++** for hot-journal rollback. Once this is done the transaction is
++** irrevocably committed.
++**
++** If an error occurs, an IO error code is returned and the pager
++** moves into the error state. Otherwise, SQLITE_OK is returned.
+ */
+-SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
+-  assert( eMode==PAGER_LOCKINGMODE_QUERY
+-            || eMode==PAGER_LOCKINGMODE_NORMAL
+-            || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
+-  assert( PAGER_LOCKINGMODE_QUERY<0 );
+-  assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
+-  assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
+-  if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
+-    pPager->exclusiveMode = (u8)eMode;
++SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
++  int rc = SQLITE_OK;                  /* Return code */
++
++  /* This routine should not be called if a prior error has occurred.
++  ** But if (due to a coding error elsewhere in the system) it does get
++  ** called, just return the same error code without doing anything. */
++  if( NEVER(pPager->errCode) ) return pPager->errCode;
++
++  assert( pPager->eState==PAGER_WRITER_LOCKED
++       || pPager->eState==PAGER_WRITER_FINISHED
++       || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
++  );
++  assert( assert_pager_state(pPager) );
++
++  /* An optimization. If the database was not actually modified during
++  ** this transaction, the pager is running in exclusive-mode and is
++  ** using persistent journals, then this function is a no-op.
++  **
++  ** The start of the journal file currently contains a single journal 
++  ** header with the nRec field set to 0. If such a journal is used as
++  ** a hot-journal during hot-journal rollback, 0 changes will be made
++  ** to the database file. So there is no need to zero the journal 
++  ** header. Since the pager is in exclusive mode, there is no need
++  ** to drop any locks either.
++  */
++  if( pPager->eState==PAGER_WRITER_LOCKED 
++   && pPager->exclusiveMode 
++   && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
++  ){
++    assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
++    pPager->eState = PAGER_READER;
++    return SQLITE_OK;
+   }
+-  return (int)pPager->exclusiveMode;
++
++  PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
++  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
++  return pager_error(pPager, rc);
+ }
+ 
+ /*
+-** Set the journal-mode for this pager. Parameter eMode must be one of:
++** If a write transaction is open, then all changes made within the 
++** transaction are reverted and the current write-transaction is closed.
++** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
++** state if an error occurs.
+ **
+-**    PAGER_JOURNALMODE_DELETE
+-**    PAGER_JOURNALMODE_TRUNCATE
+-**    PAGER_JOURNALMODE_PERSIST
+-**    PAGER_JOURNALMODE_OFF
+-**    PAGER_JOURNALMODE_MEMORY
+-**    PAGER_JOURNALMODE_WAL
++** If the pager is already in PAGER_ERROR state when this function is called,
++** it returns Pager.errCode immediately. No work is performed in this case.
+ **
+-** The journalmode is set to the value specified if the change is allowed.
+-** The change may be disallowed for the following reasons:
++** Otherwise, in rollback mode, this function performs two functions:
+ **
+-**   *  An in-memory database can only have its journal_mode set to _OFF
+-**      or _MEMORY.
++**   1) It rolls back the journal file, restoring all database file and 
++**      in-memory cache pages to the state they were in when the transaction
++**      was opened, and
+ **
+-**   *  Temporary databases cannot have _WAL journalmode.
++**   2) It finalizes the journal file, so that it is not used for hot
++**      rollback at any point in the future.
+ **
+-** The returned indicate the current (possibly updated) journal-mode.
++** Finalization of the journal file (task 2) is only performed if the 
++** rollback is successful.
++**
++** In WAL mode, all cache-entries containing data modified within the
++** current transaction are either expelled from the cache or reverted to
++** their pre-transaction state by re-reading data from the database or
++** WAL files. The WAL transaction is then closed.
+ */
+-SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
+-  u8 eOld = pPager->journalMode;    /* Prior journalmode */
+-
+-#ifdef SQLITE_DEBUG
+-  /* The print_pager_state() routine is intended to be used by the debugger
+-  ** only.  We invoke it once here to suppress a compiler warning. */
+-  print_pager_state(pPager);
+-#endif
+-
+-
+-  /* The eMode parameter is always valid */
+-  assert(      eMode==PAGER_JOURNALMODE_DELETE
+-            || eMode==PAGER_JOURNALMODE_TRUNCATE
+-            || eMode==PAGER_JOURNALMODE_PERSIST
+-            || eMode==PAGER_JOURNALMODE_OFF 
+-            || eMode==PAGER_JOURNALMODE_WAL 
+-            || eMode==PAGER_JOURNALMODE_MEMORY );
+-
+-  /* This routine is only called from the OP_JournalMode opcode, and
+-  ** the logic there will never allow a temporary file to be changed
+-  ** to WAL mode.
+-  */
+-  assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );
++SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
++  int rc = SQLITE_OK;                  /* Return code */
++  PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
+ 
+-  /* Do allow the journalmode of an in-memory database to be set to
+-  ** anything other than MEMORY or OFF
++  /* PagerRollback() is a no-op if called in READER or OPEN state. If
++  ** the pager is already in the ERROR state, the rollback is not 
++  ** attempted here. Instead, the error code is returned to the caller.
+   */
+-  if( MEMDB ){
+-    assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
+-    if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
+-      eMode = eOld;
+-    }
+-  }
+-
+-  if( eMode!=eOld ){
+-
+-    /* Change the journal mode. */
+-    assert( pPager->eState!=PAGER_ERROR );
+-    pPager->journalMode = (u8)eMode;
+-
+-    /* When transistioning from TRUNCATE or PERSIST to any other journal
+-    ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
+-    ** delete the journal file.
+-    */
+-    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
+-    assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
+-    assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
+-    assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
+-    assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
+-    assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
+-
+-    assert( isOpen(pPager->fd) || pPager->exclusiveMode );
+-    if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
++  assert( assert_pager_state(pPager) );
++  if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
++  if( pPager->eState<=PAGER_READER ) return SQLITE_OK;
+ 
+-      /* In this case we would like to delete the journal file. If it is
+-      ** not possible, then that is not a problem. Deleting the journal file
+-      ** here is an optimization only.
+-      **
+-      ** Before deleting the journal file, obtain a RESERVED lock on the
+-      ** database file. This ensures that the journal file is not deleted
+-      ** while it is in use by some other client.
++  if( pagerUseWal(pPager) ){
++    int rc2;
++    rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
++    rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
++    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, 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.
+       */
+-      sqlite3OsClose(pPager->jfd);
+-      if( pPager->eLock>=RESERVED_LOCK ){
+-        sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+-      }else{
+-        int rc = SQLITE_OK;
+-        int state = pPager->eState;
+-        assert( state==PAGER_OPEN || state==PAGER_READER );
+-        if( state==PAGER_OPEN ){
+-          rc = sqlite3PagerSharedLock(pPager);
+-        }
+-        if( pPager->eState==PAGER_READER ){
+-          assert( rc==SQLITE_OK );
+-          rc = pagerLockDb(pPager, RESERVED_LOCK);
+-        }
+-        if( rc==SQLITE_OK ){
+-          sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+-        }
+-        if( rc==SQLITE_OK && state==PAGER_READER ){
+-          pagerUnlockDb(pPager, SHARED_LOCK);
+-        }else if( state==PAGER_OPEN ){
+-          pager_unlock(pPager);
+-        }
+-        assert( state==pPager->eState );
+-      }
++      pPager->errCode = SQLITE_ABORT;
++      pPager->eState = PAGER_ERROR;
++      return rc;
+     }
++  }else{
++    rc = pager_playback(pPager, 0);
+   }
+ 
+-  /* Return the new journal mode */
+-  return (int)pPager->journalMode;
++  assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
++  assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
++          || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
++
++  /* If an error occurs during a ROLLBACK, we can no longer trust the pager
++  ** cache. So call pager_error() on the way out to make any error persistent.
++  */
++  return pager_error(pPager, rc);
+ }
+ 
+ /*
+-** Return the current journal mode.
++** Return TRUE if the database file is opened read-only.  Return FALSE
++** if the database is (in theory) writable.
+ */
+-SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
+-  return (int)pPager->journalMode;
++SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){
++  return pPager->readOnly;
+ }
+ 
+ /*
+-** Return TRUE if the pager is in a state where it is OK to change the
+-** journalmode.  Journalmode changes can only happen when the database
+-** is unmodified.
++** Return the number of references to the pager.
+ */
+-SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
+-  assert( assert_pager_state(pPager) );
+-  if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
+-  if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
+-  return 1;
++SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
++  return sqlite3PcacheRefCount(pPager->pPCache);
+ }
+ 
+ /*
+-** Get/set the size-limit used for persistent journal files.
+-**
+-** Setting the size limit to -1 means no limit is enforced.
+-** An attempt to set a limit smaller than -1 is a no-op.
++** Return the approximate number of bytes of memory currently
++** used by the pager and its associated cache.
+ */
+-SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
+-  if( iLimit>=-1 ){
+-    pPager->journalSizeLimit = iLimit;
+-    sqlite3WalLimit(pPager->pWal, iLimit);
+-  }
+-  return pPager->journalSizeLimit;
++SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){
++  int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
++                                     + 5*sizeof(void*);
++  return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
++           + sqlite3MallocSize(pPager)
++           + pPager->pageSize;
+ }
+ 
+ /*
+-** Return a pointer to the pPager->pBackup variable. The backup module
+-** in backup.c maintains the content of this variable. This module
+-** uses it opaquely as an argument to sqlite3BackupRestart() and
+-** sqlite3BackupUpdate() only.
++** Return the number of references to the specified page.
+ */
+-SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
+-  return &pPager->pBackup;
++SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
++  return sqlite3PcachePageRefcount(pPage);
+ }
+ 
+-#ifndef SQLITE_OMIT_VACUUM
++#ifdef SQLITE_TEST
+ /*
+-** Unless this is an in-memory or temporary database, clear the pager cache.
++** This routine is used for testing and analysis only.
+ */
+-SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
+-  if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
++SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
++  static int a[11];
++  a[0] = sqlite3PcacheRefCount(pPager->pPCache);
++  a[1] = sqlite3PcachePagecount(pPager->pPCache);
++  a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
++  a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
++  a[4] = pPager->eState;
++  a[5] = pPager->errCode;
++  a[6] = pPager->aStat[PAGER_STAT_HIT];
++  a[7] = pPager->aStat[PAGER_STAT_MISS];
++  a[8] = 0;  /* Used to be pPager->nOvfl */
++  a[9] = pPager->nRead;
++  a[10] = pPager->aStat[PAGER_STAT_WRITE];
++  return a;
+ }
+ #endif
+ 
 -#ifndef SQLITE_OMIT_WAL
+ /*
+-** This function is called when the user invokes "PRAGMA wal_checkpoint",
+-** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
+-** or wal_blocking_checkpoint() API functions.
+-**
+-** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
++** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
++** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
++** current cache hit or miss count, according to the value of eStat. If the 
++** reset parameter is non-zero, the cache hit or miss count is zeroed before 
++** returning.
+ */
+-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
+-  int rc = SQLITE_OK;
+-  if( pPager->pWal ){
+-    rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
+-        pPager->xBusyHandler, pPager->pBusyHandlerArg,
+-        pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
+-        pnLog, pnCkpt
+-    );
+-  }
+-  return rc;
+-}
++SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
+ 
+-SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
+-  return sqlite3WalCallback(pPager->pWal);
+-}
++  assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
++       || eStat==SQLITE_DBSTATUS_CACHE_MISS
++       || eStat==SQLITE_DBSTATUS_CACHE_WRITE
++  );
+ 
+-/*
+-** Return true if the underlying VFS for the given pager supports the
+-** primitives necessary for write-ahead logging.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
+-  const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
+-  return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
++  assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
++  assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
++  assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
++
++  *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
++  if( reset ){
++    pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
++  }
+ }
+ 
+ /*
+-** Attempt to take an exclusive lock on the database file. If a PENDING lock
+-** is obtained instead, immediately release it.
++** Return true if this is an in-memory pager.
+ */
+-static int pagerExclusiveLock(Pager *pPager){
+-  int rc;                         /* Return code */
+-
+-  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+-  rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+-  if( rc!=SQLITE_OK ){
+-    /* If the attempt to grab the exclusive lock failed, release the 
+-    ** pending lock that may have been obtained instead.  */
+-    pagerUnlockDb(pPager, SHARED_LOCK);
+-  }
+-
+-  return rc;
++SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
++  return MEMDB;
+ }
+ 
+ /*
+-** Call sqlite3WalOpen() to open the WAL handle. If the pager is in 
+-** exclusive-locking mode when this function is called, take an EXCLUSIVE
+-** lock on the database file and use heap-memory to store the wal-index
+-** in. Otherwise, use the normal shared-memory.
++** Check that there are at least nSavepoint savepoints open. If there are
++** currently less than nSavepoints open, then open one or more savepoints
++** to make up the difference. If the number of savepoints is already
++** equal to nSavepoint, then this function is a no-op.
++**
++** If a memory allocation fails, SQLITE_NOMEM is returned. If an error 
++** occurs while opening the sub-journal file, then an IO error code is
++** returned. Otherwise, SQLITE_OK.
+ */
+-static int pagerOpenWal(Pager *pPager){
+-  int rc = SQLITE_OK;
++SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
++  int rc = SQLITE_OK;                       /* Return code */
++  int nCurrent = pPager->nSavepoint;        /* Current number of savepoints */
+ 
+-  assert( pPager->pWal==0 && pPager->tempFile==0 );
+-  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
++  assert( pPager->eState>=PAGER_WRITER_LOCKED );
++  assert( assert_pager_state(pPager) );
+ 
+-  /* If the pager is already in exclusive-mode, the WAL module will use 
+-  ** heap-memory for the wal-index instead of the VFS shared-memory 
+-  ** implementation. Take the exclusive lock now, before opening the WAL
+-  ** file, to make sure this is safe.
+-  */
+-  if( pPager->exclusiveMode ){
+-    rc = pagerExclusiveLock(pPager);
+-  }
++  if( nSavepoint>nCurrent && pPager->useJournal ){
++    int ii;                                 /* Iterator variable */
++    PagerSavepoint *aNew;                   /* New Pager.aSavepoint array */
+ 
+-  /* Open the connection to the log file. If this operation fails, 
+-  ** (e.g. due to malloc() failure), return an error code.
+-  */
+-  if( rc==SQLITE_OK ){
+-    rc = sqlite3WalOpen(pPager->pVfs,
+-        pPager->fd, pPager->zWal, pPager->exclusiveMode,
+-        pPager->journalSizeLimit, &pPager->pWal
++    /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
++    ** if the allocation fails. Otherwise, zero the new portion in case a 
++    ** malloc failure occurs while populating it in the for(...) loop below.
++    */
++    aNew = (PagerSavepoint *)sqlite3Realloc(
++        pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
+     );
++    if( !aNew ){
++      return SQLITE_NOMEM;
++    }
++    memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
++    pPager->aSavepoint = aNew;
++
++    /* Populate the PagerSavepoint structures just allocated. */
++    for(ii=nCurrent; ii<nSavepoint; ii++){
++      aNew[ii].nOrig = pPager->dbSize;
++      if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
++        aNew[ii].iOffset = pPager->journalOff;
++      }else{
++        aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
++      }
++      aNew[ii].iSubRec = pPager->nSubRec;
++      aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
++      if( !aNew[ii].pInSavepoint ){
++        return SQLITE_NOMEM;
++      }
++      if( pagerUseWal(pPager) ){
++        sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
++      }
++      pPager->nSavepoint = ii+1;
++    }
++    assert( pPager->nSavepoint==nSavepoint );
++    assertTruncateConstraint(pPager);
+   }
+-  pagerFixMaplimit(pPager);
+ 
+   return rc;
+ }
+ 
 -
+ /*
+-** The caller must be holding a SHARED lock on the database file to call
+-** this function.
++** This function is called to rollback or release (commit) a savepoint.
++** The savepoint to release or rollback need not be the most recently 
++** created savepoint.
++**
++** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
++** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
++** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
++** that have occurred since the specified savepoint was created.
++**
++** The savepoint to rollback or release is identified by parameter 
++** iSavepoint. A value of 0 means to operate on the outermost savepoint
++** (the first created). A value of (Pager.nSavepoint-1) means operate
++** on the most recently created savepoint. If iSavepoint is greater than
++** (Pager.nSavepoint-1), then this function is a no-op.
+ **
+-** If the pager passed as the first argument is open on a real database
+-** file (not a temp file or an in-memory database), and the WAL file
+-** is not already open, make an attempt to open it now. If successful,
+-** return SQLITE_OK. If an error occurs or the VFS used by the pager does 
+-** not support the xShmXXX() methods, return an error code. *pbOpen is
+-** not modified in either case.
++** If a negative value is passed to this function, then the current
++** transaction is rolled back. This is different to calling 
++** sqlite3PagerRollback() because this function does not terminate
++** the transaction or unlock the database, it just restores the 
++** contents of the database to its original state. 
+ **
+-** If the pager is open on a temp-file (or in-memory database), or if
+-** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
+-** without doing anything.
+-*/
+-SQLITE_PRIVATE int sqlite3PagerOpenWal(
+-  Pager *pPager,                  /* Pager object */
+-  int *pbOpen                     /* OUT: Set to true if call is a no-op */
+-){
+-  int rc = SQLITE_OK;             /* Return code */
++** In any case, all savepoints with an index greater than iSavepoint 
++** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
++** then savepoint iSavepoint is also destroyed.
++**
++** This function may return SQLITE_NOMEM if a memory allocation fails,
++** or an IO error code if an IO error occurs while rolling back a 
++** savepoint. If no errors occur, SQLITE_OK is returned.
++*/ 
++SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
++  int rc = pPager->errCode;       /* Return code */
+ 
+-  assert( assert_pager_state(pPager) );
+-  assert( pPager->eState==PAGER_OPEN   || pbOpen );
+-  assert( pPager->eState==PAGER_READER || !pbOpen );
+-  assert( pbOpen==0 || *pbOpen==0 );
+-  assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
++  assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
++  assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
+ 
+-  if( !pPager->tempFile && !pPager->pWal ){
+-    if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
++  if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
++    int ii;            /* Iterator variable */
++    int nNew;          /* Number of remaining savepoints after this op. */
+ 
+-    /* Close any rollback journal previously open */
+-    sqlite3OsClose(pPager->jfd);
++    /* Figure out how many savepoints will still be active after this
++    ** operation. Store this value in nNew. Then free resources associated 
++    ** with any savepoints that are destroyed by this operation.
++    */
++    nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
++    for(ii=nNew; ii<pPager->nSavepoint; ii++){
++      sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
++    }
++    pPager->nSavepoint = nNew;
+ 
+-    rc = pagerOpenWal(pPager);
+-    if( rc==SQLITE_OK ){
+-      pPager->journalMode = PAGER_JOURNALMODE_WAL;
+-      pPager->eState = PAGER_OPEN;
++    /* If this is a release of the outermost savepoint, truncate 
++    ** the sub-journal to zero bytes in size. */
++    if( op==SAVEPOINT_RELEASE ){
++      if( nNew==0 && isOpen(pPager->sjfd) ){
++        /* Only truncate if it is an in-memory sub-journal. */
++        if( sqlite3IsMemJournal(pPager->sjfd) ){
++          rc = sqlite3OsTruncate(pPager->sjfd, 0);
++          assert( rc==SQLITE_OK );
++        }
++        pPager->nSubRec = 0;
++      }
++    }
++    /* Else this is a rollback operation, playback the specified savepoint.
++    ** If this is a temp-file, it is possible that the journal file has
++    ** not yet been opened. In this case there have been no changes to
++    ** the database file, so the playback operation can be skipped.
++    */
++    else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
++      PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
++      rc = pagerPlaybackSavepoint(pPager, pSavepoint);
++      assert(rc!=SQLITE_DONE);
+     }
+-  }else{
+-    *pbOpen = 1;
+   }
+ 
+   return rc;
+ }
+ 
+ /*
+-** This function is called to close the connection to the log file prior
+-** to switching from WAL to rollback mode.
++** Return the full pathname of the database file.
+ **
+-** Before closing the log file, this function attempts to take an 
+-** EXCLUSIVE lock on the database file. If this cannot be obtained, an
+-** error (SQLITE_BUSY) is returned and the log connection is not closed.
+-** If successful, the EXCLUSIVE lock is not released before returning.
++** Except, if the pager is in-memory only, then return an empty string if
++** nullIfMemDb is true.  This routine is called with nullIfMemDb==1 when
++** used to report the filename to the user, for compatibility with legacy
++** behavior.  But when the Btree needs to know the filename for matching to
++** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
++** participate in shared-cache.
+ */
+-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
+-  int rc = SQLITE_OK;
++SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
++  return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
++}
+ 
+-  assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
++/*
++** Return the VFS structure for the pager.
++*/
++SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
++  return pPager->pVfs;
++}
+ 
+-  /* If the log file is not already open, but does exist in the file-system,
+-  ** it may need to be checkpointed before the connection can switch to
+-  ** rollback mode. Open it now so this can happen.
+-  */
+-  if( !pPager->pWal ){
+-    int logexists = 0;
+-    rc = pagerLockDb(pPager, SHARED_LOCK);
+-    if( rc==SQLITE_OK ){
+-      rc = sqlite3OsAccess(
+-          pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
+-      );
+-    }
+-    if( rc==SQLITE_OK && logexists ){
+-      rc = pagerOpenWal(pPager);
+-    }
+-  }
+-    
+-  /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
+-  ** the database file, the log and log-summary files will be deleted.
+-  */
+-  if( rc==SQLITE_OK && pPager->pWal ){
+-    rc = pagerExclusiveLock(pPager);
+-    if( rc==SQLITE_OK ){
+-      rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
+-                           pPager->pageSize, (u8*)pPager->pTmpSpace);
+-      pPager->pWal = 0;
+-      pagerFixMaplimit(pPager);
+-    }
+-  }
+-  return rc;
++/*
++** Return the file handle for the database file associated
++** with the pager.  This might return NULL if the file has
++** not yet been opened.
++*/
++SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
++  return pPager->fd;
+ }
+ 
+-#endif /* !SQLITE_OMIT_WAL */
++/*
++** Return the full pathname of the journal file.
++*/
++SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
++  return pPager->zJournal;
++}
+ 
+-#ifdef SQLITE_ENABLE_ZIPVFS
+ /*
+-** A read-lock must be held on the pager when this function is called. If
+-** the pager is in WAL mode and the WAL file currently contains one or more
+-** frames, return the size in bytes of the page images stored within the
+-** WAL frames. Otherwise, if this is not a WAL database or the WAL file
+-** is empty, return 0.
++** Return true if fsync() calls are disabled for this pager.  Return FALSE
++** if fsync()s are executed normally.
+ */
+-SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
+-  assert( pPager->eState==PAGER_READER );
+-  return sqlite3WalFramesize(pPager->pWal);
++SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
++  return pPager->noSync;
+ }
+-#endif
+ 
+ #ifdef SQLITE_HAS_CODEC
+ /*
+-** This function is called by the wal module when writing page content
+-** into the log file.
+-**
+-** This function returns a pointer to a buffer containing the encrypted
+-** page content. If a malloc fails, this function may return NULL.
++** Set or retrieve the codec for this pager
+ */
+-SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
+-  void *aData = 0;
+-  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
+-  return aData;
++SQLITE_PRIVATE void sqlite3PagerSetCodec(
++  Pager *pPager,
++  void *(*xCodec)(void*,void*,Pgno,int),
++  void (*xCodecSizeChng)(void*,int,int),
++  void (*xCodecFree)(void*),
++  void *pCodec
++){
++  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
++  pPager->xCodec = pPager->memDb ? 0 : xCodec;
++  pPager->xCodecSizeChng = xCodecSizeChng;
++  pPager->xCodecFree = xCodecFree;
++  pPager->pCodec = pCodec;
++  pagerReportSize(pPager);
+ }
+-#endif /* SQLITE_HAS_CODEC */
 -
+-#endif /* SQLITE_OMIT_DISKIO */
++SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
++  return pPager->pCodec;
++}
++#endif
+ 
+-/************** End of pager.c ***********************************************/
+-/************** Begin file wal.c *********************************************/
++#ifndef SQLITE_OMIT_AUTOVACUUM
+ /*
+-** 2010 February 1
+-**
+-** The author disclaims copyright to this source code.  In place of
+-** a legal notice, here is a blessing:
+-**
+-**    May you do good and not evil.
+-**    May you find forgiveness for yourself and forgive others.
+-**    May you share freely, never taking more than you give.
+-**
+-*************************************************************************
+-**
+-** This file contains the implementation of a write-ahead log (WAL) used in 
+-** "journal_mode=WAL" mode.
+-**
+-** WRITE-AHEAD LOG (WAL) FILE FORMAT
+-**
+-** A WAL file consists of a header followed by zero or more "frames".
+-** Each frame records the revised content of a single page from the
+-** database file.  All changes to the database are recorded by writing
+-** frames into the WAL.  Transactions commit when a frame is written that
+-** contains a commit marker.  A single WAL can and usually does record 
+-** multiple transactions.  Periodically, the content of the WAL is
+-** transferred back into the database file in an operation called a
+-** "checkpoint".
+-**
+-** A single WAL file can be used multiple times.  In other words, the
+-** WAL can fill up with frames and then be checkpointed and then new
+-** frames can overwrite the old ones.  A WAL always grows from beginning
+-** toward the end.  Checksums and counters attached to each frame are
+-** used to determine which frames within the WAL are valid and which
+-** are leftovers from prior checkpoints.
+-**
+-** The WAL header is 32 bytes in size and consists of the following eight
+-** big-endian 32-bit unsigned integer values:
+-**
+-**     0: Magic number.  0x377f0682 or 0x377f0683
+-**     4: File format version.  Currently 3007000
+-**     8: Database page size.  Example: 1024
+-**    12: Checkpoint sequence number
+-**    16: Salt-1, random integer incremented with each checkpoint
+-**    20: Salt-2, a different random integer changing with each ckpt
+-**    24: Checksum-1 (first part of checksum for first 24 bytes of header).
+-**    28: Checksum-2 (second part of checksum for first 24 bytes of header).
+-**
+-** Immediately following the wal-header are zero or more frames. Each
+-** frame consists of a 24-byte frame-header followed by a <page-size> bytes
+-** of page data. The frame-header is six big-endian 32-bit unsigned 
+-** integer values, as follows:
+-**
+-**     0: Page number.
+-**     4: For commit records, the size of the database image in pages 
+-**        after the commit. For all other records, zero.
+-**     8: Salt-1 (copied from the header)
+-**    12: Salt-2 (copied from the header)
+-**    16: Checksum-1.
+-**    20: Checksum-2.
+-**
+-** A frame is considered valid if and only if the following conditions are
+-** true:
+-**
+-**    (1) The salt-1 and salt-2 values in the frame-header match
+-**        salt values in the wal-header
+-**
+-**    (2) The checksum values in the final 8 bytes of the frame-header
+-**        exactly match the checksum computed consecutively on the
+-**        WAL header and the first 8 bytes and the content of all frames
+-**        up to and including the current frame.
+-**
+-** The checksum is computed using 32-bit big-endian integers if the
+-** magic number in the first 4 bytes of the WAL is 0x377f0683 and it
+-** is computed using little-endian if the magic number is 0x377f0682.
+-** The checksum values are always stored in the frame header in a
+-** big-endian format regardless of which byte order is used to compute
+-** the checksum.  The checksum is computed by interpreting the input as
+-** an even number of unsigned 32-bit integers: x[0] through x[N].  The
+-** algorithm used for the checksum is as follows:
+-** 
+-**   for i from 0 to n-1 step 2:
+-**     s0 += x[i] + s1;
+-**     s1 += x[i+1] + s0;
+-**   endfor
+-**
+-** Note that s0 and s1 are both weighted checksums using fibonacci weights
+-** in reverse order (the largest fibonacci weight occurs on the first element
+-** of the sequence being summed.)  The s1 value spans all 32-bit 
+-** terms of the sequence whereas s0 omits the final term.
+-**
+-** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
+-** WAL is transferred into the database, then the database is VFS.xSync-ed.
+-** The VFS.xSync operations serve as write barriers - all writes launched
+-** before the xSync must complete before any write that launches after the
+-** xSync begins.
+-**
+-** After each checkpoint, the salt-1 value is incremented and the salt-2
+-** value is randomized.  This prevents old and new frames in the WAL from
+-** being considered valid at the same time and being checkpointing together
+-** following a crash.
+-**
+-** READER ALGORITHM
+-**
+-** To read a page from the database (call it page number P), a reader
+-** first checks the WAL to see if it contains page P.  If so, then the
+-** last valid instance of page P that is a followed by a commit frame
+-** or is a commit frame itself becomes the value read.  If the WAL
+-** contains no copies of page P that are valid and which are a commit
+-** frame or are followed by a commit frame, then page P is read from
+-** the database file.
+-**
+-** To start a read transaction, the reader records the index of the last
+-** valid frame in the WAL.  The reader uses this recorded "mxFrame" value
+-** for all subsequent read operations.  New transactions can be appended
+-** to the WAL, but as long as the reader uses its original mxFrame value
+-** and ignores the newly appended content, it will see a consistent snapshot
+-** of the database from a single point in time.  This technique allows
+-** multiple concurrent readers to view different versions of the database
+-** content simultaneously.
+-**
+-** The reader algorithm in the previous paragraphs works correctly, but 
+-** because frames for page P can appear anywhere within the WAL, the
+-** reader has to scan the entire WAL looking for page P frames.  If the
+-** WAL is large (multiple megabytes is typical) that scan can be slow,
+-** and read performance suffers.  To overcome this problem, a separate
+-** data structure called the wal-index is maintained to expedite the
+-** search for frames of a particular page.
+-** 
+-** WAL-INDEX FORMAT
+-**
+-** Conceptually, the wal-index is shared memory, though VFS implementations
+-** might choose to implement the wal-index using a mmapped file.  Because
+-** the wal-index is shared memory, SQLite does not support journal_mode=WAL 
+-** on a network filesystem.  All users of the database must be able to
+-** share memory.
+-**
+-** The wal-index is transient.  After a crash, the wal-index can (and should
+-** be) reconstructed from the original WAL file.  In fact, the VFS is required
+-** to either truncate or zero the header of the wal-index when the last
+-** connection to it closes.  Because the wal-index is transient, it can
+-** use an architecture-specific format; it does not have to be cross-platform.
+-** Hence, unlike the database and WAL file formats which store all values
+-** as big endian, the wal-index can store multi-byte values in the native
+-** byte order of the host computer.
+-**
+-** The purpose of the wal-index is to answer this question quickly:  Given
+-** a page number P and a maximum frame index M, return the index of the 
+-** last frame in the wal before frame M for page P in the WAL, or return
+-** NULL if there are no frames for page P in the WAL prior to M.
+-**
+-** The wal-index consists of a header region, followed by an one or
+-** more index blocks.  
+-**
+-** The wal-index header contains the total number of frames within the WAL
+-** in the mxFrame field.
+-**
+-** Each index block except for the first contains information on 
+-** HASHTABLE_NPAGE frames. The first index block contains information on
+-** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and 
+-** HASHTABLE_NPAGE are selected so that together the wal-index header and
+-** first index block are the same size as all other index blocks in the
+-** wal-index.
+-**
+-** Each index block contains two sections, a page-mapping that contains the
+-** database page number associated with each wal frame, and a hash-table 
+-** that allows readers to query an index block for a specific page number.
+-** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
+-** for the first index block) 32-bit page numbers. The first entry in the 
+-** first index-block contains the database page number corresponding to the
+-** first frame in the WAL file. The first entry in the second index block
+-** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
+-** the log, and so on.
+-**
+-** The last index block in a wal-index usually contains less than the full
+-** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers,
+-** depending on the contents of the WAL file. This does not change the
+-** allocated size of the page-mapping array - the page-mapping array merely
+-** contains unused entries.
+-**
+-** Even without using the hash table, the last frame for page P
+-** can be found by scanning the page-mapping sections of each index block
+-** starting with the last index block and moving toward the first, and
+-** within each index block, starting at the end and moving toward the
+-** beginning.  The first entry that equals P corresponds to the frame
+-** holding the content for that page.
+-**
+-** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
+-** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
+-** hash table for each page number in the mapping section, so the hash 
+-** table is never more than half full.  The expected number of collisions 
+-** prior to finding a match is 1.  Each entry of the hash table is an
+-** 1-based index of an entry in the mapping section of the same
+-** index block.   Let K be the 1-based index of the largest entry in
+-** the mapping section.  (For index blocks other than the last, K will
+-** always be exactly HASHTABLE_NPAGE (4096) and for the last index block
+-** K will be (mxFrame%HASHTABLE_NPAGE).)  Unused slots of the hash table
+-** contain a value of 0.
+-**
+-** To look for page P in the hash table, first compute a hash iKey on
+-** P as follows:
++** Move the page pPg to location pgno in the file.
+ **
+-**      iKey = (P * 383) % HASHTABLE_NSLOT
++** There must be no references to the page previously located at
++** pgno (which we call pPgOld) though that page is allowed to be
++** in cache.  If the page previously located at pgno is not already
++** in the rollback journal, it is not put there by by this routine.
+ **
+-** Then start scanning entries of the hash table, starting with iKey
+-** (wrapping around to the beginning when the end of the hash table is
+-** reached) until an unused hash slot is found. Let the first unused slot
+-** be at index iUnused.  (iUnused might be less than iKey if there was
+-** wrap-around.) Because the hash table is never more than half full,
+-** the search is guaranteed to eventually hit an unused entry.  Let 
+-** iMax be the value between iKey and iUnused, closest to iUnused,
+-** where aHash[iMax]==P.  If there is no iMax entry (if there exists
+-** no hash slot such that aHash[i]==p) then page P is not in the
+-** current index block.  Otherwise the iMax-th mapping entry of the
+-** current index block corresponds to the last entry that references 
+-** page P.
++** References to the page pPg remain valid. Updating any
++** meta-data associated with pPg (i.e. data stored in the nExtra bytes
++** allocated along with the page) is the responsibility of the caller.
+ **
+-** A hash search begins with the last index block and moves toward the
+-** first index block, looking for entries corresponding to page P.  On
+-** average, only two or three slots in each index block need to be
+-** examined in order to either find the last entry for page P, or to
+-** establish that no such entry exists in the block.  Each index block
+-** holds over 4000 entries.  So two or three index blocks are sufficient
+-** to cover a typical 10 megabyte WAL file, assuming 1K pages.  8 or 10
+-** comparisons (on average) suffice to either locate a frame in the
+-** WAL or to establish that the frame does not exist in the WAL.  This
+-** is much faster than scanning the entire 10MB WAL.
++** A transaction must be active when this routine is called. It used to be
++** required that a statement transaction was not active, but this restriction
++** has been removed (CREATE INDEX needs to move a page when a statement
++** transaction is active).
+ **
+-** Note that entries are added in order of increasing K.  Hence, one
+-** reader might be using some value K0 and a second reader that started
+-** at a later time (after additional transactions were added to the WAL
+-** and to the wal-index) might be using a different value K1, where K1>K0.
+-** Both readers can use the same hash table and mapping section to get
+-** the correct result.  There may be entries in the hash table with
+-** K>K0 but to the first reader, those entries will appear to be unused
+-** slots in the hash table and so the first reader will get an answer as
+-** if no values greater than K0 had ever been inserted into the hash table
+-** in the first place - which is what reader one wants.  Meanwhile, the
+-** second reader using K1 will see additional values that were inserted
+-** later, which is exactly what reader two wants.  
++** If the fourth argument, isCommit, is non-zero, then this page is being
++** moved as part of a database reorganization just before the transaction 
++** is being committed. In this case, it is guaranteed that the database page 
++** pPg refers to will not be written to again within this transaction.
+ **
+-** When a rollback occurs, the value of K is decreased. Hash table entries
+-** that correspond to frames greater than the new K value are removed
+-** from the hash table at this point.
++** This function may return SQLITE_NOMEM or an IO error code if an error
++** occurs. Otherwise, it returns SQLITE_OK.
+ */
+-#ifndef SQLITE_OMIT_WAL
++SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
++  PgHdr *pPgOld;               /* The page being overwritten. */
++  Pgno needSyncPgno = 0;       /* Old value of pPg->pgno, if sync is required */
++  int rc;                      /* Return code */
++  Pgno origPgno;               /* The original page number */
++
++  assert( pPg->nRef>0 );
++  assert( pPager->eState==PAGER_WRITER_CACHEMOD
++       || pPager->eState==PAGER_WRITER_DBMOD
++  );
++  assert( assert_pager_state(pPager) );
++
++  /* In order to be able to rollback, an in-memory database must journal
++  ** the page we are moving from.
++  */
++  if( MEMDB ){
++    rc = sqlite3PagerWrite(pPg);
++    if( rc ) return rc;
++  }
++
++  /* If the page being moved is dirty and has not been saved by the latest
++  ** savepoint, then save the current contents of the page into the 
++  ** sub-journal now. This is required to handle the following scenario:
++  **
++  **   BEGIN;
++  **     <journal page X, then modify it in memory>
++  **     SAVEPOINT one;
++  **       <Move page X to location Y>
++  **     ROLLBACK TO one;
++  **
++  ** If page X were not written to the sub-journal here, it would not
++  ** be possible to restore its contents when the "ROLLBACK TO one"
++  ** statement were is processed.
++  **
++  ** subjournalPage() may need to allocate space to store pPg->pgno into
++  ** one or more savepoint bitvecs. This is the reason this function
++  ** may return SQLITE_NOMEM.
++  */
++  if( pPg->flags&PGHDR_DIRTY
++   && subjRequiresPage(pPg)
++   && SQLITE_OK!=(rc = subjournalPage(pPg))
++  ){
++    return rc;
++  }
++
++  PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", 
++      PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
++  IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
++
++  /* If the journal needs to be sync()ed before page pPg->pgno can
++  ** be written to, store pPg->pgno in local variable needSyncPgno.
++  **
++  ** If the isCommit flag is set, there is no need to remember that
++  ** the journal needs to be sync()ed before database page pPg->pgno 
++  ** can be written to. The caller has already promised not to write to it.
++  */
++  if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
++    needSyncPgno = pPg->pgno;
++    assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
++            pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
++    assert( pPg->flags&PGHDR_DIRTY );
++  }
+ 
++  /* If the cache contains a page with page-number pgno, remove it
++  ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for 
++  ** page pgno before the 'move' operation, it needs to be retained 
++  ** for the page moved there.
++  */
++  pPg->flags &= ~PGHDR_NEED_SYNC;
++  pPgOld = pager_lookup(pPager, pgno);
++  assert( !pPgOld || pPgOld->nRef==1 );
++  if( pPgOld ){
++    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
++    if( MEMDB ){
++      /* Do not discard pages from an in-memory database since we might
++      ** need to rollback later.  Just move the page out of the way. */
++      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
++    }else{
++      sqlite3PcacheDrop(pPgOld);
++    }
++  }
+ 
 -/*
 -** Trace output macros
 -*/
@@ -2788,9 +63643,54 @@
 -# define WALTRACE(X)  if(sqlite3WalTrace) sqlite3DebugPrintf X
 -#else
 -# define WALTRACE(X)
--#endif
--
--/*
++  origPgno = pPg->pgno;
++  sqlite3PcacheMove(pPg, pgno);
++  sqlite3PcacheMakeDirty(pPg);
++
++  /* For an in-memory database, make sure the original page continues
++  ** to exist, in case the transaction needs to roll back.  Use pPgOld
++  ** as the original page since it has already been allocated.
++  */
++  if( MEMDB ){
++    assert( pPgOld );
++    sqlite3PcacheMove(pPgOld, origPgno);
++    sqlite3PagerUnref(pPgOld);
++  }
++
++  if( needSyncPgno ){
++    /* If needSyncPgno is non-zero, then the journal file needs to be 
++    ** sync()ed before any data is written to database file page needSyncPgno.
++    ** Currently, no such page exists in the page-cache and the 
++    ** "is journaled" bitvec flag has been set. This needs to be remedied by
++    ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
++    ** flag.
++    **
++    ** If the attempt to load the page into the page-cache fails, (due
++    ** to a malloc() or IO failure), clear the bit in the pInJournal[]
++    ** array. Otherwise, if the page is loaded and written again in
++    ** this transaction, it may be written to the database file before
++    ** it is synced into the journal file. This way, it may end up in
++    ** the journal file twice, but that is not a problem.
++    */
++    PgHdr *pPgHdr;
++    rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
++    if( rc!=SQLITE_OK ){
++      if( needSyncPgno<=pPager->dbOrigSize ){
++        assert( pPager->pTmpSpace!=0 );
++        sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
++      }
++      return rc;
++    }
++    pPgHdr->flags |= PGHDR_NEED_SYNC;
++    sqlite3PcacheMakeDirty(pPgHdr);
++    sqlite3PagerUnref(pPgHdr);
++  }
++
++  return SQLITE_OK;
++}
+ #endif
+ 
+ /*
 -** The maximum (and only) versions of the wal and wal-index formats
 -** that may be interpreted by this version of SQLite.
 -**
@@ -2802,14 +63702,21 @@
 -** checksum test is successful) and finds that the version field is not
 -** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
 -** returns SQLITE_CANTOPEN.
--*/
++** Return a pointer to the data for the specified page.
+ */
 -#define WAL_MAX_VERSION      3007000
 -#define WALINDEX_MAX_VERSION 3007000
--
--/*
++SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
++  assert( pPg->nRef>0 || pPg->pPager->memDb );
++  return pPg->pData;
++}
+ 
+ /*
 -** Indices of various locking bytes.   WAL_NREADER is the number
 -** of available reader locks and should be at least 3.
--*/
++** Return a pointer to the Pager.nExtra bytes of "extra" space 
++** allocated along with the specified page.
+ */
 -#define WAL_WRITE_LOCK         0
 -#define WAL_ALL_BUT_WRITE      1
 -#define WAL_CKPT_LOCK          1
@@ -2823,17 +63730,27 @@
 -typedef struct WalIterator WalIterator;
 -typedef struct WalCkptInfo WalCkptInfo;
 -
--
--/*
++SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
++  return pPg->pExtra;
++}
+ 
+ /*
 -** The following object holds a copy of the wal-index header content.
 -**
 -** The actual header in the wal-index consists of two copies of this
 -** object.
--**
++** Get/set the locking-mode for this pager. Parameter eMode must be one
++** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or 
++** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
++** the locking-mode is set to the value specified.
+ **
 -** The szPage value can be any power of 2 between 512 and 32768, inclusive.
 -** Or it can be 1 to represent a 65536-byte page.  The latter case was
 -** added in 3.7.1 when support for 64K pages was added.  
--*/
++** The returned value is either PAGER_LOCKINGMODE_NORMAL or
++** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
++** locking-mode.
+ */
 -struct WalIndexHdr {
 -  u32 iVersion;                   /* Wal-index version */
 -  u32 unused;                     /* Unused (padding) field */
@@ -2847,8 +63764,20 @@
 -  u32 aSalt[2];                   /* Two salt values copied from WAL header */
 -  u32 aCksum[2];                  /* Checksum over all prior fields */
 -};
--
--/*
++SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
++  assert( eMode==PAGER_LOCKINGMODE_QUERY
++            || eMode==PAGER_LOCKINGMODE_NORMAL
++            || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
++  assert( PAGER_LOCKINGMODE_QUERY<0 );
++  assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
++  assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
++  if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
++    pPager->exclusiveMode = (u8)eMode;
++  }
++  return (int)pPager->exclusiveMode;
++}
+ 
+ /*
 -** A copy of the following object occurs in the wal-index immediately
 -** following the second copy of the WalIndexHdr.  This object stores
 -** information used by checkpoint.
@@ -2860,7 +63789,8 @@
 -** holding the WAL_CKPT_LOCK lock (which includes a recovery thread).
 -** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from
 -** mxFrame back to zero when the WAL is reset.
--**
++** Set the journal-mode for this pager. Parameter eMode must be one of:
+ **
 -** There is one entry in aReadMark[] for each reader lock.  If a reader
 -** holds read-lock K, then the value in aReadMark[K] is no greater than
 -** the mxFrame for that reader.  The value READMARK_NOT_USED (0xffffffff)
@@ -2869,12 +63799,20 @@
 -** to avoid having to offset aReadMark[] indexs by one.  Readers holding
 -** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
 -** directly from the database.
--**
++**    PAGER_JOURNALMODE_DELETE
++**    PAGER_JOURNALMODE_TRUNCATE
++**    PAGER_JOURNALMODE_PERSIST
++**    PAGER_JOURNALMODE_OFF
++**    PAGER_JOURNALMODE_MEMORY
++**    PAGER_JOURNALMODE_WAL
+ **
 -** The value of aReadMark[K] may only be changed by a thread that
 -** is holding an exclusive lock on WAL_READ_LOCK(K).  Thus, the value of
 -** aReadMark[K] cannot changed while there is a reader is using that mark
 -** since the reader will be holding a shared lock on WAL_READ_LOCK(K).
--**
++** The journalmode is set to the value specified if the change is allowed.
++** The change may be disallowed for the following reasons:
+ **
 -** The checkpointer may only transfer frames from WAL to database where
 -** the frame numbers are less than or equal to every aReadMark[] that is
 -** in use (that is, every aReadMark[j] for which there is a corresponding
@@ -2886,24 +63824,35 @@
 -** will choose aReadMark[0] which has value 0 and hence such reader will
 -** get all their all content directly from the database file and ignore 
 -** the WAL.
--**
++**   *  An in-memory database can only have its journal_mode set to _OFF
++**      or _MEMORY.
+ **
 -** Writers normally append new frames to the end of the WAL.  However,
 -** if nBackfill equals mxFrame (meaning that all WAL content has been
 -** written back into the database) and if no readers are using the WAL
 -** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then
 -** the writer will first "reset" the WAL back to the beginning and start
 -** writing new content beginning at frame 1.
--**
++**   *  Temporary databases cannot have _WAL journalmode.
+ **
 -** We assume that 32-bit loads are atomic and so no locks are needed in
 -** order to read from any aReadMark[] entries.
--*/
++** The returned indicate the current (possibly updated) journal-mode.
+ */
 -struct WalCkptInfo {
 -  u32 nBackfill;                  /* Number of WAL frames backfilled into DB */
 -  u32 aReadMark[WAL_NREADER];     /* Reader marks */
 -};
 -#define READMARK_NOT_USED  0xffffffff
--
--
++SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
++  u8 eOld = pPager->journalMode;    /* Prior journalmode */
+ 
++#ifdef SQLITE_DEBUG
++  /* The print_pager_state() routine is intended to be used by the debugger
++  ** only.  We invoke it once here to suppress a compiler warning. */
++  print_pager_state(pPager);
++#endif
+ 
 -/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
 -** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
 -** only support mandatory file-locks, we do not read or write data
@@ -2912,14 +63861,26 @@
 -#define WALINDEX_LOCK_OFFSET   (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
 -#define WALINDEX_LOCK_RESERVED 16
 -#define WALINDEX_HDR_SIZE      (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
--
+ 
 -/* Size of header before each frame in wal */
 -#define WAL_FRAME_HDRSIZE 24
--
++  /* The eMode parameter is always valid */
++  assert(      eMode==PAGER_JOURNALMODE_DELETE
++            || eMode==PAGER_JOURNALMODE_TRUNCATE
++            || eMode==PAGER_JOURNALMODE_PERSIST
++            || eMode==PAGER_JOURNALMODE_OFF 
++            || eMode==PAGER_JOURNALMODE_WAL 
++            || eMode==PAGER_JOURNALMODE_MEMORY );
+ 
 -/* Size of write ahead log header, including checksum. */
 -/* #define WAL_HDRSIZE 24 */
 -#define WAL_HDRSIZE 32
--
++  /* This routine is only called from the OP_JournalMode opcode, and
++  ** the logic there will never allow a temporary file to be changed
++  ** to WAL mode.
++  */
++  assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );
+ 
 -/* WAL magic value. Either this value, or the same value with the least
 -** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit
 -** big-endian format in the first 4 bytes of a WAL file.
@@ -2930,7 +63891,16 @@
 -** all data as 32-bit little-endian words.
 -*/
 -#define WAL_MAGIC 0x377f0682
--
++  /* Do allow the journalmode of an in-memory database to be set to
++  ** anything other than MEMORY or OFF
++  */
++  if( MEMDB ){
++    assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
++    if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
++      eMode = eOld;
++    }
++  }
+ 
 -/*
 -** Return the offset of frame iFrame in the write-ahead log file, 
 -** assuming a database page size of szPage bytes. The offset returned
@@ -2939,11 +63909,70 @@
 -#define walFrameOffset(iFrame, szPage) (                               \
 -  WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE)         \
 -)
--
--/*
++  if( eMode!=eOld ){
++
++    /* Change the journal mode. */
++    assert( pPager->eState!=PAGER_ERROR );
++    pPager->journalMode = (u8)eMode;
++
++    /* When transistioning from TRUNCATE or PERSIST to any other journal
++    ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
++    ** delete the journal file.
++    */
++    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
++    assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
++    assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
++    assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
++    assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
++    assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
++
++    assert( isOpen(pPager->fd) || pPager->exclusiveMode );
++    if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
++
++      /* In this case we would like to delete the journal file. If it is
++      ** not possible, then that is not a problem. Deleting the journal file
++      ** here is an optimization only.
++      **
++      ** Before deleting the journal file, obtain a RESERVED lock on the
++      ** database file. This ensures that the journal file is not deleted
++      ** while it is in use by some other client.
++      */
++      sqlite3OsClose(pPager->jfd);
++      if( pPager->eLock>=RESERVED_LOCK ){
++        sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
++      }else{
++        int rc = SQLITE_OK;
++        int state = pPager->eState;
++        assert( state==PAGER_OPEN || state==PAGER_READER );
++        if( state==PAGER_OPEN ){
++          rc = sqlite3PagerSharedLock(pPager);
++        }
++        if( pPager->eState==PAGER_READER ){
++          assert( rc==SQLITE_OK );
++          rc = pagerLockDb(pPager, RESERVED_LOCK);
++        }
++        if( rc==SQLITE_OK ){
++          sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
++        }
++        if( rc==SQLITE_OK && state==PAGER_READER ){
++          pagerUnlockDb(pPager, SHARED_LOCK);
++        }else if( state==PAGER_OPEN ){
++          pager_unlock(pPager);
++        }
++        assert( state==pPager->eState );
++      }
++    }
++  }
++
++  /* Return the new journal mode */
++  return (int)pPager->journalMode;
++}
+ 
+ /*
 -** An open write-ahead log file is represented by an instance of the
 -** following object.
--*/
++** Return the current journal mode.
+ */
 -struct Wal {
 -  sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
 -  sqlite3_file *pDbFd;       /* File handle for the database file */
@@ -2970,28 +63999,59 @@
 -  u8 lockError;              /* True if a locking error has occurred */
 -#endif
 -};
--
--/*
++SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
++  return (int)pPager->journalMode;
++}
+ 
+ /*
 -** Candidate values for Wal.exclusiveMode.
--*/
++** Return TRUE if the pager is in a state where it is OK to change the
++** journalmode.  Journalmode changes can only happen when the database
++** is unmodified.
+ */
 -#define WAL_NORMAL_MODE     0
 -#define WAL_EXCLUSIVE_MODE  1     
 -#define WAL_HEAPMEMORY_MODE 2
--
--/*
++SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
++  assert( assert_pager_state(pPager) );
++  if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
++  if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
++  return 1;
++}
+ 
+ /*
 -** Possible values for WAL.readOnly
--*/
++** Get/set the size-limit used for persistent journal files.
++**
++** Setting the size limit to -1 means no limit is enforced.
++** An attempt to set a limit smaller than -1 is a no-op.
+ */
 -#define WAL_RDWR        0    /* Normal read/write connection */
 -#define WAL_RDONLY      1    /* The WAL file is readonly */
 -#define WAL_SHM_RDONLY  2    /* The SHM file is readonly */
--
--/*
++SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
++  if( iLimit>=-1 ){
++    pPager->journalSizeLimit = iLimit;
++    sqlite3WalLimit(pPager->pWal, iLimit);
++  }
++  return pPager->journalSizeLimit;
++}
+ 
+ /*
 -** Each page of the wal-index mapping contains a hash-table made up of
 -** an array of HASHTABLE_NSLOT elements of the following type.
--*/
++** Return a pointer to the pPager->pBackup variable. The backup module
++** in backup.c maintains the content of this variable. This module
++** uses it opaquely as an argument to sqlite3BackupRestart() and
++** sqlite3BackupUpdate() only.
+ */
 -typedef u16 ht_slot;
--
--/*
++SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
++  return &pPager->pBackup;
++}
+ 
++#ifndef SQLITE_OMIT_VACUUM
+ /*
 -** This structure is used to implement an iterator that loops through
 -** all frames in the WAL in database page order. Where two or more frames
 -** correspond to the same database page, the iterator visits only the 
@@ -3005,7 +64065,8 @@
 -**   walIteratorFree() - Free an iterator.
 -**
 -** This functionality is used by the checkpoint code (see walCheckpoint()).
--*/
++** Unless this is an in-memory or temporary database, clear the pager cache.
+ */
 -struct WalIterator {
 -  int iPrior;                     /* Last result returned from the iterator */
 -  int nSegment;                   /* Number of entries in aSegment[] */
@@ -3017,12 +64078,20 @@
 -    int iZero;                    /* Frame number associated with aPgno[0] */
 -  } aSegment[1];                  /* One for every 32KB page in the wal-index */
 -};
--
--/*
++SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
++  if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
++}
++#endif
+ 
++#ifndef SQLITE_OMIT_WAL
+ /*
 -** Define the parameters of the hash tables in the wal-index file. There
 -** is a hash-table following every HASHTABLE_NPAGE page numbers in the
 -** wal-index.
--**
++** This function is called when the user invokes "PRAGMA wal_checkpoint",
++** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
++** or wal_blocking_checkpoint() API functions.
+ **
 -** Changing any of these constants will alter the wal-index format and
 -** create incompatibilities.
 -*/
@@ -3034,15 +64103,30 @@
 -** The block of page numbers associated with the first hash-table in a
 -** wal-index is smaller than usual. This is so that there is a complete
 -** hash-table on each aligned 32KB page of the wal-index.
--*/
++** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
+ */
 -#define HASHTABLE_NPAGE_ONE  (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
--
++SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
++  int rc = SQLITE_OK;
++  if( pPager->pWal ){
++    rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
++        pPager->xBusyHandler, pPager->pBusyHandlerArg,
++        pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
++        pnLog, pnCkpt
++    );
++  }
++  return rc;
++}
+ 
 -/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
 -#define WALINDEX_PGSZ   (                                         \
 -    sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
 -)
--
--/*
++SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
++  return sqlite3WalCallback(pPager->pWal);
++}
+ 
+ /*
 -** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
 -** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
 -** numbered from zero.
@@ -3050,10 +64134,16 @@
 -** If this call is successful, *ppPage is set to point to the wal-index
 -** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
 -** then an SQLite error code is returned and *ppPage is set to 0.
--*/
++** Return true if the underlying VFS for the given pager supports the
++** primitives necessary for write-ahead logging.
+ */
 -static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
 -  int rc = SQLITE_OK;
--
++SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
++  const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
++  return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
++}
+ 
 -  /* Enlarge the pWal->apWiData[] array if required */
 -  if( pWal->nWiData<=iPage ){
 -    int nByte = sizeof(u32*)*(iPage+1);
@@ -3068,7 +64158,13 @@
 -    pWal->apWiData = apNew;
 -    pWal->nWiData = iPage+1;
 -  }
--
++/*
++** Attempt to take an exclusive lock on the database file. If a PENDING lock
++** is obtained instead, immediately release it.
++*/
++static int pagerExclusiveLock(Pager *pPager){
++  int rc;                         /* Return code */
+ 
 -  /* Request a pointer to the required page from the VFS */
 -  if( pWal->apWiData[iPage]==0 ){
 -    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
@@ -3083,29 +64179,65 @@
 -        rc = SQLITE_OK;
 -      }
 -    }
--  }
--
++  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
++  rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
++  if( rc!=SQLITE_OK ){
++    /* If the attempt to grab the exclusive lock failed, release the 
++    ** pending lock that may have been obtained instead.  */
++    pagerUnlockDb(pPager, SHARED_LOCK);
+   }
+ 
 -  *ppPage = pWal->apWiData[iPage];
 -  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
--  return rc;
--}
--
--/*
+   return rc;
+ }
+ 
+ /*
 -** Return a pointer to the WalCkptInfo structure in the wal-index.
--*/
++** Call sqlite3WalOpen() to open the WAL handle. If the pager is in 
++** exclusive-locking mode when this function is called, take an EXCLUSIVE
++** lock on the database file and use heap-memory to store the wal-index
++** in. Otherwise, use the normal shared-memory.
+ */
 -static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
 -  assert( pWal->nWiData>0 && pWal->apWiData[0] );
 -  return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
 -}
--
++static int pagerOpenWal(Pager *pPager){
++  int rc = SQLITE_OK;
+ 
 -/*
 -** Return a pointer to the WalIndexHdr structure in the wal-index.
 -*/
 -static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
 -  assert( pWal->nWiData>0 && pWal->apWiData[0] );
 -  return (volatile WalIndexHdr*)pWal->apWiData[0];
--}
--
++  assert( pPager->pWal==0 && pPager->tempFile==0 );
++  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
++
++  /* If the pager is already in exclusive-mode, the WAL module will use 
++  ** heap-memory for the wal-index instead of the VFS shared-memory 
++  ** implementation. Take the exclusive lock now, before opening the WAL
++  ** file, to make sure this is safe.
++  */
++  if( pPager->exclusiveMode ){
++    rc = pagerExclusiveLock(pPager);
++  }
++
++  /* Open the connection to the log file. If this operation fails, 
++  ** (e.g. due to malloc() failure), return an error code.
++  */
++  if( rc==SQLITE_OK ){
++    rc = sqlite3WalOpen(pPager->pVfs,
++        pPager->fd, pPager->zWal, pPager->exclusiveMode,
++        pPager->journalSizeLimit, &pPager->pWal
++    );
++  }
++  pagerFixMaplimit(pPager);
++
++  return rc;
+ }
+ 
 -/*
 -** The argument to this macro must be of type u32. On a little-endian
 -** architecture, it returns the u32 value that results from interpreting
@@ -3117,65 +64249,148 @@
 -    (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)  \
 -  + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24) \
 -)
--
--/*
+ 
+ /*
 -** Generate or extend an 8 byte checksum based on the data in 
 -** array aByte[] and the initial values of aIn[0] and aIn[1] (or
 -** initial values of 0 and 0 if aIn==NULL).
--**
++** The caller must be holding a SHARED lock on the database file to call
++** this function.
+ **
 -** The checksum is written back into aOut[] before returning.
--**
++** If the pager passed as the first argument is open on a real database
++** file (not a temp file or an in-memory database), and the WAL file
++** is not already open, make an attempt to open it now. If successful,
++** return SQLITE_OK. If an error occurs or the VFS used by the pager does 
++** not support the xShmXXX() methods, return an error code. *pbOpen is
++** not modified in either case.
+ **
 -** nByte must be a positive multiple of 8.
--*/
++** If the pager is open on a temp-file (or in-memory database), or if
++** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
++** without doing anything.
+ */
 -static void walChecksumBytes(
 -  int nativeCksum, /* True for native byte-order, false for non-native */
 -  u8 *a,           /* Content to be checksummed */
 -  int nByte,       /* Bytes of content in a[].  Must be a multiple of 8. */
 -  const u32 *aIn,  /* Initial checksum value input */
 -  u32 *aOut        /* OUT: Final checksum value output */
--){
++SQLITE_PRIVATE int sqlite3PagerOpenWal(
++  Pager *pPager,                  /* Pager object */
++  int *pbOpen                     /* OUT: Set to true if call is a no-op */
+ ){
 -  u32 s1, s2;
 -  u32 *aData = (u32 *)a;
 -  u32 *aEnd = (u32 *)&a[nByte];
--
++  int rc = SQLITE_OK;             /* Return code */
+ 
 -  if( aIn ){
 -    s1 = aIn[0];
 -    s2 = aIn[1];
 -  }else{
 -    s1 = s2 = 0;
 -  }
--
++  assert( assert_pager_state(pPager) );
++  assert( pPager->eState==PAGER_OPEN   || pbOpen );
++  assert( pPager->eState==PAGER_READER || !pbOpen );
++  assert( pbOpen==0 || *pbOpen==0 );
++  assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
+ 
 -  assert( nByte>=8 );
 -  assert( (nByte&0x00000007)==0 );
--
++  if( !pPager->tempFile && !pPager->pWal ){
++    if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
+ 
 -  if( nativeCksum ){
 -    do {
 -      s1 += *aData++ + s2;
 -      s2 += *aData++ + s1;
 -    }while( aData<aEnd );
--  }else{
++    /* Close any rollback journal previously open */
++    sqlite3OsClose(pPager->jfd);
++
++    rc = pagerOpenWal(pPager);
++    if( rc==SQLITE_OK ){
++      pPager->journalMode = PAGER_JOURNALMODE_WAL;
++      pPager->eState = PAGER_OPEN;
++    }
+   }else{
 -    do {
 -      s1 += BYTESWAP32(aData[0]) + s2;
 -      s2 += BYTESWAP32(aData[1]) + s1;
 -      aData += 2;
 -    }while( aData<aEnd );
--  }
--
++    *pbOpen = 1;
+   }
+ 
 -  aOut[0] = s1;
 -  aOut[1] = s2;
--}
--
++  return rc;
+ }
+ 
 -static void walShmBarrier(Wal *pWal){
 -  if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
 -    sqlite3OsShmBarrier(pWal->pDbFd);
--  }
--}
--
--/*
++/*
++** This function is called to close the connection to the log file prior
++** to switching from WAL to rollback mode.
++**
++** Before closing the log file, this function attempts to take an 
++** EXCLUSIVE lock on the database file. If this cannot be obtained, an
++** error (SQLITE_BUSY) is returned and the log connection is not closed.
++** If successful, the EXCLUSIVE lock is not released before returning.
++*/
++SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
++  int rc = SQLITE_OK;
++
++  assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
++
++  /* If the log file is not already open, but does exist in the file-system,
++  ** it may need to be checkpointed before the connection can switch to
++  ** rollback mode. Open it now so this can happen.
++  */
++  if( !pPager->pWal ){
++    int logexists = 0;
++    rc = pagerLockDb(pPager, SHARED_LOCK);
++    if( rc==SQLITE_OK ){
++      rc = sqlite3OsAccess(
++          pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
++      );
++    }
++    if( rc==SQLITE_OK && logexists ){
++      rc = pagerOpenWal(pPager);
++    }
++  }
++    
++  /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
++  ** the database file, the log and log-summary files will be deleted.
++  */
++  if( rc==SQLITE_OK && pPager->pWal ){
++    rc = pagerExclusiveLock(pPager);
++    if( rc==SQLITE_OK ){
++      rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
++                           pPager->pageSize, (u8*)pPager->pTmpSpace);
++      pPager->pWal = 0;
++      pagerFixMaplimit(pPager);
++    }
+   }
++  return rc;
+ }
+ 
++#endif /* !SQLITE_OMIT_WAL */
++
++#ifdef SQLITE_ENABLE_ZIPVFS
+ /*
 -** Write the header information in pWal->hdr into the wal-index.
 -**
 -** The checksum on pWal->hdr is updated before it is written.
--*/
++** A read-lock must be held on the pager when this function is called. If
++** the pager is in WAL mode and the WAL file currently contains one or more
++** frames, return the size in bytes of the page images stored within the
++** WAL frames. Otherwise, if this is not a WAL database or the WAL file
++** is empty, return 0.
+ */
 -static void walIndexWriteHdr(Wal *pWal){
 -  volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
 -  const int nCksum = offsetof(WalIndexHdr, aCksum);
@@ -3187,13 +64402,20 @@
 -  memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr));
 -  walShmBarrier(pWal);
 -  memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr));
--}
--
--/*
++SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
++  assert( pPager->eState==PAGER_READER );
++  return sqlite3WalFramesize(pPager->pWal);
+ }
++#endif
+ 
++#ifdef SQLITE_HAS_CODEC
+ /*
 -** This function encodes a single frame header and writes it to a buffer
 -** supplied by the caller. A frame-header is made up of a series of 
 -** 4-byte big-endian integers, as follows:
--**
++** This function is called by the wal module when writing page content
++** into the log file.
+ **
 -**     0: Page number.
 -**     4: For commit records, the size of the database image in pages 
 -**        after the commit. For all other records, zero.
@@ -3201,7 +64423,9 @@
 -**    12: Salt-2 (copied from the wal-header)
 -**    16: Checksum-1.
 -**    20: Checksum-2.
--*/
++** This function returns a pointer to a buffer containing the encrypted
++** page content. If a malloc fails, this function may return NULL.
+ */
 -static void walEncodeFrame(
 -  Wal *pWal,                      /* The write-ahead log */
 -  u32 iPage,                      /* Database page number for frame */
@@ -3215,15 +64439,26 @@
 -  sqlite3Put4byte(&aFrame[0], iPage);
 -  sqlite3Put4byte(&aFrame[4], nTruncate);
 -  memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
--
++SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
++  void *aData = 0;
++  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
++  return aData;
++}
++#endif /* SQLITE_HAS_CODEC */
+ 
 -  nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
 -  walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
 -  walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
--
++#endif /* SQLITE_OMIT_DISKIO */
+ 
 -  sqlite3Put4byte(&aFrame[16], aCksum[0]);
 -  sqlite3Put4byte(&aFrame[20], aCksum[1]);
--}
--
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
++SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx) {
++  *ctx = pPager->pCodec;
+ }
+ 
 -/*
 -** Check to see if the frame with header in aFrame[] and content
 -** in aData[] is valid.  If it is a valid frame, fill *piPage and
@@ -3235,26 +64470,47 @@
 -  u32 *pnTruncate,                /* OUT: New db size (or 0 if not commit) */
 -  u8 *aData,                      /* Pointer to page data (for checksum) */
 -  u8 *aFrame                      /* Frame data */
--){
++SQLITE_PRIVATE int sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno) {
++  return (PAGER_MJ_PGNO(pPager) == pgno) ? 1 : 0;
++}
++
++SQLITE_PRIVATE sqlite3_file *sqlite3Pager_get_fd(Pager *pPager) {
++  return (isOpen(pPager->fd)) ? pPager->fd : NULL;
++}
++
++SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetCodec(
++  Pager *pPager,
++  void *(*xCodec)(void*,void*,Pgno,int),
++  void (*xCodecSizeChng)(void*,int,int),
++  void (*xCodecFree)(void*),
++  void *pCodec
+ ){
 -  int nativeCksum;                /* True for native byte-order checksums */
 -  u32 *aCksum = pWal->hdr.aFrameCksum;
 -  u32 pgno;                       /* Page number of the frame */
 -  assert( WAL_FRAME_HDRSIZE==24 );
--
++  sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec); 
++}
+ 
 -  /* A frame is only valid if the salt values in the frame-header
 -  ** match the salt values in the wal-header. 
 -  */
 -  if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
 -    return 0;
 -  }
--
++SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetError( Pager *pPager, int error) {
++  pPager->errCode = error;
++}
+ 
 -  /* A frame is only valid if the page number is creater than zero.
 -  */
 -  pgno = sqlite3Get4byte(&aFrame[0]);
 -  if( pgno==0 ){
 -    return 0;
 -  }
--
++#endif
++/* END SQLCIPHER */
+ 
 -  /* A frame is only valid if a checksum of the WAL header,
 -  ** all prior frams, the first 16 bytes of this frame-header, 
 -  ** and the frame-data matches the checksum in the last 8 
@@ -3269,7 +64525,7 @@
 -    /* Checksum failed. */
 -    return 0;
 -  }
--
+ 
 -  /* If we reach this point, the frame is valid.  Return the page number
 -  ** and the new database size.
 -  */
@@ -3277,6 +64533,250 @@
 -  *pnTruncate = sqlite3Get4byte(&aFrame[4]);
 -  return 1;
 -}
++/************** End of pager.c ***********************************************/
++/************** Begin file wal.c *********************************************/
++/*
++** 2010 February 1
++**
++** The author disclaims copyright to this source code.  In place of
++** a legal notice, here is a blessing:
++**
++**    May you do good and not evil.
++**    May you find forgiveness for yourself and forgive others.
++**    May you share freely, never taking more than you give.
++**
++*************************************************************************
++**
++** This file contains the implementation of a write-ahead log (WAL) used in 
++** "journal_mode=WAL" mode.
++**
++** WRITE-AHEAD LOG (WAL) FILE FORMAT
++**
++** A WAL file consists of a header followed by zero or more "frames".
++** Each frame records the revised content of a single page from the
++** database file.  All changes to the database are recorded by writing
++** frames into the WAL.  Transactions commit when a frame is written that
++** contains a commit marker.  A single WAL can and usually does record 
++** multiple transactions.  Periodically, the content of the WAL is
++** transferred back into the database file in an operation called a
++** "checkpoint".
++**
++** A single WAL file can be used multiple times.  In other words, the
++** WAL can fill up with frames and then be checkpointed and then new
++** frames can overwrite the old ones.  A WAL always grows from beginning
++** toward the end.  Checksums and counters attached to each frame are
++** used to determine which frames within the WAL are valid and which
++** are leftovers from prior checkpoints.
++**
++** The WAL header is 32 bytes in size and consists of the following eight
++** big-endian 32-bit unsigned integer values:
++**
++**     0: Magic number.  0x377f0682 or 0x377f0683
++**     4: File format version.  Currently 3007000
++**     8: Database page size.  Example: 1024
++**    12: Checkpoint sequence number
++**    16: Salt-1, random integer incremented with each checkpoint
++**    20: Salt-2, a different random integer changing with each ckpt
++**    24: Checksum-1 (first part of checksum for first 24 bytes of header).
++**    28: Checksum-2 (second part of checksum for first 24 bytes of header).
++**
++** Immediately following the wal-header are zero or more frames. Each
++** frame consists of a 24-byte frame-header followed by a <page-size> bytes
++** of page data. The frame-header is six big-endian 32-bit unsigned 
++** integer values, as follows:
++**
++**     0: Page number.
++**     4: For commit records, the size of the database image in pages 
++**        after the commit. For all other records, zero.
++**     8: Salt-1 (copied from the header)
++**    12: Salt-2 (copied from the header)
++**    16: Checksum-1.
++**    20: Checksum-2.
++**
++** A frame is considered valid if and only if the following conditions are
++** true:
++**
++**    (1) The salt-1 and salt-2 values in the frame-header match
++**        salt values in the wal-header
++**
++**    (2) The checksum values in the final 8 bytes of the frame-header
++**        exactly match the checksum computed consecutively on the
++**        WAL header and the first 8 bytes and the content of all frames
++**        up to and including the current frame.
++**
++** The checksum is computed using 32-bit big-endian integers if the
++** magic number in the first 4 bytes of the WAL is 0x377f0683 and it
++** is computed using little-endian if the magic number is 0x377f0682.
++** The checksum values are always stored in the frame header in a
++** big-endian format regardless of which byte order is used to compute
++** the checksum.  The checksum is computed by interpreting the input as
++** an even number of unsigned 32-bit integers: x[0] through x[N].  The
++** algorithm used for the checksum is as follows:
++** 
++**   for i from 0 to n-1 step 2:
++**     s0 += x[i] + s1;
++**     s1 += x[i+1] + s0;
++**   endfor
++**
++** Note that s0 and s1 are both weighted checksums using fibonacci weights
++** in reverse order (the largest fibonacci weight occurs on the first element
++** of the sequence being summed.)  The s1 value spans all 32-bit 
++** terms of the sequence whereas s0 omits the final term.
++**
++** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
++** WAL is transferred into the database, then the database is VFS.xSync-ed.
++** The VFS.xSync operations serve as write barriers - all writes launched
++** before the xSync must complete before any write that launches after the
++** xSync begins.
++**
++** After each checkpoint, the salt-1 value is incremented and the salt-2
++** value is randomized.  This prevents old and new frames in the WAL from
++** being considered valid at the same time and being checkpointing together
++** following a crash.
++**
++** READER ALGORITHM
++**
++** To read a page from the database (call it page number P), a reader
++** first checks the WAL to see if it contains page P.  If so, then the
++** last valid instance of page P that is a followed by a commit frame
++** or is a commit frame itself becomes the value read.  If the WAL
++** contains no copies of page P that are valid and which are a commit
++** frame or are followed by a commit frame, then page P is read from
++** the database file.
++**
++** To start a read transaction, the reader records the index of the last
++** valid frame in the WAL.  The reader uses this recorded "mxFrame" value
++** for all subsequent read operations.  New transactions can be appended
++** to the WAL, but as long as the reader uses its original mxFrame value
++** and ignores the newly appended content, it will see a consistent snapshot
++** of the database from a single point in time.  This technique allows
++** multiple concurrent readers to view different versions of the database
++** content simultaneously.
++**
++** The reader algorithm in the previous paragraphs works correctly, but 
++** because frames for page P can appear anywhere within the WAL, the
++** reader has to scan the entire WAL looking for page P frames.  If the
++** WAL is large (multiple megabytes is typical) that scan can be slow,
++** and read performance suffers.  To overcome this problem, a separate
++** data structure called the wal-index is maintained to expedite the
++** search for frames of a particular page.
++** 
++** WAL-INDEX FORMAT
++**
++** Conceptually, the wal-index is shared memory, though VFS implementations
++** might choose to implement the wal-index using a mmapped file.  Because
++** the wal-index is shared memory, SQLite does not support journal_mode=WAL 
++** on a network filesystem.  All users of the database must be able to
++** share memory.
++**
++** The wal-index is transient.  After a crash, the wal-index can (and should
++** be) reconstructed from the original WAL file.  In fact, the VFS is required
++** to either truncate or zero the header of the wal-index when the last
++** connection to it closes.  Because the wal-index is transient, it can
++** use an architecture-specific format; it does not have to be cross-platform.
++** Hence, unlike the database and WAL file formats which store all values
++** as big endian, the wal-index can store multi-byte values in the native
++** byte order of the host computer.
++**
++** The purpose of the wal-index is to answer this question quickly:  Given
++** a page number P and a maximum frame index M, return the index of the 
++** last frame in the wal before frame M for page P in the WAL, or return
++** NULL if there are no frames for page P in the WAL prior to M.
++**
++** The wal-index consists of a header region, followed by an one or
++** more index blocks.  
++**
++** The wal-index header contains the total number of frames within the WAL
++** in the mxFrame field.
++**
++** Each index block except for the first contains information on 
++** HASHTABLE_NPAGE frames. The first index block contains information on
++** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and 
++** HASHTABLE_NPAGE are selected so that together the wal-index header and
++** first index block are the same size as all other index blocks in the
++** wal-index.
++**
++** Each index block contains two sections, a page-mapping that contains the
++** database page number associated with each wal frame, and a hash-table 
++** that allows readers to query an index block for a specific page number.
++** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
++** for the first index block) 32-bit page numbers. The first entry in the 
++** first index-block contains the database page number corresponding to the
++** first frame in the WAL file. The first entry in the second index block
++** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
++** the log, and so on.
++**
++** The last index block in a wal-index usually contains less than the full
++** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers,
++** depending on the contents of the WAL file. This does not change the
++** allocated size of the page-mapping array - the page-mapping array merely
++** contains unused entries.
++**
++** Even without using the hash table, the last frame for page P
++** can be found by scanning the page-mapping sections of each index block
++** starting with the last index block and moving toward the first, and
++** within each index block, starting at the end and moving toward the
++** beginning.  The first entry that equals P corresponds to the frame
++** holding the content for that page.
++**
++** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
++** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
++** hash table for each page number in the mapping section, so the hash 
++** table is never more than half full.  The expected number of collisions 
++** prior to finding a match is 1.  Each entry of the hash table is an
++** 1-based index of an entry in the mapping section of the same
++** index block.   Let K be the 1-based index of the largest entry in
++** the mapping section.  (For index blocks other than the last, K will
++** always be exactly HASHTABLE_NPAGE (4096) and for the last index block
++** K will be (mxFrame%HASHTABLE_NPAGE).)  Unused slots of the hash table
++** contain a value of 0.
++**
++** To look for page P in the hash table, first compute a hash iKey on
++** P as follows:
++**
++**      iKey = (P * 383) % HASHTABLE_NSLOT
++**
++** Then start scanning entries of the hash table, starting with iKey
++** (wrapping around to the beginning when the end of the hash table is
++** reached) until an unused hash slot is found. Let the first unused slot
++** be at index iUnused.  (iUnused might be less than iKey if there was
++** wrap-around.) Because the hash table is never more than half full,
++** the search is guaranteed to eventually hit an unused entry.  Let 
++** iMax be the value between iKey and iUnused, closest to iUnused,
++** where aHash[iMax]==P.  If there is no iMax entry (if there exists
++** no hash slot such that aHash[i]==p) then page P is not in the
++** current index block.  Otherwise the iMax-th mapping entry of the
++** current index block corresponds to the last entry that references 
++** page P.
++**
++** A hash search begins with the last index block and moves toward the
++** first index block, looking for entries corresponding to page P.  On
++** average, only two or three slots in each index block need to be
++** examined in order to either find the last entry for page P, or to
++** establish that no such entry exists in the block.  Each index block
++** holds over 4000 entries.  So two or three index blocks are sufficient
++** to cover a typical 10 megabyte WAL file, assuming 1K pages.  8 or 10
++** comparisons (on average) suffice to either locate a frame in the
++** WAL or to establish that the frame does not exist in the WAL.  This
++** is much faster than scanning the entire 10MB WAL.
++**
++** Note that entries are added in order of increasing K.  Hence, one
++** reader might be using some value K0 and a second reader that started
++** at a later time (after additional transactions were added to the WAL
++** and to the wal-index) might be using a different value K1, where K1>K0.
++** Both readers can use the same hash table and mapping section to get
++** the correct result.  There may be entries in the hash table with
++** K>K0 but to the first reader, those entries will appear to be unused
++** slots in the hash table and so the first reader will get an answer as
++** if no values greater than K0 had ever been inserted into the hash table
++** in the first place - which is what reader one wants.  Meanwhile, the
++** second reader using K1 will see additional values that were inserted
++** later, which is exactly what reader two wants.  
++**
++** When a rollback occurs, the value of K is decreased. Hash table entries
++** that correspond to frames greater than the new K value are removed
++** from the hash table at this point.
++*/
 +#ifndef SQLITE_OMIT_WAL
  
  
@@ -4074,8 +65574,9 @@
 -    ** checkpointing the log file.
 -    */
 -    if( pWal->hdr.nPage ){
--      sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
--          pWal->hdr.nPage, pWal->zWalName
+-      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
+-          "recovered %d frames from WAL file %s",
+-          pWal->hdr.mxFrame, pWal->zWalName
 -      );
 -    }
 +static void walShmBarrier(Wal *pWal){
@@ -4226,18 +65727,31 @@
 -  pRet->syncHeader = 1;
 -  pRet->padToSectorBoundary = 1;
 -  pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
+-
+-  /* Open file handle on the write-ahead log file. */
+-  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
+-  rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
+-  if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
+-    pRet->readOnly = WAL_RDONLY;
 +  /* A frame is only valid if the page number is creater than zero.
 +  */
 +  pgno = sqlite3Get4byte(&aFrame[0]);
 +  if( pgno==0 ){
 +    return 0;
-+  }
+   }
  
--  /* Open file handle on the write-ahead log file. */
--  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
--  rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
--  if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
--    pRet->readOnly = WAL_RDONLY;
+-  if( rc!=SQLITE_OK ){
+-    walIndexClose(pRet, 0);
+-    sqlite3OsClose(pRet->pWalFd);
+-    sqlite3_free(pRet);
+-  }else{
+-    int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
+-    if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
+-    if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
+-      pRet->padToSectorBoundary = 0;
+-    }
+-    *ppWal = pRet;
+-    WALTRACE(("WAL%d: opened\n", pRet));
 +  /* A frame is only valid if a checksum of the WAL header,
 +  ** all prior frams, the first 16 bytes of this frame-header, 
 +  ** and the frame-data matches the checksum in the last 8 
@@ -4252,25 +65766,25 @@
 +    /* Checksum failed. */
 +    return 0;
    }
- 
--  if( rc!=SQLITE_OK ){
--    walIndexClose(pRet, 0);
--    sqlite3OsClose(pRet->pWalFd);
--    sqlite3_free(pRet);
+-  return rc;
++
 +  /* If we reach this point, the frame is valid.  Return the page number
 +  ** and the new database size.
 +  */
 +  *piPage = pgno;
 +  *pnTruncate = sqlite3Get4byte(&aFrame[4]);
 +  return 1;
-+}
-+
+ }
+ 
 +
 +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-+/*
+ /*
+-** Change the size to which the WAL file is trucated on each reset.
 +** Names of locks.  This routine is used to provide debugging output and is not
 +** a part of an ordinary build.
-+*/
+ */
+-SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
+-  if( pWal ) pWal->mxWalSize = iLimit;
 +static const char *walLockName(int lockIdx){
 +  if( lockIdx==WAL_WRITE_LOCK ){
 +    return "WRITE-LOCK";
@@ -4278,34 +65792,58 @@
 +    return "CKPT-LOCK";
 +  }else if( lockIdx==WAL_RECOVER_LOCK ){
 +    return "RECOVER-LOCK";
-   }else{
--    int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
--    if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
--    if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
--      pRet->padToSectorBoundary = 0;
--    }
--    *ppWal = pRet;
--    WALTRACE(("WAL%d: opened\n", pRet));
++  }else{
 +    static char zName[15];
 +    sqlite3_snprintf(sizeof(zName), zName, "READ-LOCK[%d]",
 +                     lockIdx-WAL_READ_LOCK(0));
 +    return zName;
-   }
--  return rc;
++  }
  }
 +#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
 +    
  
  /*
--** Change the size to which the WAL file is trucated on each reset.
+-** Find the smallest page number out of all pages held in the WAL that
+-** has not been returned by any prior invocation of this method on the
+-** same WalIterator object.   Write into *piFrame the frame index where
+-** that page was last written into the WAL.  Write into *piPage the page
+-** number.
 +** Set or release locks on the WAL.  Locks are either shared or exclusive.
 +** A lock cannot be moved directly between shared and exclusive - it must go
 +** through the unlocked state first.
-+**
+ **
+-** Return 0 on success.  If there are no pages in the WAL with a page
+-** number larger than *piPage, then return 1.
 +** In locking_mode=EXCLUSIVE, all of these routines become no-ops.
  */
--SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
--  if( pWal ) pWal->mxWalSize = iLimit;
+-static int walIteratorNext(
+-  WalIterator *p,               /* Iterator */
+-  u32 *piPage,                  /* OUT: The page number of the next page */
+-  u32 *piFrame                  /* OUT: Wal frame index of next page */
+-){
+-  u32 iMin;                     /* Result pgno must be greater than iMin */
+-  u32 iRet = 0xFFFFFFFF;        /* 0xffffffff is never a valid page number */
+-  int i;                        /* For looping through segments */
+-
+-  iMin = p->iPrior;
+-  assert( iMin<0xffffffff );
+-  for(i=p->nSegment-1; i>=0; i--){
+-    struct WalSegment *pSegment = &p->aSegment[i];
+-    while( pSegment->iNext<pSegment->nEntry ){
+-      u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
+-      if( iPg>iMin ){
+-        if( iPg<iRet ){
+-          iRet = iPg;
+-          *piFrame = pSegment->iZero + pSegment->aIndex[pSegment->iNext];
+-        }
+-        break;
+-      }
+-      pSegment->iNext++;
+-    }
+-  }
+-
+-  *piPage = p->iPrior = iRet;
+-  return (iRet==0xFFFFFFFF);
 +static int walLockShared(Wal *pWal, int lockIdx){
 +  int rc;
 +  if( pWal->exclusiveMode ) return SQLITE_OK;
@@ -4341,56 +65879,6 @@
  }
  
  /*
--** Find the smallest page number out of all pages held in the WAL that
--** has not been returned by any prior invocation of this method on the
--** same WalIterator object.   Write into *piFrame the frame index where
--** that page was last written into the WAL.  Write into *piPage the page
--** number.
--**
--** Return 0 on success.  If there are no pages in the WAL with a page
--** number larger than *piPage, then return 1.
-+** Compute a hash on a page number.  The resulting hash value must land
-+** between 0 and (HASHTABLE_NSLOT-1).  The walHashNext() function advances
-+** the hash to the next value in the event of a collision.
- */
--static int walIteratorNext(
--  WalIterator *p,               /* Iterator */
--  u32 *piPage,                  /* OUT: The page number of the next page */
--  u32 *piFrame                  /* OUT: Wal frame index of next page */
--){
--  u32 iMin;                     /* Result pgno must be greater than iMin */
--  u32 iRet = 0xFFFFFFFF;        /* 0xffffffff is never a valid page number */
--  int i;                        /* For looping through segments */
--
--  iMin = p->iPrior;
--  assert( iMin<0xffffffff );
--  for(i=p->nSegment-1; i>=0; i--){
--    struct WalSegment *pSegment = &p->aSegment[i];
--    while( pSegment->iNext<pSegment->nEntry ){
--      u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
--      if( iPg>iMin ){
--        if( iPg<iRet ){
--          iRet = iPg;
--          *piFrame = pSegment->iZero + pSegment->aIndex[pSegment->iNext];
--        }
--        break;
--      }
--      pSegment->iNext++;
--    }
--  }
--
--  *piPage = p->iPrior = iRet;
--  return (iRet==0xFFFFFFFF);
-+static int walHash(u32 iPage){
-+  assert( iPage>0 );
-+  assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 );
-+  return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1);
-+}
-+static int walNextHash(int iPriorHash){
-+  return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
- }
- 
--/*
 -** This function merges two sorted lists into a single sorted list.
 -**
 -** aLeft[] and aRight[] are arrays of indices.  The sort key is
@@ -4408,6 +65896,19 @@
 -** 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
++** Compute a hash on a page number.  The resulting hash value must land
++** between 0 and (HASHTABLE_NSLOT-1).  The walHashNext() function advances
++** the hash to the next value in the event of a collision.
++*/
++static int walHash(u32 iPage){
++  assert( iPage>0 );
++  assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 );
++  return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1);
++}
++static int walNextHash(int iPriorHash){
++  return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
++}
++
 +/* 
 +** Return pointers to the hash table and page number array stored on
 +** page iHash of the wal-index. The wal-index is broken into 32KB pages
@@ -4891,7 +66392,12 @@
 +  u32 aFrameCksum[2] = {0, 0};
 +  int iLock;                      /* Lock offset to lock for checkpoint */
 +  int nLock;                      /* Number of locks to hold */
-+
+ 
+-  szPage = walPagesize(pWal);
+-  testcase( szPage<=32768 );
+-  testcase( szPage>=65536 );
+-  pInfo = walCkptInfo(pWal);
+-  if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
 +  /* Obtain an exclusive lock on all byte in the locking range not already
 +  ** locked by the caller. The caller is guaranteed to have locked the
 +  ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
@@ -4910,15 +66416,10 @@
 +  }
 +  WALTRACE(("WAL%p: recovery begin...\n", pWal));
  
--  szPage = walPagesize(pWal);
--  testcase( szPage<=32768 );
--  testcase( szPage>=65536 );
--  pInfo = walCkptInfo(pWal);
--  if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
-+  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
- 
 -  /* Allocate the iterator */
 -  rc = walIteratorInit(pWal, &pIter);
++  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
++
 +  rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
    if( rc!=SQLITE_OK ){
 -    return rc;
@@ -5004,8 +66505,8 @@
 +      goto finished;
      }
  
--    /* If the database file may grow as a result of this checkpoint, hint
--    ** about the eventual size of the db file to the VFS layer. 
+-    /* If the database may grow as a result of this checkpoint, hint
+-    ** about the eventual size of the db file to the VFS layer.
 -    */
 -    if( rc==SQLITE_OK ){
 -      i64 nReq = ((i64)mxPage * szPage);
@@ -5019,31 +66520,31 @@
 +    if( version!=WAL_MAX_VERSION ){
 +      rc = SQLITE_CANTOPEN_BKPT;
 +      goto finished;
-     }
- 
--    /* Iterate through the contents of the WAL, copying data to the db file. */
--    while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
--      i64 iOffset;
--      assert( walFramePgno(pWal, iFrame)==iDbpage );
--      if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
--      iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
--      /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
--      rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
++    }
++
 +    /* Malloc a buffer to read frames into. */
 +    szFrame = szPage + WAL_FRAME_HDRSIZE;
 +    aFrame = (u8 *)sqlite3_malloc(szFrame);
 +    if( !aFrame ){
 +      rc = SQLITE_NOMEM;
 +      goto recovery_error;
-+    }
+     }
 +    aData = &aFrame[WAL_FRAME_HDRSIZE];
-+
+ 
 +    /* Read all frames from the log file. */
 +    iFrame = 0;
 +    for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){
 +      u32 pgno;                   /* Database page number for frame */
 +      u32 nTruncate;              /* dbsize field from frame header */
-+
+ 
+-    /* Iterate through the contents of the WAL, copying data to the db file. */
+-    while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
+-      i64 iOffset;
+-      assert( walFramePgno(pWal, iFrame)==iDbpage );
+-      if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
+-      iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
+-      /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
+-      rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
 +      /* Read and decode the next log frame. */
 +      iFrame++;
 +      rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
@@ -5130,8 +66631,9 @@
 +    ** checkpointing the log file.
 +    */
 +    if( pWal->hdr.nPage ){
-+      sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
-+          pWal->hdr.nPage, pWal->zWalName
++      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
++          "recovered %d frames from WAL file %s",
++          pWal->hdr.mxFrame, pWal->zWalName
 +      );
      }
    }
@@ -5147,8 +66649,7 @@
  /*
 -** If the WAL file is currently larger than nMax bytes in size, truncate
 -** it to exactly nMax bytes. If an error occurs while doing so, ignore it.
-+** Close an open wal-index.
- */
+-*/
 -static void walLimitSize(Wal *pWal, i64 nMax){
 -  i64 sz;
 -  int rx;
@@ -5160,55 +66661,23 @@
 -  sqlite3EndBenignMalloc();
 -  if( rx ){
 -    sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
-+static void walIndexClose(Wal *pWal, int isDelete){
-+  if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
-+    int i;
-+    for(i=0; i<pWal->nWiData; i++){
-+      sqlite3_free((void *)pWal->apWiData[i]);
-+      pWal->apWiData[i] = 0;
-+    }
-+  }else{
-+    sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
-   }
- }
- 
+-  }
+-}
+-
 -/*
 -** Close a connection to a log file.
-+/* 
-+** Open a connection to the WAL file zWalName. The database file must 
-+** already be opened on connection pDbFd. The buffer that zWalName points
-+** to must remain valid for the lifetime of the returned Wal* handle.
-+**
-+** A SHARED lock should be held on the database file when this function
-+** is called. The purpose of this SHARED lock is to prevent any other
-+** client from unlinking the WAL or wal-index file. If another process
-+** were to do this just after this client opened one of these files, the
-+** system would be badly broken.
-+**
-+** If the log file is successfully opened, SQLITE_OK is returned and 
-+** *ppWal is set to point to a new WAL handle. If an error occurs,
-+** an SQLite error code is returned and *ppWal is left unmodified.
++** Close an open wal-index.
  */
 -SQLITE_PRIVATE int sqlite3WalClose(
 -  Wal *pWal,                      /* Wal to close */
 -  int sync_flags,                 /* Flags to pass to OsSync() (or 0) */
 -  int nBuf,
 -  u8 *zBuf                        /* Buffer of at least nBuf bytes */
-+SQLITE_PRIVATE int sqlite3WalOpen(
-+  sqlite3_vfs *pVfs,              /* vfs module to open wal and wal-index */
-+  sqlite3_file *pDbFd,            /* The open database file */
-+  const char *zWalName,           /* Name of the WAL file */
-+  int bNoShm,                     /* True to run in heap-memory mode */
-+  i64 mxWalSize,                  /* Truncate WAL to this size on reset */
-+  Wal **ppWal                     /* OUT: Allocated Wal handle */
- ){
+-){
 -  int rc = SQLITE_OK;
 -  if( pWal ){
 -    int isDelete = 0;             /* True to unlink wal and wal-index files */
-+  int rc;                         /* Return Code */
-+  Wal *pRet;                      /* Object to allocate and return */
-+  int flags;                      /* Flags passed to OsOpen() */
- 
+-
 -    /* If an EXCLUSIVE lock can be obtained on the database file (using the
 -    ** ordinary, rollback-mode locking methods, this guarantees that the
 -    ** connection associated with this log file is the only connection to
@@ -5246,71 +66715,30 @@
 -        }
 -      }
 -    }
-+  assert( zWalName && zWalName[0] );
-+  assert( pDbFd );
- 
+-
 -    walIndexClose(pWal, isDelete);
 -    sqlite3OsClose(pWal->pWalFd);
 -    if( isDelete ){
 -      sqlite3BeginBenignMalloc();
 -      sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
 -      sqlite3EndBenignMalloc();
-+  /* In the amalgamation, the os_unix.c and os_win.c source files come before
-+  ** this source file.  Verify that the #defines of the locking byte offsets
-+  ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
-+  */
-+#ifdef WIN_SHM_BASE
-+  assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
-+#endif
-+#ifdef UNIX_SHM_BASE
-+  assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
-+#endif
-+
-+
-+  /* Allocate an instance of struct Wal to return. */
-+  *ppWal = 0;
-+  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
-+  if( !pRet ){
-+    return SQLITE_NOMEM;
-+  }
-+
-+  pRet->pVfs = pVfs;
-+  pRet->pWalFd = (sqlite3_file *)&pRet[1];
-+  pRet->pDbFd = pDbFd;
-+  pRet->readLock = -1;
-+  pRet->mxWalSize = mxWalSize;
-+  pRet->zWalName = zWalName;
-+  pRet->syncHeader = 1;
-+  pRet->padToSectorBoundary = 1;
-+  pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
-+
-+  /* Open file handle on the write-ahead log file. */
-+  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
-+  rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
-+  if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
-+    pRet->readOnly = WAL_RDONLY;
-+  }
-+
-+  if( rc!=SQLITE_OK ){
-+    walIndexClose(pRet, 0);
-+    sqlite3OsClose(pRet->pWalFd);
-+    sqlite3_free(pRet);
-+  }else{
-+    int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
-+    if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
-+    if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
-+      pRet->padToSectorBoundary = 0;
++static void walIndexClose(Wal *pWal, int isDelete){
++  if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
++    int i;
++    for(i=0; i<pWal->nWiData; i++){
++      sqlite3_free((void *)pWal->apWiData[i]);
++      pWal->apWiData[i] = 0;
      }
 -    WALTRACE(("WAL%p: closed\n", pWal));
 -    sqlite3_free((void *)pWal->apWiData);
 -    sqlite3_free(pWal);
-+    *ppWal = pRet;
-+    WALTRACE(("WAL%d: opened\n", pRet));
++  }else{
++    sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
    }
-   return rc;
+-  return rc;
  }
  
- /*
+-/*
 -** Try to read the wal-index header.  Return 0 on success and 1 if
 -** there is a problem.
 -**
@@ -5319,23 +66747,47 @@
 -** read it, which might result in inconsistency.  A dirty read is detected
 -** by verifying that both copies of the header are the same and also by
 -** a checksum on the header.
--**
++/* 
++** Open a connection to the WAL file zWalName. The database file must 
++** already be opened on connection pDbFd. The buffer that zWalName points
++** to must remain valid for the lifetime of the returned Wal* handle.
+ **
 -** If and only if the read is consistent and the header is different from
 -** pWal->hdr, then pWal->hdr is updated to the content of the new header
 -** and *pChanged is set to 1.
--**
++** A SHARED lock should be held on the database file when this function
++** is called. The purpose of this SHARED lock is to prevent any other
++** client from unlinking the WAL or wal-index file. If another process
++** were to do this just after this client opened one of these files, the
++** system would be badly broken.
+ **
 -** If the checksum cannot be verified return non-zero. If the header
 -** is read successfully and the checksum verified, return zero.
-+** Change the size to which the WAL file is trucated on each reset.
++** If the log file is successfully opened, SQLITE_OK is returned and 
++** *ppWal is set to point to a new WAL handle. If an error occurs,
++** an SQLite error code is returned and *ppWal is left unmodified.
  */
 -static int walIndexTryHdr(Wal *pWal, int *pChanged){
 -  u32 aCksum[2];                  /* Checksum on the header content */
 -  WalIndexHdr h1, h2;             /* Two copies of the header content */
 -  WalIndexHdr volatile *aHdr;     /* Header in shared memory */
--
++SQLITE_PRIVATE int sqlite3WalOpen(
++  sqlite3_vfs *pVfs,              /* vfs module to open wal and wal-index */
++  sqlite3_file *pDbFd,            /* The open database file */
++  const char *zWalName,           /* Name of the WAL file */
++  int bNoShm,                     /* True to run in heap-memory mode */
++  i64 mxWalSize,                  /* Truncate WAL to this size on reset */
++  Wal **ppWal                     /* OUT: Allocated Wal handle */
++){
++  int rc;                         /* Return Code */
++  Wal *pRet;                      /* Object to allocate and return */
++  int flags;                      /* Flags passed to OsOpen() */
+ 
 -  /* The first page of the wal-index must be mapped at this point. */
 -  assert( pWal->nWiData>0 && pWal->apWiData[0] );
--
++  assert( zWalName && zWalName[0] );
++  assert( pDbFd );
+ 
 -  /* Read the header. This might happen concurrently with a write to the
 -  ** same area of shared memory on a different CPU in a SMP,
 -  ** meaning it is possible that an inconsistent snapshot is read
@@ -5345,43 +66797,53 @@
 -  ** When reading, read [0] first then [1].  Writes are in the reverse order.
 -  ** Memory barriers are used to prevent the compiler or the hardware from
 -  ** reordering the reads and writes.
--  */
++  /* In the amalgamation, the os_unix.c and os_win.c source files come before
++  ** this source file.  Verify that the #defines of the locking byte offsets
++  ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
+   */
 -  aHdr = walIndexHdr(pWal);
 -  memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
 -  walShmBarrier(pWal);
 -  memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
-+SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
-+  if( pWal ) pWal->mxWalSize = iLimit;
-+}
++#ifdef WIN_SHM_BASE
++  assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
++#endif
++#ifdef UNIX_SHM_BASE
++  assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
++#endif
  
 -  if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
 -    return 1;   /* Dirty read */
 -  }  
 -  if( h1.isInit==0 ){
 -    return 1;   /* Malformed header - probably all zeros */
--  }
++
++  /* Allocate an instance of struct Wal to return. */
++  *ppWal = 0;
++  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
++  if( !pRet ){
++    return SQLITE_NOMEM;
+   }
 -  walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
 -  if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
 -    return 1;   /* Checksum does not match */
--  }
-+/*
-+** Find the smallest page number out of all pages held in the WAL that
-+** has not been returned by any prior invocation of this method on the
-+** same WalIterator object.   Write into *piFrame the frame index where
-+** that page was last written into the WAL.  Write into *piPage the page
-+** number.
-+**
-+** Return 0 on success.  If there are no pages in the WAL with a page
-+** number larger than *piPage, then return 1.
-+*/
-+static int walIteratorNext(
-+  WalIterator *p,               /* Iterator */
-+  u32 *piPage,                  /* OUT: The page number of the next page */
-+  u32 *piFrame                  /* OUT: Wal frame index of next page */
-+){
-+  u32 iMin;                     /* Result pgno must be greater than iMin */
-+  u32 iRet = 0xFFFFFFFF;        /* 0xffffffff is never a valid page number */
-+  int i;                        /* For looping through segments */
++
++  pRet->pVfs = pVfs;
++  pRet->pWalFd = (sqlite3_file *)&pRet[1];
++  pRet->pDbFd = pDbFd;
++  pRet->readLock = -1;
++  pRet->mxWalSize = mxWalSize;
++  pRet->zWalName = zWalName;
++  pRet->syncHeader = 1;
++  pRet->padToSectorBoundary = 1;
++  pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
++
++  /* Open file handle on the write-ahead log file. */
++  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
++  rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
++  if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
++    pRet->readOnly = WAL_RDONLY;
+   }
  
 -  if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
 -    *pChanged = 1;
@@ -5389,59 +66851,49 @@
 -    pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
 -    testcase( pWal->szPage<=32768 );
 -    testcase( pWal->szPage>=65536 );
-+  iMin = p->iPrior;
-+  assert( iMin<0xffffffff );
-+  for(i=p->nSegment-1; i>=0; i--){
-+    struct WalSegment *pSegment = &p->aSegment[i];
-+    while( pSegment->iNext<pSegment->nEntry ){
-+      u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
-+      if( iPg>iMin ){
-+        if( iPg<iRet ){
-+          iRet = iPg;
-+          *piFrame = pSegment->iZero + pSegment->aIndex[pSegment->iNext];
-+        }
-+        break;
-+      }
-+      pSegment->iNext++;
++  if( rc!=SQLITE_OK ){
++    walIndexClose(pRet, 0);
++    sqlite3OsClose(pRet->pWalFd);
++    sqlite3_free(pRet);
++  }else{
++    int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
++    if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
++    if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
++      pRet->padToSectorBoundary = 0;
 +    }
++    *ppWal = pRet;
++    WALTRACE(("WAL%d: opened\n", pRet));
    }
++  return rc;
++}
  
 -  /* The header was successfully read. Return zero. */
 -  return 0;
-+  *piPage = p->iPrior = iRet;
-+  return (iRet==0xFFFFFFFF);
++/*
++** Change the size to which the WAL file is trucated on each reset.
++*/
++SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
++  if( pWal ) pWal->mxWalSize = iLimit;
  }
  
  /*
 -** Read the wal-index header from the wal-index and into pWal->hdr.
 -** If the wal-header appears to be corrupt, try to reconstruct the
 -** wal-index from the WAL before returning.
-+** This function merges two sorted lists into a single sorted list.
- **
+-**
 -** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
 -** changed by this opertion.  If pWal->hdr is unchanged, set *pChanged
 -** to 0.
-+** 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:
++** Find the smallest page number out of all pages held in the WAL that
++** has not been returned by any prior invocation of this method on the
++** same WalIterator object.   Write into *piFrame the frame index where
++** that page was last written into the WAL.  Write into *piPage the page
++** number.
  **
 -** If the wal-index header is successfully read, return SQLITE_OK. 
 -** Otherwise an SQLite error code.
-+**        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.
++** Return 0 on success.  If there are no pages in the WAL with a page
++** number larger than *piPage, then return 1.
  */
 -static int walIndexReadHdr(Wal *pWal, int *pChanged){
 -  int rc;                         /* Return code */
@@ -5457,30 +66909,21 @@
 -    return rc;
 -  };
 -  assert( page0 || pWal->writeLock==0 );
-+static void walMerge(
-+  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 */
-+  int *pnRight,                   /* IN/OUT: Elements in *paRight */
-+  ht_slot *aTmp                   /* Temporary buffer */
-+){
-+  int iLeft = 0;                  /* Current index in aLeft */
-+  int iRight = 0;                 /* Current index in aRight */
-+  int iOut = 0;                   /* Current index in output buffer */
-+  int nRight = *pnRight;
-+  ht_slot *aRight = *paRight;
- 
+-
 -  /* If the first page of the wal-index has been mapped, try to read the
 -  ** wal-index header immediately, without holding any lock. This usually
 -  ** works, but may fail if the wal-index header is corrupt or currently 
 -  ** being modified by another thread or process.
 -  */
 -  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
-+  assert( nLeft>0 && nRight>0 );
-+  while( iRight<nRight || iLeft<nLeft ){
-+    ht_slot logpage;
-+    Pgno dbpage;
++static int walIteratorNext(
++  WalIterator *p,               /* Iterator */
++  u32 *piPage,                  /* OUT: The page number of the next page */
++  u32 *piFrame                  /* OUT: Wal frame index of next page */
++){
++  u32 iMin;                     /* Result pgno must be greater than iMin */
++  u32 iRet = 0xFFFFFFFF;        /* 0xffffffff is never a valid page number */
++  int i;                        /* For looping through segments */
  
 -  /* If the first attempt failed, it might have been due to a race
 -  ** with a writer.  So get a WRITE lock and try again.
@@ -5503,10 +66946,71 @@
 -          */
 -          rc = walIndexRecover(pWal);
 -          *pChanged = 1;
--        }
--      }
++  iMin = p->iPrior;
++  assert( iMin<0xffffffff );
++  for(i=p->nSegment-1; i>=0; i--){
++    struct WalSegment *pSegment = &p->aSegment[i];
++    while( pSegment->iNext<pSegment->nEntry ){
++      u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
++      if( iPg>iMin ){
++        if( iPg<iRet ){
++          iRet = iPg;
++          *piFrame = pSegment->iZero + pSegment->aIndex[pSegment->iNext];
+         }
++        break;
+       }
 -      pWal->writeLock = 0;
 -      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
++      pSegment->iNext++;
++    }
++  }
++
++  *piPage = p->iPrior = iRet;
++  return (iRet==0xFFFFFFFF);
++}
++
++/*
++** 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(
++  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 */
++  int *pnRight,                   /* IN/OUT: Elements in *paRight */
++  ht_slot *aTmp                   /* Temporary buffer */
++){
++  int iLeft = 0;                  /* Current index in aLeft */
++  int iRight = 0;                 /* Current index in aRight */
++  int iOut = 0;                   /* Current index in output buffer */
++  int nRight = *pnRight;
++  ht_slot *aRight = *paRight;
++
++  assert( nLeft>0 && nRight>0 );
++  while( iRight<nRight || iLeft<nLeft ){
++    ht_slot logpage;
++    Pgno dbpage;
++
 +    if( (iLeft<nLeft) 
 +     && (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
 +    ){
@@ -5864,15 +67368,15 @@
  }
  
  /*
--** Read a page from the WAL, if it is present in the WAL and if the 
--** current read transaction is configured to use the WAL.  
+-** Search the wal file for page pgno. If found, set *piRead to the frame that
+-** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
+-** to zero.
 +** 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.
  **
--** The *pInWal is set to 1 if the requested page is in the WAL and
--** has been loaded.  Or *pInWal is set to 0 if the page was not in 
--** the WAL and needs to be read out of the database.
+-** Return SQLITE_OK if successful, or an error code if an error occurs. If an
+-** error does occur, the final value of *piRead is undefined.
 +** On success, make *pp point to the newly allocated WalInterator object
 +** return SQLITE_OK. Otherwise, return an error code. If this routine
 +** returns an error, the value of *pp is undefined.
@@ -5880,12 +67384,10 @@
 +** The calling routine should invoke walIteratorFree() to destroy the
 +** WalIterator object when it has finished with it.
  */
--SQLITE_PRIVATE int sqlite3WalRead(
+-SQLITE_PRIVATE int sqlite3WalFindFrame(
 -  Wal *pWal,                      /* WAL handle */
 -  Pgno pgno,                      /* Database page number to read data for */
--  int *pInWal,                    /* OUT: True if data is read from WAL */
--  int nOut,                       /* Size of buffer pOut in bytes */
--  u8 *pOut                        /* Buffer to write page data to */
+-  u32 *piRead                     /* OUT: Frame number (or zero) */
 -){
 -  u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
 -  u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
@@ -5911,7 +67413,7 @@
 +  ** it only runs if there is actually content in the log (mxFrame>0).
    */
 -  if( iLast==0 || pWal->readLock==0 ){
--    *pInWal = 0;
+-    *piRead = 0;
 -    return SQLITE_OK;
 +  assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
 +  iLast = pWal->hdr.mxFrame;
@@ -5962,7 +67464,13 @@
 -    int iKey;                     /* Hash slot index */
 -    int nCollide;                 /* Number of hash collisions remaining */
 -    int rc;                       /* Error code */
--
++  aTmp = (ht_slot *)sqlite3ScratchMalloc(
++      sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
++  );
++  if( !aTmp ){
++    rc = SQLITE_NOMEM;
++  }
+ 
 -    rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
 -    if( rc!=SQLITE_OK ){
 -      return rc;
@@ -5973,29 +67481,6 @@
 -      if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
 -        /* assert( iFrame>iRead ); -- not true if there is corruption */
 -        iRead = iFrame;
--      }
--      if( (nCollide--)==0 ){
--        return SQLITE_CORRUPT_BKPT;
--      }
--    }
-+  aTmp = (ht_slot *)sqlite3ScratchMalloc(
-+      sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
-+  );
-+  if( !aTmp ){
-+    rc = SQLITE_NOMEM;
-   }
- 
--#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
--  /* If expensive assert() statements are available, do a linear search
--  ** of the wal-index file content. Make sure the results agree with the
--  ** result obtained using the hash indexes above.  */
--  {
--    u32 iRead2 = 0;
--    u32 iTest;
--    for(iTest=iLast; iTest>0; iTest--){
--      if( walFramePgno(pWal, iTest)==pgno ){
--        iRead2 = iTest;
--        break;
 +  for(i=0; rc==SQLITE_OK && i<nSegment; i++){
 +    volatile ht_slot *aHash;
 +    u32 iZero;
@@ -6012,7 +67497,9 @@
 +        nEntry = (int)(iLast - iZero);
 +      }else{
 +        nEntry = (int)((u32*)aHash - (u32*)aPgno);
-+      }
+       }
+-      if( (nCollide--)==0 ){
+-        return SQLITE_CORRUPT_BKPT;
 +      aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
 +      iZero++;
 +  
@@ -6025,56 +67512,64 @@
 +      p->aSegment[i].aIndex = aIndex;
 +      p->aSegment[i].aPgno = (u32 *)aPgno;
      }
--    assert( iRead==iRead2 );
    }
--#endif
 +  sqlite3ScratchFree(aTmp);
  
--  /* If iRead is non-zero, then it is the log frame number that contains the
--  ** required page. Read and return data from the log file.
--  */
--  if( iRead ){
--    int sz;
--    i64 iOffset;
--    sz = pWal->hdr.szPage;
--    sz = (sz&0xfe00) + ((sz&0x0001)<<16);
--    testcase( sz<=32768 );
--    testcase( sz>=65536 );
--    iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
--    *pInWal = 1;
--    /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
--    return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
+-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+-  /* If expensive assert() statements are available, do a linear search
+-  ** of the wal-index file content. Make sure the results agree with the
+-  ** result obtained using the hash indexes above.  */
+-  {
+-    u32 iRead2 = 0;
+-    u32 iTest;
+-    for(iTest=iLast; iTest>0; iTest--){
+-      if( walFramePgno(pWal, iTest)==pgno ){
+-        iRead2 = iTest;
+-        break;
+-      }
+-    }
+-    assert( iRead==iRead2 );
 +  if( rc!=SQLITE_OK ){
 +    walIteratorFree(p);
    }
+-#endif
 -
--  *pInWal = 0;
+-  *piRead = iRead;
 -  return SQLITE_OK;
 +  *pp = p;
 +  return rc;
  }
  
--
--/* 
--** Return the size of the database in pages (or zero, if unknown).
-+/*
+ /*
+-** Read the contents of frame iRead from the wal file into buffer pOut
+-** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
+-** error code otherwise.
 +** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
 +** n. If the attempt fails and parameter xBusy is not NULL, then it is a
 +** busy-handler function. Invoke it and retry the lock until either the
 +** lock is successfully obtained or the busy-handler returns 0.
  */
--SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
--  if( pWal && ALWAYS(pWal->readLock>=0) ){
--    return pWal->hdr.nPage;
--  }
--  return 0;
+-SQLITE_PRIVATE int sqlite3WalReadFrame(
+-  Wal *pWal,                      /* WAL handle */
+-  u32 iRead,                      /* Frame to read */
+-  int nOut,                       /* Size of buffer pOut in bytes */
+-  u8 *pOut                        /* Buffer to write page data to */
 +static int walBusyLock(
 +  Wal *pWal,                      /* WAL connection */
 +  int (*xBusy)(void*),            /* Function to call when busy */
 +  void *pBusyArg,                 /* Context argument for xBusyHandler */
 +  int lockIdx,                    /* Offset of first byte to lock */
 +  int n                           /* Number of bytes to lock */
-+){
+ ){
+-  int sz;
+-  i64 iOffset;
+-  sz = pWal->hdr.szPage;
+-  sz = (sz&0xfe00) + ((sz&0x0001)<<16);
+-  testcase( sz<=32768 );
+-  testcase( sz>=65536 );
+-  iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
+-  /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
+-  return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
 +  int rc;
 +  do {
 +    rc = walLockExclusive(pWal, lockIdx, n);
@@ -6082,14 +67577,22 @@
 +  return rc;
  }
  
+-/* 
+-** Return the size of the database in pages (or zero, if unknown).
 +/*
 +** The cache of the wal-index header must be valid to call this function.
 +** Return the page-size in bytes used by the database.
-+*/
+ */
+-SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
+-  if( pWal && ALWAYS(pWal->readLock>=0) ){
+-    return pWal->hdr.nPage;
+-  }
+-  return 0;
 +static int walPagesize(Wal *pWal){
 +  return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
-+}
+ }
  
+-
 -/* 
 -** This function starts a write transaction on the WAL.
 +/*
@@ -6132,6 +67635,10 @@
  */
 -SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
 -  int rc;
+-
+-  /* Cannot start a write transaction without first holding a read
+-  ** transaction. */
+-  assert( pWal->readLock>=0 );
 +static int walCheckpoint(
 +  Wal *pWal,                      /* Wal connection */
 +  int eMode,                      /* One of PASSIVE, FULL or RESTART */
@@ -6151,26 +67658,31 @@
 +  volatile WalCkptInfo *pInfo;    /* The checkpoint status information */
 +  int (*xBusy)(void*) = 0;        /* Function to call when waiting for locks */
  
--  /* Cannot start a write transaction without first holding a read
--  ** transaction. */
--  assert( pWal->readLock>=0 );
+-  if( pWal->readOnly ){
+-    return SQLITE_READONLY;
+-  }
 +  szPage = walPagesize(pWal);
 +  testcase( szPage<=32768 );
 +  testcase( szPage>=65536 );
 +  pInfo = walCkptInfo(pWal);
 +  if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
  
--  if( pWal->readOnly ){
--    return SQLITE_READONLY;
+-  /* Only one writer allowed at a time.  Get the write lock.  Return
+-  ** SQLITE_BUSY if unable.
+-  */
+-  rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+-  if( rc ){
 +  /* Allocate the iterator */
 +  rc = walIteratorInit(pWal, &pIter);
 +  if( rc!=SQLITE_OK ){
-+    return rc;
+     return rc;
    }
+-  pWal->writeLock = 1;
 +  assert( pIter );
  
--  /* Only one writer allowed at a time.  Get the write lock.  Return
--  ** SQLITE_BUSY if unable.
+-  /* If another connection has written to the database file since the
+-  ** time the read transaction on this connection was started, then
+-  ** the write is disallowed.
 +  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
 +
 +  /* Compute in mxSafeFrame the index of the last frame of the WAL that is
@@ -6178,9 +67690,10 @@
 +  ** overwrite database pages that are in use by active readers and thus
 +  ** cannot be backfilled from the WAL.
    */
--  rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
--  if( rc ){
--    return rc;
+-  if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
+-    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+-    pWal->writeLock = 0;
+-    rc = SQLITE_BUSY;
 +  mxSafeFrame = pWal->hdr.mxFrame;
 +  mxPage = pWal->hdr.nPage;
 +  for(i=1; i<WAL_NREADER; i++){
@@ -6199,33 +67712,109 @@
 +      }
 +    }
    }
--  pWal->writeLock = 1;
  
--  /* If another connection has written to the database file since the
--  ** time the read transaction on this connection was started, then
--  ** the write is disallowed.
+-  return rc;
+-}
 +  if( pInfo->nBackfill<mxSafeFrame
 +   && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
 +  ){
 +    i64 nSize;                    /* Current size of database file */
 +    u32 nBackfill = pInfo->nBackfill;
-+
+ 
+-/*
+-** End a write transaction.  The commit has already been done.  This
+-** routine merely releases the lock.
+-*/
+-SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
+-  if( pWal->writeLock ){
+-    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+-    pWal->writeLock = 0;
+-    pWal->truncateOnCommit = 0;
+-  }
+-  return SQLITE_OK;
+-}
 +    /* Sync the WAL to disk */
 +    if( sync_flags ){
 +      rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
 +    }
-+
-+    /* If the database file may grow as a result of this checkpoint, hint
-+    ** about the eventual size of the db file to the VFS layer. 
-+    */
+ 
+-/*
+-** If any data has been written (but not committed) to the log file, this
+-** function moves the write-pointer back to the start of the transaction.
+-**
+-** Additionally, the callback function is invoked for each frame written
+-** to the WAL since the start of the transaction. If the callback returns
+-** other than SQLITE_OK, it is not invoked again and the error code is
+-** returned to the caller.
+-**
+-** Otherwise, if the callback function does not return an error, this
+-** function returns SQLITE_OK.
+-*/
+-SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
+-  int rc = SQLITE_OK;
+-  if( ALWAYS(pWal->writeLock) ){
+-    Pgno iMax = pWal->hdr.mxFrame;
+-    Pgno iFrame;
+-  
+-    /* Restore the clients cache of the wal-index header to the state it
+-    ** was in before the client began writing to the database. 
++    /* If the database may grow as a result of this checkpoint, hint
++    ** about the eventual size of the db file to the VFS layer.
+     */
+-    memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
+-
+-    for(iFrame=pWal->hdr.mxFrame+1; 
+-        ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; 
+-        iFrame++
+-    ){
+-      /* This call cannot fail. Unless the page for which the page number
+-      ** is passed as the second argument is (a) in the cache and 
+-      ** (b) has an outstanding reference, then xUndo is either a no-op
+-      ** (if (a) is false) or simply expels the page from the cache (if (b)
+-      ** is false).
+-      **
+-      ** If the upper layer is doing a rollback, it is guaranteed that there
+-      ** are no outstanding references to any page other than page 1. And
+-      ** page 1 is never written to the log until the transaction is
+-      ** committed. As a result, the call to xUndo may not fail.
+-      */
+-      assert( walFramePgno(pWal, iFrame)!=1 );
+-      rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
 +    if( rc==SQLITE_OK ){
 +      i64 nReq = ((i64)mxPage * szPage);
 +      rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
 +      if( rc==SQLITE_OK && nSize<nReq ){
 +        sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
 +      }
-+    }
-+
+     }
+-    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
+-  }
+-  assert( rc==SQLITE_OK );
+-  return rc;
+-}
+ 
+-/* 
+-** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 
+-** values. This function populates the array with values required to 
+-** "rollback" the write position of the WAL handle back to the current 
+-** point in the event of a savepoint rollback (via WalSavepointUndo()).
+-*/
+-SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
+-  assert( pWal->writeLock );
+-  aWalData[0] = pWal->hdr.mxFrame;
+-  aWalData[1] = pWal->hdr.aFrameCksum[0];
+-  aWalData[2] = pWal->hdr.aFrameCksum[1];
+-  aWalData[3] = pWal->nCkpt;
+-}
+ 
+-/* 
+-** Move the write position of the WAL back to the point identified by
+-** the values in the aWalData[] array. aWalData must point to an array
+-** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
+-** by a call to WalSavepoint().
+-*/
+-SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
+-  int rc = SQLITE_OK;
 +    /* Iterate through the contents of the WAL, copying data to the db file. */
 +    while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
 +      i64 iOffset;
@@ -6240,7 +67829,9 @@
 +      rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
 +      if( rc!=SQLITE_OK ) break;
 +    }
-+
+ 
+-  assert( pWal->writeLock );
+-  assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame );
 +    /* If work was actually accomplished... */
 +    if( rc==SQLITE_OK ){
 +      if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
@@ -6255,26 +67846,61 @@
 +        pInfo->nBackfill = mxSafeFrame;
 +      }
 +    }
-+
+ 
+-  if( aWalData[3]!=pWal->nCkpt ){
+-    /* This savepoint was opened immediately after the write-transaction
+-    ** was started. Right after that, the writer decided to wrap around
+-    ** to the start of the log. Update the savepoint values to match.
+-    */
+-    aWalData[0] = 0;
+-    aWalData[3] = pWal->nCkpt;
 +    /* Release the reader lock held while backfilling */
 +    walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
-+  }
-+
+   }
+ 
+-  if( aWalData[0]<pWal->hdr.mxFrame ){
+-    pWal->hdr.mxFrame = aWalData[0];
+-    pWal->hdr.aFrameCksum[0] = aWalData[1];
+-    pWal->hdr.aFrameCksum[1] = aWalData[2];
+-    walCleanupHash(pWal);
 +  if( rc==SQLITE_BUSY ){
 +    /* Reset the return code so as not to report a checkpoint failure
 +    ** just because there are active readers.  */
 +    rc = SQLITE_OK;
-+  }
-+
+   }
+ 
+-  return rc;
+-}
+-
+-
+-/*
+-** This function is called just before writing a set of frames to the log
+-** file (see sqlite3WalFrames()). It checks to see if, instead of appending
+-** to the current log file, it is possible to overwrite the start of the
+-** existing log file with the new frames (i.e. "reset" the log). If so,
+-** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left
+-** unchanged.
+-**
+-** SQLITE_OK is returned if no error is encountered (regardless of whether
+-** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned
+-** if an error occurs.
+-*/
+-static int walRestartLog(Wal *pWal){
+-  int rc = SQLITE_OK;
+-  int cnt;
+-
+-  if( pWal->readLock==0 ){
+-    volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+-    assert( pInfo->nBackfill==pWal->hdr.mxFrame );
+-    if( pInfo->nBackfill>0 ){
+-      u32 salt1;
+-      sqlite3_randomness(4, &salt1);
+-      rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
 +  /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal
 +  ** file has been copied into the database file, then block until all
 +  ** readers have finished using the wal file. This ensures that the next
 +  ** process to write to the database restarts the wal file.
-   */
--  if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
--    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
--    pWal->writeLock = 0;
--    rc = SQLITE_BUSY;
++  */
 +  if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
 +    assert( pWal->writeLock );
 +    if( pInfo->nBackfill<pWal->hdr.mxFrame ){
@@ -6282,28 +67908,92 @@
 +    }else if( eMode==SQLITE_CHECKPOINT_RESTART ){
 +      assert( mxSafeFrame==pWal->hdr.mxFrame );
 +      rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
-+      if( rc==SQLITE_OK ){
-+        walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
-+      }
-+    }
+       if( rc==SQLITE_OK ){
+-        /* If all readers are using WAL_READ_LOCK(0) (in other words if no
+-        ** readers are currently using the WAL), then the transactions
+-        ** frames will overwrite the start of the existing log. Update the
+-        ** wal-index header to reflect this.
+-        **
+-        ** In theory it would be Ok to update the cache of the header only
+-        ** at this point. But updating the actual wal-index header is also
+-        ** safe and means there is no special case for sqlite3WalUndo()
+-        ** to handle if this transaction is rolled back.
+-        */
+-        int i;                    /* Loop counter */
+-        u32 *aSalt = pWal->hdr.aSalt;       /* Big-endian salt values */
+-
+-        pWal->nCkpt++;
+-        pWal->hdr.mxFrame = 0;
+-        sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
+-        aSalt[1] = salt1;
+-        walIndexWriteHdr(pWal);
+-        pInfo->nBackfill = 0;
+-        pInfo->aReadMark[1] = 0;
+-        for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+-        assert( pInfo->aReadMark[0]==0 );
+         walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+-      }else if( rc!=SQLITE_BUSY ){
+-        return rc;
+       }
+     }
+-    walUnlockShared(pWal, WAL_READ_LOCK(0));
+-    pWal->readLock = -1;
+-    cnt = 0;
+-    do{
+-      int notUsed;
+-      rc = walTryBeginRead(pWal, &notUsed, 1, ++cnt);
+-    }while( rc==WAL_RETRY );
+-    assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */
+-    testcase( (rc&0xff)==SQLITE_IOERR );
+-    testcase( rc==SQLITE_PROTOCOL );
+-    testcase( rc==SQLITE_OK );
    }
- 
++
 + walcheckpoint_out:
 +  walIteratorFree(pIter);
    return rc;
  }
  
  /*
--** End a write transaction.  The commit has already been done.  This
--** routine merely releases the lock.
+-** Information about the current state of the WAL file and where
+-** the next fsync should occur - passed from sqlite3WalFrames() into
+-** walWriteToLog().
+-*/
+-typedef struct WalWriter {
+-  Wal *pWal;                   /* The complete WAL information */
+-  sqlite3_file *pFd;           /* The WAL file to which we write */
+-  sqlite3_int64 iSyncPoint;    /* Fsync at this offset */
+-  int syncFlags;               /* Flags for the fsync */
+-  int szPage;                  /* Size of one page */
+-} WalWriter;
+-
+-/*
+-** Write iAmt bytes of content into the WAL file beginning at iOffset.
+-** Do a sync when crossing the p->iSyncPoint boundary.
+-**
+-** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt,
+-** first write the part before iSyncPoint, then sync, then write the
+-** rest.
 +** If the WAL file is currently larger than nMax bytes in size, truncate
 +** it to exactly nMax bytes. If an error occurs while doing so, ignore it.
  */
--SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
--  if( pWal->writeLock ){
--    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
--    pWal->writeLock = 0;
--    pWal->truncateOnCommit = 0;
+-static int walWriteToLog(
+-  WalWriter *p,              /* WAL to write to */
+-  void *pContent,            /* Content to be written */
+-  int iAmt,                  /* Number of bytes to write */
+-  sqlite3_int64 iOffset      /* Start writing at this offset */
+-){
+-  int rc;
+-  if( iOffset<p->iSyncPoint && iOffset+iAmt>=p->iSyncPoint ){
+-    int iFirstAmt = (int)(p->iSyncPoint - iOffset);
+-    rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset);
+-    if( rc ) return rc;
+-    iOffset += iFirstAmt;
+-    iAmt -= iFirstAmt;
+-    pContent = (void*)(iFirstAmt + (char*)pContent);
+-    assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
+-    rc = sqlite3OsSync(p->pFd, p->syncFlags);
+-    if( iAmt==0 || rc ) return rc;
 +static void walLimitSize(Wal *pWal, i64 nMax){
 +  i64 sz;
 +  int rx;
@@ -6316,36 +68006,39 @@
 +  if( rx ){
 +    sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
    }
--  return SQLITE_OK;
+-  rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
+-  return rc;
  }
  
  /*
--** If any data has been written (but not committed) to the log file, this
--** function moves the write-pointer back to the start of the transaction.
--**
--** Additionally, the callback function is invoked for each frame written
--** to the WAL since the start of the transaction. If the callback returns
--** other than SQLITE_OK, it is not invoked again and the error code is
--** returned to the caller.
--**
--** Otherwise, if the callback function does not return an error, this
--** function returns SQLITE_OK.
+-** Write out a single frame of the WAL
 +** Close a connection to a log file.
  */
--SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
+-static int walWriteOneFrame(
+-  WalWriter *p,               /* Where to write the frame */
+-  PgHdr *pPage,               /* The page of the frame to be written */
+-  int nTruncate,              /* The commit flag.  Usually 0.  >0 for commit */
+-  sqlite3_int64 iOffset       /* Byte offset at which to write */
 +SQLITE_PRIVATE int sqlite3WalClose(
 +  Wal *pWal,                      /* Wal to close */
 +  int sync_flags,                 /* Flags to pass to OsSync() (or 0) */
 +  int nBuf,
 +  u8 *zBuf                        /* Buffer of at least nBuf bytes */
-+){
-   int rc = SQLITE_OK;
--  if( ALWAYS(pWal->writeLock) ){
--    Pgno iMax = pWal->hdr.mxFrame;
--    Pgno iFrame;
--  
--    /* Restore the clients cache of the wal-index header to the state it
--    ** was in before the client began writing to the database. 
+ ){
+-  int rc;                         /* Result code from subfunctions */
+-  void *pData;                    /* Data actually written */
+-  u8 aFrame[WAL_FRAME_HDRSIZE];   /* Buffer to assemble frame-header in */
+-#if defined(SQLITE_HAS_CODEC)
+-  if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM;
+-#else
+-  pData = pPage->pData;
+-#endif
+-  walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
+-  rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
+-  if( rc ) return rc;
+-  /* Write the page data */
+-  rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
++  int rc = SQLITE_OK;
 +  if( pWal ){
 +    int isDelete = 0;             /* True to unlink wal and wal-index files */
 +
@@ -6356,8 +68049,7 @@
 +    ** the wal and wal-index files.
 +    **
 +    ** The EXCLUSIVE lock is not released before returning.
-     */
--    memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
++    */
 +    rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
 +    if( rc==SQLITE_OK ){
 +      if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
@@ -6387,45 +68079,24 @@
 +        }
 +      }
 +    }
- 
--    for(iFrame=pWal->hdr.mxFrame+1; 
--        ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; 
--        iFrame++
--    ){
--      /* This call cannot fail. Unless the page for which the page number
--      ** is passed as the second argument is (a) in the cache and 
--      ** (b) has an outstanding reference, then xUndo is either a no-op
--      ** (if (a) is false) or simply expels the page from the cache (if (b)
--      ** is false).
--      **
--      ** If the upper layer is doing a rollback, it is guaranteed that there
--      ** are no outstanding references to any page other than page 1. And
--      ** page 1 is never written to the log until the transaction is
--      ** committed. As a result, the call to xUndo may not fail.
--      */
--      assert( walFramePgno(pWal, iFrame)!=1 );
--      rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
++
 +    walIndexClose(pWal, isDelete);
 +    sqlite3OsClose(pWal->pWalFd);
 +    if( isDelete ){
 +      sqlite3BeginBenignMalloc();
 +      sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
 +      sqlite3EndBenignMalloc();
-     }
--    walCleanupHash(pWal);
++    }
 +    WALTRACE(("WAL%p: closed\n", pWal));
 +    sqlite3_free((void *)pWal->apWiData);
 +    sqlite3_free(pWal);
-   }
--  assert( rc==SQLITE_OK );
++  }
    return rc;
  }
  
 -/* 
--** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 
--** values. This function populates the array with values required to 
--** "rollback" the write position of the WAL handle back to the current 
--** point in the event of a savepoint rollback (via WalSavepointUndo()).
+-** Write a set of frames to the log. The caller must hold the write-lock
+-** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
 +/*
 +** Try to read the wal-index header.  Return 0 on success and 1 if
 +** there is a problem.
@@ -6443,31 +68114,35 @@
 +** If the checksum cannot be verified return non-zero. If the header
 +** is read successfully and the checksum verified, return zero.
  */
--SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
--  assert( pWal->writeLock );
--  aWalData[0] = pWal->hdr.mxFrame;
--  aWalData[1] = pWal->hdr.aFrameCksum[0];
--  aWalData[2] = pWal->hdr.aFrameCksum[1];
--  aWalData[3] = pWal->nCkpt;
--}
+-SQLITE_PRIVATE int sqlite3WalFrames(
+-  Wal *pWal,                      /* Wal handle to write to */
+-  int szPage,                     /* Database page-size in bytes */
+-  PgHdr *pList,                   /* List of dirty pages to write */
+-  Pgno nTruncate,                 /* Database size after this commit */
+-  int isCommit,                   /* True if this is a commit */
+-  int sync_flags                  /* Flags to pass to OsSync() (or 0) */
+-){
+-  int rc;                         /* Used to catch return codes */
+-  u32 iFrame;                     /* Next frame address */
+-  PgHdr *p;                       /* Iterator to run through pList with. */
+-  PgHdr *pLast = 0;               /* Last frame in list */
+-  int nExtra = 0;                 /* Number of extra copies of last page */
+-  int szFrame;                    /* The size of a single frame */
+-  i64 iOffset;                    /* Next byte to write in WAL file */
+-  WalWriter w;                    /* The writer */
 +static int walIndexTryHdr(Wal *pWal, int *pChanged){
 +  u32 aCksum[2];                  /* Checksum on the header content */
 +  WalIndexHdr h1, h2;             /* Two copies of the header content */
 +  WalIndexHdr volatile *aHdr;     /* Header in shared memory */
  
--/* 
--** Move the write position of the WAL back to the point identified by
--** the values in the aWalData[] array. aWalData must point to an array
--** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
--** by a call to WalSavepoint().
--*/
--SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
--  int rc = SQLITE_OK;
+-  assert( pList );
+-  assert( pWal->writeLock );
 +  /* The first page of the wal-index must be mapped at this point. */
 +  assert( pWal->nWiData>0 && pWal->apWiData[0] );
  
--  assert( pWal->writeLock );
--  assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame );
+-  /* If this frame set completes a transaction, then nTruncate>0.  If
+-  ** nTruncate==0 then this frame set does not complete the transaction. */
+-  assert( (isCommit!=0)==(nTruncate!=0) );
 +  /* Read the header. This might happen concurrently with a write to the
 +  ** same area of shared memory on a different CPU in a SMP,
 +  ** meaning it is possible that an inconsistent snapshot is read
@@ -6483,29 +68158,70 @@
 +  walShmBarrier(pWal);
 +  memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
  
--  if( aWalData[3]!=pWal->nCkpt ){
--    /* This savepoint was opened immediately after the write-transaction
--    ** was started. Right after that, the writer decided to wrap around
--    ** to the start of the log. Update the savepoint values to match.
--    */
--    aWalData[0] = 0;
--    aWalData[3] = pWal->nCkpt;
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+-  { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
+-    WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
+-              pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
 +  if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
 +    return 1;   /* Dirty read */
 +  }  
 +  if( h1.isInit==0 ){
 +    return 1;   /* Malformed header - probably all zeros */
-+  }
+   }
+-#endif
+-
+-  /* See if it is possible to write these frames into the start of the
+-  ** log file, instead of appending to it at pWal->hdr.mxFrame.
+-  */
+-  if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
+-    return rc;
 +  walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
 +  if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
 +    return 1;   /* Checksum does not match */
    }
  
--  if( aWalData[0]<pWal->hdr.mxFrame ){
--    pWal->hdr.mxFrame = aWalData[0];
--    pWal->hdr.aFrameCksum[0] = aWalData[1];
--    pWal->hdr.aFrameCksum[1] = aWalData[2];
--    walCleanupHash(pWal);
+-  /* If this is the first frame written into the log, write the WAL
+-  ** header to the start of the WAL file. See comments at the top of
+-  ** this source file for a description of the WAL header format.
+-  */
+-  iFrame = pWal->hdr.mxFrame;
+-  if( iFrame==0 ){
+-    u8 aWalHdr[WAL_HDRSIZE];      /* Buffer to assemble wal-header in */
+-    u32 aCksum[2];                /* Checksum for wal-header */
+-
+-    sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
+-    sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
+-    sqlite3Put4byte(&aWalHdr[8], szPage);
+-    sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
+-    if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt);
+-    memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
+-    walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
+-    sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
+-    sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
+-    
+-    pWal->szPage = szPage;
+-    pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
+-    pWal->hdr.aFrameCksum[0] = aCksum[0];
+-    pWal->hdr.aFrameCksum[1] = aCksum[1];
+-    pWal->truncateOnCommit = 1;
+-
+-    rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
+-    WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
+-    if( rc!=SQLITE_OK ){
+-      return rc;
+-    }
+-
+-    /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless
+-    ** all syncing is turned off by PRAGMA synchronous=OFF).  Otherwise
+-    ** an out-of-order write following a WAL restart could result in
+-    ** database corruption.  See the ticket:
+-    **
+-    **     http://localhost:591/sqlite/info/ff5be73dee
+-    */
+-    if( pWal->syncHeader && sync_flags ){
+-      rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
+-      if( rc ) return rc;
+-    }
 +  if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
 +    *pChanged = 1;
 +    memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
@@ -6513,65 +68229,78 @@
 +    testcase( pWal->szPage<=32768 );
 +    testcase( pWal->szPage>=65536 );
    }
+-  assert( (int)pWal->szPage==szPage );
  
--  return rc;
+-  /* Setup information needed to write frames into the WAL */
+-  w.pWal = pWal;
+-  w.pFd = pWal->pWalFd;
+-  w.iSyncPoint = 0;
+-  w.syncFlags = sync_flags;
+-  w.szPage = szPage;
+-  iOffset = walFrameOffset(iFrame+1, szPage);
+-  szFrame = szPage + WAL_FRAME_HDRSIZE;
 +  /* The header was successfully read. Return zero. */
 +  return 0;
- }
++}
  
--
- /*
--** This function is called just before writing a set of frames to the log
--** file (see sqlite3WalFrames()). It checks to see if, instead of appending
--** to the current log file, it is possible to overwrite the start of the
--** existing log file with the new frames (i.e. "reset" the log). If so,
--** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left
--** unchanged.
+-  /* Write all frames into the log file exactly once */
+-  for(p=pList; p; p=p->pDirty){
+-    int nDbSize;   /* 0 normally.  Positive == commit flag */
+-    iFrame++;
+-    assert( iOffset==walFrameOffset(iFrame, szPage) );
+-    nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
+-    rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
+-    if( rc ) return rc;
+-    pLast = p;
+-    iOffset += szFrame;
+-  }
++/*
 +** Read the wal-index header from the wal-index and into pWal->hdr.
 +** If the wal-header appears to be corrupt, try to reconstruct the
 +** wal-index from the WAL before returning.
- **
--** SQLITE_OK is returned if no error is encountered (regardless of whether
--** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned
--** if an error occurs.
++**
 +** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
 +** changed by this opertion.  If pWal->hdr is unchanged, set *pChanged
 +** to 0.
 +**
 +** If the wal-index header is successfully read, return SQLITE_OK. 
 +** Otherwise an SQLite error code.
- */
--static int walRestartLog(Wal *pWal){
--  int rc = SQLITE_OK;
--  int cnt;
++*/
 +static int walIndexReadHdr(Wal *pWal, int *pChanged){
 +  int rc;                         /* Return code */
 +  int badHdr;                     /* True if a header read failed */
 +  volatile u32 *page0;            /* Chunk of wal-index containing header */
  
--  if( pWal->readLock==0 ){
--    volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
--    assert( pInfo->nBackfill==pWal->hdr.mxFrame );
--    if( pInfo->nBackfill>0 ){
--      u32 salt1;
--      sqlite3_randomness(4, &salt1);
--      rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
--      if( rc==SQLITE_OK ){
--        /* If all readers are using WAL_READ_LOCK(0) (in other words if no
--        ** readers are currently using the WAL), then the transactions
--        ** frames will overwrite the start of the existing log. Update the
--        ** wal-index header to reflect this.
--        **
--        ** In theory it would be Ok to update the cache of the header only
--        ** at this point. But updating the actual wal-index header is also
--        ** safe and means there is no special case for sqlite3WalUndo()
--        ** to handle if this transaction is rolled back.
--        */
--        int i;                    /* Loop counter */
--        u32 *aSalt = pWal->hdr.aSalt;       /* Big-endian salt values */
+-  /* If this is the end of a transaction, then we might need to pad
+-  ** the transaction and/or sync the WAL file.
+-  **
+-  ** Padding and syncing only occur if this set of frames complete a
+-  ** transaction and if PRAGMA synchronous=FULL.  If synchronous==NORMAL
+-  ** or synchonous==OFF, then no padding or syncing are needed.
+-  **
+-  ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not
+-  ** needed and only the sync is done.  If padding is needed, then the
+-  ** final frame is repeated (with its commit mark) until the next sector
+-  ** boundary is crossed.  Only the part of the WAL prior to the last
+-  ** sector boundary is synced; the part of the last frame that extends
+-  ** past the sector boundary is written after the sync.
 +  /* Ensure that page 0 of the wal-index (the page that contains the 
 +  ** wal-index header) is mapped. Return early if an error occurs here.
-+  */
+   */
+-  if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
+-    if( pWal->padToSectorBoundary ){
+-      int sectorSize = sqlite3SectorSize(pWal->pWalFd);
+-      w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
+-      while( iOffset<w.iSyncPoint ){
+-        rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
+-        if( rc ) return rc;
+-        iOffset += szFrame;
+-        nExtra++;
+-      }
+-    }else{
+-      rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
+-    }
+-  }
 +  assert( pChanged );
 +  rc = walIndexPage(pWal, 0, &page0);
 +  if( rc!=SQLITE_OK ){
@@ -6579,28 +68308,40 @@
 +  };
 +  assert( page0 || pWal->writeLock==0 );
  
--        pWal->nCkpt++;
--        pWal->hdr.mxFrame = 0;
--        sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
--        aSalt[1] = salt1;
--        walIndexWriteHdr(pWal);
--        pInfo->nBackfill = 0;
--        pInfo->aReadMark[1] = 0;
--        for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
--        assert( pInfo->aReadMark[0]==0 );
--        walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
--      }else if( rc!=SQLITE_BUSY ){
--        return rc;
+-  /* If this frame set completes the first transaction in the WAL and
+-  ** if PRAGMA journal_size_limit is set, then truncate the WAL to the
+-  ** journal size limit, if possible.
 +  /* If the first page of the wal-index has been mapped, try to read the
 +  ** wal-index header immediately, without holding any lock. This usually
 +  ** works, but may fail if the wal-index header is corrupt or currently 
 +  ** being modified by another thread or process.
-+  */
+   */
+-  if( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){
+-    i64 sz = pWal->mxWalSize;
+-    if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){
+-      sz = walFrameOffset(iFrame+nExtra+1, szPage);
+-    }
+-    walLimitSize(pWal, sz);
+-    pWal->truncateOnCommit = 0;
+-  }
 +  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
-+
+ 
+-  /* Append data to the wal-index. It is not necessary to lock the 
+-  ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
+-  ** guarantees that there are no other writers, and no data that may
+-  ** be in use by existing readers is being overwritten.
 +  /* If the first attempt failed, it might have been due to a race
 +  ** with a writer.  So get a WRITE lock and try again.
-+  */
+   */
+-  iFrame = pWal->hdr.mxFrame;
+-  for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
+-    iFrame++;
+-    rc = walIndexAppend(pWal, iFrame, p->pgno);
+-  }
+-  while( rc==SQLITE_OK && nExtra>0 ){
+-    iFrame++;
+-    nExtra--;
+-    rc = walIndexAppend(pWal, iFrame, pLast->pgno);
 +  assert( badHdr==0 || pWal->writeLock==0 );
 +  if( badHdr ){
 +    if( pWal->readOnly & WAL_SHM_RDONLY ){
@@ -6620,63 +68361,27 @@
 +          rc = walIndexRecover(pWal);
 +          *pChanged = 1;
 +        }
-       }
++      }
 +      pWal->writeLock = 0;
 +      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
-     }
--    walUnlockShared(pWal, WAL_READ_LOCK(0));
--    pWal->readLock = -1;
--    cnt = 0;
--    do{
--      int notUsed;
--      rc = walTryBeginRead(pWal, &notUsed, 1, ++cnt);
--    }while( rc==WAL_RETRY );
--    assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */
--    testcase( (rc&0xff)==SQLITE_IOERR );
--    testcase( rc==SQLITE_PROTOCOL );
--    testcase( rc==SQLITE_OK );
++    }
    }
--  return rc;
--}
--
--/*
--** Information about the current state of the WAL file and where
--** the next fsync should occur - passed from sqlite3WalFrames() into
--** walWriteToLog().
--*/
--typedef struct WalWriter {
--  Wal *pWal;                   /* The complete WAL information */
--  sqlite3_file *pFd;           /* The WAL file to which we write */
--  sqlite3_int64 iSyncPoint;    /* Fsync at this offset */
--  int syncFlags;               /* Flags for the fsync */
--  int szPage;                  /* Size of one page */
--} WalWriter;
  
--/*
--** Write iAmt bytes of content into the WAL file beginning at iOffset.
--** Do a sync when crossing the p->iSyncPoint boundary.
--**
--** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt,
--** first write the part before iSyncPoint, then sync, then write the
--** rest.
--*/
--static int walWriteToLog(
--  WalWriter *p,              /* WAL to write to */
--  void *pContent,            /* Content to be written */
--  int iAmt,                  /* Number of bytes to write */
--  sqlite3_int64 iOffset      /* Start writing at this offset */
--){
--  int rc;
--  if( iOffset<p->iSyncPoint && iOffset+iAmt>=p->iSyncPoint ){
--    int iFirstAmt = (int)(p->iSyncPoint - iOffset);
--    rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset);
--    if( rc ) return rc;
--    iOffset += iFirstAmt;
--    iAmt -= iFirstAmt;
--    pContent = (void*)(iFirstAmt + (char*)pContent);
--    assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
--    rc = sqlite3OsSync(p->pFd, p->syncFlags);
--    if( iAmt==0 || rc ) return rc;
+-  if( rc==SQLITE_OK ){
+-    /* Update the private copy of the header. */
+-    pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
+-    testcase( szPage<=32768 );
+-    testcase( szPage>=65536 );
+-    pWal->hdr.mxFrame = iFrame;
+-    if( isCommit ){
+-      pWal->hdr.iChange++;
+-      pWal->hdr.nPage = nTruncate;
+-    }
+-    /* If this is a commit, update the wal-index header too. */
+-    if( isCommit ){
+-      walIndexWriteHdr(pWal);
+-      pWal->iCallback = iFrame;
+-    }
 +  /* If the header is read successfully, check the version number to make
 +  ** sure the wal-index was not constructed with some future format that
 +  ** this version of SQLite cannot understand.
@@ -6684,51 +68389,33 @@
 +  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
 +    rc = SQLITE_CANTOPEN_BKPT;
    }
--  rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
-+
+ 
+-  WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
    return rc;
  }
  
- /*
--** Write out a single frame of the WAL
+-/* 
+-** This routine is called to implement sqlite3_wal_checkpoint() and
+-** related interfaces.
++/*
 +** This is the value that walTryBeginRead returns when it needs to
 +** be retried.
- */
--static int walWriteOneFrame(
--  WalWriter *p,               /* Where to write the frame */
--  PgHdr *pPage,               /* The page of the frame to be written */
--  int nTruncate,              /* The commit flag.  Usually 0.  >0 for commit */
--  sqlite3_int64 iOffset       /* Byte offset at which to write */
--){
--  int rc;                         /* Result code from subfunctions */
--  void *pData;                    /* Data actually written */
--  u8 aFrame[WAL_FRAME_HDRSIZE];   /* Buffer to assemble frame-header in */
--#if defined(SQLITE_HAS_CODEC)
--  if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM;
--#else
--  pData = pPage->pData;
--#endif
--  walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
--  rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
--  if( rc ) return rc;
--  /* Write the page data */
--  rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
--  return rc;
--}
++*/
 +#define WAL_RETRY  (-1)
- 
--/* 
--** Write a set of frames to the log. The caller must hold the write-lock
--** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
++
 +/*
 +** Attempt to start a read transaction.  This might fail due to a race or
 +** other transient condition.  When that happens, it returns WAL_RETRY to
 +** indicate to the caller that it is safe to retry immediately.
-+**
+ **
+-** Obtain a CHECKPOINT lock and then backfill as much information as
+-** we can from WAL into the database.
 +** On success return SQLITE_OK.  On a permanent failure (such an
 +** I/O error or an SQLITE_BUSY because another process is running
 +** recovery) return a positive error code.
-+**
+ **
+-** If parameter xBusy is not NULL, it is a pointer to a busy-handler
+-** callback. In this case this function runs a blocking checkpoint.
 +** The useWal parameter is true to force the use of the WAL and disable
 +** the case where the WAL is bypassed because it has been completely
 +** checkpointed.  If useWal==0 then this routine calls walIndexReadHdr() 
@@ -6770,29 +68457,23 @@
 +** so it takes care to hold an exclusive lock on the corresponding
 +** WAL_READ_LOCK() while changing values.
  */
--SQLITE_PRIVATE int sqlite3WalFrames(
--  Wal *pWal,                      /* Wal handle to write to */
--  int szPage,                     /* Database page-size in bytes */
--  PgHdr *pList,                   /* List of dirty pages to write */
--  Pgno nTruncate,                 /* Database size after this commit */
--  int isCommit,                   /* True if this is a commit */
--  int sync_flags                  /* Flags to pass to OsSync() (or 0) */
+-SQLITE_PRIVATE int sqlite3WalCheckpoint(
+-  Wal *pWal,                      /* Wal connection */
+-  int eMode,                      /* PASSIVE, FULL or RESTART */
+-  int (*xBusy)(void*),            /* Function to call when busy */
+-  void *pBusyArg,                 /* Context argument for xBusyHandler */
+-  int sync_flags,                 /* Flags to sync db file with (or 0) */
+-  int nBuf,                       /* Size of temporary buffer */
+-  u8 *zBuf,                       /* Temporary buffer to use */
+-  int *pnLog,                     /* OUT: Number of frames in WAL */
+-  int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
 -){
--  int rc;                         /* Used to catch return codes */
--  u32 iFrame;                     /* Next frame address */
--  PgHdr *p;                       /* Iterator to run through pList with. */
--  PgHdr *pLast = 0;               /* Last frame in list */
--  int nExtra = 0;                 /* Number of extra copies of last page */
--  int szFrame;                    /* The size of a single frame */
--  i64 iOffset;                    /* Next byte to write in WAL file */
--  WalWriter w;                    /* The writer */
--
--  assert( pList );
--  assert( pWal->writeLock );
+-  int rc;                         /* Return code */
+-  int isChanged = 0;              /* True if a new wal-index header is loaded */
+-  int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */
 -
--  /* If this frame set completes a transaction, then nTruncate>0.  If
--  ** nTruncate==0 then this frame set does not complete the transaction. */
--  assert( (isCommit!=0)==(nTruncate!=0) );
+-  assert( pWal->ckptLock==0 );
+-  assert( pWal->writeLock==0 );
 +static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
 +  volatile WalCkptInfo *pInfo;    /* Checkpoint information in wal-index */
 +  u32 mxReadMark;                 /* Largest aReadMark[] value */
@@ -6800,18 +68481,27 @@
 +  int i;                          /* Loop counter */
 +  int rc = SQLITE_OK;             /* Return code  */
  
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
--  { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
--    WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
--              pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
+-  if( pWal->readOnly ) return SQLITE_READONLY;
+-  WALTRACE(("WAL%p: checkpoint begins\n", pWal));
+-  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+-  if( rc ){
+-    /* Usually this is SQLITE_BUSY meaning that another thread or process
+-    ** is already running a checkpoint, or maybe a recovery.  But it might
+-    ** also be SQLITE_IOERR. */
+-    return rc;
 -  }
--#endif
+-  pWal->ckptLock = 1;
 +  assert( pWal->readLock<0 );     /* Not currently locked */
  
--  /* See if it is possible to write these frames into the start of the
--  ** log file, instead of appending to it at pWal->hdr.mxFrame.
+-  /* If this is a blocking-checkpoint, then obtain the write-lock as well
+-  ** to prevent any writers from running while the checkpoint is underway.
+-  ** This has to be done before the call to walIndexReadHdr() below.
 +  /* Take steps to avoid spinning forever if there is a protocol error.
-+  **
+   **
+-  ** If the writer lock cannot be obtained, then a passive checkpoint is
+-  ** run instead. Since the checkpointer is not holding the writer lock,
+-  ** there is no point in blocking waiting for any readers. Assuming no 
+-  ** other error occurs, this function will return SQLITE_BUSY to the caller.
 +  ** Circumstances that cause a RETRY should only last for the briefest
 +  ** instances of time.  No I/O or other system calls are done while the
 +  ** locks are held, so the locks should not be held for very long. But 
@@ -6827,8 +68517,8 @@
 +  ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
 +  ** The total delay time before giving up is less than 1 second.
    */
--  if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
--    return rc;
+-  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
+-    rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
 +  if( cnt>5 ){
 +    int nDelay = 1;                      /* Pause time in microseconds */
 +    if( cnt>100 ){
@@ -6837,35 +68527,8 @@
 +    }
 +    if( cnt>=10 ) nDelay = (cnt-9)*238;  /* Max delay 21ms. Total delay 996ms */
 +    sqlite3OsSleep(pWal->pVfs, nDelay);
-   }
- 
--  /* If this is the first frame written into the log, write the WAL
--  ** header to the start of the WAL file. See comments at the top of
--  ** this source file for a description of the WAL header format.
--  */
--  iFrame = pWal->hdr.mxFrame;
--  if( iFrame==0 ){
--    u8 aWalHdr[WAL_HDRSIZE];      /* Buffer to assemble wal-header in */
--    u32 aCksum[2];                /* Checksum for wal-header */
--
--    sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
--    sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
--    sqlite3Put4byte(&aWalHdr[8], szPage);
--    sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
--    if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt);
--    memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
--    walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
--    sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
--    sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
--    
--    pWal->szPage = szPage;
--    pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
--    pWal->hdr.aFrameCksum[0] = aCksum[0];
--    pWal->hdr.aFrameCksum[1] = aCksum[1];
--    pWal->truncateOnCommit = 1;
--
--    rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
--    WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
++  }
++
 +  if( !useWal ){
 +    rc = walIndexReadHdr(pWal, pChanged);
 +    if( rc==SQLITE_BUSY ){
@@ -6893,28 +68556,23 @@
 +        rc = SQLITE_BUSY_RECOVERY;
 +      }
 +    }
-     if( rc!=SQLITE_OK ){
-       return rc;
-     }
++    if( rc!=SQLITE_OK ){
++      return rc;
++    }
 +  }
- 
--    /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless
--    ** all syncing is turned off by PRAGMA synchronous=OFF).  Otherwise
--    ** an out-of-order write following a WAL restart could result in
--    ** database corruption.  See the ticket:
--    **
--    **     http://localhost:591/sqlite/info/ff5be73dee
++
 +  pInfo = walCkptInfo(pWal);
 +  if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
 +    /* The WAL has been completely backfilled (or it is empty).
 +    ** and can be safely ignored.
-     */
--    if( pWal->syncHeader && sync_flags ){
--      rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
--      if( rc ) return rc;
++    */
 +    rc = walLockShared(pWal, WAL_READ_LOCK(0));
 +    walShmBarrier(pWal);
-+    if( rc==SQLITE_OK ){
+     if( rc==SQLITE_OK ){
+-      pWal->writeLock = 1;
+-    }else if( rc==SQLITE_BUSY ){
+-      eMode2 = SQLITE_CHECKPOINT_PASSIVE;
+-      rc = SQLITE_OK;
 +      if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
 +        /* It is not safe to allow the reader to continue here if frames
 +        ** may have been appended to the log before READ_LOCK(0) was obtained.
@@ -6938,59 +68596,17 @@
 +      return rc;
      }
    }
--  assert( (int)pWal->szPage==szPage );
--
--  /* Setup information needed to write frames into the WAL */
--  w.pWal = pWal;
--  w.pFd = pWal->pWalFd;
--  w.iSyncPoint = 0;
--  w.syncFlags = sync_flags;
--  w.szPage = szPage;
--  iOffset = walFrameOffset(iFrame+1, szPage);
--  szFrame = szPage + WAL_FRAME_HDRSIZE;
--
--  /* Write all frames into the log file exactly once */
--  for(p=pList; p; p=p->pDirty){
--    int nDbSize;   /* 0 normally.  Positive == commit flag */
--    iFrame++;
--    assert( iOffset==walFrameOffset(iFrame, szPage) );
--    nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
--    rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
--    if( rc ) return rc;
--    pLast = p;
--    iOffset += szFrame;
--  }
  
--  /* If this is the end of a transaction, then we might need to pad
--  ** the transaction and/or sync the WAL file.
--  **
--  ** Padding and syncing only occur if this set of frames complete a
--  ** transaction and if PRAGMA synchronous=FULL.  If synchronous==NORMAL
--  ** or synchonous==OFF, then no padding or syncing are needed.
--  **
--  ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not
--  ** needed and only the sync is done.  If padding is needed, then the
--  ** final frame is repeated (with its commit mark) until the next sector
--  ** boundary is crossed.  Only the part of the WAL prior to the last
--  ** sector boundary is synced; the part of the last frame that extends
--  ** past the sector boundary is written after the sync.
+-  /* Read the wal-index header. */
+-  if( rc==SQLITE_OK ){
+-    rc = walIndexReadHdr(pWal, &isChanged);
+-    if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
+-      sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
 +  /* If we get this far, it means that the reader will want to use
 +  ** the WAL to get at content from recent commits.  The job now is
 +  ** to select one of the aReadMark[] entries that is closest to
 +  ** but not exceeding pWal->hdr.mxFrame and lock that entry.
-   */
--  if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
--    if( pWal->padToSectorBoundary ){
--      int sectorSize = sqlite3OsSectorSize(pWal->pWalFd);
--      w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
--      while( iOffset<w.iSyncPoint ){
--        rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
--        if( rc ) return rc;
--        iOffset += szFrame;
--        nExtra++;
--      }
--    }else{
--      rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
++  */
 +  mxReadMark = 0;
 +  mxI = 0;
 +  for(i=1; i<WAL_NREADER; i++){
@@ -7023,14 +68639,10 @@
 +      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
 +    }
  
--  /* If this frame set completes the first transaction in the WAL and
--  ** if PRAGMA journal_size_limit is set, then truncate the WAL to the
--  ** journal size limit, if possible.
--  */
--  if( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){
--    i64 sz = pWal->mxWalSize;
--    if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){
--      sz = walFrameOffset(iFrame+nExtra+1, szPage);
+-  /* Copy data from the log to the database file. */
+-  if( rc==SQLITE_OK ){
+-    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
+-      rc = SQLITE_CORRUPT_BKPT;
 +    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
 +    if( rc ){
 +      return rc==SQLITE_BUSY ? WAL_RETRY : rc;
@@ -7061,30 +68673,29 @@
 +    ){
 +      walUnlockShared(pWal, WAL_READ_LOCK(mxI));
 +      return WAL_RETRY;
-+    }else{
+     }else{
+-      rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
+-    }
+-
+-    /* If no error occurred, set the output variables. */
+-    if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
+-      if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
+-      if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
 +      assert( mxReadMark<=pWal->hdr.mxFrame );
 +      pWal->readLock = (i16)mxI;
      }
--    walLimitSize(pWal, sz);
--    pWal->truncateOnCommit = 0;
    }
 +  return rc;
 +}
  
--  /* Append data to the wal-index. It is not necessary to lock the 
--  ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
--  ** guarantees that there are no other writers, and no data that may
--  ** be in use by existing readers is being overwritten.
--  */
--  iFrame = pWal->hdr.mxFrame;
--  for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
--    iFrame++;
--    rc = walIndexAppend(pWal, iFrame, p->pgno);
--  }
--  while( rc==SQLITE_OK && nExtra>0 ){
--    iFrame++;
--    nExtra--;
--    rc = walIndexAppend(pWal, iFrame, pLast->pgno);
+-  if( isChanged ){
+-    /* If a new wal-index header was loaded before the checkpoint was 
+-    ** performed, then the pager-cache associated with pWal is now
+-    ** out of date. So zero the cached wal-index header to ensure that
+-    ** next time the pager opens a snapshot on this database it knows that
+-    ** the cache needs to be reset.
+-    */
+-    memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
 -  }
 +/*
 +** Begin a read transaction on the database.
@@ -7104,21 +68715,12 @@
 +  int rc;                         /* Return code */
 +  int cnt = 0;                    /* Number of TryBeginRead attempts */
  
--  if( rc==SQLITE_OK ){
--    /* Update the private copy of the header. */
--    pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
--    testcase( szPage<=32768 );
--    testcase( szPage>=65536 );
--    pWal->hdr.mxFrame = iFrame;
--    if( isCommit ){
--      pWal->hdr.iChange++;
--      pWal->hdr.nPage = nTruncate;
--    }
--    /* If this is a commit, update the wal-index header too. */
--    if( isCommit ){
--      walIndexWriteHdr(pWal);
--      pWal->iCallback = iFrame;
--    }
+-  /* Release the locks. */
+-  sqlite3WalEndWriteTransaction(pWal);
+-  walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
+-  pWal->ckptLock = 0;
+-  WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
+-  return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
 +  do{
 +    rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
 +  }while( rc==WAL_RETRY );
@@ -7127,76 +68729,87 @@
 +  testcase( rc==SQLITE_PROTOCOL );
 +  testcase( rc==SQLITE_OK );
 +  return rc;
-+}
-+
+ }
+ 
+-/* Return the value to pass to a sqlite3_wal_hook callback, the
+-** number of frames in the WAL at the point of the last commit since
+-** sqlite3WalCallback() was called.  If no commits have occurred since
+-** the last call, then return 0.
 +/*
 +** Finish with a read transaction.  All this does is release the
 +** read-lock.
-+*/
+ */
+-SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){
+-  u32 ret = 0;
+-  if( pWal ){
+-    ret = pWal->iCallback;
+-    pWal->iCallback = 0;
 +SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){
 +  sqlite3WalEndWriteTransaction(pWal);
 +  if( pWal->readLock>=0 ){
 +    walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
 +    pWal->readLock = -1;
    }
--
--  WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
--  return rc;
+-  return (int)ret;
  }
  
--/* 
--** This routine is called to implement sqlite3_wal_checkpoint() and
--** related interfaces.
+ /*
+-** This function is called to change the WAL subsystem into or out
+-** of locking_mode=EXCLUSIVE.
 -**
--** Obtain a CHECKPOINT lock and then backfill as much information as
--** we can from WAL into the database.
-+/*
-+** Read a page from the WAL, if it is present in the WAL and if the 
-+** current read transaction is configured to use the WAL.  
+-** If op is zero, then attempt to change from locking_mode=EXCLUSIVE
+-** into locking_mode=NORMAL.  This means that we must acquire a lock
+-** on the pWal->readLock byte.  If the WAL is already in locking_mode=NORMAL
+-** or if the acquisition of the lock fails, then return 0.  If the
+-** transition out of exclusive-mode is successful, return 1.  This
+-** operation must occur while the pager is still holding the exclusive
+-** lock on the main database file.
+-**
+-** If op is one, then change from locking_mode=NORMAL into 
+-** locking_mode=EXCLUSIVE.  This means that the pWal->readLock must
+-** be released.  Return 1 if the transition is made and 0 if the
+-** WAL is already in exclusive-locking mode - meaning that this
+-** routine is a no-op.  The pager must already hold the exclusive lock
+-** on the main database file before invoking this operation.
++** Search the wal file for page pgno. If found, set *piRead to the frame that
++** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
++** to zero.
  **
--** If parameter xBusy is not NULL, it is a pointer to a busy-handler
--** callback. In this case this function runs a blocking checkpoint.
-+** The *pInWal is set to 1 if the requested page is in the WAL and
-+** has been loaded.  Or *pInWal is set to 0 if the page was not in 
-+** the WAL and needs to be read out of the database.
+-** If op is negative, then do a dry-run of the op==1 case but do
+-** not actually change anything. The pager uses this to see if it
+-** should acquire the database exclusive lock prior to invoking
+-** the op==1 case.
++** Return SQLITE_OK if successful, or an error code if an error occurs. If an
++** error does occur, the final value of *piRead is undefined.
  */
--SQLITE_PRIVATE int sqlite3WalCheckpoint(
--  Wal *pWal,                      /* Wal connection */
--  int eMode,                      /* PASSIVE, FULL or RESTART */
--  int (*xBusy)(void*),            /* Function to call when busy */
--  void *pBusyArg,                 /* Context argument for xBusyHandler */
--  int sync_flags,                 /* Flags to sync db file with (or 0) */
--  int nBuf,                       /* Size of temporary buffer */
--  u8 *zBuf,                       /* Temporary buffer to use */
--  int *pnLog,                     /* OUT: Number of frames in WAL */
--  int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
-+SQLITE_PRIVATE int sqlite3WalRead(
+-SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
+-  int rc;
+-  assert( pWal->writeLock==0 );
+-  assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
++SQLITE_PRIVATE int sqlite3WalFindFrame(
 +  Wal *pWal,                      /* WAL handle */
 +  Pgno pgno,                      /* Database page number to read data for */
-+  int *pInWal,                    /* OUT: True if data is read from WAL */
-+  int nOut,                       /* Size of buffer pOut in bytes */
-+  u8 *pOut                        /* Buffer to write page data to */
- ){
--  int rc;                         /* Return code */
--  int isChanged = 0;              /* True if a new wal-index header is loaded */
--  int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */
++  u32 *piRead                     /* OUT: Frame number (or zero) */
++){
 +  u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
 +  u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
 +  int iHash;                      /* Used to loop through N hash tables */
  
--  assert( pWal->ckptLock==0 );
--  assert( pWal->writeLock==0 );
+-  /* pWal->readLock is usually set, but might be -1 if there was a 
+-  ** prior error while attempting to acquire are read-lock. This cannot 
+-  ** happen if the connection is actually in exclusive mode (as no xShmLock
+-  ** locks are taken in this case). Nor should the pager attempt to
+-  ** upgrade to exclusive-mode following such an error.
+-  */
 +  /* This routine is only be called from within a read transaction. */
-+  assert( pWal->readLock>=0 || pWal->lockError );
+   assert( pWal->readLock>=0 || pWal->lockError );
+-  assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
  
--  if( pWal->readOnly ) return SQLITE_READONLY;
--  WALTRACE(("WAL%p: checkpoint begins\n", pWal));
--  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
--  if( rc ){
--    /* Usually this is SQLITE_BUSY meaning that another thread or process
--    ** is already running a checkpoint, or maybe a recovery.  But it might
--    ** also be SQLITE_IOERR. */
--    return rc;
+-  if( op==0 ){
+-    if( pWal->exclusiveMode ){
+-      pWal->exclusiveMode = 0;
+-      if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
+-        pWal->exclusiveMode = 1;
 +  /* If the "last page" field of the wal-index header snapshot is 0, then
 +  ** no data will be read from the wal under any circumstances. Return early
 +  ** in this case as an optimization.  Likewise, if pWal->readLock==0, 
@@ -7204,22 +68817,14 @@
 +  ** WAL were empty.
 +  */
 +  if( iLast==0 || pWal->readLock==0 ){
-+    *pInWal = 0;
++    *piRead = 0;
 +    return SQLITE_OK;
-   }
--  pWal->ckptLock = 1;
- 
--  /* If this is a blocking-checkpoint, then obtain the write-lock as well
--  ** to prevent any writers from running while the checkpoint is underway.
--  ** This has to be done before the call to walIndexReadHdr() below.
++  }
++
 +  /* Search the hash table or tables for an entry matching page number
 +  ** pgno. Each iteration of the following for() loop searches one
 +  ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
-   **
--  ** If the writer lock cannot be obtained, then a passive checkpoint is
--  ** run instead. Since the checkpointer is not holding the writer lock,
--  ** there is no point in blocking waiting for any readers. Assuming no 
--  ** other error occurs, this function will return SQLITE_BUSY to the caller.
++  **
 +  ** This code might run concurrently to the code in walIndexAppend()
 +  ** that adds entries to the wal-index (and possibly to this hash 
 +  ** table). This means the value just read from the hash 
@@ -7240,21 +68845,7 @@
 +  **   (iFrame<=iLast): 
 +  **     This condition filters out entries that were added to the hash
 +  **     table after the current read-transaction had started.
-   */
--  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
--    rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
--    if( rc==SQLITE_OK ){
--      pWal->writeLock = 1;
--    }else if( rc==SQLITE_BUSY ){
--      eMode2 = SQLITE_CHECKPOINT_PASSIVE;
--      rc = SQLITE_OK;
--    }
--  }
--
--  /* Read the wal-index header. */
--  if( rc==SQLITE_OK ){
--    rc = walIndexReadHdr(pWal, &isChanged);
--  }
++  */
 +  for(iHash=walFramePage(iLast); iHash>=0 && iRead==0; iHash--){
 +    volatile ht_slot *aHash;      /* Pointer to hash table */
 +    volatile u32 *aPgno;          /* Pointer to array of page numbers */
@@ -7262,13 +68853,7 @@
 +    int iKey;                     /* Hash slot index */
 +    int nCollide;                 /* Number of hash collisions remaining */
 +    int rc;                       /* Error code */
- 
--  /* Copy data from the log to the database file. */
--  if( rc==SQLITE_OK ){
--    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
--      rc = SQLITE_CORRUPT_BKPT;
--    }else{
--      rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
++
 +    rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
 +    if( rc!=SQLITE_OK ){
 +      return rc;
@@ -7282,14 +68867,23 @@
 +      }
 +      if( (nCollide--)==0 ){
 +        return SQLITE_CORRUPT_BKPT;
-+      }
+       }
+-      rc = pWal->exclusiveMode==0;
+-    }else{
+-      /* Already in locking_mode=NORMAL */
+-      rc = 0;
      }
-+  }
- 
--    /* If no error occurred, set the output variables. */
--    if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
--      if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
--      if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
+-  }else if( op>0 ){
+-    assert( pWal->exclusiveMode==0 );
+-    assert( pWal->readLock>=0 );
+-    walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
+-    pWal->exclusiveMode = 1;
+-    rc = 1;
+-  }else{
+-    rc = pWal->exclusiveMode==0;
+   }
+-  return rc;
++
 +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
 +  /* If expensive assert() statements are available, do a linear search
 +  ** of the wal-index file content. Make sure the results agree with the
@@ -7302,164 +68896,62 @@
 +        iRead2 = iTest;
 +        break;
 +      }
-     }
++    }
 +    assert( iRead==iRead2 );
-   }
++  }
 +#endif
- 
--  if( isChanged ){
--    /* If a new wal-index header was loaded before the checkpoint was 
--    ** performed, then the pager-cache associated with pWal is now
--    ** out of date. So zero the cached wal-index header to ensure that
--    ** next time the pager opens a snapshot on this database it knows that
--    ** the cache needs to be reset.
--    */
--    memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
-+  /* If iRead is non-zero, then it is the log frame number that contains the
-+  ** required page. Read and return data from the log file.
-+  */
-+  if( iRead ){
-+    int sz;
-+    i64 iOffset;
-+    sz = pWal->hdr.szPage;
-+    sz = (sz&0xfe00) + ((sz&0x0001)<<16);
-+    testcase( sz<=32768 );
-+    testcase( sz>=65536 );
-+    iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
-+    *pInWal = 1;
-+    /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
-+    return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
-   }
- 
--  /* Release the locks. */
--  sqlite3WalEndWriteTransaction(pWal);
--  walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
--  pWal->ckptLock = 0;
--  WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
--  return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
-+  *pInWal = 0;
-+  return SQLITE_OK;
- }
- 
--/* Return the value to pass to a sqlite3_wal_hook callback, the
--** number of frames in the WAL at the point of the last commit since
--** sqlite3WalCallback() was called.  If no commits have occurred since
--** the last call, then return 0.
 +
-+/* 
-+** Return the size of the database in pages (or zero, if unknown).
- */
--SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){
--  u32 ret = 0;
--  if( pWal ){
--    ret = pWal->iCallback;
--    pWal->iCallback = 0;
-+SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
-+  if( pWal && ALWAYS(pWal->readLock>=0) ){
-+    return pWal->hdr.nPage;
-   }
--  return (int)ret;
-+  return 0;
++  *piRead = iRead;
++  return SQLITE_OK;
  }
  
--/*
--** This function is called to change the WAL subsystem into or out
--** of locking_mode=EXCLUSIVE.
-+
-+/* 
-+** This function starts a write transaction on the WAL.
- **
--** If op is zero, then attempt to change from locking_mode=EXCLUSIVE
--** into locking_mode=NORMAL.  This means that we must acquire a lock
--** on the pWal->readLock byte.  If the WAL is already in locking_mode=NORMAL
--** or if the acquisition of the lock fails, then return 0.  If the
--** transition out of exclusive-mode is successful, return 1.  This
--** operation must occur while the pager is still holding the exclusive
--** lock on the main database file.
-+** A read transaction must have already been started by a prior call
-+** to sqlite3WalBeginReadTransaction().
- **
--** If op is one, then change from locking_mode=NORMAL into 
--** locking_mode=EXCLUSIVE.  This means that the pWal->readLock must
--** be released.  Return 1 if the transition is made and 0 if the
--** WAL is already in exclusive-locking mode - meaning that this
--** routine is a no-op.  The pager must already hold the exclusive lock
--** on the main database file before invoking this operation.
-+** If another thread or process has written into the database since
-+** the read transaction was started, then it is not possible for this
-+** thread to write as doing so would cause a fork.  So this routine
-+** returns SQLITE_BUSY in that case and no write transaction is started.
- **
--** If op is negative, then do a dry-run of the op==1 case but do
--** not actually change anything. The pager uses this to see if it
--** should acquire the database exclusive lock prior to invoking
--** the op==1 case.
-+** There can only be a single writer active at a time.
- */
--SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
-+SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
-   int rc;
--  assert( pWal->writeLock==0 );
--  assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
- 
--  /* pWal->readLock is usually set, but might be -1 if there was a 
--  ** prior error while attempting to acquire are read-lock. This cannot 
--  ** happen if the connection is actually in exclusive mode (as no xShmLock
--  ** locks are taken in this case). Nor should the pager attempt to
--  ** upgrade to exclusive-mode following such an error.
--  */
--  assert( pWal->readLock>=0 || pWal->lockError );
--  assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
-+  /* Cannot start a write transaction without first holding a read
-+  ** transaction. */
-+  assert( pWal->readLock>=0 );
- 
--  if( op==0 ){
--    if( pWal->exclusiveMode ){
--      pWal->exclusiveMode = 0;
--      if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
--        pWal->exclusiveMode = 1;
--      }
--      rc = pWal->exclusiveMode==0;
--    }else{
--      /* Already in locking_mode=NORMAL */
--      rc = 0;
--    }
--  }else if( op>0 ){
--    assert( pWal->exclusiveMode==0 );
--    assert( pWal->readLock>=0 );
--    walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
--    pWal->exclusiveMode = 1;
--    rc = 1;
--  }else{
--    rc = pWal->exclusiveMode==0;
-+  if( pWal->readOnly ){
-+    return SQLITE_READONLY;
-   }
--  return rc;
--}
--
 -/* 
 -** Return true if the argument is non-NULL and the WAL module is using
 -** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
 -** WAL module is using shared-memory, return false. 
--*/
++/*
++** Read the contents of frame iRead from the wal file into buffer pOut
++** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
++** error code otherwise.
+ */
 -SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
 -  return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
--}
--
++SQLITE_PRIVATE int sqlite3WalReadFrame(
++  Wal *pWal,                      /* WAL handle */
++  u32 iRead,                      /* Frame to read */
++  int nOut,                       /* Size of buffer pOut in bytes */
++  u8 *pOut                        /* Buffer to write page data to */
++){
++  int sz;
++  i64 iOffset;
++  sz = pWal->hdr.szPage;
++  sz = (sz&0xfe00) + ((sz&0x0001)<<16);
++  testcase( sz<=32768 );
++  testcase( sz>=65536 );
++  iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
++  /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
++  return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
+ }
+ 
 -#ifdef SQLITE_ENABLE_ZIPVFS
 -/*
 -** If the argument is not NULL, it points to a Wal object that holds a
 -** read-lock. This function returns the database page-size if it is known,
 -** or zero if it is not (or if pWal is NULL).
--*/
++/* 
++** Return the size of the database in pages (or zero, if unknown).
+ */
 -SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
 -  assert( pWal==0 || pWal->readLock>=0 );
 -  return (pWal ? pWal->szPage : 0);
--}
++SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
++  if( pWal && ALWAYS(pWal->readLock>=0) ){
++    return pWal->hdr.nPage;
++  }
++  return 0;
+ }
 -#endif
--
+ 
 -#endif /* #ifndef SQLITE_OMIT_WAL */
  
 -/************** End of wal.c *************************************************/
@@ -7469,18 +68961,27 @@
 -**
 -** The author disclaims copyright to this source code.  In place of
 -** a legal notice, here is a blessing:
--**
++/* 
++** This function starts a write transaction on the WAL.
+ **
 -**    May you do good and not evil.
 -**    May you find forgiveness for yourself and forgive others.
 -**    May you share freely, never taking more than you give.
--**
++** A read transaction must have already been started by a prior call
++** to sqlite3WalBeginReadTransaction().
+ **
 -*************************************************************************
--**
++** If another thread or process has written into the database since
++** the read transaction was started, then it is not possible for this
++** thread to write as doing so would cause a fork.  So this routine
++** returns SQLITE_BUSY in that case and no write transaction is started.
+ **
 -** This file contains code used to implement mutexes on Btree objects.
 -** This code really belongs in btree.c.  But btree.c is getting too
 -** big and we want to break it down some.  This packaged seemed like
 -** a good breakout.
--*/
++** There can only be a single writer active at a time.
+ */
 -/************** Include btreeInt.h in the middle of btmutex.c ****************/
 -/************** Begin file btreeInt.h ****************************************/
 -/*
@@ -7686,6 +69187,17 @@
 -**    SIZE    DESCRIPTION
 -**      4     Page number of next overflow page
 -**      *     Data
++SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
++  int rc;
++
++  /* Cannot start a write transaction without first holding a read
++  ** transaction. */
++  assert( pWal->readLock>=0 );
++
++  if( pWal->readOnly ){
++    return SQLITE_READONLY;
++  }
++
 +  /* Only one writer allowed at a time.  Get the write lock.  Return
 +  ** SQLITE_BUSY if unable.
 +  */
@@ -7770,7 +69282,7 @@
 +      assert( walFramePgno(pWal, iFrame)!=1 );
 +      rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
 +    }
-+    walCleanupHash(pWal);
++    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
 +  }
 +  assert( rc==SQLITE_OK );
 +  return rc;
@@ -8062,7 +69574,40 @@
 -#define WRITE_LOCK    2
 +  assert( pList );
 +  assert( pWal->writeLock );
-+
+ 
+-/* A Btree handle
+-**
+-** A database connection contains a pointer to an instance of
+-** this object for every database file that it has open.  This structure
+-** is opaque to the database connection.  The database connection cannot
+-** see the internals of this structure and only deals with pointers to
+-** this structure.
+-**
+-** For some database files, the same underlying database cache might be 
+-** shared between multiple connections.  In that case, each connection
+-** has it own instance of this object.  But each instance of this object
+-** points to the same BtShared object.  The database cache and the
+-** schema associated with the database file are all contained within
+-** the BtShared object.
+-**
+-** All fields in this structure are accessed under sqlite3.mutex.
+-** The pBt pointer itself may not be changed while there exists cursors 
+-** in the referenced BtShared that point back to this Btree since those
+-** cursors have to go through this Btree to find their BtShared and
+-** they often do so without holding sqlite3.mutex.
+-*/
+-struct Btree {
+-  sqlite3 *db;       /* The database connection holding this btree */
+-  BtShared *pBt;     /* Sharable content of this btree */
+-  u8 inTrans;        /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
+-  u8 sharable;       /* True if we can share pBt with another db */
+-  u8 locked;         /* True if db currently has pBt locked */
+-  int wantToLock;    /* Number of nested calls to sqlite3BtreeEnter() */
+-  int nBackup;       /* Number of backup operations reading this btree */
+-  Btree *pNext;      /* List of other sharable Btrees from the same db */
+-  Btree *pPrev;      /* Back pointer of the same list */
+-#ifndef SQLITE_OMIT_SHARED_CACHE
+-  BtLock lock;       /* Object used to lock page 1 */
 +  /* If this frame set completes a transaction, then nTruncate>0.  If
 +  ** nTruncate==0 then this frame set does not complete the transaction. */
 +  assert( (isCommit!=0)==(nTruncate!=0) );
@@ -8072,8 +69617,19 @@
 +    WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
 +              pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
 +  }
-+#endif
-+
+ #endif
+-};
+ 
+-/*
+-** Btree.inTrans may take one of the following values.
+-**
+-** If the shared-data extension is enabled, there may be multiple users
+-** of the Btree structure. At most one of these may open a write transaction,
+-** but any number may have active read transactions.
+-*/
+-#define TRANS_NONE  0
+-#define TRANS_READ  1
+-#define TRANS_WRITE 2
 +  /* See if it is possible to write these frames into the start of the
 +  ** log file, instead of appending to it at pWal->hdr.mxFrame.
 +  */
@@ -8163,7 +69719,7 @@
 +  */
 +  if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
 +    if( pWal->padToSectorBoundary ){
-+      int sectorSize = sqlite3OsSectorSize(pWal->pWalFd);
++      int sectorSize = sqlite3SectorSize(pWal->pWalFd);
 +      w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
 +      while( iOffset<w.iSyncPoint ){
 +        rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
@@ -8221,80 +69777,6 @@
 +      pWal->iCallback = iFrame;
 +    }
 +  }
-+
-+  WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
-+  return rc;
-+}
- 
--/* A Btree handle
--**
--** A database connection contains a pointer to an instance of
--** this object for every database file that it has open.  This structure
--** is opaque to the database connection.  The database connection cannot
--** see the internals of this structure and only deals with pointers to
--** this structure.
-+/* 
-+** This routine is called to implement sqlite3_wal_checkpoint() and
-+** related interfaces.
- **
--** For some database files, the same underlying database cache might be 
--** shared between multiple connections.  In that case, each connection
--** has it own instance of this object.  But each instance of this object
--** points to the same BtShared object.  The database cache and the
--** schema associated with the database file are all contained within
--** the BtShared object.
-+** Obtain a CHECKPOINT lock and then backfill as much information as
-+** we can from WAL into the database.
- **
--** All fields in this structure are accessed under sqlite3.mutex.
--** The pBt pointer itself may not be changed while there exists cursors 
--** in the referenced BtShared that point back to this Btree since those
--** cursors have to go through this Btree to find their BtShared and
--** they often do so without holding sqlite3.mutex.
-+** If parameter xBusy is not NULL, it is a pointer to a busy-handler
-+** callback. In this case this function runs a blocking checkpoint.
- */
--struct Btree {
--  sqlite3 *db;       /* The database connection holding this btree */
--  BtShared *pBt;     /* Sharable content of this btree */
--  u8 inTrans;        /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
--  u8 sharable;       /* True if we can share pBt with another db */
--  u8 locked;         /* True if db currently has pBt locked */
--  int wantToLock;    /* Number of nested calls to sqlite3BtreeEnter() */
--  int nBackup;       /* Number of backup operations reading this btree */
--  Btree *pNext;      /* List of other sharable Btrees from the same db */
--  Btree *pPrev;      /* Back pointer of the same list */
--#ifndef SQLITE_OMIT_SHARED_CACHE
--  BtLock lock;       /* Object used to lock page 1 */
--#endif
--};
-+SQLITE_PRIVATE int sqlite3WalCheckpoint(
-+  Wal *pWal,                      /* Wal connection */
-+  int eMode,                      /* PASSIVE, FULL or RESTART */
-+  int (*xBusy)(void*),            /* Function to call when busy */
-+  void *pBusyArg,                 /* Context argument for xBusyHandler */
-+  int sync_flags,                 /* Flags to sync db file with (or 0) */
-+  int nBuf,                       /* Size of temporary buffer */
-+  u8 *zBuf,                       /* Temporary buffer to use */
-+  int *pnLog,                     /* OUT: Number of frames in WAL */
-+  int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
-+){
-+  int rc;                         /* Return code */
-+  int isChanged = 0;              /* True if a new wal-index header is loaded */
-+  int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */
- 
--/*
--** Btree.inTrans may take one of the following values.
--**
--** If the shared-data extension is enabled, there may be multiple users
--** of the Btree structure. At most one of these may open a write transaction,
--** but any number may have active read transactions.
--*/
--#define TRANS_NONE  0
--#define TRANS_READ  1
--#define TRANS_WRITE 2
-+  assert( pWal->ckptLock==0 );
-+  assert( pWal->writeLock==0 );
  
 -/*
 -** An instance of this object represents a single database file.
@@ -8325,12 +69807,23 @@
 -**
 -**     1) The current writer (BtShared.pWriter) concludes its transaction, OR
 -**     2) The number of locks held by other connections drops to zero.
--**
++  WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
++  return rc;
++}
++
++/* 
++** This routine is called to implement sqlite3_wal_checkpoint() and
++** related interfaces.
+ **
 -**   while in the 'pending-lock' state, no connection may start a new
 -**   transaction.
--**
++** Obtain a CHECKPOINT lock and then backfill as much information as
++** we can from WAL into the database.
+ **
 -**   This feature is included to help prevent writer-starvation.
--*/
++** If parameter xBusy is not NULL, it is a pointer to a busy-handler
++** callback. In this case this function runs a blocking checkpoint.
+ */
 -struct BtShared {
 -  Pager *pPager;        /* The page cache */
 -  sqlite3 *db;          /* Database connection currently using this Btree */
@@ -8340,6 +69833,7 @@
 -#ifndef SQLITE_OMIT_AUTOVACUUM
 -  u8 autoVacuum;        /* True if auto-vacuum is enabled */
 -  u8 incrVacuum;        /* True if incr-vacuum is enabled */
+-  u8 bDoTruncate;       /* True to truncate db on commit */
 -#endif
 -  u8 inTransaction;     /* Transaction state */
 -  u8 max1bytePayload;   /* Maximum first byte of cell for a 1-byte payload */
@@ -8364,16 +69858,20 @@
 -#endif
 -  u8 *pTmpSpace;        /* BtShared.pageSize bytes of space for tmp use */
 -};
-+  if( pWal->readOnly ) return SQLITE_READONLY;
-+  WALTRACE(("WAL%p: checkpoint begins\n", pWal));
-+  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
-+  if( rc ){
-+    /* Usually this is SQLITE_BUSY meaning that another thread or process
-+    ** is already running a checkpoint, or maybe a recovery.  But it might
-+    ** also be SQLITE_IOERR. */
-+    return rc;
-+  }
-+  pWal->ckptLock = 1;
++SQLITE_PRIVATE int sqlite3WalCheckpoint(
++  Wal *pWal,                      /* Wal connection */
++  int eMode,                      /* PASSIVE, FULL or RESTART */
++  int (*xBusy)(void*),            /* Function to call when busy */
++  void *pBusyArg,                 /* Context argument for xBusyHandler */
++  int sync_flags,                 /* Flags to sync db file with (or 0) */
++  int nBuf,                       /* Size of temporary buffer */
++  u8 *zBuf,                       /* Temporary buffer to use */
++  int *pnLog,                     /* OUT: Number of frames in WAL */
++  int *pnCkpt                     /* OUT: Number of backfilled frames in WAL */
++){
++  int rc;                         /* Return code */
++  int isChanged = 0;              /* True if a new wal-index header is loaded */
++  int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */
  
 -/*
 -** Allowed values for BtShared.btsFlags
@@ -8385,24 +69883,8 @@
 -#define BTS_NO_WAL           0x0010   /* Do not open write-ahead-log files */
 -#define BTS_EXCLUSIVE        0x0020   /* pWriter has an exclusive lock */
 -#define BTS_PENDING          0x0040   /* Waiting for read-locks to clear */
-+  /* If this is a blocking-checkpoint, then obtain the write-lock as well
-+  ** to prevent any writers from running while the checkpoint is underway.
-+  ** This has to be done before the call to walIndexReadHdr() below.
-+  **
-+  ** If the writer lock cannot be obtained, then a passive checkpoint is
-+  ** run instead. Since the checkpointer is not holding the writer lock,
-+  ** there is no point in blocking waiting for any readers. Assuming no 
-+  ** other error occurs, this function will return SQLITE_BUSY to the caller.
-+  */
-+  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
-+    rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
-+    if( rc==SQLITE_OK ){
-+      pWal->writeLock = 1;
-+    }else if( rc==SQLITE_BUSY ){
-+      eMode2 = SQLITE_CHECKPOINT_PASSIVE;
-+      rc = SQLITE_OK;
-+    }
-+  }
++  assert( pWal->ckptLock==0 );
++  assert( pWal->writeLock==0 );
  
 -/*
 -** An instance of the following structure is used to hold information
@@ -8420,10 +69902,16 @@
 -  u16 iOverflow; /* Offset to overflow page number.  Zero if no overflow */
 -  u16 nSize;     /* Size of the cell content on the main b-tree page */
 -};
-+  /* Read the wal-index header. */
-+  if( rc==SQLITE_OK ){
-+    rc = walIndexReadHdr(pWal, &isChanged);
++  if( pWal->readOnly ) return SQLITE_READONLY;
++  WALTRACE(("WAL%p: checkpoint begins\n", pWal));
++  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
++  if( rc ){
++    /* Usually this is SQLITE_BUSY meaning that another thread or process
++    ** is already running a checkpoint, or maybe a recovery.  But it might
++    ** also be SQLITE_IOERR. */
++    return rc;
 +  }
++  pWal->ckptLock = 1;
  
 -/*
 -** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
@@ -8435,13 +69923,24 @@
 -** assumed that the database is corrupt.
 -*/
 -#define BTCURSOR_MAX_DEPTH 20
-+  /* Copy data from the log to the database file. */
-+  if( rc==SQLITE_OK ){
-+    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
-+      rc = SQLITE_CORRUPT_BKPT;
-+    }else{
-+      rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
++  /* If this is a blocking-checkpoint, then obtain the write-lock as well
++  ** to prevent any writers from running while the checkpoint is underway.
++  ** This has to be done before the call to walIndexReadHdr() below.
++  **
++  ** If the writer lock cannot be obtained, then a passive checkpoint is
++  ** run instead. Since the checkpointer is not holding the writer lock,
++  ** there is no point in blocking waiting for any readers. Assuming no 
++  ** other error occurs, this function will return SQLITE_BUSY to the caller.
++  */
++  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
++    rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
++    if( rc==SQLITE_OK ){
++      pWal->writeLock = 1;
++    }else if( rc==SQLITE_BUSY ){
++      eMode2 = SQLITE_CHECKPOINT_PASSIVE;
++      rc = SQLITE_OK;
 +    }
++  }
  
 -/*
 -** A cursor is a pointer to a particular entry within a particular
@@ -8483,10 +69982,11 @@
 -  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
 -  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
 -};
-+    /* If no error occurred, set the output variables. */
-+    if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
-+      if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
-+      if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
++  /* Read the wal-index header. */
++  if( rc==SQLITE_OK ){
++    rc = walIndexReadHdr(pWal, &isChanged);
++    if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
++      sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
 +    }
 +  }
  
@@ -8519,27 +70019,24 @@
 -#define CURSOR_VALID             1
 -#define CURSOR_REQUIRESEEK       2
 -#define CURSOR_FAULT             3
-+  if( isChanged ){
-+    /* If a new wal-index header was loaded before the checkpoint was 
-+    ** performed, then the pager-cache associated with pWal is now
-+    ** out of date. So zero the cached wal-index header to ensure that
-+    ** next time the pager opens a snapshot on this database it knows that
-+    ** the cache needs to be reset.
-+    */
-+    memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
-+  }
++  /* Copy data from the log to the database file. */
++  if( rc==SQLITE_OK ){
++    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
++      rc = SQLITE_CORRUPT_BKPT;
++    }else{
++      rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
++    }
  
 -/* 
 -** The database page the PENDING_BYTE occupies. This page is never used.
 -*/
 -# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
-+  /* Release the locks. */
-+  sqlite3WalEndWriteTransaction(pWal);
-+  walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
-+  pWal->ckptLock = 0;
-+  WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
-+  return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
-+}
++    /* If no error occurred, set the output variables. */
++    if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
++      if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
++      if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
++    }
++  }
  
 -/*
 -** These macros define the location of the pointer-map entry for a 
@@ -8555,6 +70052,24 @@
 -** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
 -** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
 -** this test.
++  if( isChanged ){
++    /* If a new wal-index header was loaded before the checkpoint was 
++    ** performed, then the pager-cache associated with pWal is now
++    ** out of date. So zero the cached wal-index header to ensure that
++    ** next time the pager opens a snapshot on this database it knows that
++    ** the cache needs to be reset.
++    */
++    memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
++  }
++
++  /* Release the locks. */
++  sqlite3WalEndWriteTransaction(pWal);
++  walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
++  pWal->ckptLock = 0;
++  WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
++  return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
++}
++
 +/* Return the value to pass to a sqlite3_wal_hook callback, the
 +** number of frames in the WAL at the point of the last commit since
 +** sqlite3WalCallback() was called.  If no commits have occurred since
@@ -8753,51 +70268,59 @@
  #ifndef SQLITE_OMIT_SHARED_CACHE
  #if SQLITE_THREADSAFE
  
-@@ -86559,10 +88241,16 @@
+@@ -88696,10 +91032,24 @@
  */
  SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
    int rc = sqlite3_overload_function(db, "MATCH", 2);
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
 +#ifndef OMIT_EXPORT
 +  extern void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **);
 +#endif
++#endif
++/* END SQLCIPHER */
    assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
    if( rc==SQLITE_NOMEM ){
      db->mallocFailed = 1;
    }
++/* BEGIN SQLCIPHER */
++#ifdef SQLITE_HAS_CODEC
 +#ifndef OMIT_EXPORT
 +  sqlite3CreateFunc(db, "sqlcipher_export", 1, SQLITE_TEXT, 0, sqlcipher_exportFunc, 0, 0, 0);
 +#endif
++#endif
++/* END SQLCIPHER */
  }
  
  /*
-@@ -91386,6 +93074,12 @@
+@@ -93695,6 +96045,12 @@
    sqlite3 *db = pParse->db;    /* The database connection */
    Db *pDb;                     /* The specific database being pragmaed */
-   Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);  /* Prepared statement */
-+/** BEGIN CRYPTO **/
+   Vdbe *v = sqlite3GetVdbe(pParse);  /* Prepared statement */
++/* BEGIN SQLCIPHER */
 +#ifdef SQLITE_HAS_CODEC
 +  extern int codec_pragma(sqlite3*, int, Parse *, const char *, const char *);
 +#endif
-+/** END CRYPTO **/
++/* END SQLCIPHER */
 +
  
    if( v==0 ) return;
    sqlite3VdbeRunOnlyOnce(v);
-@@ -91445,6 +93139,13 @@
+@@ -93755,6 +96111,13 @@
      pParse->rc = rc;
    }else
                              
-+/** BEGIN CRYPTO **/
++/* BEGIN SQLCIPHER */
 +#ifdef SQLITE_HAS_CODEC
 +  if(codec_pragma(db, iDb, pParse, zLeft, zRight)) { 
 +    /* codec_pragma executes internal */
 +  }else
 +  #endif
-+/** END CRYPTO **/
++/* END SQLCIPHER */
   
  #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
    /*
-@@ -92000,60 +93701,6 @@
+@@ -94348,60 +96711,6 @@
  
  #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
    /*


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]