[libgda] Upgraded SQLite to 3.7.14.1 and SqlCipher to 2.1.1



commit 23c186535232bade4acd8b0f51f8ec3eea491bb4
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Dec 22 18:22:25 2012 +0100

    Upgraded SQLite to 3.7.14.1 and SqlCipher to 2.1.1

 libgda/sqlite/sqlite-src/PragmasPatch |    6 +-
 libgda/sqlite/sqlite-src/sqlite3.c    | 6859 ++++++++++++++++-----------------
 libgda/sqlite/sqlite-src/sqlite3.h    |  157 +-
 providers/sqlcipher/sqlcipher.patch   | 3241 ++++++++++------
 4 files changed, 5342 insertions(+), 4921 deletions(-)
---
diff --git a/libgda/sqlite/sqlite-src/PragmasPatch b/libgda/sqlite/sqlite-src/PragmasPatch
index b622a53..b0b53da 100644
--- a/libgda/sqlite/sqlite-src/PragmasPatch
+++ b/libgda/sqlite/sqlite-src/PragmasPatch
@@ -1,6 +1,6 @@
---- sqlite3.c.orig	2012-05-22 13:03:50.000000000 +0200
-+++ sqlite3.c	2012-08-27 14:52:58.000000000 +0200
-@@ -93389,6 +93389,60 @@
+--- 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 @@
  
  #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
    /*
diff --git a/libgda/sqlite/sqlite-src/sqlite3.c b/libgda/sqlite/sqlite-src/sqlite3.c
index f9a6648..712a8bc 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.12.1.  By combining all the individual C code files into this 
+** version 3.7.14.1.  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
@@ -389,6 +389,7 @@
 **
 **     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
 **     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
+**     SQLITE_ZERO_MALLOC            // Use a stub allocator that always fails
 **     SQLITE_MEMDEBUG               // Debugging version of system malloc()
 **
 ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
@@ -402,11 +403,19 @@
 ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
 ** the default.
 */
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
-# error "At most one of the following compile-time configuration options\
- is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
-#endif
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
+#if defined(SQLITE_SYSTEM_MALLOC) \
+  + defined(SQLITE_WIN32_MALLOC) \
+  + defined(SQLITE_ZERO_MALLOC) \
+  + defined(SQLITE_MEMDEBUG)>1
+# error "Two or more of the following compile-time configuration options\
+ are defined but at most one is allowed:\
+ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
+ SQLITE_ZERO_MALLOC"
+#endif
+#if defined(SQLITE_SYSTEM_MALLOC) \
+  + defined(SQLITE_WIN32_MALLOC) \
+  + defined(SQLITE_ZERO_MALLOC) \
+  + defined(SQLITE_MEMDEBUG)==0
 # define SQLITE_SYSTEM_MALLOC 1
 #endif
 
@@ -443,15 +452,22 @@
 #endif
 
 /*
-** Many people are failing to set -DNDEBUG=1 when compiling SQLite.
-** Setting NDEBUG makes the code smaller and run faster.  So the following
-** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1
-** option is set.  Thus NDEBUG becomes an opt-in rather than an opt-out
+** NDEBUG and SQLITE_DEBUG are opposites.  It should always be true that
+** defined(NDEBUG)==!defined(SQLITE_DEBUG).  If this is not currently true,
+** make it true by defining or undefining NDEBUG.
+**
+** Setting NDEBUG makes the code smaller and run faster by disabling the
+** number assert() statements in the code.  So we want the default action
+** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
+** is set.  Thus NDEBUG becomes an opt-in rather than an opt-out
 ** feature.
 */
 #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
 # define NDEBUG 1
 #endif
+#if defined(NDEBUG) && defined(SQLITE_DEBUG)
+# undef NDEBUG
+#endif
 
 /*
 ** The testcase() macro is used to aid in coverage testing.  When 
@@ -657,9 +673,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.12.1"
-#define SQLITE_VERSION_NUMBER 3007012
-#define SQLITE_SOURCE_ID      "2012-05-22 02:45:53 6d326d44fd1d626aae0e8456e5fa2049f1ce0789"
+#define SQLITE_VERSION        "3.7.14.1"
+#define SQLITE_VERSION_NUMBER 3007014
+#define SQLITE_SOURCE_ID      "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -769,7 +785,8 @@ SQLITE_API int sqlite3_threadsafe(void);
 ** the opaque structure named "sqlite3".  It is useful to think of an sqlite3
 ** pointer as an object.  The [sqlite3_open()], [sqlite3_open16()], and
 ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
-** is its destructor.  There are many other interfaces (such as
+** and [sqlite3_close_v2()] are its destructors.  There are many other
+** interfaces (such as
 ** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
 ** [sqlite3_busy_timeout()] to name but three) that are methods on an
 ** sqlite3 object.
@@ -816,28 +833,46 @@ typedef sqlite_uint64 sqlite3_uint64;
 /*
 ** CAPI3REF: Closing A Database Connection
 **
-** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.
-** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is
-** successfully destroyed and all associated resources are deallocated.
-**
-** Applications must [sqlite3_finalize | finalize] all [prepared statements]
-** and [sqlite3_blob_close | close] all [BLOB handles] associated with
-** the [sqlite3] object prior to attempting to close the object.  ^If
+** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
+** for the [sqlite3] object.
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
+** the [sqlite3] object is successfully destroyed and all associated
+** resources are deallocated.
+**
+** ^If the database connection is associated with unfinalized prepared
+** statements or unfinished sqlite3_backup objects then sqlite3_close()
+** will leave the database connection open and return [SQLITE_BUSY].
+** ^If sqlite3_close_v2() is called with unfinalized prepared statements
+** and unfinished sqlite3_backups, then the database connection becomes
+** an unusable "zombie" which will automatically be deallocated when the
+** last prepared statement is finalized or the last sqlite3_backup is
+** finished.  The sqlite3_close_v2() interface is intended for use with
+** host languages that are garbage collected, and where the order in which
+** destructors are called is arbitrary.
+**
+** Applications should [sqlite3_finalize | finalize] all [prepared statements],
+** [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
-** outstanding [prepared statements] or [BLOB handles], then it returns
-** SQLITE_BUSY.
+** 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],
+** and [sqlite3_backup] objects are also destroyed.
 **
-** ^If [sqlite3_close()] is invoked while a transaction is open,
+** ^If an [sqlite3] object is destroyed while a transaction is open,
 ** the transaction is automatically rolled back.
 **
-** The C parameter to [sqlite3_close(C)] must be either a NULL
+** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
+** must be either a NULL
 ** pointer or an [sqlite3] object pointer obtained
 ** from [sqlite3_open()], [sqlite3_open16()], or
 ** [sqlite3_open_v2()], and not previously closed.
-** ^Calling sqlite3_close() with a NULL pointer argument is a 
-** harmless no-op.
+** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
+** argument is a harmless no-op.
 */
-SQLITE_API int sqlite3_close(sqlite3 *);
+SQLITE_API int sqlite3_close(sqlite3*);
+SQLITE_API int sqlite3_close_v2(sqlite3*);
 
 /*
 ** The type for a callback function.
@@ -1028,6 +1063,7 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_OPEN_EXCLUSIVE        0x00000010  /* VFS only */
 #define SQLITE_OPEN_AUTOPROXY        0x00000020  /* VFS only */
 #define SQLITE_OPEN_URI              0x00000040  /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MEMORY           0x00000080  /* Ok for sqlite3_open_v2() */
 #define SQLITE_OPEN_MAIN_DB          0x00000100  /* VFS only */
 #define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
 #define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
@@ -1047,7 +1083,7 @@ SQLITE_API int sqlite3_exec(
 ** CAPI3REF: Device Characteristics
 **
 ** The xDeviceCharacteristics method of the [sqlite3_io_methods]
-** object returns an integer which is a vector of the these
+** object returns an integer which is a vector of these
 ** bit values expressing I/O characteristics of the mass storage
 ** device that holds the file that the [sqlite3_io_methods]
 ** refers to.
@@ -2719,12 +2755,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
 ** implementation of these routines to be omitted.  That capability
 ** is no longer provided.  Only built-in memory allocators can be used.
 **
-** The Windows OS interface layer calls
+** Prior to SQLite version 3.7.10, the Windows OS interface layer called
 ** the system malloc() and free() directly when converting
 ** filenames between the UTF-8 encoding used by SQLite
 ** and whatever filename encoding is used by the particular Windows
-** installation.  Memory allocation errors are detected, but
-** they are reported back as [SQLITE_CANTOPEN] or
+** installation.  Memory allocation errors were detected, but
+** they were reported back as [SQLITE_CANTOPEN] or
 ** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
 **
 ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
@@ -3125,18 +3161,20 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     present, then the VFS specified by the option takes precedence over
 **     the value passed as the fourth parameter to sqlite3_open_v2().
 **
-**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
-**     "rwc". Attempting to set it to any other value is an error)^. 
+**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
+**     "rwc", or "memory". Attempting to set it to any other value is
+**     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 
 **     "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 
-**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is 
-**     used, it is an error to specify a value for the mode parameter that is 
-**     less restrictive than that specified by the flags passed as the third 
-**     parameter.
+**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.  ^If the mode option is
+**     set to "memory" then a pure [in-memory database] that never reads
+**     or writes from disk is used. ^It is an error to specify a value for
+**     the mode parameter that is less restrictive than that specified by
+**     the flags passed in the third parameter to sqlite3_open_v2().
 **
 **   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
 **     "private". ^Setting it to "shared" is equivalent to setting the
@@ -3195,6 +3233,12 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** codepage is currently defined.  Filenames containing international
 ** characters must be converted to UTF-8 prior to passing them into
 ** sqlite3_open() or sqlite3_open_v2().
+**
+** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
+** prior to calling sqlite3_open() or sqlite3_open_v2().  Otherwise, various
+** features that require the use of temporary files may fail.
+**
+** See also: [sqlite3_temp_directory]
 */
 SQLITE_API int sqlite3_open(
   const char *filename,   /* Database filename (UTF-8) */
@@ -3687,8 +3731,11 @@ typedef struct sqlite3_context sqlite3_context;
 ** ^(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
 ** number of <u>bytes</u> in the value, not the number of characters.)^
-** ^If the fourth parameter is negative, the length of the string is
+** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** is negative, then the length of the string is
 ** the number of bytes up to the first zero terminator.
+** If the fourth parameter to sqlite3_bind_blob() is negative, then
+** the behavior is undefined.
 ** If a non-negative fourth parameter is provided to sqlite3_bind_text()
 ** or sqlite3_bind_text16() then that parameter must be the byte offset
 ** where the NUL terminator would occur assuming the string were NUL
@@ -4685,11 +4732,11 @@ typedef void (*sqlite3_destructor_type)(void*);
 ** the error code is SQLITE_ERROR.  ^A subsequent call to sqlite3_result_error()
 ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
 **
-** ^The sqlite3_result_toobig() interface causes SQLite to throw an error
-** indicating that a string or BLOB is too long to represent.
+** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
+** error indicating that a string or BLOB is too long to represent.
 **
-** ^The sqlite3_result_nomem() interface causes SQLite to throw an error
-** indicating that a memory allocation failed.
+** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
+** error indicating that a memory allocation failed.
 **
 ** ^The sqlite3_result_int() interface sets the return value
 ** of the application-defined function to be the 32-bit signed integer
@@ -4996,10 +5043,62 @@ SQLITE_API int sqlite3_sleep(int);
 ** Hence, if this variable is modified directly, either it should be
 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
 ** or else the use of the [temp_store_directory pragma] should be avoided.
+**
+** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
+** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
+** features that require the use of temporary files may fail.  Here is an
+** example of how to do this using C++ with the Windows Runtime:
+**
+** <blockquote><pre>
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+** &nbsp;     TemporaryFolder->Path->Data();
+** char zPathBuf&#91;MAX_PATH + 1&#93;;
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+** &nbsp;     NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** </pre></blockquote>
 */
 SQLITE_API char *sqlite3_temp_directory;
 
 /*
+** CAPI3REF: Name Of The Folder Holding Database Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all database files
+** specified with a relative pathname and created or accessed by
+** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
+** to be relative to that directory.)^ ^If this variable is a NULL
+** pointer, then SQLite assumes that all database files specified
+** with a relative pathname are relative to the current directory
+** for the process.  Only the windows VFS makes use of this global
+** variable; it is ignored by the unix VFS.
+**
+** Changing the value of this variable while a database connection is
+** open can result in a corrupt database.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time.  It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [data_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
+** the [data_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from 
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [data_store_directory pragma] should be avoided.
+*/
+SQLITE_API char *sqlite3_data_directory;
+
+/*
 ** CAPI3REF: Test For Auto-Commit Mode
 ** KEYWORDS: {autocommit mode}
 **
@@ -5177,7 +5276,6 @@ SQLITE_API void *sqlite3_update_hook(
 
 /*
 ** CAPI3REF: Enable Or Disable Shared Pager Cache
-** KEYWORDS: {shared cache}
 **
 ** ^(This routine enables or disables the sharing of the database cache
 ** and schema data structures between [database connection | connections]
@@ -6005,7 +6103,6 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** implementations are available in the SQLite core:
 **
 ** <ul>
-** <li>   SQLITE_MUTEX_OS2
 ** <li>   SQLITE_MUTEX_PTHREADS
 ** <li>   SQLITE_MUTEX_W32
 ** <li>   SQLITE_MUTEX_NOOP
@@ -6013,9 +6110,9 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 **
 ** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
 ** that does no real locking and is appropriate for use in
-** a single-threaded application.  ^The SQLITE_MUTEX_OS2,
-** SQLITE_MUTEX_PTHREADS, and SQLITE_MUTEX_W32 implementations
-** are appropriate for use on OS/2, Unix, and Windows.
+** a single-threaded application.  ^The SQLITE_MUTEX_PTHREADS and
+** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
+** and Windows.
 **
 ** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
 ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
@@ -8326,6 +8423,12 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 #define BTREE_USER_VERSION        6
 #define BTREE_INCR_VACUUM         7
 
+/*
+** Values that may be OR'd together to form the second argument of an
+** sqlite3BtreeCursorHints() call.
+*/
+#define BTREE_BULKLOAD 0x00000001
+
 SQLITE_PRIVATE int sqlite3BtreeCursor(
   Btree*,                              /* BTree containing table to open */
   int iTable,                          /* Index of root page */
@@ -8369,8 +8472,8 @@ SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
 SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
 SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
 SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
-
 SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
+SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
 
 #ifndef NDEBUG
 SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
@@ -9016,7 +9119,7 @@ SQLITE_PRIVATE   int sqlite3PagerWalFramesize(Pager *pPager);
 SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*);
+SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
 SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
@@ -9244,7 +9347,7 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 /*
 ** Figure out if we are dealing with Unix, Windows, or some other
 ** operating system.  After the following block of preprocess macros,
-** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER 
+** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER 
 ** will defined to either 1 or 0.  One of the four will be 1.  The other 
 ** three will be 0.
 */
@@ -9254,8 +9357,6 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 #   define SQLITE_OS_UNIX 0
 #   undef SQLITE_OS_WIN
 #   define SQLITE_OS_WIN 0
-#   undef SQLITE_OS_OS2
-#   define SQLITE_OS_OS2 0
 # else
 #   undef SQLITE_OS_OTHER
 # endif
@@ -9266,19 +9367,12 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 #   if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
 #     define SQLITE_OS_WIN 1
 #     define SQLITE_OS_UNIX 0
-#     define SQLITE_OS_OS2 0
-#   elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__)
-#     define SQLITE_OS_WIN 0
-#     define SQLITE_OS_UNIX 0
-#     define SQLITE_OS_OS2 1
 #   else
 #     define SQLITE_OS_WIN 0
 #     define SQLITE_OS_UNIX 1
-#     define SQLITE_OS_OS2 0
 #  endif
 # else
 #  define SQLITE_OS_UNIX 0
-#  define SQLITE_OS_OS2 0
 # endif
 #else
 # ifndef SQLITE_OS_WIN
@@ -9286,28 +9380,8 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 # endif
 #endif
 
-/*
-** Define the maximum size of a temporary filename
-*/
 #if SQLITE_OS_WIN
 # include <windows.h>
-# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
-#elif SQLITE_OS_OS2
-# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY)
-#  include <os2safe.h> /* has to be included before os2.h for linking to work */
-# endif
-# define INCL_DOSDATETIME
-# define INCL_DOSFILEMGR
-# define INCL_DOSERRORS
-# define INCL_DOSMISC
-# define INCL_DOSPROCESS
-# define INCL_DOSMODULEMGR
-# define INCL_DOSSEMAPHORES
-# include <os2.h>
-# include <uconv.h>
-# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
-#else
-# define SQLITE_TEMPNAME_SIZE 200
 #endif
 
 /*
@@ -9341,6 +9415,22 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 # define SQLITE_OS_WINCE 0
 #endif
 
+/*
+** Determine if we are dealing with WinRT, which provides only a subset of
+** the full Win32 API.
+*/
+#if !defined(SQLITE_OS_WINRT)
+# 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
 */
@@ -9563,8 +9653,6 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
 **   SQLITE_MUTEX_PTHREADS     For multi-threaded applications on Unix.
 **
 **   SQLITE_MUTEX_W32          For multi-threaded applications on Win32.
-**
-**   SQLITE_MUTEX_OS2          For multi-threaded applications on OS/2.
 */
 #if !SQLITE_THREADSAFE
 # define SQLITE_MUTEX_OMIT
@@ -9574,8 +9662,6 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
 #    define SQLITE_MUTEX_PTHREADS
 #  elif SQLITE_OS_WIN
 #    define SQLITE_MUTEX_W32
-#  elif SQLITE_OS_OS2
-#    define SQLITE_MUTEX_OS2
 #  else
 #    define SQLITE_MUTEX_NOOP
 #  endif
@@ -9896,6 +9982,7 @@ struct sqlite3 {
 #define SQLITE_MAGIC_SICK     0x4b771290  /* Error and awaiting close */
 #define SQLITE_MAGIC_BUSY     0xf03b7906  /* Database currently in use */
 #define SQLITE_MAGIC_ERROR    0xb5357930  /* An SQLITE_MISUSE error occurred */
+#define SQLITE_MAGIC_ZOMBIE   0x64cffc7f  /* Close with last statement close */
 
 /*
 ** Each SQL function is defined by an instance of the following
@@ -10602,8 +10689,9 @@ struct Expr {
   i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
   i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
   u8 flags2;             /* Second set of flags.  EP2_... */
-  u8 op2;                /* If a TK_REGISTER, the original value of Expr.op */
-                         /* If TK_COLUMN, the value of p5 for OP_Column */
+  u8 op2;                /* TK_REGISTER: original value of Expr.op
+                         ** TK_COLUMN: the value of p5 for OP_Column
+                         ** 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
@@ -10828,7 +10916,7 @@ struct WherePlan {
 /*
 ** For each nested loop in a WHERE clause implementation, the WhereInfo
 ** structure contains a single instance of this structure.  This structure
-** is intended to be private the the where.c module and should not be
+** is intended to be private to the where.c module and should not be
 ** access or modified by other modules.
 **
 ** The pIdxInfo field is used to help pick the best index on a
@@ -10858,6 +10946,7 @@ struct WhereLevel {
         int addrInTop;         /* Top of the IN loop */
       } *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;
 
   /* The following field is really not part of the current level.  But
@@ -11030,10 +11119,10 @@ struct Select {
 typedef struct SelectDest SelectDest;
 struct SelectDest {
   u8 eDest;         /* How to dispose of the results */
-  u8 affinity;      /* Affinity used when eDest==SRT_Set */
-  int iParm;        /* A parameter used by the eDest disposal method */
-  int iMem;         /* Base register where results are written */
-  int nMem;         /* Number of registers allocated */
+  u8 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 */
 };
 
 /*
@@ -11229,6 +11318,8 @@ struct AuthContext {
 #define OPFLAG_CLEARCACHE    0x20    /* Clear pseudo-table cache in OP_Column */
 #define OPFLAG_LENGTHARG     0x40    /* OP_Column only used for length() */
 #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 */
 
 /*
  * Each trigger present in the database schema is stored as an instance of
@@ -11408,10 +11499,12 @@ struct Walker {
   int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
   int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
   Parse *pParse;                            /* Parser context.  */
+  int walkerDepth;                          /* Number of subqueries */
   union {                                   /* Extra data for callback */
     NameContext *pNC;                          /* Naming context */
     int i;                                     /* Integer value */
     SrcList *pSrcList;                         /* FROM clause */
+    struct SrcCount *pSrcCount;                /* Counting column references */
   } u;
 };
 
@@ -11631,7 +11724,9 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
 SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
 SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
 SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
-SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int);
+SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
+SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
+SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
 SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
@@ -11711,7 +11806,8 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, E
 #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);
+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);
@@ -11743,6 +11839,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
 SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*);
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
+SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
 SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
 SQLITE_PRIVATE void sqlite3PrngSaveState(void);
 SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
@@ -11755,6 +11852,7 @@ SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
 SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
 SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
 SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
+SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
 SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
 SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*);
@@ -12036,6 +12134,7 @@ SQLITE_PRIVATE   int sqlite3Utf8To8(unsigned char*);
 #  define sqlite3GetVTable(X,Y)  ((VTable*)0)
 #else
 SQLITE_PRIVATE    void sqlite3VtabClear(sqlite3 *db, Table*);
+SQLITE_PRIVATE    void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
 SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, char **);
 SQLITE_PRIVATE    int sqlite3VtabRollback(sqlite3 *db);
 SQLITE_PRIVATE    int sqlite3VtabCommit(sqlite3 *db);
@@ -12490,6 +12589,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_COVERAGE_TEST
   "COVERAGE_TEST",
 #endif
+#ifdef SQLITE_CURDIR
+  "CURDIR",
+#endif
 #ifdef SQLITE_DEBUG
   "DEBUG",
 #endif
@@ -13292,11 +13394,11 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
 #else
 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
-SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
-SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
-SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
-SQLITE_PRIVATE int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
+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 *);
 #endif
 
 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
@@ -15443,14 +15545,14 @@ static int sqlite3MemInit(void *NotUsed){
   }else{
     /* only 1 core, use our own zone to contention over global locks, 
     ** e.g. we have our own dedicated locks */
-    bool success;		
+    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 ){	
+    if( !success ){
       /* somebody registered a zone first */
       malloc_destroy_zone(newzone);
     }
@@ -17656,7 +17758,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
 #endif /* !defined(SQLITE_MUTEX_OMIT) */
 
 /************** End of mutex_noop.c ******************************************/
-/************** Begin file mutex_os2.c ***************************************/
+/************** Begin file mutex_unix.c **************************************/
 /*
 ** 2007 August 28
 **
@@ -17668,49 +17770,85 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file contains the C functions that implement mutexes for OS/2
+** This file contains the C functions that implement mutexes for pthreads
 */
 
 /*
-** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
-** See the mutex.h file for details.
+** 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.
 */
-#ifdef SQLITE_MUTEX_OS2
+#ifdef SQLITE_MUTEX_PTHREADS
 
-/********************** OS/2 Mutex Implementation **********************
-**
-** This implementation of mutexes is built using the OS/2 API.
+#include <pthread.h>
+
+/*
+** 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.
 */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
+# define SQLITE_MUTEX_NREF 1
+#else
+# define SQLITE_MUTEX_NREF 0
+#endif
 
 /*
-** The mutex object
 ** Each recursive mutex is an instance of the following structure.
 */
 struct sqlite3_mutex {
-  HMTX mutex;       /* Mutex controlling the lock */
-  int  id;          /* Mutex type */
-#ifdef SQLITE_DEBUG
- int   trace;       /* True to trace changes */
+  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
 };
-
-#ifdef SQLITE_DEBUG
-#define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
+#if SQLITE_MUTEX_NREF
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
 #else
-#define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
+#endif
+
+/*
+** 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()));
+}
+static int pthreadMutexNotheld(sqlite3_mutex *p){
+  return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
+}
 #endif
 
 /*
 ** Initialize and deinitialize the mutex subsystem.
 */
-static int os2MutexInit(void){ return SQLITE_OK; }
-static int os2MutexEnd(void){ return SQLITE_OK; }
+static int pthreadMutexInit(void){ return SQLITE_OK; }
+static int pthreadMutexEnd(void){ return SQLITE_OK; }
 
 /*
 ** 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
+** 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>
@@ -17721,7 +17859,7 @@ static int os2MutexEnd(void){ return SQLITE_OK; }
 ** <li>  SQLITE_MUTEX_STATIC_MEM2
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** <li>  SQLITE_MUTEX_STATIC_LRU
-** <li>  SQLITE_MUTEX_STATIC_LRU2
+** <li>  SQLITE_MUTEX_STATIC_PMEM
 ** </ul>
 **
 ** The first two constants cause sqlite3_mutex_alloc() to create
@@ -17744,67 +17882,59 @@ static int os2MutexEnd(void){ return SQLITE_OK; }
 **
 ** 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
+** 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.
 */
-static sqlite3_mutex *os2MutexAlloc(int iType){
-  sqlite3_mutex *p = NULL;
+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_FAST:
     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;
-        if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
-          sqlite3_free( p );
-          p = NULL;
-        }
+#endif
+        pthread_mutex_init(&p->mutex, 0);
       }
       break;
     }
     default: {
-      static volatile int isInit = 0;
-      static sqlite3_mutex staticMutexes[6] = {
-        SQLITE3_MUTEX_INITIALIZER,
-        SQLITE3_MUTEX_INITIALIZER,
-        SQLITE3_MUTEX_INITIALIZER,
-        SQLITE3_MUTEX_INITIALIZER,
-        SQLITE3_MUTEX_INITIALIZER,
-        SQLITE3_MUTEX_INITIALIZER,
-      };
-      if ( !isInit ){
-        APIRET rc;
-        PTIB ptib;
-        PPIB ppib;
-        HMTX mutex;
-        char name[32];
-        DosGetInfoBlocks( &ptib, &ppib );
-        sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
-                          ppib->pib_ulpid );
-        while( !isInit ){
-          mutex = 0;
-          rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
-          if( rc == NO_ERROR ){
-            unsigned int i;
-            if( !isInit ){
-              for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
-                DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
-              }
-              isInit = 1;
-            }
-            DosCloseMutexSem( mutex );
-          }else if( rc == ERROR_DUPLICATE_NAME ){
-            DosSleep( 1 );
-          }else{
-            return p;
-          }
-        }
-      }
       assert( iType-2 >= 0 );
-      assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
+      assert( iType-2 < ArraySize(staticMutexes) );
       p = &staticMutexes[iType-2];
+#if SQLITE_MUTEX_NREF
       p->id = iType;
+#endif
       break;
     }
   }
@@ -17813,57 +17943,16 @@ static sqlite3_mutex *os2MutexAlloc(int iType){
 
 
 /*
-** This routine deallocates a previously allocated mutex.
-** SQLite is careful to deallocate every mutex that it allocates.
+** This routine deallocates a previously
+** allocated mutex.  SQLite is careful to deallocate every
+** mutex that it allocates.
 */
-static void os2MutexFree(sqlite3_mutex *p){
-#ifdef SQLITE_DEBUG
-  TID tid;
-  PID pid;
-  ULONG ulCount;
-  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
-  assert( ulCount==0 );
+static void pthreadMutexFree(sqlite3_mutex *p){
+  assert( p->nRef==0 );
   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-#endif
-  DosCloseMutexSem( p->mutex );
-  sqlite3_free( p );
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use inside assert() statements.
-*/
-static int os2MutexHeld(sqlite3_mutex *p){
-  TID tid;
-  PID pid;
-  ULONG ulCount;
-  PTIB ptib;
-  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
-  if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
-    return 0;
-  DosGetInfoBlocks(&ptib, NULL);
-  return tid==ptib->tib_ptib2->tib2_ultid;
-}
-static int os2MutexNotheld(sqlite3_mutex *p){
-  TID tid;
-  PID pid;
-  ULONG ulCount;
-  PTIB ptib;
-  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
-  if( ulCount==0 )
-    return 1;
-  DosGetInfoBlocks(&ptib, NULL);
-  return tid!=ptib->tib_ptib2->tib2_ultid;
-}
-static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
-  TID   tid;
-  PID   pid;
-  ULONG ulCount;
-  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
-  printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
+  pthread_mutex_destroy(&p->mutex);
+  sqlite3_free(p);
 }
-#endif
 
 /*
 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
@@ -17876,22 +17965,96 @@ static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
 ** can enter.  If the same thread tries to enter any other kind of mutex
 ** more than once, the behavior is undefined.
 */
-static void os2MutexEnter(sqlite3_mutex *p){
-  assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
-  DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
+static void pthreadMutexEnter(sqlite3_mutex *p){
+  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
+
+#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.
+  */
+  {
+    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.
+  */
+  pthread_mutex_lock(&p->mutex);
+#if SQLITE_MUTEX_NREF
+  assert( p->nRef>0 || p->owner==0 );
+  p->owner = pthread_self();
+  p->nRef++;
+#endif
+#endif
+
 #ifdef SQLITE_DEBUG
-  if( p->trace ) os2MutexTrace(p, "enter");
+  if( p->trace ){
+    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+  }
 #endif
 }
-static int os2MutexTry(sqlite3_mutex *p){
-  int rc = SQLITE_BUSY;
-  assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
-  if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
+static int pthreadMutexTry(sqlite3_mutex *p){
+  int rc;
+  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
+
+#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.
+  */
+  {
+    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.
+  */
+  if( pthread_mutex_trylock(&p->mutex)==0 ){
+#if SQLITE_MUTEX_NREF
+    p->owner = pthread_self();
+    p->nRef++;
+#endif
     rc = SQLITE_OK;
-#ifdef SQLITE_DEBUG
-    if( p->trace ) os2MutexTrace(p, "try");
+  }else{
+    rc = SQLITE_BUSY;
+  }
 #endif
+
+#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;
 }
 
@@ -17901,26 +18064,41 @@ static int os2MutexTry(sqlite3_mutex *p){
 ** is undefined if the mutex is not currently entered or
 ** is not currently allocated.  SQLite will never do either.
 */
-static void os2MutexLeave(sqlite3_mutex *p){
-  assert( os2MutexHeld(p) );
-  DosReleaseMutexSem(p->mutex);
+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);
+  }
+#else
+  pthread_mutex_unlock(&p->mutex);
+#endif
+
 #ifdef SQLITE_DEBUG
-  if( p->trace ) os2MutexTrace(p, "leave");
+  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 = {
-    os2MutexInit,
-    os2MutexEnd,
-    os2MutexAlloc,
-    os2MutexFree,
-    os2MutexEnter,
-    os2MutexTry,
-    os2MutexLeave,
+    pthreadMutexInit,
+    pthreadMutexEnd,
+    pthreadMutexAlloc,
+    pthreadMutexFree,
+    pthreadMutexEnter,
+    pthreadMutexTry,
+    pthreadMutexLeave,
 #ifdef SQLITE_DEBUG
-    os2MutexHeld,
-    os2MutexNotheld
+    pthreadMutexHeld,
+    pthreadMutexNotheld
 #else
     0,
     0
@@ -17929,12 +18107,13 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
 
   return &sMutex;
 }
-#endif /* SQLITE_MUTEX_OS2 */
 
-/************** End of mutex_os2.c *******************************************/
-/************** Begin file mutex_unix.c **************************************/
+#endif /* SQLITE_MUTEX_PTHREADS */
+
+/************** End of mutex_unix.c ******************************************/
+/************** Begin file mutex_w32.c ***************************************/
 /*
-** 2007 August 28
+** 2007 August 14
 **
 ** The author disclaims copyright to this source code.  In place of
 ** a legal notice, here is a blessing:
@@ -17944,489 +18123,142 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** 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.
+** This file contains the C functions that implement mutexes for win32
 */
-#ifdef SQLITE_MUTEX_PTHREADS
-
-#include <pthread.h>
 
 /*
-** 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 code in this file is only used if we are compiling multithreaded
+** on a win32 system.
 */
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
-# define SQLITE_MUTEX_NREF 1
-#else
-# define SQLITE_MUTEX_NREF 0
-#endif
+#ifdef SQLITE_MUTEX_W32
 
 /*
 ** 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
+  CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
   int id;                    /* Mutex type */
-  volatile int nRef;         /* Number of entrances */
-  volatile pthread_t owner;  /* Thread that is within this mutex */
+#ifdef SQLITE_DEBUG
+  volatile int nRef;         /* Number of enterances */
+  volatile DWORD owner;      /* Thread holding 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 }
+#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 { PTHREAD_MUTEX_INITIALIZER }
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
 #endif
 
 /*
-** 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.
+** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
+** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
 **
-** 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.
+** 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.
 */
-#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
-static int pthreadMutexHeld(sqlite3_mutex *p){
-  return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
+#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;
+  }
+#endif /* SQLITE_OS_WINCE */
+#endif
+
+#ifdef SQLITE_DEBUG
+/*
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+** intended for use only inside assert() statements.
+*/
+static int winMutexHeld(sqlite3_mutex *p){
+  return p->nRef!=0 && p->owner==GetCurrentThreadId();
 }
-static int pthreadMutexNotheld(sqlite3_mutex *p){
-  return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
+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
 
+
 /*
 ** Initialize and deinitialize the mutex subsystem.
 */
-static int pthreadMutexInit(void){ return SQLITE_OK; }
-static int pthreadMutexEnd(void){ return SQLITE_OK; }
-
-/*
-** 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.
-*/
-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;
-}
-
-
-/*
-** 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);
-}
-
-/*
-** 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.
-*/
-static void pthreadMutexEnter(sqlite3_mutex *p){
-  assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-
-#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.
-  */
-  {
-    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.
-  */
-  pthread_mutex_lock(&p->mutex);
-#if SQLITE_MUTEX_NREF
-  assert( p->nRef>0 || p->owner==0 );
-  p->owner = pthread_self();
-  p->nRef++;
-#endif
-#endif
-
-#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) );
-
-#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.
-  */
-  {
-    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.
-  */
-  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
-
-#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.
-*/
-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);
-  }
-#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);
-  }
-#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.
-**
-*************************************************************************
-** This file contains the C functions that implement mutexes for win32
-*/
-
-/*
-** 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.
-**
-** 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.
-*/
-#if 0
-#if SQLITE_OS_WINCE
-# 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;
-  }
-#endif /* SQLITE_OS_WINCE */
-#endif
-
-#ifdef SQLITE_DEBUG
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use only inside assert() statements.
-*/
-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
-
-
-/*
-** 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.
-*/
-static long winMutex_lock = 0;
-
-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++){
-      InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
-    }
-    winMutex_isInit = 1;
-  }else{
-    /* Someone else is in the process of initing the static mutexes */
-    while( !winMutex_isInit ){
-      Sleep(1);
-    }
-  }
-  return SQLITE_OK; 
-}
-
-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; 
-}
+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{
+    /* Someone else is in the process of initing the static mutexes */
+    while( !winMutex_isInit ){
+      sqlite3_win32_sleep(1);
+    }
+  }
+  return SQLITE_OK; 
+}
+
+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; 
+}
 
 /*
 ** The sqlite3_mutex_alloc() routine allocates a new
@@ -18481,7 +18313,11 @@ static sqlite3_mutex *winMutexAlloc(int iType){
 #ifdef SQLITE_DEBUG
         p->id = iType;
 #endif
+#if SQLITE_OS_WINRT
+        InitializeCriticalSectionEx(&p->mutex, 0, 0);
+#else
         InitializeCriticalSection(&p->mutex);
+#endif
       }
       break;
     }
@@ -19529,7 +19365,8 @@ static const et_info fmtinfo[] = {
 static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
   int digit;
   LONGDOUBLE_TYPE d;
-  if( (*cnt)++ >= 16 ) return '0';
+  if( (*cnt)<=0 ) return '0';
+  (*cnt)--;
   digit = (int)*val;
   d = digit;
   digit += '0';
@@ -19833,9 +19670,12 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
           break;
         }
         if( realvalue>0.0 ){
-          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
-          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
-          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
+          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 ){
@@ -19868,7 +19708,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
             xtype = etFLOAT;
           }
         }else{
-          flag_rtz = 0;
+          flag_rtz = flag_altform2;
         }
         if( xtype==etEXP ){
           e2 = 0;
@@ -19883,7 +19723,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
           }
         }
         zOut = bufpt;
-        nsd = 0;
+        nsd = 16 + flag_altform2*10;
         flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
         /* The sign in front of the number */
         if( prefix ){
@@ -21456,7 +21296,7 @@ do_atof_calc:
     /* if exponent, scale significand as appropriate
     ** and store in result. */
     if( e ){
-      double scale = 1.0;
+      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; }
@@ -22385,7 +22225,11 @@ static int rehash(Hash *pH, unsigned int new_size){
 
   /* 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.
+  ** 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) );
@@ -22711,2140 +22555,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 #endif
 
 /************** End of opcodes.c *********************************************/
-/************** Begin file os_os2.c ******************************************/
-/*
-** 2006 Feb 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 code that is specific to OS/2.
-*/
-
-
-#if SQLITE_OS_OS2
-
-/*
-** A Note About Memory Allocation:
-**
-** This driver uses malloc()/free() directly rather than going through
-** the SQLite-wrappers sqlite3_malloc()/sqlite3_free().  Those wrappers
-** are designed for use on embedded systems where memory is scarce and
-** malloc failures happen frequently.  OS/2 does not typically run on
-** embedded systems, and when it does the developers normally have bigger
-** problems to worry about than running out of memory.  So there is not
-** a compelling need to use the wrappers.
-**
-** But there is a good reason to not use the wrappers.  If we use the
-** wrappers then we will get simulated malloc() failures within this
-** driver.  And that causes all kinds of problems for our tests.  We
-** could enhance SQLite to deal with simulated malloc failures within
-** the OS driver, but the code to deal with those failure would not
-** be exercised on Linux (which does not need to malloc() in the driver)
-** and so we would have difficulty writing coverage tests for that
-** code.  Better to leave the code out, we think.
-**
-** The point of this discussion is as follows:  When creating a new
-** OS layer for an embedded system, if you use this file as an example,
-** avoid the use of malloc()/free().  Those routines work ok on OS/2
-** desktops but not so well in embedded systems.
-*/
-
-/*
-** Macros used to determine whether or not to use threads.
-*/
-#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE
-# define SQLITE_OS2_THREADS 1
-#endif
-
-/*
-** Include code that is common to all os_*.c files
-*/
-/************** Include os_common.h in the middle of os_os2.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.
-*/
-#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
-
-/*
-** 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.
-**
-******************************************************************************
-**
-** 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.
-*/
-#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__))
-
-  __inline__ sqlite_uint64 sqlite3Hwtime(void){
-      unsigned long val;
-      __asm__ __volatile__ ("rdtsc" : "=A" (val));
-      return val;
-  }
- 
-#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;
-  }
-
-#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
-
-/*
-** 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
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif
-
-/*
-** 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
-#define OpenCounter(X)
-#endif
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in os_os2.c *********************/
-
-/* Forward references */
-typedef struct os2File os2File;         /* The file structure */
-typedef struct os2ShmNode os2ShmNode;   /* A shared descritive memory node */
-typedef struct os2ShmLink os2ShmLink;   /* A connection to shared-memory */
-
-/*
-** The os2File structure is subclass of sqlite3_file specific for the OS/2
-** protability layer.
-*/
-struct os2File {
-  const sqlite3_io_methods *pMethod;  /* Always the first entry */
-  HFILE h;                  /* Handle for accessing the file */
-  int flags;                /* Flags provided to os2Open() */
-  int locktype;             /* Type of lock currently held on this file */
-  int szChunk;              /* Chunk size configured by FCNTL_CHUNK_SIZE */
-  char *zFullPathCp;        /* Full path name of this file */
-  os2ShmLink *pShmLink;     /* Instance of shared memory on this file */
-};
-
-#define LOCK_TIMEOUT 10L /* the default locking timeout */
-
-/*
-** Missing from some versions of the OS/2 toolkit -
-** used to allocate from high memory if possible
-*/
-#ifndef OBJ_ANY
-# define OBJ_ANY 0x00000400
-#endif
-
-/*****************************************************************************
-** The next group of routines implement the I/O methods specified
-** by the sqlite3_io_methods object.
-******************************************************************************/
-
-/*
-** Close a file.
-*/
-static int os2Close( sqlite3_file *id ){
-  APIRET rc;
-  os2File *pFile = (os2File*)id;
-
-  assert( id!=0 );
-  OSTRACE(( "CLOSE %d (%s)\n", pFile->h, pFile->zFullPathCp ));
-
-  rc = DosClose( pFile->h );
-
-  if( pFile->flags & SQLITE_OPEN_DELETEONCLOSE )
-    DosForceDelete( (PSZ)pFile->zFullPathCp );
-
-  free( pFile->zFullPathCp );
-  pFile->zFullPathCp = NULL;
-  pFile->locktype = NO_LOCK;
-  pFile->h = (HFILE)-1;
-  pFile->flags = 0;
-
-  OpenCounter( -1 );
-  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
-}
-
-/*
-** 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 os2Read(
-  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 */
-){
-  ULONG fileLocation = 0L;
-  ULONG got;
-  os2File *pFile = (os2File*)id;
-  assert( id!=0 );
-  SimulateIOError( return SQLITE_IOERR_READ );
-  OSTRACE(( "READ %d lock=%d\n", pFile->h, pFile->locktype ));
-  if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
-    return SQLITE_IOERR;
-  }
-  if( DosRead( pFile->h, pBuf, amt, &got ) != NO_ERROR ){
-    return SQLITE_IOERR_READ;
-  }
-  if( got == (ULONG)amt )
-    return SQLITE_OK;
-  else {
-    /* Unread portions of the input buffer must be zero-filled */
-    memset(&((char*)pBuf)[got], 0, amt-got);
-    return SQLITE_IOERR_SHORT_READ;
-  }
-}
-
-/*
-** Write data from a buffer into a file.  Return SQLITE_OK on success
-** or some other error code on failure.
-*/
-static int os2Write(
-  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 */
-){
-  ULONG fileLocation = 0L;
-  APIRET rc = NO_ERROR;
-  ULONG wrote;
-  os2File *pFile = (os2File*)id;
-  assert( id!=0 );
-  SimulateIOError( return SQLITE_IOERR_WRITE );
-  SimulateDiskfullError( return SQLITE_FULL );
-  OSTRACE(( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ));
-  if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
-    return SQLITE_IOERR;
-  }
-  assert( amt>0 );
-  while( amt > 0 &&
-         ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR &&
-         wrote > 0
-  ){
-    amt -= wrote;
-    pBuf = &((char*)pBuf)[wrote];
-  }
-
-  return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
-}
-
-/*
-** Truncate an open file to a specified size
-*/
-static int os2Truncate( sqlite3_file *id, i64 nByte ){
-  APIRET rc;
-  os2File *pFile = (os2File*)id;
-  assert( id!=0 );
-  OSTRACE(( "TRUNCATE %d %lld\n", pFile->h, nByte ));
-  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).
-  */
-  if( pFile->szChunk ){
-    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
-  }
-  
-  rc = DosSetFileSize( pFile->h, nByte );
-  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
-}
-
-#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.
-*/
-static int os2Sync( sqlite3_file *id, int flags ){
-  os2File *pFile = (os2File*)id;
-  OSTRACE(( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ));
-#ifdef SQLITE_TEST
-  if( flags & SQLITE_SYNC_FULL){
-    sqlite3_fullsync_count++;
-  }
-  sqlite3_sync_count++;
-#endif
-  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
-  ** no-op
-  */
-#ifdef SQLITE_NO_SYNC
-  UNUSED_PARAMETER(pFile);
-  return SQLITE_OK;
-#else
-  return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
-#endif
-}
-
-/*
-** Determine the current size of a file in bytes
-*/
-static int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){
-  APIRET rc = NO_ERROR;
-  FILESTATUS3 fsts3FileInfo;
-  memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
-  assert( id!=0 );
-  SimulateIOError( return SQLITE_IOERR_FSTAT );
-  rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
-  if( rc == NO_ERROR ){
-    *pSize = fsts3FileInfo.cbFile;
-    return SQLITE_OK;
-  }else{
-    return SQLITE_IOERR_FSTAT;
-  }
-}
-
-/*
-** Acquire a reader lock.
-*/
-static int getReadLock( os2File *pFile ){
-  FILELOCK  LockArea,
-            UnlockArea;
-  APIRET res;
-  memset(&LockArea, 0, sizeof(LockArea));
-  memset(&UnlockArea, 0, sizeof(UnlockArea));
-  LockArea.lOffset = SHARED_FIRST;
-  LockArea.lRange = SHARED_SIZE;
-  UnlockArea.lOffset = 0L;
-  UnlockArea.lRange = 0L;
-  res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
-  OSTRACE(( "GETREADLOCK %d res=%d\n", pFile->h, res ));
-  return res;
-}
-
-/*
-** Undo a readlock
-*/
-static int unlockReadLock( os2File *id ){
-  FILELOCK  LockArea,
-            UnlockArea;
-  APIRET res;
-  memset(&LockArea, 0, sizeof(LockArea));
-  memset(&UnlockArea, 0, sizeof(UnlockArea));
-  LockArea.lOffset = 0L;
-  LockArea.lRange = 0L;
-  UnlockArea.lOffset = SHARED_FIRST;
-  UnlockArea.lRange = SHARED_SIZE;
-  res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
-  OSTRACE(( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ));
-  return res;
-}
-
-/*
-** 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 os2Unlock() 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 os2Lock( sqlite3_file *id, int locktype ){
-  int rc = SQLITE_OK;       /* Return code from subroutines */
-  APIRET res = NO_ERROR;    /* Result of an OS/2 lock call */
-  int newLocktype;       /* Set pFile->locktype to this value before exiting */
-  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
-  FILELOCK  LockArea,
-            UnlockArea;
-  os2File *pFile = (os2File*)id;
-  memset(&LockArea, 0, sizeof(LockArea));
-  memset(&UnlockArea, 0, sizeof(UnlockArea));
-  assert( pFile!=0 );
-  OSTRACE(( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ));
-
-  /* If there is already a lock of this type or more restrictive on the
-  ** os2File, do nothing. Don't use the end_lock: exit path, as
-  ** sqlite3_mutex_enter() hasn't been called yet.
-  */
-  if( pFile->locktype>=locktype ){
-    OSTRACE(( "LOCK %d %d ok (already held)\n", pFile->h, locktype ));
-    return SQLITE_OK;
-  }
-
-  /* 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 );
-
-  /* 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)
-  ){
-    LockArea.lOffset = PENDING_BYTE;
-    LockArea.lRange = 1L;
-    UnlockArea.lOffset = 0L;
-    UnlockArea.lRange = 0L;
-
-    /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */
-    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L );
-    if( res == NO_ERROR ){
-      gotPendingLock = 1;
-      OSTRACE(( "LOCK %d pending lock boolean set.  res=%d\n", pFile->h, res ));
-    }
-  }
-
-  /* Acquire a shared lock
-  */
-  if( locktype==SHARED_LOCK && res == NO_ERROR ){
-    assert( pFile->locktype==NO_LOCK );
-    res = getReadLock(pFile);
-    if( res == NO_ERROR ){
-      newLocktype = SHARED_LOCK;
-    }
-    OSTRACE(( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ));
-  }
-
-  /* Acquire a RESERVED lock
-  */
-  if( locktype==RESERVED_LOCK && res == NO_ERROR ){
-    assert( pFile->locktype==SHARED_LOCK );
-    LockArea.lOffset = RESERVED_BYTE;
-    LockArea.lRange = 1L;
-    UnlockArea.lOffset = 0L;
-    UnlockArea.lRange = 0L;
-    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    if( res == NO_ERROR ){
-      newLocktype = RESERVED_LOCK;
-    }
-    OSTRACE(( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ));
-  }
-
-  /* Acquire a PENDING lock
-  */
-  if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
-    newLocktype = PENDING_LOCK;
-    gotPendingLock = 0;
-    OSTRACE(( "LOCK %d acquire pending lock. pending lock boolean unset.\n",
-               pFile->h ));
-  }
-
-  /* Acquire an EXCLUSIVE lock
-  */
-  if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
-    assert( pFile->locktype>=SHARED_LOCK );
-    res = unlockReadLock(pFile);
-    OSTRACE(( "unreadlock = %d\n", res ));
-    LockArea.lOffset = SHARED_FIRST;
-    LockArea.lRange = SHARED_SIZE;
-    UnlockArea.lOffset = 0L;
-    UnlockArea.lRange = 0L;
-    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    if( res == NO_ERROR ){
-      newLocktype = EXCLUSIVE_LOCK;
-    }else{
-      OSTRACE(( "OS/2 error-code = %d\n", res ));
-      getReadLock(pFile);
-    }
-    OSTRACE(( "LOCK %d acquire exclusive lock.  res=%d\n", pFile->h, res ));
-  }
-
-  /* If we are holding a PENDING lock that ought to be released, then
-  ** release it now.
-  */
-  if( gotPendingLock && locktype==SHARED_LOCK ){
-    int r;
-    LockArea.lOffset = 0L;
-    LockArea.lRange = 0L;
-    UnlockArea.lOffset = PENDING_BYTE;
-    UnlockArea.lRange = 1L;
-    r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    OSTRACE(( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ));
-  }
-
-  /* Update the state of the lock has held in the file descriptor then
-  ** return the appropriate result code.
-  */
-  if( res == NO_ERROR ){
-    rc = SQLITE_OK;
-  }else{
-    OSTRACE(( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
-              locktype, newLocktype ));
-    rc = SQLITE_BUSY;
-  }
-  pFile->locktype = newLocktype;
-  OSTRACE(( "LOCK %d now %d\n", pFile->h, pFile->locktype ));
-  return rc;
-}
-
-/*
-** 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 os2CheckReservedLock( sqlite3_file *id, int *pOut ){
-  int r = 0;
-  os2File *pFile = (os2File*)id;
-  assert( pFile!=0 );
-  if( pFile->locktype>=RESERVED_LOCK ){
-    r = 1;
-    OSTRACE(( "TEST WR-LOCK %d %d (local)\n", pFile->h, r ));
-  }else{
-    FILELOCK  LockArea,
-              UnlockArea;
-    APIRET rc = NO_ERROR;
-    memset(&LockArea, 0, sizeof(LockArea));
-    memset(&UnlockArea, 0, sizeof(UnlockArea));
-    LockArea.lOffset = RESERVED_BYTE;
-    LockArea.lRange = 1L;
-    UnlockArea.lOffset = 0L;
-    UnlockArea.lRange = 0L;
-    rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    OSTRACE(( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ));
-    if( rc == NO_ERROR ){
-      APIRET rcu = NO_ERROR; /* return code for unlocking */
-      LockArea.lOffset = 0L;
-      LockArea.lRange = 0L;
-      UnlockArea.lOffset = RESERVED_BYTE;
-      UnlockArea.lRange = 1L;
-      rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-      OSTRACE(( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ));
-    }
-    r = !(rc == NO_ERROR);
-    OSTRACE(( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r ));
-  }
-  *pOut = r;
-  return SQLITE_OK;
-}
-
-/*
-** 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 os2Unlock( sqlite3_file *id, int locktype ){
-  int type;
-  os2File *pFile = (os2File*)id;
-  APIRET rc = SQLITE_OK;
-  APIRET res = NO_ERROR;
-  FILELOCK  LockArea,
-            UnlockArea;
-  memset(&LockArea, 0, sizeof(LockArea));
-  memset(&UnlockArea, 0, sizeof(UnlockArea));
-  assert( pFile!=0 );
-  assert( locktype<=SHARED_LOCK );
-  OSTRACE(( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ));
-  type = pFile->locktype;
-  if( type>=EXCLUSIVE_LOCK ){
-    LockArea.lOffset = 0L;
-    LockArea.lRange = 0L;
-    UnlockArea.lOffset = SHARED_FIRST;
-    UnlockArea.lRange = SHARED_SIZE;
-    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    OSTRACE(( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ));
-    if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
-      /* This should never happen.  We should always be able to
-      ** reacquire the read lock */
-      OSTRACE(( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ));
-      rc = SQLITE_IOERR_UNLOCK;
-    }
-  }
-  if( type>=RESERVED_LOCK ){
-    LockArea.lOffset = 0L;
-    LockArea.lRange = 0L;
-    UnlockArea.lOffset = RESERVED_BYTE;
-    UnlockArea.lRange = 1L;
-    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    OSTRACE(( "UNLOCK %d reserved res=%d\n", pFile->h, res ));
-  }
-  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
-    res = unlockReadLock(pFile);
-    OSTRACE(( "UNLOCK %d is %d want %d res=%d\n",
-              pFile->h, type, locktype, res ));
-  }
-  if( type>=PENDING_LOCK ){
-    LockArea.lOffset = 0L;
-    LockArea.lRange = 0L;
-    UnlockArea.lOffset = PENDING_BYTE;
-    UnlockArea.lRange = 1L;
-    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
-    OSTRACE(( "UNLOCK %d pending res=%d\n", pFile->h, res ));
-  }
-  pFile->locktype = locktype;
-  OSTRACE(( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ));
-  return rc;
-}
-
-/*
-** Control and query of the open file handle.
-*/
-static int os2FileControl(sqlite3_file *id, int op, void *pArg){
-  switch( op ){
-    case SQLITE_FCNTL_LOCKSTATE: {
-      *(int*)pArg = ((os2File*)id)->locktype;
-      OSTRACE(( "FCNTL_LOCKSTATE %d lock=%d\n",
-                ((os2File*)id)->h, ((os2File*)id)->locktype ));
-      return SQLITE_OK;
-    }
-    case SQLITE_FCNTL_CHUNK_SIZE: {
-      ((os2File*)id)->szChunk = *(int*)pArg;
-      return SQLITE_OK;
-    }
-    case SQLITE_FCNTL_SIZE_HINT: {
-      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
-      SimulateIOErrorBenign(1);
-      os2Truncate(id, sz);
-      SimulateIOErrorBenign(0);
-      return SQLITE_OK;
-    }
-    case SQLITE_FCNTL_SYNC_OMITTED: {
-      return SQLITE_OK;
-    }
-  }
-  return SQLITE_NOTFOUND;
-}
-
-/*
-** 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 os2SectorSize(sqlite3_file *id){
-  UNUSED_PARAMETER(id);
-  return SQLITE_DEFAULT_SECTOR_SIZE;
-}
-
-/*
-** Return a vector of device characteristics.
-*/
-static int os2DeviceCharacteristics(sqlite3_file *id){
-  UNUSED_PARAMETER(id);
-  return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
-}
-
-
-/*
-** Character set conversion objects used by conversion routines.
-*/
-static UconvObject ucUtf8 = NULL; /* convert between UTF-8 and UCS-2 */
-static UconvObject uclCp = NULL;  /* convert between local codepage and UCS-2 */
-
-/*
-** Helper function to initialize the conversion objects from and to UTF-8.
-*/
-static void initUconvObjects( void ){
-  if( UniCreateUconvObject( UTF_8, &ucUtf8 ) != ULS_SUCCESS )
-    ucUtf8 = NULL;
-  if ( UniCreateUconvObject( (UniChar *)L"@path=yes", &uclCp ) != ULS_SUCCESS )
-    uclCp = NULL;
-}
-
-/*
-** Helper function to free the conversion objects from and to UTF-8.
-*/
-static void freeUconvObjects( void ){
-  if ( ucUtf8 )
-    UniFreeUconvObject( ucUtf8 );
-  if ( uclCp )
-    UniFreeUconvObject( uclCp );
-  ucUtf8 = NULL;
-  uclCp = NULL;
-}
-
-/*
-** Helper function to convert UTF-8 filenames to local OS/2 codepage.
-** The two-step process: first convert the incoming UTF-8 string
-** into UCS-2 and then from UCS-2 to the current codepage.
-** The returned char pointer has to be freed.
-*/
-static char *convertUtf8PathToCp( const char *in ){
-  UniChar tempPath[CCHMAXPATH];
-  char *out = (char *)calloc( CCHMAXPATH, 1 );
-
-  if( !out )
-    return NULL;
-
-  if( !ucUtf8 || !uclCp )
-    initUconvObjects();
-
-  /* determine string for the conversion of UTF-8 which is CP1208 */
-  if( UniStrToUcs( ucUtf8, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
-    return out; /* if conversion fails, return the empty string */
-
-  /* conversion for current codepage which can be used for paths */
-  UniStrFromUcs( uclCp, out, tempPath, CCHMAXPATH );
-
-  return out;
-}
-
-/*
-** Helper function to convert filenames from local codepage to UTF-8.
-** The two-step process: first convert the incoming codepage-specific
-** string into UCS-2 and then from UCS-2 to the codepage of UTF-8.
-** The returned char pointer has to be freed.
-**
-** This function is non-static to be able to use this in shell.c and
-** similar applications that take command line arguments.
-*/
-char *convertCpPathToUtf8( const char *in ){
-  UniChar tempPath[CCHMAXPATH];
-  char *out = (char *)calloc( CCHMAXPATH, 1 );
-
-  if( !out )
-    return NULL;
-
-  if( !ucUtf8 || !uclCp )
-    initUconvObjects();
-
-  /* conversion for current codepage which can be used for paths */
-  if( UniStrToUcs( uclCp, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
-    return out; /* if conversion fails, return the empty string */
-
-  /* determine string for the conversion of UTF-8 which is CP1208 */
-  UniStrFromUcs( ucUtf8, out, tempPath, CCHMAXPATH );
-
-  return out;
-}
-
-
-#ifndef SQLITE_OMIT_WAL
-
-/*
-** Use main database file for interprocess locking. If un-defined
-** a separate file is created for this purpose. The file will be
-** used only to set file locks. There will be no data written to it.
-*/
-#define SQLITE_OS2_NO_WAL_LOCK_FILE     
-
-#if 0
-static void _ERR_TRACE( const char *fmt, ... ) {
-  va_list  ap;
-  va_start(ap, fmt);
-  vfprintf(stderr, fmt, ap);
-  fflush(stderr);
-}
-#define ERR_TRACE(rc, msg)        \
-        if( (rc) != SQLITE_OK ) _ERR_TRACE msg;
-#else
-#define ERR_TRACE(rc, msg)
-#endif
-
-/*
-** Helper functions to obtain and relinquish the global mutex. The
-** global mutex is used to protect os2ShmNodeList.
-**
-** Function os2ShmMutexHeld() is used to assert() that the global mutex 
-** is held when required. This function is only used as part of assert() 
-** statements. e.g.
-**
-**   os2ShmEnterMutex()
-**     assert( os2ShmMutexHeld() );
-**   os2ShmLeaveMutex()
-*/
-static void os2ShmEnterMutex(void){
-  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-}
-static void os2ShmLeaveMutex(void){
-  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-}
-#ifdef SQLITE_DEBUG
-static int os2ShmMutexHeld(void) {
-  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-}
-int GetCurrentProcessId(void) {
-  PPIB pib;
-  DosGetInfoBlocks(NULL, &pib);
-  return (int)pib->pib_ulpid;
-}
-#endif
-
-/*
-** Object used to represent a the shared memory area for a single log file.
-** When multiple threads all reference the same log-summary, each thread has
-** its own os2File object, but they all point to a single instance of this 
-** object.  In other words, each log-summary is opened only once per process.
-**
-** os2ShmMutexHeld() 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:
-** 
-**      szRegion
-**      hLockFile
-**      shmBaseName
-**
-** Either os2ShmNode.mutex must be held or os2ShmNode.nRef==0 and
-** os2ShmMutexHeld() is true when reading or writing any other field
-** in this structure.
-**
-*/
-struct os2ShmNode {
-  sqlite3_mutex *mutex;      /* Mutex to access this object */
-  os2ShmNode *pNext;         /* Next in list of all os2ShmNode objects */
-
-  int szRegion;              /* Size of shared-memory regions */
-
-  int nRegion;               /* Size of array apRegion */
-  void **apRegion;           /* Array of pointers to shared-memory regions */
-
-  int nRef;                  /* Number of os2ShmLink objects pointing to this */
-  os2ShmLink *pFirst;        /* First os2ShmLink object pointing to this */
-
-  HFILE hLockFile;           /* File used for inter-process memory locking */
-  char shmBaseName[1];       /* Name of the memory object !!! must last !!! */
-};
-
-
-/*
-** 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:
-**
-**    os2Shm.pShmNode
-**    os2Shm.id
-**
-** All other fields are read/write.  The os2Shm.pShmNode->mutex must be held
-** while accessing any read/write fields.
-*/
-struct os2ShmLink {
-  os2ShmNode *pShmNode;      /* The underlying os2ShmNode object */
-  os2ShmLink *pNext;         /* Next os2Shm with the same os2ShmNode */
-  u32 sharedMask;            /* Mask of shared locks held */
-  u32 exclMask;              /* Mask of exclusive locks held */
-#ifdef SQLITE_DEBUG
-  u8 id;                     /* Id of this connection with its os2ShmNode */
-#endif
-};
-
-
-/*
-** A global list of all os2ShmNode objects.
-**
-** The os2ShmMutexHeld() must be true while reading or writing this list.
-*/
-static os2ShmNode *os2ShmNodeList = NULL;
-
-/*
-** Constants used for locking
-*/
-#ifdef  SQLITE_OS2_NO_WAL_LOCK_FILE
-#define OS2_SHM_BASE   (PENDING_BYTE + 0x10000)         /* first lock byte */
-#else
-#define OS2_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
-#endif
-
-#define OS2_SHM_DMS    (OS2_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
-
-/*
-** Apply advisory locks for all n bytes beginning at ofst.
-*/
-#define _SHM_UNLCK  1   /* no lock */
-#define _SHM_RDLCK  2   /* shared lock, no wait */
-#define _SHM_WRLCK  3   /* exlusive lock, no wait */
-#define _SHM_WRLCK_WAIT 4 /* exclusive lock, wait */
-static int os2ShmSystemLock(
-  os2ShmNode *pNode,    /* Apply locks to this open shared-memory segment */
-  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, _SHM_WRLCK or _SHM_WRLCK_WAIT */
-  int ofst,             /* Offset to first byte to be locked/unlocked */
-  int nByte             /* Number of bytes to lock or unlock */
-){
-  APIRET rc;
-  FILELOCK area;
-  ULONG mode, timeout;
-
-  /* Access to the os2ShmNode object is serialized by the caller */
-  assert( sqlite3_mutex_held(pNode->mutex) || pNode->nRef==0 );
-
-  mode = 1;     /* shared lock */
-  timeout = 0;  /* no wait */
-  area.lOffset = ofst;
-  area.lRange = nByte;
-
-  switch( lockType ) {
-    case _SHM_WRLCK_WAIT:
-      timeout = (ULONG)-1;      /* wait forever */
-    case _SHM_WRLCK:
-      mode = 0;                 /* exclusive lock */
-    case _SHM_RDLCK:
-      rc = DosSetFileLocks(pNode->hLockFile, 
-                           NULL, &area, timeout, mode);
-      break;
-    /* case _SHM_UNLCK: */
-    default:
-      rc = DosSetFileLocks(pNode->hLockFile, 
-                           &area, NULL, 0, 0);
-      break;
-  }
-                          
-  OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n", 
-           pNode->hLockFile,
-           rc==SQLITE_OK ? "ok" : "failed",
-           lockType==_SHM_UNLCK ? "Unlock" : "Lock",
-           rc));
-
-  ERR_TRACE(rc, ("os2ShmSystemLock: %d %s\n", rc, pNode->shmBaseName))
-
-  return ( rc == 0 ) ?  SQLITE_OK : SQLITE_BUSY;
-}
-
-/*
-** Find an os2ShmNode in global list or allocate a new one, if not found.
-**
-** This is not a VFS shared-memory method; it is a utility function called
-** by VFS shared-memory methods.
-*/
-static int os2OpenSharedMemory( os2File *fd, int szRegion ) {
-  os2ShmLink *pLink;
-  os2ShmNode *pNode;
-  int cbShmName, rc = SQLITE_OK;
-  char shmName[CCHMAXPATH + 30];
-#ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
-  ULONG action;
-#endif
-  
-  /* We need some additional space at the end to append the region number */
-  cbShmName = sprintf(shmName, "\\SHAREMEM\\%s", fd->zFullPathCp );
-  if( cbShmName >= CCHMAXPATH-8 )
-    return SQLITE_IOERR_SHMOPEN; 
-
-  /* Replace colon in file name to form a valid shared memory name */
-  shmName[10+1] = '!';
-
-  /* Allocate link object (we free it later in case of failure) */
-  pLink = sqlite3_malloc( sizeof(*pLink) );
-  if( !pLink )
-    return SQLITE_NOMEM;
-
-  /* Access node list */
-  os2ShmEnterMutex();
-
-  /* Find node by it's shared memory base name */
-  for( pNode = os2ShmNodeList; 
-       pNode && stricmp(shmName, pNode->shmBaseName) != 0; 
-       pNode = pNode->pNext )   ;
-
-  /* Not found: allocate a new node */
-  if( !pNode ) {
-    pNode = sqlite3_malloc( sizeof(*pNode) + cbShmName );
-    if( pNode ) {
-      memset(pNode, 0, sizeof(*pNode) );
-      pNode->szRegion = szRegion;
-      pNode->hLockFile = (HFILE)-1;      
-      strcpy(pNode->shmBaseName, shmName);
-
-#ifdef SQLITE_OS2_NO_WAL_LOCK_FILE
-      if( DosDupHandle(fd->h, &pNode->hLockFile) != 0 ) {
-#else
-      sprintf(shmName, "%s-lck", fd->zFullPathCp);
-      if( DosOpen((PSZ)shmName, &pNode->hLockFile, &action, 0, FILE_NORMAL, 
-                  OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
-                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | 
-                  OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR,
-                  NULL) != 0 ) {
-#endif
-        sqlite3_free(pNode);  
-        rc = SQLITE_IOERR;
-      } else {
-        pNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
-        if( !pNode->mutex ) {
-          sqlite3_free(pNode);  
-          rc = SQLITE_NOMEM;
-        }
-      }   
-    } else {
-      rc = SQLITE_NOMEM;
-    }
-    
-    if( rc == SQLITE_OK ) {
-      pNode->pNext = os2ShmNodeList;
-      os2ShmNodeList = pNode;
-    } else {
-      pNode = NULL;
-    }
-  } else if( pNode->szRegion != szRegion ) {
-    rc = SQLITE_IOERR_SHMSIZE;
-    pNode = NULL;
-  }
-
-  if( pNode ) {
-    sqlite3_mutex_enter(pNode->mutex);
-
-    memset(pLink, 0, sizeof(*pLink));
-
-    pLink->pShmNode = pNode;
-    pLink->pNext = pNode->pFirst;
-    pNode->pFirst = pLink;
-    pNode->nRef++;
-
-    fd->pShmLink = pLink;
-
-    sqlite3_mutex_leave(pNode->mutex);
-    
-  } else {
-    /* Error occured. Free our link object. */
-    sqlite3_free(pLink);  
-  }
-
-  os2ShmLeaveMutex();
-
-  ERR_TRACE(rc, ("os2OpenSharedMemory: %d  %s\n", rc, fd->zFullPathCp))  
-  
-  return rc;
-}
-
-/*
-** Purge the os2ShmNodeList list of all entries with nRef==0.
-**
-** This is not a VFS shared-memory method; it is a utility function called
-** by VFS shared-memory methods.
-*/
-static void os2PurgeShmNodes( int deleteFlag ) {
-  os2ShmNode *pNode;
-  os2ShmNode **ppNode;
-
-  os2ShmEnterMutex();
-  
-  ppNode = &os2ShmNodeList;
-
-  while( *ppNode ) {
-    pNode = *ppNode;
-
-    if( pNode->nRef == 0 ) {
-      *ppNode = pNode->pNext;   
-     
-      if( pNode->apRegion ) {
-        /* Prevent other processes from resizing the shared memory */
-        os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);
-
-        while( pNode->nRegion-- ) {
-#ifdef SQLITE_DEBUG
-          int rc = 
-#endif          
-          DosFreeMem(pNode->apRegion[pNode->nRegion]);
-
-          OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
-                  (int)GetCurrentProcessId(), pNode->nRegion,
-                  rc == 0 ? "ok" : "failed"));
-        }
-
-        /* Allow other processes to resize the shared memory */
-        os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
-
-        sqlite3_free(pNode->apRegion);
-      }  
-
-      DosClose(pNode->hLockFile);
-      
-#ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
-      if( deleteFlag ) {
-         char fileName[CCHMAXPATH];
-         /* Skip "\\SHAREMEM\\" */
-         sprintf(fileName, "%s-lck", pNode->shmBaseName + 10);
-         /* restore colon */
-         fileName[1] = ':';
-         
-         DosForceDelete(fileName); 
-      }
-#endif
-
-      sqlite3_mutex_free(pNode->mutex);
-
-      sqlite3_free(pNode);
-      
-    } else {
-      ppNode = &pNode->pNext;
-    }
-  } 
-
-  os2ShmLeaveMutex();
-}
-
-/*
-** This function is called to obtain a pointer to region iRegion of the
-** shared-memory associated with the database file id. 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 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 os2ShmMap(
-  sqlite3_file *id,               /* Handle open on database file */
-  int iRegion,                    /* Region to retrieve */
-  int szRegion,                   /* Size of regions */
-  int bExtend,                    /* True to extend block if necessary */
-  void volatile **pp              /* OUT: Mapped memory */
-){
-  PVOID pvTemp;
-  void **apRegion;
-  os2ShmNode *pNode;
-  int n, rc = SQLITE_OK;
-  char shmName[CCHMAXPATH];
-  os2File *pFile = (os2File*)id;
-  
-  *pp = NULL;
-
-  if( !pFile->pShmLink )
-    rc = os2OpenSharedMemory( pFile, szRegion );
-  
-  if( rc == SQLITE_OK ) {
-    pNode = pFile->pShmLink->pShmNode ;
-    
-    sqlite3_mutex_enter(pNode->mutex);
-    
-    assert( szRegion==pNode->szRegion );
-
-    /* Unmapped region ? */
-    if( iRegion >= pNode->nRegion ) {
-      /* Prevent other processes from resizing the shared memory */
-      os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);
-
-      apRegion = sqlite3_realloc(
-        pNode->apRegion, (iRegion + 1) * sizeof(apRegion[0]));
-
-      if( apRegion ) {
-        pNode->apRegion = apRegion;
-
-        while( pNode->nRegion <= iRegion ) {
-          sprintf(shmName, "%s-%u", 
-                  pNode->shmBaseName, pNode->nRegion);
-
-          if( DosGetNamedSharedMem(&pvTemp, (PSZ)shmName, 
-                PAG_READ | PAG_WRITE) != NO_ERROR ) {
-            if( !bExtend )
-              break;
-
-            if( DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
-                  PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_ANY) != NO_ERROR && 
-                DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
-                  PAG_READ | PAG_WRITE | PAG_COMMIT) != NO_ERROR ) { 
-              rc = SQLITE_NOMEM;
-              break;
-            }
-          }
-
-          apRegion[pNode->nRegion++] = pvTemp;
-        }
-
-        /* zero out remaining entries */ 
-        for( n = pNode->nRegion; n <= iRegion; n++ )
-          pNode->apRegion[n] = NULL;
-
-        /* Return this region (maybe zero) */
-        *pp = pNode->apRegion[iRegion];
-      } else {
-        rc = SQLITE_NOMEM;
-      }
-
-      /* Allow other processes to resize the shared memory */
-      os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
-      
-    } else {
-      /* Region has been mapped previously */
-      *pp = pNode->apRegion[iRegion];
-    }
-
-    sqlite3_mutex_leave(pNode->mutex);
-  } 
-
-  ERR_TRACE(rc, ("os2ShmMap: %s iRgn = %d, szRgn = %d, bExt = %d : %d\n", 
-                 pFile->zFullPathCp, iRegion, szRegion, bExtend, rc))
-          
-  return rc;
-}
-
-/*
-** 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 os2ShmUnmap(
-  sqlite3_file *id,               /* The underlying database file */
-  int deleteFlag                  /* Delete shared-memory if true */
-){
-  os2File *pFile = (os2File*)id;
-  os2ShmLink *pLink = pFile->pShmLink;
-  
-  if( pLink ) {
-    int nRef = -1;
-    os2ShmLink **ppLink;
-    os2ShmNode *pNode = pLink->pShmNode;
-
-    sqlite3_mutex_enter(pNode->mutex);
-    
-    for( ppLink = &pNode->pFirst;
-         *ppLink && *ppLink != pLink;
-         ppLink = &(*ppLink)->pNext )   ;
-         
-    assert(*ppLink);
-
-    if( *ppLink ) {
-      *ppLink = pLink->pNext;
-      nRef = --pNode->nRef;
-    } else {
-      ERR_TRACE(1, ("os2ShmUnmap: link not found ! %s\n", 
-                    pNode->shmBaseName))
-    }
-    
-    pFile->pShmLink = NULL;
-    sqlite3_free(pLink);
-
-    sqlite3_mutex_leave(pNode->mutex);
-    
-    if( nRef == 0 )
-      os2PurgeShmNodes( deleteFlag );
-  }
-
-  return SQLITE_OK;
-}
-
-/*
-** Change the lock state for a shared-memory segment.
-**
-** 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 os2ShmLock(
-  sqlite3_file *id,          /* 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 */
-){
-  u32 mask;                             /* Mask of locks to take or release */
-  int rc = SQLITE_OK;                   /* Result code */
-  os2File *pFile = (os2File*)id;
-  os2ShmLink *p = pFile->pShmLink;      /* The shared memory being locked */
-  os2ShmLink *pX;                       /* For looping over all siblings */
-  os2ShmNode *pShmNode = p->pShmNode;   /* Our node */
-  
-  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 );
-
-  mask = (u32)((1U<<(ofst+n)) - (1U<<ofst));
-  assert( n>1 || mask==(1<<ofst) );
-
-
-  sqlite3_mutex_enter(pShmNode->mutex);
-
-  if( flags & SQLITE_SHM_UNLOCK ){
-    u32 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 = os2ShmSystemLock(pShmNode, _SHM_UNLCK, ofst+OS2_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 ){
-    u32 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 = os2ShmSystemLock(pShmNode, _SHM_RDLCK, ofst+OS2_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 = os2ShmSystemLock(pShmNode, _SHM_WRLCK, ofst+OS2_SHM_BASE, n);
-      if( rc==SQLITE_OK ){
-        assert( (p->sharedMask & mask)==0 );
-        p->exclMask |= mask;
-      }
-    }
-  }
-
-  sqlite3_mutex_leave(pShmNode->mutex);
-  
-  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
-           p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask,
-           rc ? "failed" : "ok"));
-
-  ERR_TRACE(rc, ("os2ShmLock: ofst = %d, n = %d, flags = 0x%x -> %d \n", 
-                 ofst, n, flags, rc))
-                  
-  return rc; 
-}
-
-/*
-** 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 os2ShmBarrier(
-  sqlite3_file *id                /* Database file holding the shared memory */
-){
-  UNUSED_PARAMETER(id);
-  os2ShmEnterMutex();
-  os2ShmLeaveMutex();
-}
-
-#else
-# define os2ShmMap     0
-# define os2ShmLock    0
-# define os2ShmBarrier 0
-# define os2ShmUnmap   0
-#endif /* #ifndef SQLITE_OMIT_WAL */
-
-
-/*
-** This vector defines all the methods that can operate on an
-** sqlite3_file for os2.
-*/
-static const sqlite3_io_methods os2IoMethod = {
-  2,                              /* iVersion */
-  os2Close,                       /* xClose */
-  os2Read,                        /* xRead */
-  os2Write,                       /* xWrite */
-  os2Truncate,                    /* xTruncate */
-  os2Sync,                        /* xSync */
-  os2FileSize,                    /* xFileSize */
-  os2Lock,                        /* xLock */
-  os2Unlock,                      /* xUnlock */
-  os2CheckReservedLock,           /* xCheckReservedLock */
-  os2FileControl,                 /* xFileControl */
-  os2SectorSize,                  /* xSectorSize */
-  os2DeviceCharacteristics,       /* xDeviceCharacteristics */
-  os2ShmMap,                      /* xShmMap */
-  os2ShmLock,                     /* xShmLock */
-  os2ShmBarrier,                  /* xShmBarrier */
-  os2ShmUnmap                     /* xShmUnmap */
-};
-
-
-/***************************************************************************
-** Here ends the I/O methods that form the sqlite3_io_methods object.
-**
-** The next block of code implements the VFS methods.
-****************************************************************************/
-
-/*
-** Create a temporary file name in zBuf.  zBuf must be big enough to
-** hold at pVfs->mxPathname characters.
-*/
-static int getTempname(int nBuf, char *zBuf ){
-  static const char zChars[] =
-    "abcdefghijklmnopqrstuvwxyz"
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "0123456789";
-  int i, j;
-  PSZ zTempPathCp;      
-  char zTempPath[CCHMAXPATH];
-  ULONG ulDriveNum, ulDriveMap;
-  
-  /* 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 );
-
-  if( sqlite3_temp_directory ) {
-    sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", sqlite3_temp_directory);
-  } else if( DosScanEnv( (PSZ)"TEMP",   &zTempPathCp ) == NO_ERROR ||
-             DosScanEnv( (PSZ)"TMP",    &zTempPathCp ) == NO_ERROR ||
-             DosScanEnv( (PSZ)"TMPDIR", &zTempPathCp ) == NO_ERROR ) {
-    char *zTempPathUTF = convertCpPathToUtf8( (char *)zTempPathCp );
-    sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", zTempPathUTF);
-    free( zTempPathUTF );
-  } else if( DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ) == NO_ERROR ) {
-    zTempPath[0] = (char)('A' + ulDriveNum - 1);
-    zTempPath[1] = ':'; 
-    zTempPath[2] = '\0'; 
-  } else {
-    zTempPath[0] = '\0'; 
-  }
-  
-  /* Strip off a trailing slashes or backslashes, otherwise we would get *
-   * multiple (back)slashes which causes DosOpen() to fail.              *
-   * Trailing spaces are not allowed, either.                            */
-  j = sqlite3Strlen30(zTempPath);
-  while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' || 
-                    zTempPath[j-1] == ' ' ) ){
-    j--;
-  }
-  zTempPath[j] = '\0';
-  
-  /* We use 20 bytes to randomize the name */
-  sqlite3_snprintf(nBuf-22, zBuf,
-                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
-  j = sqlite3Strlen30(zBuf);
-  sqlite3_randomness( 20, &zBuf[j] );
-  for( i = 0; i < 20; i++, j++ ){
-    zBuf[j] = zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
-  }
-  zBuf[j] = 0;
-
-  OSTRACE(( "TEMP FILENAME: %s\n", zBuf ));
-  return SQLITE_OK;
-}
-
-
-/*
-** Turn a relative pathname into a full pathname.  Write the full
-** pathname into zFull[].  zFull[] will be at least pVfs->mxPathname
-** bytes in size.
-*/
-static int os2FullPathname(
-  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 */
-){
-  char *zRelativeCp = convertUtf8PathToCp( zRelative );
-  char zFullCp[CCHMAXPATH] = "\0";
-  char *zFullUTF;
-  APIRET rc = DosQueryPathInfo( (PSZ)zRelativeCp, FIL_QUERYFULLNAME, 
-                                zFullCp, CCHMAXPATH );
-  free( zRelativeCp );
-  zFullUTF = convertCpPathToUtf8( zFullCp );
-  sqlite3_snprintf( nFull, zFull, zFullUTF );
-  free( zFullUTF );
-  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
-}
-
-
-/*
-** Open a file.
-*/
-static int os2Open(
-  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 */
-){
-  HFILE h;
-  ULONG ulOpenFlags = 0;
-  ULONG ulOpenMode = 0;
-  ULONG ulAction = 0;
-  ULONG rc;
-  os2File *pFile = (os2File*)id;
-  const char *zUtf8Name = zName;
-  char *zNameCp;
-  char  zTmpname[CCHMAXPATH];
-
-  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
-  int isCreate     = (flags & SQLITE_OPEN_CREATE);
-  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
-#ifndef NDEBUG
-  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
-  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
-  int eType        = (flags & 0xFFFFFF00);
-  int isOpenJournal = (isCreate && (
-        eType==SQLITE_OPEN_MASTER_JOURNAL 
-     || eType==SQLITE_OPEN_MAIN_JOURNAL 
-     || eType==SQLITE_OPEN_WAL
-  ));
-#endif
-
-  UNUSED_PARAMETER(pVfs);
-  assert( id!=0 );
-
-  /* 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( pFile, 0, sizeof(*pFile) );
-  pFile->h = (HFILE)-1;
-
-  /* If the second argument to this function is NULL, generate a 
-  ** temporary file name to use 
-  */
-  if( !zUtf8Name ){
-    assert(isDelete && !isOpenJournal);
-    rc = getTempname(CCHMAXPATH, zTmpname);
-    if( rc!=SQLITE_OK ){
-      return rc;
-    }
-    zUtf8Name = zTmpname;
-  }
-
-  if( isReadWrite ){
-    ulOpenMode |= OPEN_ACCESS_READWRITE;
-  }else{
-    ulOpenMode |= OPEN_ACCESS_READONLY;
-  }
-
-  /* Open in random access mode for possibly better speed.  Allow full
-  ** sharing because file locks will provide exclusive access when needed.
-  ** The handle should not be inherited by child processes and we don't 
-  ** want popups from the critical error handler.
-  */
-  ulOpenMode |= OPEN_FLAGS_RANDOM | OPEN_SHARE_DENYNONE | 
-                OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR;
-
-  /* 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. */
-    ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
-  }else if( isCreate ){
-    /* Open existing file, or create if it doesn't exist */
-    ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
-  }else{
-    /* Opens a file, only if it exists. */
-    ulOpenFlags |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
-  }
-
-  zNameCp = convertUtf8PathToCp( zUtf8Name );
-  rc = DosOpen( (PSZ)zNameCp,
-                &h,
-                &ulAction,
-                0L,
-                FILE_NORMAL,
-                ulOpenFlags,
-                ulOpenMode,
-                (PEAOP2)NULL );
-  free( zNameCp );
-
-  if( rc != NO_ERROR ){
-    OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
-              rc, zUtf8Name, ulAction, ulOpenFlags, ulOpenMode ));
-
-    if( isReadWrite ){
-      return os2Open( pVfs, zName, id,
-                      ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
-                      pOutFlags );
-    }else{
-      return SQLITE_CANTOPEN;
-    }
-  }
-
-  if( pOutFlags ){
-    *pOutFlags = isReadWrite ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
-  }
-
-  os2FullPathname( pVfs, zUtf8Name, sizeof( zTmpname ), zTmpname );
-  pFile->zFullPathCp = convertUtf8PathToCp( zTmpname );
-  pFile->pMethod = &os2IoMethod;
-  pFile->flags = flags;
-  pFile->h = h;
-
-  OpenCounter(+1);
-  OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
-  return SQLITE_OK;
-}
-
-/*
-** Delete the named file.
-*/
-static int os2Delete(
-  sqlite3_vfs *pVfs,                     /* Not used on os2 */
-  const char *zFilename,                 /* Name of file to delete */
-  int syncDir                            /* Not used on os2 */
-){
-  APIRET rc;
-  char *zFilenameCp;
-  SimulateIOError( return SQLITE_IOERR_DELETE );
-  zFilenameCp = convertUtf8PathToCp( zFilename );
-  rc = DosDelete( (PSZ)zFilenameCp );
-  free( zFilenameCp );
-  OSTRACE(( "DELETE \"%s\"\n", zFilename ));
-  return (rc == NO_ERROR ||
-          rc == ERROR_FILE_NOT_FOUND ||
-          rc == ERROR_PATH_NOT_FOUND ) ? SQLITE_OK : SQLITE_IOERR_DELETE;
-}
-
-/*
-** Check the existance and status of a file.
-*/
-static int os2Access(
-  sqlite3_vfs *pVfs,        /* Not used on os2 */
-  const char *zFilename,    /* Name of file to check */
-  int flags,                /* Type of test to make on this file */
-  int *pOut                 /* Write results here */
-){
-  APIRET rc;
-  FILESTATUS3 fsts3ConfigInfo;
-  char *zFilenameCp;
-
-  UNUSED_PARAMETER(pVfs);
-  SimulateIOError( return SQLITE_IOERR_ACCESS; );
-  
-  zFilenameCp = convertUtf8PathToCp( zFilename );
-  rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
-                         &fsts3ConfigInfo, sizeof(FILESTATUS3) );
-  free( zFilenameCp );
-  OSTRACE(( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
-            fsts3ConfigInfo.attrFile, flags, rc ));
-
-  switch( flags ){
-    case SQLITE_ACCESS_EXISTS:
-      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
-      ** as if it does not exist.
-      */
-      if( fsts3ConfigInfo.cbFile == 0 ) 
-        rc = ERROR_FILE_NOT_FOUND;
-      break;
-    case SQLITE_ACCESS_READ:
-      break;
-    case SQLITE_ACCESS_READWRITE:
-      if( fsts3ConfigInfo.attrFile & FILE_READONLY )
-        rc = ERROR_ACCESS_DENIED;
-      break;
-    default:
-      rc = ERROR_FILE_NOT_FOUND;
-      assert( !"Invalid flags argument" );
-  }
-
-  *pOut = (rc == NO_ERROR);
-  OSTRACE(( "ACCESS %s flags %d: rc=%d\n", zFilename, flags, *pOut ));
-
-  return SQLITE_OK;
-}
-
-
-#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.
-*/
-static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
-  HMODULE hmod;
-  APIRET rc;
-  char *zFilenameCp = convertUtf8PathToCp(zFilename);
-  rc = DosLoadModule(NULL, 0, (PSZ)zFilenameCp, &hmod);
-  free(zFilenameCp);
-  return rc != NO_ERROR ? 0 : (void*)hmod;
-}
-/*
-** A no-op since the error code is returned on the DosLoadModule call.
-** os2Dlopen returns zero if DosLoadModule is not successful.
-*/
-static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
-/* no-op */
-}
-static void (*os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
-  PFN pfn;
-  APIRET rc;
-  rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)zSymbol, &pfn);
-  if( rc != NO_ERROR ){
-    /* if the symbol itself was not found, search again for the same
-     * symbol with an extra underscore, that might be needed depending
-     * on the calling convention */
-    char _zSymbol[256] = "_";
-    strncat(_zSymbol, zSymbol, 254);
-    rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)_zSymbol, &pfn);
-  }
-  return rc != NO_ERROR ? 0 : (void(*)(void))pfn;
-}
-static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){
-  DosFreeModule((HMODULE)pHandle);
-}
-#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
-  #define os2DlOpen 0
-  #define os2DlError 0
-  #define os2DlSym 0
-  #define os2DlClose 0
-#endif
-
-
-/*
-** Write up to nBuf bytes of randomness into zBuf.
-*/
-static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){
-  int n = 0;
-#if defined(SQLITE_TEST)
-  n = nBuf;
-  memset(zBuf, 0, nBuf);
-#else
-  int i;                           
-  PPIB ppib;
-  PTIB ptib;
-  DATETIME dt; 
-  static unsigned c = 0;
-  /* Ordered by variation probability */
-  static ULONG svIdx[6] = { QSV_MS_COUNT, QSV_TIME_LOW,
-                            QSV_MAXPRMEM, QSV_MAXSHMEM,
-                            QSV_TOTAVAILMEM, QSV_TOTRESMEM };
-
-  /* 8 bytes; timezone and weekday don't increase the randomness much */
-  if( (int)sizeof(dt)-3 <= nBuf - n ){
-    c += 0x0100;
-    DosGetDateTime(&dt);
-    dt.year = (USHORT)((dt.year - 1900) | c);
-    memcpy(&zBuf[n], &dt, sizeof(dt)-3);
-    n += sizeof(dt)-3;
-  }
-
-  /* 4 bytes; PIDs and TIDs are 16 bit internally, so combine them */
-  if( (int)sizeof(ULONG) <= nBuf - n ){
-    DosGetInfoBlocks(&ptib, &ppib);
-    *(PULONG)&zBuf[n] = MAKELONG(ppib->pib_ulpid,
-                                 ptib->tib_ptib2->tib2_ultid);
-    n += sizeof(ULONG);
-  }
-
-  /* Up to 6 * 4 bytes; variables depend on the system state */
-  for( i = 0; i < 6 && (int)sizeof(ULONG) <= nBuf - n; i++ ){
-    DosQuerySysInfo(svIdx[i], svIdx[i], 
-                    (PULONG)&zBuf[n], sizeof(ULONG));
-    n += sizeof(ULONG);
-  } 
-#endif
-
-  return n;
-}
-
-/*
-** 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 os2Sleep( sqlite3_vfs *pVfs, int microsec ){
-  DosSleep( (microsec/1000) );
-  return microsec;
-}
-
-/*
-** The following variable, if set to a non-zero value, becomes the result
-** returned from sqlite3OsCurrentTime().  This is used for testing.
-*/
-#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_current_time = 0;
-#endif
-
-/*
-** 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 0.  Return 1 if the time and date cannot be found.
-*/
-static int os2CurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
-#ifdef SQLITE_TEST
-  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-#endif
-  int year, month, datepart, timepart;
- 
-  DATETIME dt;
-  DosGetDateTime( &dt );
-
-  year = dt.year;
-  month = dt.month;
-
-  /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
-  ** http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c
-  ** Calculate the Julian days
-  */
-  datepart = (int)dt.day - 32076 +
-    1461*(year + 4800 + (month - 14)/12)/4 +
-    367*(month - 2 - (month - 14)/12*12)/12 -
-    3*((year + 4900 + (month - 14)/12)/100)/4;
-
-  /* Time in milliseconds, hours to noon added */
-  timepart = 12*3600*1000 + dt.hundredths*10 + dt.seconds*1000 +
-    ((int)dt.minutes + dt.timezone)*60*1000 + dt.hours*3600*1000;
-
-  *piNow = (sqlite3_int64)datepart*86400*1000 + timepart;
-   
-#ifdef SQLITE_TEST
-  if( sqlite3_current_time ){
-    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
-  }
-#endif
-
-  UNUSED_PARAMETER(pVfs);
-  return 0;
-}
-
-/*
-** 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 os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
-  int rc;
-  sqlite3_int64 i;
-  rc = os2CurrentTimeInt64(pVfs, &i);
-  if( !rc ){
-    *prNow = i/86400000.0;
-  }
-  return rc;
-}
-
-/*
-** 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.
-*/
-static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-  assert(zBuf[0]=='\0');
-  return 0;
-}
-
-/*
-** Initialize and deinitialize the operating system interface.
-*/
-SQLITE_API int sqlite3_os_init(void){
-  static sqlite3_vfs os2Vfs = {
-    3,                 /* iVersion */
-    sizeof(os2File),   /* szOsFile */
-    CCHMAXPATH,        /* mxPathname */
-    0,                 /* pNext */
-    "os2",             /* zName */
-    0,                 /* pAppData */
-
-    os2Open,           /* xOpen */
-    os2Delete,         /* xDelete */
-    os2Access,         /* xAccess */
-    os2FullPathname,   /* xFullPathname */
-    os2DlOpen,         /* xDlOpen */
-    os2DlError,        /* xDlError */
-    os2DlSym,          /* xDlSym */
-    os2DlClose,        /* xDlClose */
-    os2Randomness,     /* xRandomness */
-    os2Sleep,          /* xSleep */
-    os2CurrentTime,    /* xCurrentTime */
-    os2GetLastError,   /* xGetLastError */
-    os2CurrentTimeInt64, /* xCurrentTimeInt64 */
-    0,                 /* xSetSystemCall */
-    0,                 /* xGetSystemCall */
-    0                  /* xNextSystemCall */
-  };
-  sqlite3_vfs_register(&os2Vfs, 1);
-  initUconvObjects();
-/*  sqlite3OSTrace = 1; */
-  return SQLITE_OK;
-}
-SQLITE_API int sqlite3_os_end(void){
-  freeUconvObjects();
-  return SQLITE_OK;
-}
-
-#endif /* SQLITE_OS_OS2 */
-
-/************** End of os_os2.c **********************************************/
 /************** Begin file os_unix.c *****************************************/
 /*
 ** 2004 May 22
@@ -25074,7 +22784,7 @@ struct unixFile {
 #if OS_VXWORKS
   struct vxworksFileId *pId;          /* Unique file ID */
 #endif
-#ifndef NDEBUG
+#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
@@ -25109,7 +22819,6 @@ 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_CHOWN      0x100     /* File ownership was changed */
 
 /*
 ** Include code that is common to all os_*.c files
@@ -25363,6 +23072,15 @@ static int posixOpen(const char *zFile, int flags, int mode){
   return open(zFile, flags, mode);
 }
 
+/*
+** 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 posixFchown(int fd, uid_t uid, gid_t gid){
+  return geteuid() ? 0 : fchown(fd,uid,gid);
+}
+
 /* Forward reference */
 static int openDirectory(const char*, int*);
 
@@ -25474,7 +23192,7 @@ static struct unix_syscall {
   { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
 #define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
 
-  { "fchown",       (sqlite3_syscall_ptr)fchown,          0 },
+  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
 #define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
 
   { "umask",        (sqlite3_syscall_ptr)umask,           0 },
@@ -25762,9 +23480,9 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
   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) ){
+        (sqliteIOErr == SQLITE_IOERR_UNLOCK) || 
+        (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+        (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
       return SQLITE_BUSY;
     }
     /* else fall through */
@@ -26099,7 +23817,7 @@ static unixInodeInfo *inodeList = 0;
 ** 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 the associated file-system path,
+** failed (e.g. "unlink", "open") and the associated file-system path,
 ** if any.
 */
 #define unixLogError(a,b,c)     unixLogErrorAtLine(a,b,c,__LINE__)
@@ -26122,7 +23840,7 @@ static int unixLogErrorAtLine(
   zErr = aErr;
 
   /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
-  ** assume that the system provides the the GNU version of strerror_r() that 
+  ** 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 
@@ -26618,7 +24336,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
   }
   
 
-#ifndef NDEBUG
+#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
@@ -26697,7 +24415,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
   if( pFile->eFileLock>SHARED_LOCK ){
     assert( pInode->eFileLock==pFile->eFileLock );
 
-#ifndef NDEBUG
+#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
@@ -26811,7 +24529,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
         pInode->eFileLock = NO_LOCK;
       }else{
         rc = SQLITE_IOERR_UNLOCK;
-	pFile->lastErrno = errno;
+        pFile->lastErrno = errno;
         pInode->eFileLock = NO_LOCK;
         pFile->eFileLock = NO_LOCK;
       }
@@ -26827,7 +24545,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
       closePendingFds(pFile);
     }
   }
-	
+
 end_unlock:
   unixLeaveMutex();
   if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
@@ -27094,7 +24812,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
 
   assert( pFile );
   OSTRACE(("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
-	   pFile->eFileLock, getpid()));
+           pFile->eFileLock, getpid()));
   assert( eFileLock<=SHARED_LOCK );
   
   /* no-op if possible */
@@ -27481,7 +25199,7 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
   assert( pFile );
   assert( pSem );
   OSTRACE(("UNLOCK  %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
-	   pFile->eFileLock, getpid()));
+           pFile->eFileLock, getpid()));
   assert( eFileLock<=SHARED_LOCK );
   
   /* no-op if possible */
@@ -27896,7 +25614,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
     SimulateIOError( h=(-1) )
     SimulateIOErrorBenign(0);
     
-#ifndef NDEBUG
+#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
@@ -28071,7 +25789,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
       if( newOffset == -1 ){
         ((unixFile*)id)->lastErrno = errno;
       }else{
-        ((unixFile*)id)->lastErrno = 0;			
+        ((unixFile*)id)->lastErrno = 0;
       }
       return -1;
     }
@@ -28159,7 +25877,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
       if( newOffset == -1 ){
         ((unixFile*)id)->lastErrno = errno;
       }else{
-        ((unixFile*)id)->lastErrno = 0;			
+        ((unixFile*)id)->lastErrno = 0;
       }
       return -1;
     }
@@ -28200,7 +25918,7 @@ static int unixWrite(
   );
 #endif
 
-#ifndef NDEBUG
+#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
@@ -28491,7 +26209,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
     pFile->lastErrno = errno;
     return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
   }else{
-#ifndef NDEBUG
+#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,
@@ -28648,7 +26366,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
       return SQLITE_OK;
     }
-#ifndef NDEBUG
+#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
@@ -28999,14 +26717,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
 
       /* 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. If this process is
-      ** not root, the following fchown() will fail, but we don't care.  The
-      ** if(){..} and the UNIXFILE_CHOWN flag are purely to silence compiler
-      ** warnings.
+      ** the original owner will not be able to connect.
       */
-      if( osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid)==0 ){
-        pDbFd->ctrlFlags |= UNIXFILE_CHOWN;
-      }
+      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. 
@@ -30212,13 +27925,10 @@ static int unixOpen(
 
     /* 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 we are not running as root,
-    ** then the fchown() call will fail, but that's ok.  The "if(){}" and
-    ** the setting of the UNIXFILE_CHOWN flag are purely to silence compiler
-    ** warnings from gcc.
+    ** the same as the original database.
     */
     if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
-      if( osFchown(fd, uid, gid)==0 ){ p->ctrlFlags |= UNIXFILE_CHOWN; }
+      osFchown(fd, uid, gid);
     }
   }
   assert( fd>=0 );
@@ -30681,7 +28391,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
 ** address in the shared range is taken for a SHARED lock, the entire
 ** shared range is taken for an EXCLUSIVE lock):
 **
-**      PENDING_BYTE        0x40000000		   	
+**      PENDING_BYTE        0x40000000
 **      RESERVED_BYTE       0x40000001
 **      SHARED_RANGE        0x40000002 -> 0x40000200
 **
@@ -32180,15 +29890,32 @@ SQLITE_API int sqlite3_open_file_count = 0;
 /************** Continuing where we left off in os_win.c *********************/
 
 /*
+** Macro to find the minimum of two numeric values.
+*/
+#ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+/*
 ** Some Microsoft compilers lack this definition.
 */
 #ifndef INVALID_FILE_ATTRIBUTES
 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 
 #endif
 
+#ifndef FILE_FLAG_MASK
+# define FILE_FLAG_MASK          (0xFF3C0000)
+#endif
+
+#ifndef FILE_ATTRIBUTE_MASK
+# define FILE_ATTRIBUTE_MASK     (0x0003FFF7)
+#endif
+
+#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
 
 /*
 ** WinCE lacks native support for file locking so we have to fake it
@@ -32216,7 +29943,9 @@ struct winFile {
   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
@@ -32235,10 +29964,52 @@ struct winFile {
 #define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
 
 /*
+ * 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
+
+/*
+ * 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
+
+/*
+ * 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
+
+/*
  * 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 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
+
 /*
  * The initial size of the Win32-specific heap.  This value may be zero.
  */
@@ -32323,17 +30094,11 @@ SQLITE_API int sqlite3_os_type = 0;
 static int sqlite3_os_type = 0;
 #endif
 
-/*
-** 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.
-*/
-#if !SQLITE_OS_WINCE
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
 #  define SQLITE_WIN32_HAS_ANSI
 #endif
 
-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT
+#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
 #  define SQLITE_WIN32_HAS_WIDE
 #endif
 
@@ -32341,40 +30106,35 @@ static int sqlite3_os_type = 0;
 #  define SYSCALL sqlite3_syscall_ptr
 #endif
 
-#if SQLITE_OS_WINCE
-/*
-** These macros are necessary because Windows CE does not natively support the
-** Win32 APIs LockFile, UnlockFile, and LockFileEx.
- */
-
-#  define LockFile(a,b,c,d,e)       winceLockFile(&a, b, c, d, e)
-#  define UnlockFile(a,b,c,d,e)     winceUnlockFile(&a, b, c, d, e)
-#  define LockFileEx(a,b,c,d,e,f)   winceLockFileEx(&a, b, c, d, e, f)
-
 /*
-** These are the special syscall hacks for Windows CE.  The locking related
-** defines here refer to the macros defined just above.
+** This function is not available on Windows CE or WinRT.
  */
 
+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
 #  define osAreFileApisANSI()       1
-#  define osLockFile                LockFile
-#  define osUnlockFile              UnlockFile
-#  define osLockFileEx              LockFileEx
 #endif
 
+/*
+** 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 sytem call */
   sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   sqlite3_syscall_ptr pDefault; /* Default value */
 } aSyscall[] = {
-#if !SQLITE_OS_WINCE
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "AreFileApisANSI",         (SYSCALL)AreFileApisANSI,         0 },
-
-#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
 #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
@@ -32404,7 +30164,7 @@ static struct win_syscall {
 #define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
         LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "CreateFileW",             (SYSCALL)CreateFileW,             0 },
 #else
   { "CreateFileW",             (SYSCALL)0,                       0 },
@@ -32413,28 +30173,24 @@ static struct win_syscall {
 #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
         LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
 
-  { "CreateFileMapping",       (SYSCALL)CreateFileMapping,       0 },
-
-#define osCreateFileMapping ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-        DWORD,DWORD,DWORD,LPCTSTR))aSyscall[6].pCurrent)
-
-#if defined(SQLITE_WIN32_HAS_WIDE)
+#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
 
 #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
+        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[6].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "CreateMutexW",            (SYSCALL)CreateMutexW,            0 },
 #else
   { "CreateMutexW",            (SYSCALL)0,                       0 },
 #endif
 
 #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
-        LPCWSTR))aSyscall[8].pCurrent)
+        LPCWSTR))aSyscall[7].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "DeleteFileA",             (SYSCALL)DeleteFileA,             0 },
@@ -32442,7 +30198,7 @@ static struct win_syscall {
   { "DeleteFileA",             (SYSCALL)0,                       0 },
 #endif
 
-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
+#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[8].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "DeleteFileW",             (SYSCALL)DeleteFileW,             0 },
@@ -32450,7 +30206,7 @@ static struct win_syscall {
   { "DeleteFileW",             (SYSCALL)0,                       0 },
 #endif
 
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[9].pCurrent)
 
 #if SQLITE_OS_WINCE
   { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
@@ -32459,7 +30215,7 @@ static struct win_syscall {
 #endif
 
 #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-        LPFILETIME))aSyscall[11].pCurrent)
+        LPFILETIME))aSyscall[10].pCurrent)
 
 #if SQLITE_OS_WINCE
   { "FileTimeToSystemTime",    (SYSCALL)FileTimeToSystemTime,    0 },
@@ -32468,11 +30224,11 @@ static struct win_syscall {
 #endif
 
 #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-        LPSYSTEMTIME))aSyscall[12].pCurrent)
+        LPSYSTEMTIME))aSyscall[11].pCurrent)
 
   { "FlushFileBuffers",        (SYSCALL)FlushFileBuffers,        0 },
 
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[12].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "FormatMessageA",          (SYSCALL)FormatMessageA,          0 },
@@ -32481,7 +30237,7 @@ static struct win_syscall {
 #endif
 
 #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
-        DWORD,va_list*))aSyscall[14].pCurrent)
+        DWORD,va_list*))aSyscall[13].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "FormatMessageW",          (SYSCALL)FormatMessageW,          0 },
@@ -32490,15 +30246,15 @@ static struct win_syscall {
 #endif
 
 #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
-        DWORD,va_list*))aSyscall[15].pCurrent)
+        DWORD,va_list*))aSyscall[14].pCurrent)
 
   { "FreeLibrary",             (SYSCALL)FreeLibrary,             0 },
 
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[15].pCurrent)
 
   { "GetCurrentProcessId",     (SYSCALL)GetCurrentProcessId,     0 },
 
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[16].pCurrent)
 
 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
   { "GetDiskFreeSpaceA",       (SYSCALL)GetDiskFreeSpaceA,       0 },
@@ -32507,16 +30263,16 @@ static struct win_syscall {
 #endif
 
 #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
-        LPDWORD))aSyscall[18].pCurrent)
+        LPDWORD))aSyscall[17].pCurrent)
 
-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetDiskFreeSpaceW",       (SYSCALL)GetDiskFreeSpaceW,       0 },
 #else
   { "GetDiskFreeSpaceW",       (SYSCALL)0,                       0 },
 #endif
 
 #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
-        LPDWORD))aSyscall[19].pCurrent)
+        LPDWORD))aSyscall[18].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetFileAttributesA",      (SYSCALL)GetFileAttributesA,      0 },
@@ -32524,15 +30280,15 @@ static struct win_syscall {
   { "GetFileAttributesA",      (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
+#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[19].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFileAttributesW",      (SYSCALL)GetFileAttributesW,      0 },
 #else
   { "GetFileAttributesW",      (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[20].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFileAttributesExW",    (SYSCALL)GetFileAttributesExW,    0 },
@@ -32541,11 +30297,15 @@ static struct win_syscall {
 #endif
 
 #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
-        LPVOID))aSyscall[22].pCurrent)
+        LPVOID))aSyscall[21].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "GetFileSize",             (SYSCALL)GetFileSize,             0 },
+#else
+  { "GetFileSize",             (SYSCALL)0,                       0 },
+#endif
 
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
+#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[22].pCurrent)
 
 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
   { "GetFullPathNameA",        (SYSCALL)GetFullPathNameA,        0 },
@@ -32554,20 +30314,20 @@ static struct win_syscall {
 #endif
 
 #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
-        LPSTR*))aSyscall[24].pCurrent)
+        LPSTR*))aSyscall[23].pCurrent)
 
-#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFullPathNameW",        (SYSCALL)GetFullPathNameW,        0 },
 #else
   { "GetFullPathNameW",        (SYSCALL)0,                       0 },
 #endif
 
 #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
-        LPWSTR*))aSyscall[25].pCurrent)
+        LPWSTR*))aSyscall[24].pCurrent)
 
   { "GetLastError",            (SYSCALL)GetLastError,            0 },
 
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[25].pCurrent)
 
 #if SQLITE_OS_WINCE
   /* The GetProcAddressA() routine is only available on Windows CE. */
@@ -32579,15 +30339,19 @@ static struct win_syscall {
 #endif
 
 #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
-        LPCSTR))aSyscall[27].pCurrent)
+        LPCSTR))aSyscall[26].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "GetSystemInfo",           (SYSCALL)GetSystemInfo,           0 },
+#else
+  { "GetSystemInfo",           (SYSCALL)0,                       0 },
+#endif
 
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[27].pCurrent)
 
   { "GetSystemTime",           (SYSCALL)GetSystemTime,           0 },
 
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
+#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[28].pCurrent)
 
 #if !SQLITE_OS_WINCE
   { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
@@ -32596,7 +30360,7 @@ static struct win_syscall {
 #endif
 
 #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
-        LPFILETIME))aSyscall[30].pCurrent)
+        LPFILETIME))aSyscall[29].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetTempPathA",            (SYSCALL)GetTempPathA,            0 },
@@ -32604,19 +30368,23 @@ static struct win_syscall {
   { "GetTempPathA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
+#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[30].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetTempPathW",            (SYSCALL)GetTempPathW,            0 },
 #else
   { "GetTempPathW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[31].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "GetTickCount",            (SYSCALL)GetTickCount,            0 },
+#else
+  { "GetTickCount",            (SYSCALL)0,                       0 },
+#endif
 
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
+#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[32].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
@@ -32625,40 +30393,52 @@ static struct win_syscall {
 #endif
 
 #define osGetVersionExA ((BOOL(WINAPI*)( \
-        LPOSVERSIONINFOA))aSyscall[34].pCurrent)
+        LPOSVERSIONINFOA))aSyscall[33].pCurrent)
 
   { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },
 
 #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
-        SIZE_T))aSyscall[35].pCurrent)
+        SIZE_T))aSyscall[34].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "HeapCreate",              (SYSCALL)HeapCreate,              0 },
+#else
+  { "HeapCreate",              (SYSCALL)0,                       0 },
+#endif
 
 #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
-        SIZE_T))aSyscall[36].pCurrent)
+        SIZE_T))aSyscall[35].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },
+#else
+  { "HeapDestroy",             (SYSCALL)0,                       0 },
+#endif
 
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent)
 
   { "HeapFree",                (SYSCALL)HeapFree,                0 },
 
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[37].pCurrent)
 
   { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },
 
 #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
-        SIZE_T))aSyscall[39].pCurrent)
+        SIZE_T))aSyscall[38].pCurrent)
 
   { "HeapSize",                (SYSCALL)HeapSize,                0 },
 
 #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[40].pCurrent)
+        LPCVOID))aSyscall[39].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "HeapValidate",            (SYSCALL)HeapValidate,            0 },
+#else
+  { "HeapValidate",            (SYSCALL)0,                       0 },
+#endif
 
 #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[41].pCurrent)
+        LPCVOID))aSyscall[40].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
@@ -32666,107 +30446,251 @@ static struct win_syscall {
   { "LoadLibraryA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[41].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "LoadLibraryW",            (SYSCALL)LoadLibraryW,            0 },
 #else
   { "LoadLibraryW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[42].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "LocalFree",               (SYSCALL)LocalFree,               0 },
+#else
+  { "LocalFree",               (SYSCALL)0,                       0 },
+#endif
 
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[43].pCurrent)
 
-#if !SQLITE_OS_WINCE
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "LockFile",                (SYSCALL)LockFile,                0 },
-
-#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[45].pCurrent)
 #else
   { "LockFile",                (SYSCALL)0,                       0 },
 #endif
 
+#ifndef osLockFile
+#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+        DWORD))aSyscall[44].pCurrent)
+#endif
+
 #if !SQLITE_OS_WINCE
   { "LockFileEx",              (SYSCALL)LockFileEx,              0 },
-
-#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[46].pCurrent)
 #else
   { "LockFileEx",              (SYSCALL)0,                       0 },
 #endif
 
+#ifndef osLockFileEx
+#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
+        LPOVERLAPPED))aSyscall[45].pCurrent)
+#endif
+
+#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
   { "MapViewOfFile",           (SYSCALL)MapViewOfFile,           0 },
+#else
+  { "MapViewOfFile",           (SYSCALL)0,                       0 },
+#endif
 
 #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        SIZE_T))aSyscall[47].pCurrent)
+        SIZE_T))aSyscall[46].pCurrent)
 
   { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },
 
 #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
-        int))aSyscall[48].pCurrent)
+        int))aSyscall[47].pCurrent)
 
   { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
 
 #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
-        LARGE_INTEGER*))aSyscall[49].pCurrent)
+        LARGE_INTEGER*))aSyscall[48].pCurrent)
 
   { "ReadFile",                (SYSCALL)ReadFile,                0 },
 
 #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[50].pCurrent)
+        LPOVERLAPPED))aSyscall[49].pCurrent)
 
   { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },
 
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[50].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },
+#else
+  { "SetFilePointer",          (SYSCALL)0,                       0 },
+#endif
 
 #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
-        DWORD))aSyscall[52].pCurrent)
+        DWORD))aSyscall[51].pCurrent)
 
+#if !SQLITE_OS_WINRT
   { "Sleep",                   (SYSCALL)Sleep,                   0 },
+#else
+  { "Sleep",                   (SYSCALL)0,                       0 },
+#endif
 
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[52].pCurrent)
 
   { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },
 
 #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
-        LPFILETIME))aSyscall[54].pCurrent)
+        LPFILETIME))aSyscall[53].pCurrent)
 
-#if !SQLITE_OS_WINCE
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "UnlockFile",              (SYSCALL)UnlockFile,              0 },
-
-#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[55].pCurrent)
 #else
   { "UnlockFile",              (SYSCALL)0,                       0 },
 #endif
 
+#ifndef osUnlockFile
+#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+        DWORD))aSyscall[54].pCurrent)
+#endif
+
 #if !SQLITE_OS_WINCE
   { "UnlockFileEx",            (SYSCALL)UnlockFileEx,            0 },
-
-#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[56].pCurrent)
 #else
   { "UnlockFileEx",            (SYSCALL)0,                       0 },
 #endif
 
+#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+        LPOVERLAPPED))aSyscall[55].pCurrent)
+
+#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
   { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },
+#else
+  { "UnmapViewOfFile",         (SYSCALL)0,                       0 },
+#endif
 
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent)
 
   { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },
 
 #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
-        LPCSTR,LPBOOL))aSyscall[58].pCurrent)
+        LPCSTR,LPBOOL))aSyscall[57].pCurrent)
 
   { "WriteFile",               (SYSCALL)WriteFile,               0 },
 
 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[59].pCurrent)
+        LPOVERLAPPED))aSyscall[58].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "CreateEventExW",          (SYSCALL)CreateEventExW,          0 },
+#else
+  { "CreateEventExW",          (SYSCALL)0,                       0 },
+#endif
+
+#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
+        DWORD,DWORD))aSyscall[59].pCurrent)
+
+#if !SQLITE_OS_WINRT
+  { "WaitForSingleObject",     (SYSCALL)WaitForSingleObject,     0 },
+#else
+  { "WaitForSingleObject",     (SYSCALL)0,                       0 },
+#endif
+
+#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
+        DWORD))aSyscall[60].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "WaitForSingleObjectEx",   (SYSCALL)WaitForSingleObjectEx,   0 },
+#else
+  { "WaitForSingleObjectEx",   (SYSCALL)0,                       0 },
+#endif
+
+#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
+        BOOL))aSyscall[61].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "SetFilePointerEx",        (SYSCALL)SetFilePointerEx,        0 },
+#else
+  { "SetFilePointerEx",        (SYSCALL)0,                       0 },
+#endif
+
+#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
+        PLARGE_INTEGER,DWORD))aSyscall[62].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
+#else
+  { "GetFileInformationByHandleEx", (SYSCALL)0,                  0 },
+#endif
+
+#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
+        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[63].pCurrent)
+
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
+  { "MapViewOfFileFromApp",    (SYSCALL)MapViewOfFileFromApp,    0 },
+#else
+  { "MapViewOfFileFromApp",    (SYSCALL)0,                       0 },
+#endif
+
+#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
+        SIZE_T))aSyscall[64].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "CreateFile2",             (SYSCALL)CreateFile2,             0 },
+#else
+  { "CreateFile2",             (SYSCALL)0,                       0 },
+#endif
+
+#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
+        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[65].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "LoadPackagedLibrary",     (SYSCALL)LoadPackagedLibrary,     0 },
+#else
+  { "LoadPackagedLibrary",     (SYSCALL)0,                       0 },
+#endif
+
+#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
+        DWORD))aSyscall[66].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "GetTickCount64",          (SYSCALL)GetTickCount64,          0 },
+#else
+  { "GetTickCount64",          (SYSCALL)0,                       0 },
+#endif
+
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[67].pCurrent)
+
+#if SQLITE_OS_WINRT
+  { "GetNativeSystemInfo",     (SYSCALL)GetNativeSystemInfo,     0 },
+#else
+  { "GetNativeSystemInfo",     (SYSCALL)0,                       0 },
+#endif
+
+#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
+        LPSYSTEM_INFO))aSyscall[68].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+  { "OutputDebugStringA",      (SYSCALL)OutputDebugStringA,      0 },
+#else
+  { "OutputDebugStringA",      (SYSCALL)0,                       0 },
+#endif
+
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[69].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+  { "OutputDebugStringW",      (SYSCALL)OutputDebugStringW,      0 },
+#else
+  { "OutputDebugStringW",      (SYSCALL)0,                       0 },
+#endif
+
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent)
+
+  { "GetProcessHeap",          (SYSCALL)GetProcessHeap,          0 },
+
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent)
+
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
+  { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
+#else
+  { "CreateFileMappingFromApp", (SYSCALL)0,                      0 },
+#endif
+
+#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
+        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[72].pCurrent)
 
 }; /* End of the overrideable system calls */
 
@@ -32854,6 +30778,64 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
 }
 
 /*
+** This function outputs the specified (ANSI) string to the Win32 debugger
+** (if available).
+*/
+
+SQLITE_API void sqlite3_win32_write_debug(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);
+#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;
+#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
+}
+
+/*
 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
 ** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
 **
@@ -32864,7 +30846,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
 ** WinNT/2K/XP so that we will know whether or not we can safely call
 ** the LockFileEx() API.
 */
-#if SQLITE_OS_WINCE
+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
 # define isNT()  (1)
 #else
   static int isNT(void){
@@ -32890,7 +30872,7 @@ static void *winMemMalloc(int nBytes){
   hHeap = winMemGetHeap();
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
-#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
   assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
 #endif
   assert( nBytes>=0 );
@@ -32912,7 +30894,7 @@ static void winMemFree(void *pPrior){
   hHeap = winMemGetHeap();
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
-#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+#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. */
@@ -32933,7 +30915,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
   hHeap = winMemGetHeap();
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
-#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
   assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
 #endif
   assert( nBytes>=0 );
@@ -32961,7 +30943,7 @@ static int winMemSize(void *p){
   hHeap = winMemGetHeap();
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
-#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
   assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
 #endif
   if( !p ) return 0;
@@ -32989,6 +30971,8 @@ static int winMemInit(void *pAppData){
 
   if( !pWinMemData ) return SQLITE_ERROR;
   assert( pWinMemData->magic==WINMEM_MAGIC );
+
+#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
   if( !pWinMemData->hHeap ){
     pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
                                       SQLITE_WIN32_HEAP_INIT_SIZE,
@@ -33001,10 +30985,21 @@ static int winMemInit(void *pAppData){
       return SQLITE_NOMEM;
     }
     pWinMemData->bOwned = TRUE;
+    assert( pWinMemData->bOwned );
   }
+#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 );
-#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
   assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
 #endif
   return SQLITE_OK;
@@ -33019,7 +31014,7 @@ static void winMemShutdown(void *pAppData){
   if( !pWinMemData ) return;
   if( pWinMemData->hHeap ){
     assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
     assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
 #endif
     if( pWinMemData->bOwned ){
@@ -33204,6 +31199,42 @@ SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
   return zFilenameMbcs;
 }
 
+/*
+** 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;
+#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
@@ -33219,6 +31250,17 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
   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 |
@@ -33229,20 +31271,20 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
                              (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
     }
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-** Since the ANSI version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     char *zTemp = NULL;
     dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                              FORMAT_MESSAGE_FROM_SYSTEM |
@@ -33261,8 +31303,8 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
       /* free the system buffer allocated by FormatMessage */
       osLocalFree(zTemp);
     }
-#endif
   }
+#endif
   if( 0 == dwLen ){
     sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno);
   }else{
@@ -33287,7 +31329,7 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
 ** 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 the associated file-system path, if any.
+** failed and the associated file-system path, if any.
 */
 #define winLogError(a,b,c,d)   winLogErrorAtLine(a,b,c,d,__LINE__)
 static int winLogErrorAtLine(
@@ -33345,7 +31387,7 @@ static int retryIoerr(int *pnRetry, DWORD *pError){
   if( e==ERROR_ACCESS_DENIED ||
       e==ERROR_LOCK_VIOLATION ||
       e==ERROR_SHARING_VIOLATION ){
-    osSleep(win32IoerrRetryDelay*(1+*pnRetry));
+    sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
     ++*pnRetry;
     return 1;
   }
@@ -33406,7 +31448,7 @@ struct tm *__cdecl localtime(const time_t *t)
 static void winceMutexAcquire(HANDLE h){
    DWORD dwErr;
    do {
-     dwErr = WaitForSingleObject(h, INFINITE);
+     dwErr = osWaitForSingleObject(h, INFINITE);
    } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
 }
 /*
@@ -33537,7 +31579,7 @@ static void winceDestroyLock(winFile *pFile){
 ** An implementation of the LockFile() API of Windows for CE
 */
 static BOOL winceLockFile(
-  HANDLE *phFile,
+  LPHANDLE phFile,
   DWORD dwFileOffsetLow,
   DWORD dwFileOffsetHigh,
   DWORD nNumberOfBytesToLockLow,
@@ -33601,7 +31643,7 @@ static BOOL winceLockFile(
 ** An implementation of the UnlockFile API of Windows for CE
 */
 static BOOL winceUnlockFile(
-  HANDLE *phFile,
+  LPHANDLE phFile,
   DWORD dwFileOffsetLow,
   DWORD dwFileOffsetHigh,
   DWORD nNumberOfBytesToUnlockLow,
@@ -33658,34 +31700,73 @@ static BOOL winceUnlockFile(
   winceMutexRelease(pFile->hMutex);
   return bReturn;
 }
+/*
+** End of the special code for wince
+*****************************************************************************/
+#endif /* SQLITE_OS_WINCE */
 
 /*
-** An implementation of the LockFileEx() API of Windows for CE
+** Lock a file region.
 */
-static BOOL winceLockFileEx(
-  HANDLE *phFile,
-  DWORD dwFlags,
-  DWORD dwReserved,
-  DWORD nNumberOfBytesToLockLow,
-  DWORD nNumberOfBytesToLockHigh,
-  LPOVERLAPPED lpOverlapped
+static BOOL winLockFile(
+  LPHANDLE phFile,
+  DWORD flags,
+  DWORD offsetLow,
+  DWORD offsetHigh,
+  DWORD numBytesLow,
+  DWORD numBytesHigh
 ){
-  UNUSED_PARAMETER(dwReserved);
-  UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
-
-  /* If the caller wants a shared read lock, forward this call
-  ** to winceLockFile */
-  if (lpOverlapped->Offset == (DWORD)SHARED_FIRST &&
-      dwFlags == 1 &&
-      nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
-    return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
+#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);
   }
-  return FALSE;
+#endif
 }
+
 /*
-** End of the special code for wince
-*****************************************************************************/
-#endif /* SQLITE_OS_WINCE */
+** 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);
+#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
+}
 
 /*****************************************************************************
 ** The next group of routines implement the I/O methods specified
@@ -33705,6 +31786,7 @@ static BOOL winceLockFileEx(
 ** 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() */
@@ -33731,6 +31813,26 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
   }
 
   return 0;
+#else
+  /*
+  ** Same as above, except that this implementation works for WinRT.
+  */
+
+  LARGE_INTEGER x;                /* The new offset */
+  BOOL bRet;                      /* Value returned by SetFilePointerEx() */
+
+  x.QuadPart = iOffset;
+  bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+
+  if(!bRet){
+    pFile->lastErrno = osGetLastError();
+    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
+             "seekWinFile", pFile->zPath);
+    return 1;
+  }
+
+  return 0;
+#endif
 }
 
 /*
@@ -33749,12 +31851,14 @@ static int winClose(sqlite3_file *id){
   winFile *pFile = (winFile*)id;
 
   assert( id!=0 );
+#ifndef SQLITE_OMIT_WAL
   assert( pFile->pShm==0 );
+#endif
   OSTRACE(("CLOSE %d\n", pFile->h));
   do{
     rc = osCloseHandle(pFile->h);
     /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
-  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (osSleep(100), 1) );
+  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
 #if SQLITE_OS_WINCE
 #define WINCE_DELETION_ATTEMPTS 3
   winceDestroyLock(pFile);
@@ -33765,7 +31869,7 @@ static int winClose(sqlite3_file *id){
         && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff 
         && cnt++ < WINCE_DELETION_ATTEMPTS
     ){
-       osSleep(100);  /* Wait a little before trying again */
+       sqlite3_win32_sleep(100);  /* Wait a little before trying again */
     }
     sqlite3_free(pFile->zDeleteOnClose);
   }
@@ -34020,23 +32124,40 @@ static int winSync(sqlite3_file *id, int flags){
 ** Determine the current size of a file in bytes
 */
 static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
-  DWORD upperBits;
-  DWORD lowerBits;
   winFile *pFile = (winFile*)id;
-  DWORD lastErrno;
+  int rc = SQLITE_OK;
 
   assert( id!=0 );
   SimulateIOError(return SQLITE_IOERR_FSTAT);
-  lowerBits = osGetFileSize(pFile->h, &upperBits);
-  if(   (lowerBits == INVALID_FILE_SIZE)
-     && ((lastErrno = osGetLastError())!=NO_ERROR) )
+#if SQLITE_OS_WINRT
   {
-    pFile->lastErrno = lastErrno;
-    return winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
+    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);
+    }
+  }
+#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);
+    }
   }
-  *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
-  return SQLITE_OK;
+#endif
+  return rc;
 }
 
 /*
@@ -34046,6 +32167,30 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
 # define LOCKFILE_FAIL_IMMEDIATELY 1
 #endif
 
+#ifndef LOCKFILE_EXCLUSIVE_LOCK
+# define LOCKFILE_EXCLUSIVE_LOCK 2
+#endif
+
+/*
+** 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
+
+/*
+** 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
@@ -34054,22 +32199,26 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
 static int getReadLock(winFile *pFile){
   int res;
   if( isNT() ){
-    OVERLAPPED ovlp;
-    ovlp.Offset = SHARED_FIRST;
-    ovlp.OffsetHigh = 0;
-    ovlp.hEvent = 0;
-    res = osLockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
-                       0, SHARED_SIZE, 0, &ovlp);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+#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{
     int lk;
     sqlite3_randomness(sizeof(lk), &lk);
     pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
-    res = osLockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
-#endif
+    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 */
@@ -34084,14 +32233,13 @@ static int unlockReadLock(winFile *pFile){
   int res;
   DWORD lastErrno;
   if( isNT() ){
-    res = osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
-    res = osUnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
-#endif
+    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,
@@ -34162,7 +32310,8 @@ static int winLock(sqlite3_file *id, int locktype){
          && (pFile->locktype==RESERVED_LOCK))
   ){
     int cnt = 3;
-    while( cnt-->0 && (res = osLockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
+    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.
@@ -34170,7 +32319,7 @@ static int winLock(sqlite3_file *id, int locktype){
       ** copy this retry logic.  It is a hack intended for Windows only.
       */
       OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
-      if( cnt ) osSleep(1);
+      if( cnt ) sqlite3_win32_sleep(1);
     }
     gotPendingLock = res;
     if( !res ){
@@ -34194,7 +32343,7 @@ static int winLock(sqlite3_file *id, int locktype){
   */
   if( locktype==RESERVED_LOCK && res ){
     assert( pFile->locktype==SHARED_LOCK );
-    res = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
     if( res ){
       newLocktype = RESERVED_LOCK;
     }else{
@@ -34215,7 +32364,8 @@ static int winLock(sqlite3_file *id, int locktype){
     assert( pFile->locktype>=SHARED_LOCK );
     res = unlockReadLock(pFile);
     OSTRACE(("unreadlock = %d\n", res));
-    res = osLockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
+                      SHARED_SIZE, 0);
     if( res ){
       newLocktype = EXCLUSIVE_LOCK;
     }else{
@@ -34229,7 +32379,7 @@ static int winLock(sqlite3_file *id, int locktype){
   ** release it now.
   */
   if( gotPendingLock && locktype==SHARED_LOCK ){
-    osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
+    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
   }
 
   /* Update the state of the lock has held in the file descriptor then
@@ -34263,9 +32413,9 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
     rc = 1;
     OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
   }else{
-    rc = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+    rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
     if( rc ){
-      osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+      winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
     }
     rc = !rc;
     OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
@@ -34295,7 +32445,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
           pFile->locktype, pFile->sharedLockByte));
   type = pFile->locktype;
   if( type>=EXCLUSIVE_LOCK ){
-    osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+    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 */
@@ -34304,13 +32454,13 @@ static int winUnlock(sqlite3_file *id, int locktype){
     }
   }
   if( type>=RESERVED_LOCK ){
-    osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+    winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
   }
   if( locktype==NO_LOCK && type>=SHARED_LOCK ){
     unlockReadLock(pFile);
   }
   if( type>=PENDING_LOCK ){
-    osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
+    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
   }
   pFile->locktype = (u8)locktype;
   return rc;
@@ -34548,25 +32698,19 @@ static int winShmSystemLock(
   int ofst,             /* Offset to first byte to be locked/unlocked */
   int nByte             /* Number of bytes to lock or unlock */
 ){
-  OVERLAPPED ovlp;
-  DWORD dwFlags;
   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 );
 
-  /* Initialize the locking parameters */
-  dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
-  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
-
-  memset(&ovlp, 0, sizeof(OVERLAPPED));
-  ovlp.Offset = ofst;
-
   /* Release/Acquire the system-level lock */
   if( lockType==_SHM_UNLCK ){
-    rc = osUnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp);
+    rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
   }else{
-    rc = osLockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
+    /* 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 ){
@@ -35004,18 +33148,30 @@ static int winShmMap(
       HANDLE hMap;                /* file-mapping handle */
       void *pMap = 0;             /* Mapped memory region */
      
-      hMap = osCreateFileMapping(pShmNode->hFile.h, 
+#if SQLITE_OS_WINRT
+      hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
+          NULL, PAGE_READWRITE, nByte, NULL
+      );
+#else
+      hMap = osCreateFileMappingW(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,
                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
         );
+#endif
         OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n",
                  (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
                  szRegion, pMap ? "ok" : "failed"));
@@ -35101,13 +33257,12 @@ static void *convertUtf8Filename(const char *zFilename){
   void *zConverted = 0;
   if( isNT() ){
     zConverted = utf8ToUnicode(zFilename);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
-#endif
   }
+#endif
   /* caller will handle out of memory */
   return zConverted;
 }
@@ -35122,6 +33277,7 @@ static int getTempname(int nBuf, char *zBuf){
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     "0123456789";
   size_t i, j;
+  int nTempPath;
   char zTempPath[MAX_PATH+2];
 
   /* It's odd to simulate an io-error here, but really this is just
@@ -35130,9 +33286,13 @@ static int getTempname(int nBuf, char *zBuf){
   */
   SimulateIOError( return SQLITE_IOERR );
 
+  memset(zTempPath, 0, MAX_PATH+2);
+
   if( sqlite3_temp_directory ){
     sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
-  }else if( isNT() ){
+  }
+#if !SQLITE_OS_WINRT
+  else if( isNT() ){
     char *zMulti;
     WCHAR zWidePath[MAX_PATH];
     osGetTempPathW(MAX_PATH-30, zWidePath);
@@ -35143,12 +33303,9 @@ static int getTempname(int nBuf, char *zBuf){
     }else{
       return SQLITE_IOERR_NOMEM;
     }
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-** Since the ANSI version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     char *zUtf8;
     char zMbcsPath[MAX_PATH];
     osGetTempPathA(MAX_PATH-30, zMbcsPath);
@@ -35159,21 +33316,25 @@ static int getTempname(int nBuf, char *zBuf){
     }else{
       return SQLITE_IOERR_NOMEM;
     }
-#endif
   }
+#endif
+#endif
 
   /* Check that the output buffer is large enough for the temporary file 
   ** name. If it is not, return SQLITE_ERROR.
   */
-  if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
+  nTempPath = sqlite3Strlen30(zTempPath);
+
+  if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
     return SQLITE_ERROR;
   }
 
-  for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
+  for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
   zTempPath[i] = 0;
 
-  sqlite3_snprintf(nBuf-18, zBuf,
-                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
+  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++){
@@ -35294,6 +33455,13 @@ static int winOpen(
   assert( id!=0 );
   UNUSED_PARAMETER(pVfs);
 
+#if SQLITE_OS_WINRT
+  if( !sqlite3_temp_directory ){
+    sqlite3_log(SQLITE_ERROR,
+        "sqlite3_temp_directory variable should be set for WinRT");
+  }
+#endif
+
   pFile->h = INVALID_HANDLE_VALUE;
 
   /* If the second argument to this function is NULL, generate a 
@@ -35369,6 +33537,24 @@ static int winOpen(
 #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,
@@ -35378,8 +33564,10 @@ static int winOpen(
                               retryIoerr(&cnt, &lastErrno) ){
                /* Noop */
     }
-#if SQLITE_OS_WINCE==0
-  }else{
+#endif
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     while( (h = osCreateFileA((LPCSTR)zConverted,
                               dwDesiredAccess,
                               dwShareMode, NULL,
@@ -35389,9 +33577,8 @@ static int winOpen(
                               retryIoerr(&cnt, &lastErrno) ){
                /* Noop */
     }
-#endif
   }
-
+#endif
   logIoerr(cnt);
 
   OSTRACE(("OPEN %d %s 0x%lx %s\n", 
@@ -35423,7 +33610,9 @@ static int winOpen(
   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;
@@ -35481,7 +33670,19 @@ static int winDelete(
   }
   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{
+        rc = SQLITE_OK; /* Already gone? */
+        break;
+      }
+#else
       attr = osGetFileAttributesW(zConverted);
+#endif
       if ( attr==INVALID_FILE_ATTRIBUTES ){
         rc = SQLITE_OK; /* Already gone? */
         break;
@@ -35499,12 +33700,9 @@ static int winDelete(
         break;
       }
     } while(1);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-** Since the ANSI version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     do {
       attr = osGetFileAttributesA(zConverted);
       if ( attr==INVALID_FILE_ATTRIBUTES ){
@@ -35524,8 +33722,8 @@ static int winDelete(
         break;
       }
     } while(1);
-#endif
   }
+#endif
   if( rc ){
     rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
              "winDelete", zFilename);
@@ -35577,7 +33775,7 @@ static int winAccess(
       }
     }else{
       logIoerr(cnt);
-      if( lastErrno!=ERROR_FILE_NOT_FOUND ){
+      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;
@@ -35585,15 +33783,12 @@ static int winAccess(
         attr = INVALID_FILE_ATTRIBUTES;
       }
     }
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-** Since the ANSI version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     attr = osGetFileAttributesA((char*)zConverted);
-#endif
   }
+#endif
   sqlite3_free(zConverted);
   switch( flags ){
     case SQLITE_ACCESS_READ:
@@ -35613,6 +33808,43 @@ static int winAccess(
 
 
 /*
+** 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).
+*/
+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;
+  }
+
+  /*
+  ** 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.
@@ -35627,19 +33859,51 @@ static int winFullPathname(
 #if defined(__CYGWIN__)
   SimulateIOError( return SQLITE_ERROR );
   UNUSED_PARAMETER(nFull);
-  cygwin_conv_to_full_win32_path(zRelative, zFull);
+  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_to_win32_path(zRelative, zOut); /* POSIX to Win32 */
+    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);
+  }
   return SQLITE_OK;
 #endif
 
-#if SQLITE_OS_WINCE
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
   SimulateIOError( return SQLITE_ERROR );
-  UNUSED_PARAMETER(nFull);
   /* WinCE has no concept of a relative pathname, or so I am told. */
-  sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
+  /* 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
 
-#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
   int nByte;
   void *zConverted;
   char *zOut;
@@ -35657,7 +33921,17 @@ static int winFullPathname(
   ** current working directory has been unlinked.
   */
   SimulateIOError( return SQLITE_ERROR );
-  UNUSED_PARAMETER(nFull);
+  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;
@@ -35674,12 +33948,9 @@ static int winFullPathname(
     sqlite3_free(zConverted);
     zOut = unicodeToUtf8(zTemp);
     sqlite3_free(zTemp);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-** Since the ANSI version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
     char *zTemp;
     nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
     zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
@@ -35691,10 +33962,10 @@ static int winFullPathname(
     sqlite3_free(zConverted);
     zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
     sqlite3_free(zTemp);
-#endif
   }
+#endif
   if( zOut ){
-    sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
+    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
     sqlite3_free(zOut);
     return SQLITE_OK;
   }else{
@@ -35720,16 +33991,17 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
     return 0;
   }
   if( isNT() ){
+#if SQLITE_OS_WINRT
+    h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
+#else
     h = osLoadLibraryW((LPCWSTR)zConverted);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-** Since the ANSI version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
-  }else{
-    h = osLoadLibraryA((char*)zConverted);
 #endif
   }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
+    h = osLoadLibraryA((char*)zConverted);
+  }
+#endif
   sqlite3_free(zConverted);
   return (void*)h;
 }
@@ -35774,11 +34046,19 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
     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);
@@ -35794,7 +34074,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
 ** Sleep for a little while.  Return the amount of time slept.
 */
 static int winSleep(sqlite3_vfs *pVfs, int microsec){
-  osSleep((microsec+999)/1000);
+  sqlite3_win32_sleep((microsec+999)/1000);
   UNUSED_PARAMETER(pVfs);
   return ((microsec+999)/1000)*1000;
 }
@@ -35936,12 +34216,16 @@ SQLITE_API int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==60 );
+  assert( ArraySize(aSyscall)==73 );
 
 #ifndef SQLITE_OMIT_WAL
   /* 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);
 #endif
 
@@ -35950,6 +34234,12 @@ SQLITE_API int sqlite3_os_init(void){
 }
 
 SQLITE_API int sqlite3_os_end(void){ 
+#if SQLITE_OS_WINRT
+  if( sleepObj != NULL ){
+    osCloseHandle(sleepObj);
+    sleepObj = NULL;
+  }
+#endif
   return SQLITE_OK;
 }
 
@@ -36298,10 +34588,9 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
   /* Allocate the Bitvec to be tested and a linear array of
   ** bits to act as the reference */
   pBitvec = sqlite3BitvecCreate( sz );
-  pV = sqlite3_malloc( (sz+7)/8 + 1 );
+  pV = sqlite3MallocZero( (sz+7)/8 + 1 );
   pTmpSpace = sqlite3_malloc(BITVEC_SZ);
   if( pBitvec==0 || pV==0 || pTmpSpace==0  ) goto bitvec_end;
-  memset(pV, 0, (sz+7)/8 + 1);
 
   /* NULL pBitvec tests */
   sqlite3BitvecSet(0, 1);
@@ -37201,12 +35490,14 @@ static void *pcache1Alloc(int nByte){
     ** 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;
@@ -37233,9 +35524,11 @@ static int pcache1Free(void *p){
     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;
@@ -37381,11 +35674,10 @@ static int pcache1ResizeHash(PCache1 *p){
 
   pcache1LeaveMutex(p->pGroup);
   if( p->nHash ){ sqlite3BeginBenignMalloc(); }
-  apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
+  apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
   if( p->nHash ){ sqlite3EndBenignMalloc(); }
   pcache1EnterMutex(p->pGroup);
   if( apNew ){
-    memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
     for(i=0; i<p->nHash; i++){
       PgHdr1 *pPage;
       PgHdr1 *pNext = p->apHash[i];
@@ -37569,9 +35861,8 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
   assert( szExtra < 300 );
 
   sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
-  pCache = (PCache1 *)sqlite3_malloc(sz);
+  pCache = (PCache1 *)sqlite3MallocZero(sz);
   if( pCache ){
-    memset(pCache, 0, sz);
     if( separateCache ){
       pGroup = (PGroup*)&pCache[1];
       pGroup->mxPinned = 10;
@@ -38449,7 +36740,7 @@ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
 }
 
 /*
-** Check to see if element iRowid was inserted into the the rowset as
+** Check to see if element iRowid was inserted into the rowset as
 ** part of any insert batch prior to iBatch.  Return 1 or 0.
 **
 ** If this is the first test of a new batch and if there exist entires
@@ -38733,7 +37024,7 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
 ** 
 ** 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 the content of freelist leaf
+** all queries.  Note in particular the content of freelist leaf
 ** pages can be changed arbitarily without effecting the logical equivalence
 ** of the database.
 ** 
@@ -42507,7 +40798,7 @@ SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
 **
 ** 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 the file-system, as follows:
+** device characteristics of the file-system, as follows:
 **
 **   * If the journal file is an in-memory journal file, no action need
 **     be taken.
@@ -43018,7 +41309,12 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
 #ifndef SQLITE_OMIT_MEMORYDB
   if( flags & PAGER_MEMORY ){
     memDb = 1;
-    zFilename = 0;
+    if( zFilename && zFilename[0] ){
+      zPathname = sqlite3DbStrDup(0, zFilename);
+      if( zPathname==0  ) return SQLITE_NOMEM;
+      nPathname = sqlite3Strlen30(zPathname);
+      zFilename = 0;
+    }
   }
 #endif
 
@@ -43029,7 +41325,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
   if( zFilename && zFilename[0] ){
     const char *z;
     nPathname = pVfs->mxPathname+1;
-    zPathname = sqlite3Malloc(nPathname*2);
+    zPathname = sqlite3DbMallocRaw(0, nPathname*2);
     if( zPathname==0 ){
       return SQLITE_NOMEM;
     }
@@ -43053,7 +41349,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
       rc = SQLITE_CANTOPEN_BKPT;
     }
     if( rc!=SQLITE_OK ){
-      sqlite3_free(zPathname);
+      sqlite3DbFree(0, zPathname);
       return rc;
     }
   }
@@ -43083,7 +41379,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
   );
   assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
   if( !pPtr ){
-    sqlite3_free(zPathname);
+    sqlite3DbFree(0, zPathname);
     return SQLITE_NOMEM;
   }
   pPager =              (Pager*)(pPtr);
@@ -43099,7 +41395,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
     assert( nPathname>0 );
     pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
     memcpy(pPager->zFilename, zPathname, nPathname);
-    memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
+    if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
     memcpy(pPager->zJournal, zPathname, nPathname);
     memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1);
     sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
@@ -43109,7 +41405,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
     memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
     sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
 #endif
-    sqlite3_free(zPathname);
+    sqlite3DbFree(0, zPathname);
   }
   pPager->pVfs = pVfs;
   pPager->vfsFlags = vfsFlags;
@@ -44954,9 +43250,16 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
 
 /*
 ** 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.
 */
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager){
-  return pPager->zFilename;
+SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
+  return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
 }
 
 /*
@@ -45726,14 +44029,15 @@ SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
 ** byte order of the host computer.
 **
 ** The purpose of the wal-index is to answer this question quickly:  Given
-** a page number P, return the index of the last frame for page P in the WAL,
-** or return NULL if there are no frames for page P in the WAL.
+** 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 the mxFrame field.  
+** in the mxFrame field.
 **
 ** Each index block except for the first contains information on 
 ** HASHTABLE_NPAGE frames. The first index block contains information on
@@ -46781,6 +45085,7 @@ finished:
     pInfo->nBackfill = 0;
     pInfo->aReadMark[0] = 0;
     for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+    if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
 
     /* If more than one frame was recovered from the log file, report an
     ** event via sqlite3_log(). This is to help with identifying performance
@@ -47281,7 +45586,7 @@ static int walCheckpoint(
       assert( y<=pWal->hdr.mxFrame );
       rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
       if( rc==SQLITE_OK ){
-        pInfo->aReadMark[i] = READMARK_NOT_USED;
+        pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
         walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
       }else if( rc==SQLITE_BUSY ){
         mxSafeFrame = y;
@@ -48194,7 +46499,8 @@ static int walRestartLog(Wal *pWal){
         aSalt[1] = salt1;
         walIndexWriteHdr(pWal);
         pInfo->nBackfill = 0;
-        for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+        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 ){
@@ -49197,6 +47503,7 @@ struct BtCursor {
 #ifndef SQLITE_OMIT_INCRBLOB
   u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
 #endif
+  u8 hints;                             /* As configured by CursorSetHints() */
   i16 iPage;                            /* Index of current page in apPage */
   u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
   MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
@@ -51081,7 +49388,7 @@ static int btreeInitPage(MemPage *pPage){
       size = get2byte(&data[pc+2]);
       if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
         /* Free blocks must be in ascending order. And the last byte of
-	** the free-block must lie on the database page.  */
+        ** the free-block must lie on the database page.  */
         return SQLITE_CORRUPT_BKPT; 
       }
       nFree = nFree + size;
@@ -51341,7 +49648,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
   const int isMemdb = 0;
 #else
   const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
-                       || (isTempDb && sqlite3TempInMemory(db));
+                       || (isTempDb && sqlite3TempInMemory(db))
+                       || (vfsFlags & SQLITE_OPEN_MEMORY)!=0;
 #endif
 
   assert( db!=0 );
@@ -51377,7 +49685,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
   ** If this Btree is a candidate for shared cache, try to find an
   ** existing BtShared object that we can share with
   */
-  if( isMemdb==0 && isTempDb==0 ){
+  if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
     if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
       int nFullPathname = pVfs->mxPathname+1;
       char *zFullPathname = sqlite3Malloc(nFullPathname);
@@ -51387,11 +49695,16 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
         sqlite3_free(p);
         return SQLITE_NOMEM;
       }
-      rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
-      if( rc ){
-        sqlite3_free(zFullPathname);
-        sqlite3_free(p);
-        return rc;
+      if( isMemdb ){
+        memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
+      }else{
+        rc = sqlite3OsFullPathname(pVfs, zFilename,
+                                   nFullPathname, zFullPathname);
+        if( rc ){
+          sqlite3_free(zFullPathname);
+          sqlite3_free(p);
+          return rc;
+        }
       }
 #if SQLITE_THREADSAFE
       mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
@@ -51401,7 +49714,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
 #endif
       for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
         assert( pBt->nRef>0 );
-        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
+        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
                  && sqlite3PagerVfs(pBt->pPager)==pVfs ){
           int iDb;
           for(iDb=db->nDb-1; iDb>=0; iDb--){
@@ -52249,7 +50562,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
       pBt->nTransaction++;
 #ifndef SQLITE_OMIT_SHARED_CACHE
       if( p->sharable ){
-	assert( p->lock.pBtree==p && p->lock.iTable==1 );
+        assert( p->lock.pBtree==p && p->lock.iTable==1 );
         p->lock.eLock = READ_LOCK;
         p->lock.pNext = pBt->pLock;
         pBt->pLock = &p->lock;
@@ -55536,11 +53849,15 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
 ** If aOvflSpace is set to a null pointer, this function returns 
 ** SQLITE_NOMEM.
 */
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
+#pragma optimize("", off)
+#endif
 static int balance_nonroot(
   MemPage *pParent,               /* Parent page of siblings being balanced */
   int iParentIdx,                 /* Index of "the page" in pParent */
   u8 *aOvflSpace,                 /* page-size bytes of space for parent ovfl */
-  int isRoot                      /* True if pParent is a root-page */
+  int isRoot,                     /* True if pParent is a root-page */
+  int bBulk                       /* True if this call is part of a bulk load */
 ){
   BtShared *pBt;               /* The whole database */
   int nCell = 0;               /* Number of cells in apCell[] */
@@ -55604,18 +53921,19 @@ static int balance_nonroot(
   i = pParent->nOverflow + pParent->nCell;
   if( i<2 ){
     nxDiv = 0;
-    nOld = i+1;
   }else{
-    nOld = 3;
+    assert( bBulk==0 || bBulk==1 );
     if( iParentIdx==0 ){                 
       nxDiv = 0;
     }else if( iParentIdx==i ){
-      nxDiv = i-2;
+      nxDiv = i-2+bBulk;
     }else{
+      assert( bBulk==0 );
       nxDiv = iParentIdx-1;
     }
-    i = 2;
+    i = 2-bBulk;
   }
+  nOld = i+1;
   if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
     pRight = &pParent->aData[pParent->hdrOffset+8];
   }else{
@@ -55695,7 +54013,7 @@ static int balance_nonroot(
   /*
   ** Load pointers to all cells on sibling pages and the divider cells
   ** into the local apCell[] array.  Make copies of the divider cells
-  ** into space obtained from aSpace1[] and remove the the divider Cells
+  ** into space obtained from aSpace1[] and remove the divider cells
   ** from pParent.
   **
   ** If the siblings are on leaf pages, then the child pointers of the
@@ -55824,7 +54142,9 @@ static int balance_nonroot(
     d = r + 1 - leafData;
     assert( d<nMaxCells );
     assert( r<nMaxCells );
-    while( szRight==0 || szRight+szCell[d]+2<=szLeft-(szCell[r]+2) ){
+    while( szRight==0 
+       || (!bBulk && szRight+szCell[d]+2<=szLeft-(szCell[r]+2)) 
+    ){
       szRight += szCell[d] + 2;
       szLeft -= szCell[r] + 2;
       cntNew[i-1]--;
@@ -55871,7 +54191,7 @@ static int balance_nonroot(
       if( rc ) goto balance_cleanup;
     }else{
       assert( i>0 );
-      rc = allocateBtreePage(pBt, &pNew, &pgno, pgno, 0);
+      rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
       if( rc ) goto balance_cleanup;
       apNew[i] = pNew;
       nNew++;
@@ -56083,6 +54403,7 @@ static int balance_nonroot(
         ** sibling page j. If the siblings are not leaf pages of an
         ** intkey b-tree, then cell i was a divider cell. */
         assert( j+1 < ArraySize(apCopy) );
+        assert( j+1 < nOld );
         pOld = apCopy[++j];
         iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
         if( pOld->nOverflow ){
@@ -56161,6 +54482,9 @@ balance_cleanup:
 
   return rc;
 }
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
+#pragma optimize("", on)
+#endif
 
 
 /*
@@ -56321,7 +54645,7 @@ static int balance(BtCursor *pCur){
           ** pSpace buffer passed to the latter call to balance_nonroot().
           */
           u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
-          rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1);
+          rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints);
           if( pFree ){
             /* If pFree is not NULL, it points to the pSpace buffer used 
             ** by a previous call to balance_nonroot(). Its contents are
@@ -57666,14 +55990,15 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
 /*
-** Return the full pathname of the underlying database file.
+** Return the full pathname of the underlying database file.  Return
+** an empty string if the database is in-memory or a TEMP database.
 **
 ** The pager filename is invariant as long as the pager is
 ** open so it is safe to access without the BtShared mutex.
 */
 SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){
   assert( p->pBt->pPager!=0 );
-  return sqlite3PagerFilename(p->pBt->pPager);
+  return sqlite3PagerFilename(p->pBt->pPager, 1);
 }
 
 /*
@@ -57908,6 +56233,15 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
   return rc;
 }
 
+/*
+** set the mask of hint flags for cursor pCsr. Currently the only valid
+** values are 0 and BTREE_BULKLOAD.
+*/
+SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
+  assert( mask==BTREE_BULKLOAD || mask==0 );
+  pCsr->hints = mask;
+}
+
 /************** End of btree.c ***********************************************/
 /************** Begin file backup.c ******************************************/
 /*
@@ -58074,7 +56408,7 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init(
     ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
     ** call to sqlite3_backup_init() and is destroyed by a call to
     ** sqlite3_backup_finish(). */
-    p = (sqlite3_backup *)sqlite3_malloc(sizeof(sqlite3_backup));
+    p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
     if( !p ){
       sqlite3Error(pDestDb, SQLITE_NOMEM, 0);
     }
@@ -58082,7 +56416,6 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init(
 
   /* If the allocation succeeded, populate the new object. */
   if( p ){
-    memset(p, 0, sizeof(sqlite3_backup));
     p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
     p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
     p->pDestDb = pDestDb;
@@ -58324,7 +56657,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
       rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
       if( rc==SQLITE_OK ){
         if( p->pDestDb ){
-          sqlite3ResetInternalSchema(p->pDestDb, -1);
+          sqlite3ResetAllSchemasOfConnection(p->pDestDb);
         }
         if( destMode==PAGER_JOURNALMODE_WAL ){
           rc = sqlite3BtreeSetVersion(p->pDest, 2);
@@ -58453,14 +56786,14 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 */
 SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
   sqlite3_backup **pp;                 /* Ptr to head of pagers backup list */
-  MUTEX_LOGIC( sqlite3_mutex *mutex; ) /* Mutex to protect source database */
+  sqlite3 *pSrcDb;                     /* Source database connection */
   int rc;                              /* Value to return */
 
   /* Enter the mutexes */
   if( p==0 ) return SQLITE_OK;
-  sqlite3_mutex_enter(p->pSrcDb->mutex);
+  pSrcDb = p->pSrcDb;
+  sqlite3_mutex_enter(pSrcDb->mutex);
   sqlite3BtreeEnter(p->pSrc);
-  MUTEX_LOGIC( mutex = p->pSrcDb->mutex; )
   if( p->pDestDb ){
     sqlite3_mutex_enter(p->pDestDb->mutex);
   }
@@ -58486,7 +56819,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
 
   /* Exit the mutexes and free the backup context structure. */
   if( p->pDestDb ){
-    sqlite3_mutex_leave(p->pDestDb->mutex);
+    sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
   }
   sqlite3BtreeLeave(p->pSrc);
   if( p->pDestDb ){
@@ -58495,7 +56828,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
     ** sqlite3_backup_finish(). */
     sqlite3_free(p);
   }
-  sqlite3_mutex_leave(mutex);
+  sqlite3LeaveMutexAndCloseZombie(pSrcDb);
   return rc;
 }
 
@@ -60564,7 +58897,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
 
 #ifndef NDEBUG
 /*
-** Change the comment on the the most recently coded instruction.  Or
+** Change the comment on the most recently coded instruction.  Or
 ** insert a No-op and add the comment to that new instruction.  This
 ** makes the code easier to read during debugging.  None of this happens
 ** in a production build.
@@ -62259,6 +60592,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
 
   if( NEVER(p==0) ) return;
   db = p->db;
+  assert( sqlite3_mutex_held(db->mutex) );
   if( p->pPrev ){
     p->pPrev->pNext = p->pNext;
   }else{
@@ -63098,17 +61432,11 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
   }else{
     Vdbe *v = (Vdbe*)pStmt;
     sqlite3 *db = v->db;
-#if SQLITE_THREADSAFE
-    sqlite3_mutex *mutex;
-#endif
     if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
-#if SQLITE_THREADSAFE
-    mutex = v->db->mutex;
-#endif
-    sqlite3_mutex_enter(mutex);
+    sqlite3_mutex_enter(db->mutex);
     rc = sqlite3VdbeFinalize(v);
     rc = sqlite3ApiExit(db, rc);
-    sqlite3_mutex_leave(mutex);
+    sqlite3LeaveMutexAndCloseZombie(db);
   }
   return rc;
 }
@@ -64511,9 +62839,8 @@ SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe *pVdbe){
   if( pVdbe ){
     Explain *p;
     sqlite3BeginBenignMalloc();
-    p = sqlite3_malloc( sizeof(Explain) );
+    p = (Explain *)sqlite3MallocZero( sizeof(Explain) );
     if( p ){
-      memset(p, 0, sizeof(*p));
       p->pVdbe = pVdbe;
       sqlite3_free(pVdbe->pExplain);
       pVdbe->pExplain = p;
@@ -65782,7 +64109,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     }
 #endif
 
-    /* On any opcode with the "out2-prerelase" tag, free any
+    /* On any opcode with the "out2-prerelease" tag, free any
     ** external allocations out of mem[p2] and set mem[p2] to be
     ** an undefined integer.  Opcodes will either fill in the integer
     ** value or convert mem[p2] to a different type.
@@ -67909,7 +66236,7 @@ case OP_Savepoint: {
         }
         if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
           sqlite3ExpirePreparedStatements(db);
-          sqlite3ResetInternalSchema(db, -1);
+          sqlite3ResetAllSchemasOfConnection(db);
           db->flags = (db->flags | SQLITE_InternChanges);
         }
       }
@@ -68223,7 +66550,7 @@ case OP_VerifyCookie: {
     ** a v-table method.
     */
     if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){
-      sqlite3ResetInternalSchema(db, pOp->p1);
+      sqlite3ResetOneSchema(db, pOp->p1);
     }
 
     p->expired = 1;
@@ -68294,6 +66621,9 @@ case OP_OpenWrite: {
   Db *pDb;
 #endif /* local variables moved into u.ax */
 
+  assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
+  assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+
   if( p->expired ){
     rc = SQLITE_ABORT;
     break;
@@ -68317,7 +66647,7 @@ case OP_OpenWrite: {
   }else{
     u.ax.wrFlag = 0;
   }
-  if( pOp->p5 ){
+  if( pOp->p5 & OPFLAG_P2ISREG ){
     assert( u.ax.p2>0 );
     assert( u.ax.p2<=p->nMem );
     pIn2 = &aMem[u.ax.p2];
@@ -68348,6 +66678,8 @@ case OP_OpenWrite: {
   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;
+  assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
+  sqlite3BtreeCursorHints(u.ax.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
 
   /* Since it performs no memory allocation or IO, the only value that
   ** sqlite3BtreeCursor() may return is SQLITE_OK. */
@@ -69416,7 +67748,6 @@ case OP_RowData: {
   assert( u.bl.pC!=0 );
   assert( u.bl.pC->nullRow==0 );
   assert( u.bl.pC->pseudoTableReg==0 );
-  assert( !u.bl.pC->isSorter );
   assert( u.bl.pC->pCursor!=0 );
   u.bl.pCrsr = u.bl.pC->pCursor;
   assert( sqlite3BtreeCursorIsValid(u.bl.pCrsr) );
@@ -70092,7 +68423,7 @@ case OP_ParseSchema: {
       db->init.busy = 0;
     }
   }
-  if( rc ) sqlite3ResetInternalSchema(db, -1);
+  if( rc ) sqlite3ResetAllSchemasOfConnection(db);
   if( rc==SQLITE_NOMEM ){
     goto no_mem;
   }
@@ -70759,7 +69090,7 @@ case OP_JournalMode: {    /* out2-prerelease */
   if( !sqlite3PagerOkToChangeJournalMode(u.ci.pPager) ) u.ci.eNew = u.ci.eOld;
 
 #ifndef SQLITE_OMIT_WAL
-  u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager);
+  u.ci.zFilename = sqlite3PagerFilename(u.ci.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
@@ -71425,7 +69756,7 @@ vdbe_error_halt:
   if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
   rc = SQLITE_ERROR;
   if( resetSchemaOnFault>0 ){
-    sqlite3ResetInternalSchema(db, resetSchemaOnFault-1);
+    sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
   }
 
   /* This is the only way out of this procedure.  We have to
@@ -71968,6 +70299,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
 
 typedef struct VdbeSorterIter VdbeSorterIter;
 typedef struct SorterRecord SorterRecord;
+typedef struct FileWriter FileWriter;
 
 /*
 ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
@@ -72065,6 +70397,24 @@ struct VdbeSorterIter {
   sqlite3_file *pFile;            /* File iterator is reading from */
   u8 *aAlloc;                     /* Allocated space */
   u8 *aKey;                       /* Pointer to current key */
+  u8 *aBuffer;                    /* Current read buffer */
+  int nBuffer;                    /* Size of read buffer in bytes */
+};
+
+/*
+** An instance of this structure is used to organize the stream of records
+** being written to files by the merge-sort code into aligned, page-sized
+** blocks.  Doing all I/O in aligned page-sized blocks helps I/O to go
+** faster on many operating systems.
+*/
+struct FileWriter {
+  int eFWErr;                     /* Non-zero if in an error state */
+  u8 *aBuffer;                    /* Pointer to write buffer */
+  int nBuffer;                    /* Size of write buffer in bytes */
+  int iBufStart;                  /* First byte of buffer to write */
+  int iBufEnd;                    /* Last byte of buffer to write */
+  i64 iWriteOff;                  /* Offset of start of buffer in file */
+  sqlite3_file *pFile;            /* File to write to */
 };
 
 /*
@@ -72090,108 +70440,144 @@ struct SorterRecord {
 */
 static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
   sqlite3DbFree(db, pIter->aAlloc);
+  sqlite3DbFree(db, pIter->aBuffer);
   memset(pIter, 0, sizeof(VdbeSorterIter));
 }
 
 /*
-** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
-** no error occurs, or an SQLite error code if one does.
-*/
-static int vdbeSorterIterNext(
-  sqlite3 *db,                    /* Database handle (for sqlite3DbMalloc() ) */
-  VdbeSorterIter *pIter           /* Iterator to advance */
-){
-  int rc;                         /* Return Code */
-  int nRead;                      /* Number of bytes read */
-  int nRec = 0;                   /* Size of record in bytes */
-  int iOff = 0;                   /* Size of serialized size varint in bytes */
-
-  assert( pIter->iEof>=pIter->iReadOff );
-  if( pIter->iEof-pIter->iReadOff>5 ){
-    nRead = 5;
-  }else{
-    nRead = (int)(pIter->iEof - pIter->iReadOff);
-  }
-  if( nRead<=0 ){
-    /* This is an EOF condition */
-    vdbeSorterIterZero(db, pIter);
-    return SQLITE_OK;
+** Read nByte bytes of data from the stream of data iterated by object p.
+** If successful, set *ppOut to point to a buffer containing the data
+** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite
+** error code.
+**
+** The buffer indicated by *ppOut may only be considered valid until the
+** next call to this function.
+*/
+static int vdbeSorterIterRead(
+  sqlite3 *db,                    /* Database handle (for malloc) */
+  VdbeSorterIter *p,              /* Iterator */
+  int nByte,                      /* Bytes of data to read */
+  u8 **ppOut                      /* OUT: Pointer to buffer containing data */
+){
+  int iBuf;                       /* Offset within buffer to read from */
+  int nAvail;                     /* Bytes of data available in buffer */
+  assert( p->aBuffer );
+
+  /* If there is no more data to be read from the buffer, read the next 
+  ** p->nBuffer bytes of data from the file into it. Or, if there are less
+  ** than p->nBuffer bytes remaining in the PMA, read all remaining data.  */
+  iBuf = p->iReadOff % p->nBuffer;
+  if( iBuf==0 ){
+    int nRead;                    /* Bytes to read from disk */
+    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;
+    assert( nRead>0 );
+
+    /* Read data from the file. Return early if an error occurs. */
+    rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff);
+    assert( rc!=SQLITE_IOERR_SHORT_READ );
+    if( rc!=SQLITE_OK ) return rc;
   }
+  nAvail = p->nBuffer - iBuf; 
+
+  if( nByte<=nAvail ){
+    /* The requested data is available in the in-memory buffer. In this
+    ** case there is no need to make a copy of the data, just return a 
+    ** pointer into the buffer to the caller.  */
+    *ppOut = &p->aBuffer[iBuf];
+    p->iReadOff += nByte;
+  }else{
+    /* The requested data is not all available in the in-memory buffer.
+    ** In this case, allocate space at p->aAlloc[] to copy the requested
+    ** range into. Then return a copy of pointer p->aAlloc to the caller.  */
+    int nRem;                     /* Bytes remaining to copy */
+
+    /* Extend the p->aAlloc[] allocation if required. */
+    if( p->nAlloc<nByte ){
+      int nNew = p->nAlloc*2;
+      while( nByte>nNew ) nNew = nNew*2;
+      p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew);
+      if( !p->aAlloc ) return SQLITE_NOMEM;
+      p->nAlloc = nNew;
+    }
+
+    /* Copy as much data as is available in the buffer into the start of
+    ** p->aAlloc[].  */
+    memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail);
+    p->iReadOff += nAvail;
+    nRem = nByte - nAvail;
+
+    /* The following loop copies up to p->nBuffer bytes per iteration into
+    ** the p->aAlloc[] buffer.  */
+    while( nRem>0 ){
+      int rc;                     /* vdbeSorterIterRead() return code */
+      int nCopy;                  /* Number of bytes to copy */
+      u8 *aNext;                  /* Pointer to buffer to copy data from */
 
-  rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
-  if( rc==SQLITE_OK ){
-    iOff = getVarint32(pIter->aAlloc, nRec);
-    if( (iOff+nRec)>nRead ){
-      int nRead2;                   /* Number of extra bytes to read */
-      if( (iOff+nRec)>pIter->nAlloc ){
-        int nNew = pIter->nAlloc*2;
-        while( (iOff+nRec)>nNew ) nNew = nNew*2;
-        pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
-        if( !pIter->aAlloc ) return SQLITE_NOMEM;
-        pIter->nAlloc = nNew;
-      }
-  
-      nRead2 = iOff + nRec - nRead;
-      rc = sqlite3OsRead(
-          pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
-      );
+      nCopy = nRem;
+      if( nRem>p->nBuffer ) nCopy = p->nBuffer;
+      rc = vdbeSorterIterRead(db, p, nCopy, &aNext);
+      if( rc!=SQLITE_OK ) return rc;
+      assert( aNext!=p->aAlloc );
+      memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
+      nRem -= nCopy;
     }
+
+    *ppOut = p->aAlloc;
   }
 
-  assert( rc!=SQLITE_OK || nRec>0 );
-  pIter->iReadOff += iOff+nRec;
-  pIter->nKey = nRec;
-  pIter->aKey = &pIter->aAlloc[iOff];
-  return rc;
+  return SQLITE_OK;
 }
 
 /*
-** Write a single varint, value iVal, to file-descriptor pFile. Return
-** SQLITE_OK if successful, or an SQLite error code if some error occurs.
-**
-** The value of *piOffset when this function is called is used as the byte
-** offset in file pFile to write to. Before returning, *piOffset is 
-** incremented by the number of bytes written.
+** Read a varint from the stream of data accessed by p. Set *pnOut to
+** the value read.
 */
-static int vdbeSorterWriteVarint(
-  sqlite3_file *pFile,            /* File to write to */
-  i64 iVal,                       /* Value to write as a varint */
-  i64 *piOffset                   /* IN/OUT: Write offset in file pFile */
-){
-  u8 aVarint[9];                  /* Buffer large enough for a varint */
-  int nVarint;                    /* Number of used bytes in varint */
-  int rc;                         /* Result of write() call */
+static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){
+  int iBuf;
 
-  nVarint = sqlite3PutVarint(aVarint, iVal);
-  rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
-  *piOffset += nVarint;
+  iBuf = p->iReadOff % p->nBuffer;
+  if( iBuf && (p->nBuffer-iBuf)>=9 ){
+    p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
+  }else{
+    u8 aVarint[16], *a;
+    int i = 0, rc;
+    do{
+      rc = vdbeSorterIterRead(db, p, 1, &a);
+      if( rc ) return rc;
+      aVarint[(i++)&0xf] = a[0];
+    }while( (a[0]&0x80)!=0 );
+    sqlite3GetVarint(aVarint, pnOut);
+  }
 
-  return rc;
+  return SQLITE_OK;
 }
 
+
 /*
-** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
-** successful, or an SQLite error code if some error occurs.
-**
-** The value of *piOffset when this function is called is used as the
-** byte offset in file pFile from whence to read the varint. If successful
-** (i.e. if no IO error occurs), then *piOffset is set to the offset of
-** the first byte past the end of the varint before returning. *piVal is
-** set to the integer value read. If an error occurs, the final values of
-** both *piOffset and *piVal are undefined.
+** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
+** no error occurs, or an SQLite error code if one does.
 */
-static int vdbeSorterReadVarint(
-  sqlite3_file *pFile,            /* File to read from */
-  i64 *piOffset,                  /* IN/OUT: Read offset in pFile */
-  i64 *piVal                      /* OUT: Value read from file */
+static int vdbeSorterIterNext(
+  sqlite3 *db,                    /* Database handle (for sqlite3DbMalloc() ) */
+  VdbeSorterIter *pIter           /* Iterator to advance */
 ){
-  u8 aVarint[9];                  /* Buffer large enough for a varint */
-  i64 iOff = *piOffset;           /* Offset in file to read from */
-  int rc;                         /* Return code */
+  int rc;                         /* Return Code */
+  u64 nRec = 0;                   /* Size of record in bytes */
+
+  if( pIter->iReadOff>=pIter->iEof ){
+    /* This is an EOF condition */
+    vdbeSorterIterZero(db, pIter);
+    return SQLITE_OK;
+  }
 
-  rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
+  rc = vdbeSorterIterVarint(db, pIter, &nRec);
   if( rc==SQLITE_OK ){
-    *piOffset += getVarint(aVarint, (u64 *)piVal);
+    pIter->nKey = (int)nRec;
+    rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey);
   }
 
   return rc;
@@ -72205,27 +70591,52 @@ static int vdbeSorterReadVarint(
 */
 static int vdbeSorterIterInit(
   sqlite3 *db,                    /* Database handle */
-  VdbeSorter *pSorter,            /* Sorter object */
+  const VdbeSorter *pSorter,      /* Sorter object */
   i64 iStart,                     /* Start offset in pFile */
   VdbeSorterIter *pIter,          /* Iterator to populate */
   i64 *pnByte                     /* IN/OUT: Increment this value by PMA size */
 ){
-  int rc;
+  int rc = SQLITE_OK;
+  int nBuf;
+
+  nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
 
   assert( pSorter->iWriteOff>iStart );
   assert( pIter->aAlloc==0 );
+  assert( pIter->aBuffer==0 );
   pIter->pFile = pSorter->pTemp1;
   pIter->iReadOff = iStart;
   pIter->nAlloc = 128;
   pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
-  if( !pIter->aAlloc ){
+  pIter->nBuffer = nBuf;
+  pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
+
+  if( !pIter->aBuffer ){
     rc = SQLITE_NOMEM;
   }else{
-    i64 nByte;                         /* Total size of PMA in bytes */
-    rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
-    *pnByte += nByte;
-    pIter->iEof = pIter->iReadOff + nByte;
+    int iBuf;
+
+    iBuf = iStart % nBuf;
+    if( iBuf ){
+      int nRead = nBuf - iBuf;
+      if( (iStart + nRead) > pSorter->iWriteOff ){
+        nRead = (int)(pSorter->iWriteOff - iStart);
+      }
+      rc = sqlite3OsRead(
+          pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
+      );
+      assert( rc!=SQLITE_IOERR_SHORT_READ );
+    }
+
+    if( rc==SQLITE_OK ){
+      u64 nByte;                       /* Size of PMA in bytes */
+      pIter->iEof = pSorter->iWriteOff;
+      rc = vdbeSorterIterVarint(db, pIter, &nByte);
+      pIter->iEof = pIter->iReadOff + nByte;
+      *pnByte += nByte;
+    }
   }
+
   if( rc==SQLITE_OK ){
     rc = vdbeSorterIterNext(db, pIter);
   }
@@ -72249,10 +70660,10 @@ static int vdbeSorterIterInit(
 ** has been allocated and contains an unpacked record that is used as key2.
 */
 static void vdbeSorterCompare(
-  VdbeCursor *pCsr,               /* Cursor object (for pKeyInfo) */
+  const VdbeCursor *pCsr,         /* Cursor object (for pKeyInfo) */
   int bOmitRowid,                 /* Ignore rowid field at end of keys */
-  void *pKey1, int nKey1,         /* Left side of comparison */
-  void *pKey2, int nKey2,         /* Right side of comparison */
+  const void *pKey1, int nKey1,   /* Left side of comparison */
+  const void *pKey2, int nKey2,   /* Right side of comparison */
   int *pRes                       /* OUT: Result of comparison */
 ){
   KeyInfo *pKeyInfo = pCsr->pKeyInfo;
@@ -72284,7 +70695,7 @@ static void vdbeSorterCompare(
 ** multiple b-tree segments. Parameter iOut is the index of the aTree[] 
 ** value to recalculate.
 */
-static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
+static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){
   VdbeSorter *pSorter = pCsr->pSorter;
   int i1;
   int i2;
@@ -72410,7 +70821,7 @@ static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
 ** Set *ppOut to the head of the new list.
 */
 static void vdbeSorterMerge(
-  VdbeCursor *pCsr,               /* For pKeyInfo */
+  const VdbeCursor *pCsr,         /* For pKeyInfo */
   SorterRecord *p1,               /* First list to merge */
   SorterRecord *p2,               /* Second list to merge */
   SorterRecord **ppOut            /* OUT: Head of merged list */
@@ -72444,7 +70855,7 @@ static void vdbeSorterMerge(
 ** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
 ** occurs.
 */
-static int vdbeSorterSort(VdbeCursor *pCsr){
+static int vdbeSorterSort(const VdbeCursor *pCsr){
   int i;
   SorterRecord **aSlot;
   SorterRecord *p;
@@ -72477,6 +70888,91 @@ static int vdbeSorterSort(VdbeCursor *pCsr){
   return SQLITE_OK;
 }
 
+/*
+** Initialize a file-writer object.
+*/
+static void fileWriterInit(
+  sqlite3 *db,                    /* Database (for malloc) */
+  sqlite3_file *pFile,            /* File to write to */
+  FileWriter *p,                  /* Object to populate */
+  i64 iStart                      /* Offset of pFile to begin writing at */
+){
+  int nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+
+  memset(p, 0, sizeof(FileWriter));
+  p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
+  if( !p->aBuffer ){
+    p->eFWErr = SQLITE_NOMEM;
+  }else{
+    p->iBufEnd = p->iBufStart = (iStart % nBuf);
+    p->iWriteOff = iStart - p->iBufStart;
+    p->nBuffer = nBuf;
+    p->pFile = pFile;
+  }
+}
+
+/*
+** Write nData bytes of data to the file-write object. Return SQLITE_OK
+** if successful, or an SQLite error code if an error occurs.
+*/
+static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){
+  int nRem = nData;
+  while( nRem>0 && p->eFWErr==0 ){
+    int nCopy = nRem;
+    if( nCopy>(p->nBuffer - p->iBufEnd) ){
+      nCopy = p->nBuffer - p->iBufEnd;
+    }
+
+    memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy);
+    p->iBufEnd += nCopy;
+    if( p->iBufEnd==p->nBuffer ){
+      p->eFWErr = sqlite3OsWrite(p->pFile, 
+          &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, 
+          p->iWriteOff + p->iBufStart
+      );
+      p->iBufStart = p->iBufEnd = 0;
+      p->iWriteOff += p->nBuffer;
+    }
+    assert( p->iBufEnd<p->nBuffer );
+
+    nRem -= nCopy;
+  }
+}
+
+/*
+** Flush any buffered data to disk and clean up the file-writer object.
+** The results of using the file-writer after this call are undefined.
+** Return SQLITE_OK if flushing the buffered data succeeds or is not 
+** required. Otherwise, return an SQLite error code.
+**
+** Before returning, set *piEof to the offset immediately following the
+** last byte written to the file.
+*/
+static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){
+  int rc;
+  if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
+    p->eFWErr = sqlite3OsWrite(p->pFile, 
+        &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, 
+        p->iWriteOff + p->iBufStart
+    );
+  }
+  *piEof = (p->iWriteOff + p->iBufEnd);
+  sqlite3DbFree(db, p->aBuffer);
+  rc = p->eFWErr;
+  memset(p, 0, sizeof(FileWriter));
+  return rc;
+}
+
+/*
+** Write value iVal encoded as a varint to the file-write object. Return 
+** SQLITE_OK if successful, or an SQLite error code if an error occurs.
+*/
+static void fileWriterWriteVarint(FileWriter *p, u64 iVal){
+  int nByte; 
+  u8 aByte[10];
+  nByte = sqlite3PutVarint(aByte, iVal);
+  fileWriterWrite(p, aByte, nByte);
+}
 
 /*
 ** Write the current contents of the in-memory linked-list to a PMA. Return
@@ -72491,9 +70987,12 @@ static int vdbeSorterSort(VdbeCursor *pCsr){
 **       Each record consists of a varint followed by a blob of data (the 
 **       key). The varint is the number of bytes in the blob of data.
 */
-static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
+static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){
   int rc = SQLITE_OK;             /* Return code */
   VdbeSorter *pSorter = pCsr->pSorter;
+  FileWriter writer;
+
+  memset(&writer, 0, sizeof(FileWriter));
 
   if( pSorter->nInMemory==0 ){
     assert( pSorter->pRecord==0 );
@@ -72511,39 +71010,20 @@ static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
   }
 
   if( rc==SQLITE_OK ){
-    i64 iOff = pSorter->iWriteOff;
     SorterRecord *p;
     SorterRecord *pNext = 0;
-    static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
+    fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff);
     pSorter->nPMA++;
-    rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
-    for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
+    fileWriterWriteVarint(&writer, pSorter->nInMemory);
+    for(p=pSorter->pRecord; p; p=pNext){
       pNext = p->pNext;
-      rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);
-
-      if( rc==SQLITE_OK ){
-        rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
-        iOff += p->nVal;
-      }
-
+      fileWriterWriteVarint(&writer, p->nVal);
+      fileWriterWrite(&writer, p->pVal, p->nVal);
       sqlite3DbFree(db, p);
     }
-
-    /* This assert verifies that unless an error has occurred, the size of 
-    ** the PMA on disk is the same as the expected size stored in
-    ** pSorter->nInMemory. */ 
-    assert( rc!=SQLITE_OK || pSorter->nInMemory==(
-          iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
-    ));
-
-    pSorter->iWriteOff = iOff;
-    if( rc==SQLITE_OK ){
-      /* Terminate each file with 8 extra bytes so that from any offset
-      ** in the file we can always read 9 bytes without a SHORT_READ error */
-      rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
-    }
     pSorter->pRecord = p;
+    rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff);
   }
 
   return rc;
@@ -72554,7 +71034,7 @@ static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
 */
 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
   sqlite3 *db,                    /* Database handle */
-  VdbeCursor *pCsr,               /* Sorter cursor */
+  const VdbeCursor *pCsr,               /* Sorter cursor */
   Mem *pVal                       /* Memory cell containing record */
 ){
   VdbeSorter *pSorter = pCsr->pSorter;
@@ -72588,8 +71068,14 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
         (pSorter->nInMemory>pSorter->mxPmaSize)
      || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
   )){
+#ifdef SQLITE_DEBUG
+    i64 nExpect = pSorter->iWriteOff
+                + sqlite3VarintLen(pSorter->nInMemory)
+                + pSorter->nInMemory;
+#endif
     rc = vdbeSorterListToPMA(db, pCsr);
     pSorter->nInMemory = 0;
+    assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) );
   }
 
   return rc;
@@ -72600,7 +71086,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
 */
 static int vdbeSorterInitMerge(
   sqlite3 *db,                    /* Database handle */
-  VdbeCursor *pCsr,               /* Cursor handle for this sorter */
+  const VdbeCursor *pCsr,         /* Cursor handle for this sorter */
   i64 *pnByte                     /* Sum of bytes in all opened PMAs */
 ){
   VdbeSorter *pSorter = pCsr->pSorter;
@@ -72630,7 +71116,7 @@ static int vdbeSorterInitMerge(
 ** Once the sorter has been populated, this function is called to prepare
 ** for iterating through its contents in sorted order.
 */
-SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
   VdbeSorter *pSorter = pCsr->pSorter;
   int rc;                         /* Return code */
   sqlite3_file *pTemp2 = 0;       /* Second temp file to use */
@@ -72650,7 +71136,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *p
     return vdbeSorterSort(pCsr);
   }
 
-  /* Write the current b-tree to a PMA. Close the b-tree cursor. */
+  /* Write the current in-memory list to a PMA. */
   rc = vdbeSorterListToPMA(db, pCsr);
   if( rc!=SQLITE_OK ) return rc;
 
@@ -72672,8 +71158,12 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *p
         rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA; 
         iNew++
     ){
+      int rc2;                    /* Return code from fileWriterFinish() */
+      FileWriter writer;          /* Object used to write to disk */
       i64 nWrite;                 /* Number of bytes in new PMA */
 
+      memset(&writer, 0, sizeof(FileWriter));
+
       /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
       ** initialize an iterator for each of them and break out of the loop.
       ** These iterators will be incrementally merged as the VDBE layer calls
@@ -72696,22 +71186,19 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *p
       }
 
       if( rc==SQLITE_OK ){
-        rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
-      }
-
-      if( rc==SQLITE_OK ){
         int bEof = 0;
+        fileWriterInit(db, pTemp2, &writer, iWrite2);
+        fileWriterWriteVarint(&writer, nWrite);
         while( rc==SQLITE_OK && bEof==0 ){
-          int nToWrite;
           VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
           assert( pIter->pFile );
-          nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
-          rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
-          iWrite2 += nToWrite;
-          if( rc==SQLITE_OK ){
-            rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
-          }
+
+          fileWriterWriteVarint(&writer, pIter->nKey);
+          fileWriterWrite(&writer, pIter->aKey, pIter->nKey);
+          rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
         }
+        rc2 = fileWriterFinish(db, &writer, &iWrite2);
+        if( rc==SQLITE_OK ) rc = rc2;
       }
     }
 
@@ -72738,7 +71225,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *p
 /*
 ** Advance to the next element in the sorter.
 */
-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
   VdbeSorter *pSorter = pCsr->pSorter;
   int rc;                         /* Return code */
 
@@ -72768,7 +71255,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbE
 ** current key.
 */
 static void *vdbeSorterRowkey(
-  VdbeSorter *pSorter,            /* Sorter object */
+  const VdbeSorter *pSorter,      /* Sorter object */
   int *pnKey                      /* OUT: Size of current key in bytes */
 ){
   void *pKey;
@@ -72787,7 +71274,7 @@ static void *vdbeSorterRowkey(
 /*
 ** Copy the current sorter key into the memory cell pOut.
 */
-SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
+SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
   VdbeSorter *pSorter = pCsr->pSorter;
   void *pKey; int nKey;           /* Sorter key to copy into pOut */
 
@@ -72813,7 +71300,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
 ** key.
 */
 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
-  VdbeCursor *pCsr,               /* Sorter cursor */
+  const VdbeCursor *pCsr,         /* Sorter cursor */
   Mem *pVal,                      /* Value to compare to current sorter key */
   int *pRes                       /* OUT: Result of comparison */
 ){
@@ -73456,13 +71943,19 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
   int rc;
   if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
   rc = WRC_Continue;
-  while( p  ){
+  pWalker->walkerDepth++;
+  while( p ){
     rc = pWalker->xSelectCallback(pWalker, p);
     if( rc ) break;
-    if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
-    if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
+    if( sqlite3WalkSelectExpr(pWalker, p)
+     || sqlite3WalkSelectFrom(pWalker, p)
+    ){
+      pWalker->walkerDepth--;
+      return WRC_Abort;
+    }
     p = p->pPrior;
   }
+  pWalker->walkerDepth--;
   return rc & WRC_Abort;
 }
 
@@ -73488,6 +71981,29 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
 /* #include <string.h> */
 
 /*
+** Walk the expression tree pExpr and increase the aggregate function
+** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
+** This needs to occur when copying a TK_AGG_FUNCTION node from an
+** outer query into an inner subquery.
+**
+** incrAggFunctionDepth(pExpr,n) is the main routine.  incrAggDepth(..)
+** is a helper function - a callback for the tree walker.
+*/
+static int incrAggDepth(Walker *pWalker, Expr *pExpr){
+  if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i;
+  return WRC_Continue;
+}
+static void incrAggFunctionDepth(Expr *pExpr, int N){
+  if( N>0 ){
+    Walker w;
+    memset(&w, 0, sizeof(w));
+    w.xExprCallback = incrAggDepth;
+    w.u.i = N;
+    sqlite3WalkExpr(&w, pExpr);
+  }
+}
+
+/*
 ** Turn the pExpr expression into an alias for the iCol-th column of the
 ** result set in pEList.
 **
@@ -73513,13 +72029,20 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
 ** The result of random()%5 in the GROUP BY clause is probably different
 ** from the result in the result-set.  We might fix this someday.  Or
 ** then again, we might not...
+**
+** 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
+** of the original expression.  The Expr.op2 field of TK_AGG_FUNCTION
+** structures must be increased by the nSubquery amount.
 */
 static void resolveAlias(
   Parse *pParse,         /* Parsing context */
   ExprList *pEList,      /* A result set */
   int iCol,              /* A column in the result set.  0..pEList->nExpr-1 */
   Expr *pExpr,           /* Transform this into an alias to the result set */
-  const char *zType      /* "GROUP" or "ORDER" or "" */
+  const char *zType,     /* "GROUP" or "ORDER" or "" */
+  int nSubquery          /* Number of subqueries that the label is moving */
 ){
   Expr *pOrig;           /* The iCol-th column of the result set */
   Expr *pDup;            /* Copy of pOrig */
@@ -73532,6 +72055,7 @@ static void resolveAlias(
   db = pParse->db;
   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;
     if( pEList->a[iCol].iAlias==0 ){
@@ -73620,9 +72144,10 @@ static int lookupName(
   NameContext *pNC,    /* The name context used to resolve the name */
   Expr *pExpr          /* Make this EXPR node point to the selected column */
 ){
-  int i, j;            /* Loop counters */
+  int i, j;                         /* Loop counters */
   int cnt = 0;                      /* Number of matching column names */
   int cntTab = 0;                   /* Number of matching table names */
+  int nSubquery = 0;                /* How many levels of subquery */
   sqlite3 *db = pParse->db;         /* The database connection */
   struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
   struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
@@ -73784,7 +72309,7 @@ static int lookupName(
             sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
             return WRC_Abort;
           }
-          resolveAlias(pParse, pEList, j, pExpr, "");
+          resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
           cnt = 1;
           pMatch = 0;
           assert( zTab==0 && zDb==0 );
@@ -73798,6 +72323,7 @@ static int lookupName(
     */
     if( cnt==0 ){
       pNC = pNC->pNext;
+      nSubquery++;
     }
   }
 
@@ -74037,13 +72563,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
              nId, zId);
         pNC->nErr++;
       }
+      if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
+      sqlite3WalkExprList(pWalker, pList);
       if( is_agg ){
+        NameContext *pNC2 = pNC;
         pExpr->op = TK_AGG_FUNCTION;
-        pNC->ncFlags |= NC_HasAgg;
+        pExpr->op2 = 0;
+        while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
+          pExpr->op2++;
+          pNC2 = pNC2->pNext;
+        }
+        if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
+        pNC->ncFlags |= NC_AllowAgg;
       }
-      if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
-      sqlite3WalkExprList(pWalker, pList);
-      if( is_agg ) pNC->ncFlags |= NC_AllowAgg;
       /* FIX ME:  Compute pExpr->affinity based on the expected return
       ** type of the function 
       */
@@ -74322,7 +72854,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
         resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
         return 1;
       }
-      resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType);
+      resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
     }
   }
   return 0;
@@ -76400,7 +74932,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
 
         assert( !isRowid );
         sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
-        dest.affinity = (u8)affinity;
+        dest.affSdst = (u8)affinity;
         assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
         pExpr->x.pSelect->iLimit = 0;
         if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
@@ -76493,11 +75025,11 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
       sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
       if( pExpr->op==TK_SELECT ){
         dest.eDest = SRT_Mem;
-        sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iParm);
+        sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
         VdbeComment((v, "Init subquery result"));
       }else{
         dest.eDest = SRT_Exists;
-        sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm);
+        sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
         VdbeComment((v, "Init EXISTS result"));
       }
       sqlite3ExprDelete(pParse->db, pSel->pLimit);
@@ -76507,7 +75039,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
       if( sqlite3Select(pParse, pSel, &dest) ){
         return 0;
       }
-      rReg = dest.iParm;
+      rReg = dest.iSDParm;
       ExprSetIrreducible(pExpr);
       break;
     }
@@ -77822,9 +76354,12 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
       }else{
         pFarg = pExpr->x.pList;
       }
-      sqlite3ExplainPrintf(pOut, "%sFUNCTION:%s(",
-                           op==TK_AGG_FUNCTION ? "AGG_" : "",
-                           pExpr->u.zToken);
+      if( op==TK_AGG_FUNCTION ){
+        sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(",
+                             pExpr->op2, pExpr->u.zToken);
+      }else{
+        sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken);
+      }
       if( pFarg ){
         sqlite3ExplainExprList(pOut, pFarg);
       }
@@ -78515,38 +77050,60 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
 }
 
 /*
-** This is the expression callback for sqlite3FunctionUsesOtherSrc().
-**
-** Determine if an expression references any table other than one of the
-** tables in pWalker->u.pSrcList and abort if it does.
+** An instance of the following structure is used by the tree walker
+** to count references to table columns in the arguments of an 
+** aggregate function, in order to implement the
+** sqlite3FunctionThisSrc() routine.
+*/
+struct SrcCount {
+  SrcList *pSrc;   /* One particular FROM clause in a nested query */
+  int nThis;       /* Number of references to columns in pSrcList */
+  int nOther;      /* Number of references to columns in other FROM clauses */
+};
+
+/*
+** Count the number of references to columns.
 */
-static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){
-  if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
+static int exprSrcCount(Walker *pWalker, Expr *pExpr){
+  /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
+  ** is always called before sqlite3ExprAnalyzeAggregates() and so the
+  ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN.  If
+  ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
+  ** NEVER() will need to be removed. */
+  if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
     int i;
-    SrcList *pSrc = pWalker->u.pSrcList;
+    struct SrcCount *p = pWalker->u.pSrcCount;
+    SrcList *pSrc = p->pSrc;
     for(i=0; i<pSrc->nSrc; i++){
-      if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue;
+      if( pExpr->iTable==pSrc->a[i].iCursor ) break;
+    }
+    if( i<pSrc->nSrc ){
+      p->nThis++;
+    }else{
+      p->nOther++;
     }
-    return WRC_Abort;
-  }else{
-    return WRC_Continue;
   }
+  return WRC_Continue;
 }
 
 /*
-** Determine if any of the arguments to the pExpr Function references
-** any SrcList other than pSrcList.  Return true if they do.  Return
-** false if pExpr has no argument or has only constant arguments or
-** only references tables named in pSrcList.
+** Determine if any of the arguments to the pExpr Function reference
+** pSrcList.  Return true if they do.  Also return true if the function
+** has no arguments or has only constant arguments.  Return false if pExpr
+** references columns but not columns of tables found in pSrcList.
 */
-static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){
+SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
   Walker w;
+  struct SrcCount cnt;
   assert( pExpr->op==TK_AGG_FUNCTION );
   memset(&w, 0, sizeof(w));
-  w.xExprCallback = exprUsesOtherSrc;
-  w.u.pSrcList = pSrcList;
-  if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1;
-  return 0;
+  w.xExprCallback = exprSrcCount;
+  w.u.pSrcCount = &cnt;
+  cnt.pSrc = pSrcList;
+  cnt.nThis = 0;
+  cnt.nOther = 0;
+  sqlite3WalkExprList(&w, pExpr->x.pList);
+  return cnt.nThis>0 || cnt.nOther==0;
 }
 
 /*
@@ -78665,7 +77222,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
     }
     case TK_AGG_FUNCTION: {
       if( (pNC->ncFlags & NC_InAggFunc)==0
-       && !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList)
+       && pWalker->walkerDepth==pExpr->op2
       ){
         /* Check to see if pExpr is a duplicate of another aggregate 
         ** function that is already in the pAggInfo structure
@@ -79821,7 +78378,7 @@ static void openStatTable(
           "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
       );
       aRoot[i] = pParse->regRoot;
-      aCreateTbl[i] = 1;
+      aCreateTbl[i] = OPFLAG_P2ISREG;
     }else{
       /* The table already exists. If zWhere is not NULL, delete all entries 
       ** associated with the table zWhere. If zWhere is NULL, delete the
@@ -79901,12 +78458,11 @@ static void stat3Init(
   nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
   mxSample = sqlite3_value_int(argv[1]);
   n = sizeof(*p) + sizeof(p->a[0])*mxSample;
-  p = sqlite3_malloc( n );
+  p = sqlite3MallocZero( n );
   if( p==0 ){
     sqlite3_result_error_nomem(context);
     return;
   }
-  memset(p, 0, n);
   p->a = (struct Stat3Sample*)&p[1];
   p->nRow = nRow;
   p->mxSample = mxSample;
@@ -80988,7 +79544,7 @@ static void attachFunc(
       db->aDb[iDb].pBt = 0;
       db->aDb[iDb].pSchema = 0;
     }
-    sqlite3ResetInternalSchema(db, -1);
+    sqlite3ResetAllSchemasOfConnection(db);
     db->nDb = iDb;
     if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
       db->mallocFailed = 1;
@@ -81060,7 +79616,7 @@ static void detachFunc(
   sqlite3BtreeClose(pDb->pBt);
   pDb->pBt = 0;
   pDb->pSchema = 0;
-  sqlite3ResetInternalSchema(db, -1);
+  sqlite3ResetAllSchemasOfConnection(db);
   return;
 
 detach_error:
@@ -81976,58 +80532,15 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char
 }
 
 /*
-** Erase all schema information from the in-memory hash tables of
-** a single database.  This routine is called to reclaim memory
-** before the database closes.  It is also called during a rollback
-** if there were schema changes during the transaction or if a
-** schema-cookie mismatch occurs.
+** Look through the list of open database files in db->aDb[] and if
+** any have been closed, remove them from the list.  Reallocate the
+** db->aDb[] structure to a smaller size, if possible.
 **
-** If iDb<0 then reset the internal schema tables for all database
-** files.  If iDb>=0 then reset the internal schema for only the
-** single file indicated.
+** Entry 0 (the "main" database) and entry 1 (the "temp" database)
+** are never candidates for being collapsed.
 */
-SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
+SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){
   int i, j;
-  assert( iDb<db->nDb );
-
-  if( iDb>=0 ){
-    /* Case 1:  Reset the single schema identified by iDb */
-    Db *pDb = &db->aDb[iDb];
-    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
-    assert( pDb->pSchema!=0 );
-    sqlite3SchemaClear(pDb->pSchema);
-
-    /* If any database other than TEMP is reset, then also reset TEMP
-    ** since TEMP might be holding triggers that reference tables in the
-    ** other database.
-    */
-    if( iDb!=1 ){
-      pDb = &db->aDb[1];
-      assert( pDb->pSchema!=0 );
-      sqlite3SchemaClear(pDb->pSchema);
-    }
-    return;
-  }
-  /* Case 2 (from here to the end): Reset all schemas for all attached
-  ** databases. */
-  assert( iDb<0 );
-  sqlite3BtreeEnterAll(db);
-  for(i=0; i<db->nDb; i++){
-    Db *pDb = &db->aDb[i];
-    if( pDb->pSchema ){
-      sqlite3SchemaClear(pDb->pSchema);
-    }
-  }
-  db->flags &= ~SQLITE_InternChanges;
-  sqlite3VtabUnlockList(db);
-  sqlite3BtreeLeaveAll(db);
-
-  /* If one or more of the auxiliary database files has been closed,
-  ** then remove them from the auxiliary database list.  We take the
-  ** opportunity to do this here since we have just deleted all of the
-  ** schema hash tables and therefore do not have to make any changes
-  ** to any of those tables.
-  */
   for(i=j=2; i<db->nDb; i++){
     struct Db *pDb = &db->aDb[i];
     if( pDb->pBt==0 ){
@@ -82050,6 +80563,51 @@ SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
 }
 
 /*
+** Reset the schema for the database at index iDb.  Also reset the
+** TEMP schema.
+*/
+SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
+  Db *pDb;
+  assert( iDb<db->nDb );
+
+  /* Case 1:  Reset the single schema identified by iDb */
+  pDb = &db->aDb[iDb];
+  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+  assert( pDb->pSchema!=0 );
+  sqlite3SchemaClear(pDb->pSchema);
+
+  /* If any database other than TEMP is reset, then also reset TEMP
+  ** since TEMP might be holding triggers that reference tables in the
+  ** other database.
+  */
+  if( iDb!=1 ){
+    pDb = &db->aDb[1];
+    assert( pDb->pSchema!=0 );
+    sqlite3SchemaClear(pDb->pSchema);
+  }
+  return;
+}
+
+/*
+** Erase all schema information from all attached databases (including
+** "main" and "temp") for a single database connection.
+*/
+SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
+  int i;
+  sqlite3BtreeEnterAll(db);
+  for(i=0; i<db->nDb; i++){
+    Db *pDb = &db->aDb[i];
+    if( pDb->pSchema ){
+      sqlite3SchemaClear(pDb->pSchema);
+    }
+  }
+  db->flags &= ~SQLITE_InternChanges;
+  sqlite3VtabUnlockList(db);
+  sqlite3BtreeLeaveAll(db);
+  sqlite3CollapseDatabaseArray(db);
+}
+
+/*
 ** This routine is called when a commit occurs.
 */
 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
@@ -82114,7 +80672,7 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
     if( !db || db->pnBytesFreed==0 ){
       char *zName = pIndex->zName; 
       TESTONLY ( Index *pOld = ) sqlite3HashInsert(
-	  &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
+         &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
       );
       assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
       assert( pOld==pIndex || pOld==0 );
@@ -83161,7 +81719,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
 
       assert(pParse->nTab==1);
       sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
-      sqlite3VdbeChangeP5(v, 1);
+      sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
       pParse->nTab = 2;
       sqlite3SelectDestInit(&dest, SRT_Table, 1);
       sqlite3Select(pParse, pSelect, &dest);
@@ -83977,9 +82535,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   pKey = sqlite3IndexKeyinfo(pParse, pIndex);
   sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                     (char *)pKey, P4_KEYINFO_HANDOFF);
-  if( memRootPage>=0 ){
-    sqlite3VdbeChangeP5(v, 1);
-  }
+  sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
 
 #ifndef SQLITE_OMIT_MERGE_SORT
   /* Open the sorter cursor if we are to use one. */
@@ -84118,7 +82674,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     assert( pName && pName->z );
 
 #ifndef SQLITE_OMIT_TEMPDB
-    /* If the index name was unqualified, check if the the table
+    /* If the index name was unqualified, check if the table
     ** is a temp table. If so, set the database to 1. Do not do this
     ** if initialising a database schema.
     */
@@ -84345,7 +82901,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     }else{
       zColl = pTab->aCol[j].zColl;
       if( !zColl ){
-        zColl = db->pDfltColl->zName;
+        zColl = "BINARY";
       }
     }
     if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
@@ -86272,7 +84828,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
     */
     sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
     pWInfo = sqlite3WhereBegin(
-        pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
+        pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
     );
     if( pWInfo==0 ) goto delete_from_cleanup;
     regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
@@ -87416,8 +85972,19 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   assert( argc==1 );
   UNUSED_PARAMETER(argc);
   switch( sqlite3_value_type(argv[0]) ){
-    case SQLITE_INTEGER:
     case SQLITE_FLOAT: {
+      double r1, r2;
+      char zBuf[50];
+      r1 = sqlite3_value_double(argv[0]);
+      sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
+      sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
+      if( r1!=r2 ){
+        sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
+      }
+      sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+      break;
+    }
+    case SQLITE_INTEGER: {
       sqlite3_result_value(context, argv[0]);
       break;
     }
@@ -88729,7 +87296,7 @@ static void fkScanChildren(
   ** clause. If the constraint is not deferred, throw an exception for
   ** each row found. Otherwise, for deferred constraints, increment the
   ** deferred constraint counter by nIncr for each row selected.  */
-  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
+  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
   if( nIncr>0 && pFKey->isDeferred==0 ){
     sqlite3ParseToplevel(pParse)->mayAbort = 1;
   }
@@ -89987,7 +88554,7 @@ SQLITE_PRIVATE void sqlite3Insert(
     VdbeComment((v, "SELECT eof flag"));
     sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);
     addrSelect = sqlite3VdbeCurrentAddr(v)+2;
-    sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iParm);
+    sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iSDParm);
     j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
     VdbeComment((v, "Jump over SELECT coroutine"));
 
@@ -89998,15 +88565,15 @@ SQLITE_PRIVATE void sqlite3Insert(
       goto insert_cleanup;
     }
     sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);         /* EOF <- 1 */
-    sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);   /* yield X */
+    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: */
 
-    regFromSelect = dest.iMem;
+    regFromSelect = dest.iSdst;
     assert( pSelect->pEList );
     nColumn = pSelect->pEList->nExpr;
-    assert( dest.nMem==nColumn );
+    assert( dest.nSdst==nColumn );
 
     /* Set useTempTable to TRUE if the result of the SELECT statement
     ** should be written into a temporary table (template 4).  Set to
@@ -90042,7 +88609,7 @@ SQLITE_PRIVATE void sqlite3Insert(
       regRec = sqlite3GetTempReg(pParse);
       regTempRowid = sqlite3GetTempReg(pParse);
       sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
-      addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);
+      addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
       addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
       sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
       sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
@@ -90179,7 +88746,7 @@ SQLITE_PRIVATE void sqlite3Insert(
     **         goto C
     **      D: ...
     */
-    addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);
+    addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
     addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
   }
 
@@ -90661,7 +89228,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Replace: {
         /* If there are DELETE triggers on this table and the
         ** recursive-triggers flag is set, call GenerateRowDelete() to
-        ** remove the conflicting row from the the table. This will fire
+        ** remove the conflicting row from the table. This will fire
         ** the triggers and remove both the table and index b-tree entries.
         **
         ** Otherwise, if there are no triggers or the recursive-triggers
@@ -92620,7 +91187,7 @@ static int invalidateTempStorage(Parse *pParse){
     }
     sqlite3BtreeClose(db->aDb[1].pBt);
     db->aDb[1].pBt = 0;
-    sqlite3ResetInternalSchema(db, -1);
+    sqlite3ResetAllSchemasOfConnection(db);
   }
   return SQLITE_OK;
 }
@@ -93306,6 +91873,50 @@ SQLITE_PRIVATE void sqlite3Pragma(
     }
   }else
 
+#if SQLITE_OS_WIN
+  /*
+  **   PRAGMA data_store_directory
+  **   PRAGMA data_store_directory = ""|"directory_name"
+  **
+  ** Return or set the local value of the data_store_directory flag.  Changing
+  ** the value sets a specific directory to be used for database files that
+  ** were specified with a relative pathname.  Setting to a null string reverts
+  ** to the default database directory, which for database files specified with
+  ** a relative path will probably be based on the current directory for the
+  ** process.  Database file specified with an absolute path are not impacted
+  ** by this setting, regardless of its value.
+  **
+  */
+  if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){
+    if( !zRight ){
+      if( sqlite3_data_directory ){
+        sqlite3VdbeSetNumCols(v, 1);
+        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, 
+            "data_store_directory", SQLITE_STATIC);
+        sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+      }
+    }else{
+#ifndef SQLITE_OMIT_WSD
+      if( zRight[0] ){
+        int res;
+        rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
+        if( rc!=SQLITE_OK || res==0 ){
+          sqlite3ErrorMsg(pParse, "not a writable directory");
+          goto pragma_out;
+        }
+      }
+      sqlite3_free(sqlite3_data_directory);
+      if( zRight[0] ){
+        sqlite3_data_directory = sqlite3_mprintf("%s", zRight);
+      }else{
+        sqlite3_data_directory = 0;
+      }
+#endif /* SQLITE_OMIT_WSD */
+    }
+  }else
+#endif
+
 #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
 #  if defined(__APPLE__)
 #    define SQLITE_ENABLE_LOCKING_STYLE 1
@@ -93672,6 +92283,19 @@ SQLITE_PRIVATE void sqlite3Pragma(
 
     int isQuick = (sqlite3Tolower(zLeft[0])=='q');
 
+    /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
+    ** then iDb is set to the index of the database identified by <db>.
+    ** In this case, the integrity of database iDb only is verified by
+    ** the VDBE created below.
+    **
+    ** Otherwise, if the command was simply "PRAGMA integrity_check" (or
+    ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb
+    ** to -1 here, to indicate that the VDBE should verify the integrity
+    ** of all attached databases.  */
+    assert( iDb>=0 );
+    assert( iDb==0 || pId2->z );
+    if( pId2->z==0 ) iDb = -1;
+
     /* Initialize the VDBE program */
     if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pParse->nMem = 6;
@@ -93695,6 +92319,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
       int cnt = 0;
 
       if( OMIT_TEMPDB && i==1 ) continue;
+      if( iDb>=0 && i!=iDb ) continue;
 
       sqlite3CodeVerifySchema(pParse, i);
       addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
@@ -93706,7 +92331,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
       ** Begin by filling registers 2, 3, ... with the root pages numbers
       ** for all tables and indices in the database.
       */
-      assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+      assert( sqlite3SchemaMutexHeld(db, i, 0) );
       pTbls = &db->aDb[i].pSchema->tblHash;
       for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
         Table *pTab = sqliteHashData(x);
@@ -94392,7 +93017,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
       encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
       if( encoding==0 ) encoding = SQLITE_UTF8;
       ENC(db) = encoding;
-      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
     }else{
       /* If opening an attached database, the encoding much match ENC(db) */
       if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
@@ -94472,7 +93096,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   }
   if( db->mallocFailed ){
     rc = SQLITE_NOMEM;
-    sqlite3ResetInternalSchema(db, -1);
+    sqlite3ResetAllSchemasOfConnection(db);
   }
   if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
     /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
@@ -94525,7 +93149,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
     if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
     rc = sqlite3InitOne(db, i, pzErrMsg);
     if( rc ){
-      sqlite3ResetInternalSchema(db, i);
+      sqlite3ResetOneSchema(db, i);
     }
   }
 
@@ -94538,7 +93162,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
                     && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
     rc = sqlite3InitOne(db, 1, pzErrMsg);
     if( rc ){
-      sqlite3ResetInternalSchema(db, 1);
+      sqlite3ResetOneSchema(db, 1);
     }
   }
 #endif
@@ -94606,7 +93230,7 @@ static void schemaIsValid(Parse *pParse){
     sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
     if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
-      sqlite3ResetInternalSchema(db, iDb);
+      sqlite3ResetOneSchema(db, iDb);
       pParse->rc = SQLITE_SCHEMA;
     }
 
@@ -95031,10 +93655,10 @@ static void clearSelect(sqlite3 *db, Select *p){
 */
 SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
   pDest->eDest = (u8)eDest;
-  pDest->iParm = iParm;
-  pDest->affinity = 0;
-  pDest->iMem = 0;
-  pDest->nMem = 0;
+  pDest->iSDParm = iParm;
+  pDest->affSdst = 0;
+  pDest->iSdst = 0;
+  pDest->nSdst = 0;
 }
 
 
@@ -95546,7 +94170,7 @@ static void selectInnerLoop(
   int hasDistinct;        /* True if the DISTINCT keyword is present */
   int regResult;              /* Start of memory holding result set */
   int eDest = pDest->eDest;   /* How to dispose of results */
-  int iParm = pDest->iParm;   /* First argument to disposal method */
+  int iParm = pDest->iSDParm; /* First argument to disposal method */
   int nResultCol;             /* Number of result columns */
 
   assert( v );
@@ -95564,14 +94188,14 @@ static void selectInnerLoop(
   }else{
     nResultCol = pEList->nExpr;
   }
-  if( pDest->iMem==0 ){
-    pDest->iMem = pParse->nMem+1;
-    pDest->nMem = nResultCol;
+  if( pDest->iSdst==0 ){
+    pDest->iSdst = pParse->nMem+1;
+    pDest->nSdst = nResultCol;
     pParse->nMem += nResultCol;
   }else{ 
-    assert( pDest->nMem==nResultCol );
+    assert( pDest->nSdst==nResultCol );
   }
-  regResult = pDest->iMem;
+  regResult = pDest->iSdst;
   if( nColumn>0 ){
     for(i=0; i<nColumn; i++){
       sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
@@ -95650,7 +94274,7 @@ static void selectInnerLoop(
     */
     case SRT_Set: {
       assert( nColumn==1 );
-      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
+      p->affinity = 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
@@ -95705,7 +94329,7 @@ static void selectInnerLoop(
         pushOntoSorter(pParse, pOrderBy, p, r1);
         sqlite3ReleaseTempReg(pParse, r1);
       }else if( eDest==SRT_Coroutine ){
-        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
+        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
       }else{
         sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
         sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
@@ -95885,7 +94509,7 @@ static void generateSortTail(
   ExprList *pOrderBy = p->pOrderBy;
 
   int eDest = pDest->eDest;
-  int iParm = pDest->iParm;
+  int iParm = pDest->iSDParm;
 
   int regRow;
   int regRowid;
@@ -95944,17 +94568,17 @@ static void generateSortTail(
       testcase( eDest==SRT_Output );
       testcase( eDest==SRT_Coroutine );
       for(i=0; i<nColumn; i++){
-        assert( regRow!=pDest->iMem+i );
-        sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
+        assert( regRow!=pDest->iSdst+i );
+        sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i);
         if( i==0 ){
           sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
         }
       }
       if( eDest==SRT_Output ){
-        sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
-        sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
+        sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
       }else{
-        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
+        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
       }
       break;
     }
@@ -96605,7 +95229,7 @@ static int multiSelect(
   */
   if( dest.eDest==SRT_EphemTab ){
     assert( p->pEList );
-    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
+    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
     sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
     dest.eDest = SRT_Table;
   }
@@ -96691,7 +95315,7 @@ static int multiSelect(
                                      ** of a 3-way or more compound */
         assert( p->pLimit==0 );      /* Not allowed on leftward elements */
         assert( p->pOffset==0 );     /* Not allowed on leftward elements */
-        unionTab = dest.iParm;
+        unionTab = dest.iSDParm;
       }else{
         /* We will need to create our own temporary table to hold the
         ** intermediate results.
@@ -96748,7 +95372,7 @@ static int multiSelect(
       /* Convert the data in the temporary table into whatever form
       ** it is that we currently need.
       */
-      assert( unionTab==dest.iParm || dest.eDest!=priorOp );
+      assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
       if( dest.eDest!=priorOp ){
         int iCont, iBreak, iStart;
         assert( p->pEList );
@@ -96812,7 +95436,7 @@ static int multiSelect(
       p->pLimit = 0;
       pOffset = p->pOffset;
       p->pOffset = 0;
-      intersectdest.iParm = tab2;
+      intersectdest.iSDParm = tab2;
       explainSetInteger(iSub2, pParse->iNextSelectId);
       rc = sqlite3Select(pParse, p, &intersectdest);
       testcase( rc!=SQLITE_OK );
@@ -96906,8 +95530,8 @@ static int multiSelect(
   }
 
 multi_select_end:
-  pDest->iMem = dest.iMem;
-  pDest->nMem = dest.nMem;
+  pDest->iSdst = dest.iSdst;
+  pDest->nSdst = dest.nSdst;
   sqlite3SelectDelete(db, pDelete);
   return rc;
 }
@@ -96917,8 +95541,8 @@ multi_select_end:
 ** Code an output subroutine for a coroutine implementation of a
 ** SELECT statment.
 **
-** The data to be output is contained in pIn->iMem.  There are
-** pIn->nMem columns to be output.  pDest is where the output should
+** The data to be output is contained in pIn->iSdst.  There are
+** pIn->nSdst columns to be output.  pDest is where the output should
 ** be sent.
 **
 ** regReturn is the number of the register holding the subroutine
@@ -96956,16 +95580,16 @@ static int generateOutputSubroutine(
   if( regPrev ){
     int j1, j2;
     j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
-    j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem,
+    j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
                               (char*)pKeyInfo, p4type);
     sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
     sqlite3VdbeJumpHere(v, j1);
-    sqlite3ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem);
+    sqlite3ExprCodeCopy(pParse, pIn->iSdst, regPrev+1, pIn->nSdst);
     sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
   }
   if( pParse->db->mallocFailed ) return 0;
 
-  /* Suppress the the first OFFSET entries if there is an OFFSET clause
+  /* Suppress the first OFFSET entries if there is an OFFSET clause
   */
   codeOffset(v, p, iContinue);
 
@@ -96978,9 +95602,9 @@ static int generateOutputSubroutine(
       int r2 = sqlite3GetTempReg(pParse);
       testcase( pDest->eDest==SRT_Table );
       testcase( pDest->eDest==SRT_EphemTab );
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1);
-      sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2);
-      sqlite3VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
+      sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
+      sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
       sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
       sqlite3ReleaseTempReg(pParse, r2);
       sqlite3ReleaseTempReg(pParse, r1);
@@ -96994,13 +95618,13 @@ static int generateOutputSubroutine(
     */
     case SRT_Set: {
       int r1;
-      assert( pIn->nMem==1 );
+      assert( pIn->nSdst==1 );
       p->affinity = 
-         sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);
+         sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
       r1 = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1);
-      sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, 1);
-      sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iParm, r1);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &p->affinity, 1);
+      sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
+      sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
       sqlite3ReleaseTempReg(pParse, r1);
       break;
     }
@@ -97009,7 +95633,7 @@ static int generateOutputSubroutine(
     /* If any row exist in the result set, record that fact and abort.
     */
     case SRT_Exists: {
-      sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iParm);
+      sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
       /* The LIMIT clause will terminate the loop for us */
       break;
     }
@@ -97020,23 +95644,23 @@ static int generateOutputSubroutine(
     ** of the scan loop.
     */
     case SRT_Mem: {
-      assert( pIn->nMem==1 );
-      sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iParm, 1);
+      assert( pIn->nSdst==1 );
+      sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
       /* The LIMIT clause will jump out of the loop for us */
       break;
     }
 #endif /* #ifndef SQLITE_OMIT_SUBQUERY */
 
     /* The results are stored in a sequence of registers
-    ** starting at pDest->iMem.  Then the co-routine yields.
+    ** starting at pDest->iSdst.  Then the co-routine yields.
     */
     case SRT_Coroutine: {
-      if( pDest->iMem==0 ){
-        pDest->iMem = sqlite3GetTempRange(pParse, pIn->nMem);
-        pDest->nMem = pIn->nMem;
+      if( pDest->iSdst==0 ){
+        pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
+        pDest->nSdst = pIn->nSdst;
       }
-      sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem);
-      sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
+      sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst);
+      sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
       break;
     }
 
@@ -97050,8 +95674,8 @@ static int generateOutputSubroutine(
     */
     default: {
       assert( pDest->eDest==SRT_Output );
-      sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
-      sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
+      sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
+      sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
       break;
     }
   }
@@ -97470,7 +96094,7 @@ static int multiSelectOrderBy(
   */
   sqlite3VdbeResolveLabel(v, labelCmpr);
   sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
-  sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
+  sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
                          (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
   sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
 
@@ -97684,6 +96308,12 @@ static void substSelect(
 **        operators have an implied DISTINCT which is disallowed by
 **        restriction (4).
 **
+**        Also, each component of the sub-query must return the same number
+**        of result columns. This is actually a requirement for any compound
+**        SELECT statement, but all the code here does is make sure that no
+**        such (illegal) sub-query is flattened. The caller will detect the
+**        syntax error and return a detailed message.
+**
 **  (18)  If the sub-query is a compound select, then all terms of the
 **        ORDER by clause of the parent must be simple references to 
 **        columns of the sub-query.
@@ -97827,6 +96457,7 @@ static int flattenSubquery(
       if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
        || (pSub1->pPrior && pSub1->op!=TK_ALL) 
        || pSub1->pSrc->nSrc<1
+       || pSub->pEList->nExpr!=pSub1->pEList->nExpr
       ){
         return 0;
       }
@@ -98144,7 +96775,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
 
   if( IsVirtual(pTab) ) return 0;
   if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
-  if( pAggInfo->nFunc==0 ) return 0;
+  if( NEVER(pAggInfo->nFunc==0) ) return 0;
   if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
   if( pExpr->flags&EP_Distinct ) return 0;
 
@@ -98516,7 +97147,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
 
 
 /*
-** This routine sets of a SELECT statement for processing.  The
+** This routine sets up a SELECT statement for processing.  The
 ** following is accomplished:
 **
 **     *  VDBE Cursor numbers are assigned to all FROM-clause terms.
@@ -98548,7 +97179,8 @@ SQLITE_PRIVATE void sqlite3SelectPrep(
 **
 ** The aggregate accumulator is a set of memory cells that hold
 ** intermediate results while calculating an aggregate.  This
-** routine simply stores NULLs in all of those memory cells.
+** routine generates code that stores NULLs in all of those memory
+** cells.
 */
 static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
   Vdbe *v = pParse->pVdbe;
@@ -98716,23 +97348,24 @@ static void explainSimpleCount(
 **
 **     SRT_Mem         Only valid if the result is a single column.
 **                     Store the first column of the first result row
-**                     in register pDest->iParm then abandon the rest
+**                     in register pDest->iSDParm then abandon the rest
 **                     of the query.  This destination implies "LIMIT 1".
 **
 **     SRT_Set         The result must be a single column.  Store each
-**                     row of result as the key in table pDest->iParm. 
-**                     Apply the affinity pDest->affinity before storing
+**                     row of result as the key in table pDest->iSDParm. 
+**                     Apply the affinity pDest->affSdst before storing
 **                     results.  Used to implement "IN (SELECT ...)".
 **
-**     SRT_Union       Store results as a key in a temporary table pDest->iParm.
+**     SRT_Union       Store results as a key in a temporary table 
+**                     identified by pDest->iSDParm.
 **
-**     SRT_Except      Remove results from the temporary table pDest->iParm.
+**     SRT_Except      Remove results from the temporary table pDest->iSDParm.
 **
-**     SRT_Table       Store results in temporary table pDest->iParm.
+**     SRT_Table       Store results in temporary table pDest->iSDParm.
 **                     This is like SRT_EphemTab except that the table
 **                     is assumed to already be open.
 **
-**     SRT_EphemTab    Create an temporary table pDest->iParm and store
+**     SRT_EphemTab    Create an temporary table pDest->iSDParm and store
 **                     the result there. The cursor is left open after
 **                     returning.  This is like SRT_Table except that
 **                     this destination uses OP_OpenEphemeral to create
@@ -98740,9 +97373,9 @@ static void explainSimpleCount(
 **
 **     SRT_Coroutine   Generate a co-routine that returns a new row of
 **                     results each time it is invoked.  The entry point
-**                     of the co-routine is stored in register pDest->iParm.
+**                     of the co-routine is stored in register pDest->iSDParm.
 **
-**     SRT_Exists      Store a 1 in memory cell pDest->iParm if the result
+**     SRT_Exists      Store a 1 in memory cell pDest->iSDParm if the result
 **                     set is not empty.
 **
 **     SRT_Discard     Throw the results away.  This is used by SELECT
@@ -98986,7 +97619,7 @@ SQLITE_PRIVATE int sqlite3Select(
   /* If the output is destined for a temporary table, open that table.
   */
   if( pDest->eDest==SRT_EphemTab ){
-    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr);
+    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
   }
 
   /* Set the limiter.
@@ -99017,7 +97650,7 @@ SQLITE_PRIVATE int sqlite3Select(
     ExprList *pDist = (isDistinct ? p->pEList : 0);
 
     /* Begin the database scan. */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 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;
 
@@ -99190,7 +97823,7 @@ 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);
+      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0);
       if( pWInfo==0 ) goto select_end;
       if( pGroupBy==0 ){
         /* The optimizer is able to deliver rows in group by order so
@@ -99459,7 +98092,7 @@ SQLITE_PRIVATE int sqlite3Select(
         ** of output.
         */
         resetAccumulator(pParse, &sAggInfo);
-        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
+        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0);
         if( pWInfo==0 ){
           sqlite3ExprListDelete(db, pDel);
           goto select_end;
@@ -99931,7 +98564,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
     iDb = 1;
     pName = pName1;
   }else{
-    /* Figure out the db that the the trigger will be created in */
+    /* Figure out the db that the trigger will be created in */
     iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
     if( iDb<0 ){
       goto trigger_cleanup;
@@ -101259,7 +99892,7 @@ SQLITE_PRIVATE void sqlite3Update(
   */
   sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
   pWInfo = sqlite3WhereBegin(
-      pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
+      pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
   );
   if( pWInfo==0 ) goto update_cleanup;
   okOnePass = pWInfo->okOnePass;
@@ -101959,7 +100592,7 @@ end_of_vacuum:
 
   /* This both clears the schemas and reduces the size of the db->aDb[]
   ** array. */ 
-  sqlite3ResetInternalSchema(db, -1);
+  sqlite3ResetAllSchemasOfConnection(db);
 
   return rc;
 }
@@ -101991,8 +100624,8 @@ end_of_vacuum:
 ** are invoked only from within xCreate and xConnect methods.
 */
 struct VtabCtx {
-  Table *pTab;
-  VTable *pVTable;
+  VTable *pVTable;    /* The virtual table being constructed */
+  Table *pTab;        /* The Table object to which the virtual table belongs */
 };
 
 /*
@@ -102007,33 +100640,35 @@ static int createModule(
   void *pAux,                     /* Context pointer for xCreate/xConnect */
   void (*xDestroy)(void *)        /* Module destructor function */
 ){
-  int rc, nName;
-  Module *pMod;
+  int rc = SQLITE_OK;
+  int nName;
 
   sqlite3_mutex_enter(db->mutex);
   nName = sqlite3Strlen30(zName);
-  pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
-  if( pMod ){
-    Module *pDel;
-    char *zCopy = (char *)(&pMod[1]);
-    memcpy(zCopy, zName, nName+1);
-    pMod->zName = zCopy;
-    pMod->pModule = pModule;
-    pMod->pAux = pAux;
-    pMod->xDestroy = xDestroy;
-    pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
-    if( pDel && pDel->xDestroy ){
-      sqlite3ResetInternalSchema(db, -1);
-      pDel->xDestroy(pDel->pAux);
-    }
-    sqlite3DbFree(db, pDel);
-    if( pDel==pMod ){
-      db->mallocFailed = 1;
+  if( sqlite3HashFind(&db->aModule, zName, nName) ){
+    rc = SQLITE_MISUSE_BKPT;
+  }else{
+    Module *pMod;
+    pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
+    if( pMod ){
+      Module *pDel;
+      char *zCopy = (char *)(&pMod[1]);
+      memcpy(zCopy, zName, nName+1);
+      pMod->zName = zCopy;
+      pMod->pModule = pModule;
+      pMod->pAux = pAux;
+      pMod->xDestroy = xDestroy;
+      pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod);
+      assert( pDel==0 || pDel==pMod );
+      if( pDel ){
+        db->mallocFailed = 1;
+        sqlite3DbFree(db, pDel);
+      }
     }
-  }else if( xDestroy ){
-    xDestroy(pAux);
   }
-  rc = sqlite3ApiExit(db, SQLITE_OK);
+  rc = sqlite3ApiExit(db, rc);
+  if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
+
   sqlite3_mutex_leave(db->mutex);
   return rc;
 }
@@ -102098,7 +100733,7 @@ SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){
 
   assert( db );
   assert( pVTab->nRef>0 );
-  assert( sqlite3SafetyCheckOk(db) );
+  assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE );
 
   pVTab->nRef--;
   if( pVTab->nRef==0 ){
@@ -102149,6 +100784,31 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
   return pRet;
 }
 
+/*
+** Table *p is a virtual table. This function removes the VTable object
+** for table *p associated with database connection db from the linked
+** list in p->pVTab. It also decrements the VTable ref count. This is
+** used when closing database connection db to free all of its VTable
+** objects without disturbing the rest of the Schema object (which may
+** be being used by other shared-cache connections).
+*/
+SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
+  VTable **ppVTab;
+
+  assert( IsVirtual(p) );
+  assert( sqlite3BtreeHoldsAllMutexes(db) );
+  assert( sqlite3_mutex_held(db->mutex) );
+
+  for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
+    if( (*ppVTab)->db==db  ){
+      VTable *pVTab = *ppVTab;
+      *ppVTab = pVTab->pNext;
+      sqlite3VtabUnlock(pVTab);
+      break;
+    }
+  }
+}
+
 
 /*
 ** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
@@ -106661,7 +105321,7 @@ static int codeAllEqualityTerms(
     int r1;
     int k = pIdx->aiColumn[j];
     pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
-    if( NEVER(pTerm==0) ) break;
+    if( pTerm==0 ) break;
     /* The following true for indices with redundant columns. 
     ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
     testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
@@ -107336,6 +105996,8 @@ static Bitmask codeOneLoopStart(
     */
     WhereClause *pOrWc;    /* The OR-clause broken out into subterms */
     SrcList *pOrTab;       /* Shortened table list or OR-clause generation */
+    Index *pCov = 0;             /* Potential covering index (or NULL) */
+    int iCovCur = pParse->nTab++;  /* Cursor used for index scans (if any) */
 
     int regReturn = ++pParse->nMem;           /* Register used with OP_Gosub */
     int regRowset = 0;                        /* Register for RowSet object */
@@ -107354,7 +106016,7 @@ static Bitmask codeOneLoopStart(
     pLevel->op = OP_Return;
     pLevel->p1 = regReturn;
 
-    /* Set up a new SrcList ni pOrTab containing the table being scanned
+    /* Set up a new SrcList in pOrTab containing the table being scanned
     ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
     ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
     */
@@ -107431,8 +106093,10 @@ static Bitmask codeOneLoopStart(
         /* Loop through table entries that match term pOrTerm. */
         pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
                         WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
-                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
+                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
+        assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
         if( pSubWInfo ){
+          WhereLevel *pLvl;
           explainOneScan(
               pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
           );
@@ -107453,11 +106117,36 @@ static Bitmask codeOneLoopStart(
           */
           if( pSubWInfo->untestedTerms ) untestedTerms = 1;
 
+          /* If all of the OR-connected terms are optimized using the same
+          ** index, and the index is opened using the same cursor number
+          ** by each call to sqlite3WhereBegin() made by this loop, it may
+          ** be possible to use that index as a covering index.
+          **
+          ** If the call to sqlite3WhereBegin() above resulted in a scan that
+          ** uses an index, and this is either the first OR-connected term
+          ** processed or the index is the same as that used by all previous
+          ** terms, set pCov to the candidate covering index. Otherwise, set 
+          ** pCov to NULL to indicate that no candidate covering index will 
+          ** be available.
+          */
+          pLvl = &pSubWInfo->a[0];
+          if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
+           && (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
+           && (ii==0 || pLvl->plan.u.pIdx==pCov)
+          ){
+            assert( pLvl->iIdxCur==iCovCur );
+            pCov = pLvl->plan.u.pIdx;
+          }else{
+            pCov = 0;
+          }
+
           /* Finish the loop through table entries that match term pOrTerm. */
           sqlite3WhereEnd(pSubWInfo);
         }
       }
     }
+    pLevel->u.pCovidx = pCov;
+    if( pCov ) pLevel->iIdxCur = iCovCur;
     if( pAndExpr ){
       pAndExpr->pLeft = 0;
       sqlite3ExprDelete(pParse->db, pAndExpr);
@@ -107675,7 +106364,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   Expr *pWhere,         /* The WHERE clause */
   ExprList **ppOrderBy, /* 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 */
+  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 */
@@ -107995,7 +106685,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
     testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
     if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
-      pLevel->iIdxCur = pParse->nTab++;
+      if( (wctrlFlags & WHERE_ONETABLE_ONLY) 
+       && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0 
+      ){
+        pLevel->iIdxCur = iIdxCur;
+      }else{
+        pLevel->iIdxCur = pParse->nTab++;
+      }
     }else{
       pLevel->iIdxCur = -1;
     }
@@ -108096,10 +106792,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
       Index *pIx = pLevel->plan.u.pIdx;
       KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
-      int iIdxCur = pLevel->iIdxCur;
+      int iIndexCur = pLevel->iIdxCur;
       assert( pIx->pSchema==pTab->pSchema );
-      assert( iIdxCur>=0 );
-      sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb,
+      assert( iIndexCur>=0 );
+      sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb,
                         (char*)pKey, P4_KEYINFO_HANDOFF);
       VdbeComment((v, "%s", pIx->zName));
     }
@@ -108247,6 +106943,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
   */
   assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
   for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
+    Index *pIdx = 0;
     struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
@@ -108276,12 +106973,15 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
     ** that reference the table and converts them into opcodes that
     ** reference the index.
     */
-    if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 && !db->mallocFailed){
+    if( pLevel->plan.wsFlags & WHERE_INDEXED ){
+      pIdx = pLevel->plan.u.pIdx;
+    }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
+      pIdx = pLevel->u.pCovidx;
+    }
+    if( pIdx && !db->mallocFailed){
       int k, j, last;
       VdbeOp *pOp;
-      Index *pIdx = pLevel->plan.u.pIdx;
 
-      assert( pIdx!=0 );
       pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
       last = sqlite3VdbeCurrentAddr(v);
       for(k=pWInfo->iTop; k<last; k++, pOp++){
@@ -113039,6 +111739,15 @@ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0;
 SQLITE_API char *sqlite3_temp_directory = 0;
 
 /*
+** If the following global variable points to a string which is the
+** name of a directory, then that directory will be used to store
+** all database files specified with a relative pathname.
+**
+** See also the "PRAGMA data_store_directory" SQL command.
+*/
+SQLITE_API char *sqlite3_data_directory = 0;
+
+/*
 ** Initialize SQLite.  
 **
 ** This routine must be called to initialize the memory allocation,
@@ -113236,6 +111945,18 @@ SQLITE_API int sqlite3_shutdown(void){
   if( sqlite3GlobalConfig.isMallocInit ){
     sqlite3MallocEnd();
     sqlite3GlobalConfig.isMallocInit = 0;
+
+#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
+    /* The heap subsystem has now been shutdown and these values are supposed
+    ** to be NULL or point to memory that was obtained from sqlite3_malloc(),
+    ** which would rely on that heap subsystem; therefore, make sure these
+    ** values cannot refer to heap memory that was just invalidated when the
+    ** heap subsystem was shutdown.  This is only done if the current call to
+    ** this function resulted in the heap subsystem actually being shutdown.
+    */
+    sqlite3_data_directory = 0;
+    sqlite3_temp_directory = 0;
+#endif
   }
   if( sqlite3GlobalConfig.isMutexInit ){
     sqlite3MutexEnd();
@@ -113685,12 +112406,48 @@ static void functionDestroy(sqlite3 *db, FuncDef *p){
 }
 
 /*
-** Close an existing SQLite database
+** Disconnect all sqlite3_vtab objects that belong to database connection
+** db. This is called when db is being closed.
 */
-SQLITE_API int sqlite3_close(sqlite3 *db){
-  HashElem *i;                    /* Hash table iterator */
+static void disconnectAllVtab(sqlite3 *db){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+  int i;
+  sqlite3BtreeEnterAll(db);
+  for(i=0; i<db->nDb; i++){
+    Schema *pSchema = db->aDb[i].pSchema;
+    if( db->aDb[i].pSchema ){
+      HashElem *p;
+      for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
+        Table *pTab = (Table *)sqliteHashData(p);
+        if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
+      }
+    }
+  }
+  sqlite3BtreeLeaveAll(db);
+#else
+  UNUSED_PARAMETER(db);
+#endif
+}
+
+/*
+** Return TRUE if database connection db has unfinalized prepared
+** statements or unfinished sqlite3_backup objects.  
+*/
+static int connectionIsBusy(sqlite3 *db){
   int j;
+  assert( sqlite3_mutex_held(db->mutex) );
+  if( db->pVdbe ) return 1;
+  for(j=0; j<db->nDb; j++){
+    Btree *pBt = db->aDb[j].pBt;
+    if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1;
+  }
+  return 0;
+}
 
+/*
+** Close an existing SQLite database
+*/
+static int sqlite3Close(sqlite3 *db, int forceZombie){
   if( !db ){
     return SQLITE_OK;
   }
@@ -113699,10 +112456,10 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
   }
   sqlite3_mutex_enter(db->mutex);
 
-  /* Force xDestroy calls on all virtual tables */
-  sqlite3ResetInternalSchema(db, -1);
+  /* Force xDisconnect calls on all virtual tables */
+  disconnectAllVtab(db);
 
-  /* If a transaction is open, the ResetInternalSchema() call above
+  /* If a transaction is open, the disconnectAllVtab() call above
   ** will not have called the xDisconnect() method on any virtual
   ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
   ** call will do so. We need to do this before the check for active
@@ -113711,28 +112468,67 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
   */
   sqlite3VtabRollback(db);
 
-  /* If there are any outstanding VMs, return SQLITE_BUSY. */
-  if( db->pVdbe ){
-    sqlite3Error(db, SQLITE_BUSY, 
-        "unable to close due to unfinalised statements");
+  /* Legacy behavior (sqlite3_close() behavior) is to return
+  ** SQLITE_BUSY if the connection can not be closed immediately.
+  */
+  if( !forceZombie && connectionIsBusy(db) ){
+    sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized "
+       "statements or unfinished backups");
     sqlite3_mutex_leave(db->mutex);
     return SQLITE_BUSY;
   }
-  assert( sqlite3SafetyCheckSickOrOk(db) );
 
-  for(j=0; j<db->nDb; j++){
-    Btree *pBt = db->aDb[j].pBt;
-    if( pBt && sqlite3BtreeIsInBackup(pBt) ){
-      sqlite3Error(db, SQLITE_BUSY, 
-          "unable to close due to unfinished backup operation");
-      sqlite3_mutex_leave(db->mutex);
-      return SQLITE_BUSY;
-    }
+  /* Convert the connection into a zombie and then close it.
+  */
+  db->magic = SQLITE_MAGIC_ZOMBIE;
+  sqlite3LeaveMutexAndCloseZombie(db);
+  return SQLITE_OK;
+}
+
+/*
+** Two variations on the public interface for closing a database
+** connection. The sqlite3_close() version returns SQLITE_BUSY and
+** leaves the connection option if there are unfinalized prepared
+** statements or unfinished sqlite3_backups.  The sqlite3_close_v2()
+** version forces the connection to become a zombie if there are
+** unclosed resources, and arranges for deallocation when the last
+** prepare statement or sqlite3_backup closes.
+*/
+SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
+SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
+
+
+/*
+** Close the mutex on database connection db.
+**
+** Furthermore, if database connection db is a zombie (meaning that there
+** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and
+** every sqlite3_stmt has now been finalized and every sqlite3_backup has
+** finished, then free all resources.
+*/
+SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
+  HashElem *i;                    /* Hash table iterator */
+  int j;
+
+  /* If there are outstanding sqlite3_stmt or sqlite3_backup objects
+  ** or if the connection has not yet been closed by sqlite3_close_v2(),
+  ** then just leave the mutex and return.
+  */
+  if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
+    sqlite3_mutex_leave(db->mutex);
+    return;
   }
 
+  /* 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,
+  ** go ahead and free all resources.
+  */
+
   /* Free any outstanding Savepoint structures. */
   sqlite3CloseSavepoints(db);
 
+  /* Close all database connections */
   for(j=0; j<db->nDb; j++){
     struct Db *pDb = &db->aDb[j];
     if( pDb->pBt ){
@@ -113743,15 +112539,22 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
       }
     }
   }
-  sqlite3ResetInternalSchema(db, -1);
+  /* Clear the TEMP schema separately and last */
+  if( db->aDb[1].pSchema ){
+    sqlite3SchemaClear(db->aDb[1].pSchema);
+  }
+  sqlite3VtabUnlockList(db);
+
+  /* Free up the array of auxiliary databases */
+  sqlite3CollapseDatabaseArray(db);
+  assert( db->nDb<=2 );
+  assert( db->aDb==db->aDbStatic );
 
   /* Tell the code in notify.c that the connection no longer holds any
   ** locks and does not require any further unlock-notify callbacks.
   */
   sqlite3ConnectionClosed(db);
 
-  assert( db->nDb<=2 );
-  assert( db->aDb==db->aDbStatic );
   for(j=0; j<ArraySize(db->aFunc.a); j++){
     FuncDef *pNext, *pHash, *p;
     for(p=db->aFunc.a[j]; p; p=pHash){
@@ -113809,7 +112612,6 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
     sqlite3_free(db->lookaside.pStart);
   }
   sqlite3_free(db);
-  return SQLITE_OK;
 }
 
 /*
@@ -113838,7 +112640,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
 
   if( db->flags&SQLITE_InternChanges ){
     sqlite3ExpirePreparedStatements(db);
-    sqlite3ResetInternalSchema(db, -1);
+    sqlite3ResetAllSchemasOfConnection(db);
   }
 
   /* Any deferred constraint violations have now been resolved. */
@@ -114976,10 +113778,12 @@ SQLITE_PRIVATE int sqlite3ParseUri(
             { "ro",  SQLITE_OPEN_READONLY },
             { "rw",  SQLITE_OPEN_READWRITE }, 
             { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
+            { "memory", SQLITE_OPEN_MEMORY },
             { 0, 0 }
           };
 
-          mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
+          mask = SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE
+                   | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY;
           aMode = aOpenMode;
           limit = mask & flags;
           zModeType = "access";
@@ -115000,7 +113804,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
             rc = SQLITE_ERROR;
             goto parse_uri_out;
           }
-          if( mode>limit ){
+          if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){
             *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
                                         zModeType, zVal);
             rc = SQLITE_PERM;
@@ -115019,6 +113823,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
     memcpy(zFile, zUri, nUri);
     zFile[nUri] = '\0';
     zFile[nUri+1] = '\0';
+    flags &= ~SQLITE_OPEN_URI;
   }
 
   *ppVfs = sqlite3_vfs_find(zVfs);
@@ -117350,10 +116155,20 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*
 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
 
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
 SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
 SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
+SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
+#else
+# define sqlite3Fts3FreeDeferredTokens(x)
+# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
+# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
+# define sqlite3Fts3FreeDeferredDoclists(x)
+# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
+#endif
+
 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
 SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *);
 
@@ -117462,7 +116277,12 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iC
 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
 SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
 
-SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
+/* fts3_unicode2.c (functions generated by parsing unicode text files) */
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
+#endif
 
 #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
 #endif /* _FTSINT_H */
@@ -120732,6 +119552,9 @@ static void hashDestroy(void *p){
 */
 SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
 SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
+#endif
 #ifdef SQLITE_ENABLE_ICU
 SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
 #endif
@@ -120747,12 +119570,19 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
   Fts3Hash *pHash = 0;
   const sqlite3_tokenizer_module *pSimple = 0;
   const sqlite3_tokenizer_module *pPorter = 0;
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+  const sqlite3_tokenizer_module *pUnicode = 0;
+#endif
 
 #ifdef SQLITE_ENABLE_ICU
   const sqlite3_tokenizer_module *pIcu = 0;
   sqlite3Fts3IcuTokenizerModule(&pIcu);
 #endif
 
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+  sqlite3Fts3UnicodeTokenizer(&pUnicode);
+#endif
+
 #ifdef SQLITE_TEST
   rc = sqlite3Fts3InitTerm(db);
   if( rc!=SQLITE_OK ) return rc;
@@ -120776,6 +119606,10 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
   if( rc==SQLITE_OK ){
     if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
      || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) 
+
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+     || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) 
+#endif
 #ifdef SQLITE_ENABLE_ICU
      || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
 #endif
@@ -121600,6 +120434,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
   fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
 
   /* Determine which, if any, tokens in the expression should be deferred. */
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
   if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
     Fts3TokenAndCost *aTC;
     Fts3Expr **apOr;
@@ -121630,6 +120465,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
       sqlite3_free(aTC);
     }
   }
+#endif
 
   fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
   return rc;
@@ -122013,6 +120849,7 @@ static int fts3EvalTestExpr(
         break;
 
       default: {
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
         if( pCsr->pDeferred 
          && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
         ){
@@ -122024,7 +120861,9 @@ static int fts3EvalTestExpr(
           *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
           bHit = (pPhrase->doclist.pList!=0);
           pExpr->iDocid = pCsr->iPrevId;
-        }else{
+        }else
+#endif
+        {
           bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
         }
         break;
@@ -125238,10 +124077,9 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
 /*
 ** Implementation of a special SQL scalar function for testing tokenizers 
 ** designed to be used in concert with the Tcl testing framework. This
-** function must be called with two arguments:
+** function must be called with two or more arguments:
 **
-**   SELECT <function-name>(<key-name>, <input-string>);
-**   SELECT <function-name>(<key-name>, <pointer>);
+**   SELECT <function-name>(<key-name>, ..., <input-string>);
 **
 ** where <function-name> is the name passed as the second argument
 ** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer')
@@ -125278,27 +124116,27 @@ static void testFunc(
   const char *zInput;
   int nInput;
 
-  const char *zArg = 0;
+  const char *azArg[64];
 
   const char *zToken;
   int nToken;
   int iStart;
   int iEnd;
   int iPos;
+  int i;
 
   Tcl_Obj *pRet;
 
-  assert( argc==2 || argc==3 );
+  if( argc<2 ){
+    sqlite3_result_error(context, "insufficient arguments", -1);
+    return;
+  }
 
   nName = sqlite3_value_bytes(argv[0]);
   zName = (const char *)sqlite3_value_text(argv[0]);
   nInput = sqlite3_value_bytes(argv[argc-1]);
   zInput = (const char *)sqlite3_value_text(argv[argc-1]);
 
-  if( argc==3 ){
-    zArg = (const char *)sqlite3_value_text(argv[1]);
-  }
-
   pHash = (Fts3Hash *)sqlite3_user_data(context);
   p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
 
@@ -125312,7 +124150,11 @@ static void testFunc(
   pRet = Tcl_NewObj();
   Tcl_IncrRefCount(pRet);
 
-  if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
+  for(i=1; i<argc-1; i++){
+    azArg[i-1] = (const char *)sqlite3_value_text(argv[i]);
+  }
+
+  if( SQLITE_OK!=p->xCreate(argc-2, azArg, &pTokenizer) ){
     zErr = "error in xCreate()";
     goto finish;
   }
@@ -125496,10 +124338,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable(
   }
 #ifdef SQLITE_TEST
   if( SQLITE_OK==rc ){
-    rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0);
-  }
-  if( SQLITE_OK==rc ){
-    rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0);
+    rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0);
   }
   if( SQLITE_OK==rc ){
     rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0);
@@ -125890,7 +124729,8 @@ struct Fts3DeferredToken {
 */
 struct Fts3SegReader {
   int iIdx;                       /* Index within level, or 0x7FFFFFFF for PT */
-  int bLookup;                    /* True for a lookup only */
+  u8 bLookup;                     /* True for a lookup only */
+  u8 rootOnly;                    /* True for a root-only reader */
 
   sqlite3_int64 iStartBlock;      /* Rowid of first leaf block to traverse */
   sqlite3_int64 iLeafEndBlock;    /* Rowid of final leaf block to traverse */
@@ -125924,7 +124764,7 @@ struct Fts3SegReader {
 };
 
 #define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
-#define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
+#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0)
 
 /*
 ** An instance of this structure is used to create a segment b-tree in the
@@ -127335,7 +126175,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
   }
   memset(pReader, 0, sizeof(Fts3SegReader));
   pReader->iIdx = iAge;
-  pReader->bLookup = bLookup;
+  pReader->bLookup = bLookup!=0;
   pReader->iStartBlock = iStartLeaf;
   pReader->iLeafEndBlock = iEndLeaf;
   pReader->iEndBlock = iEndBlock;
@@ -127343,6 +126183,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
   if( nExtra ){
     /* The entire segment is stored in the root node. */
     pReader->aNode = (char *)&pReader[1];
+    pReader->rootOnly = 1;
     pReader->nNode = nRoot;
     memcpy(pReader->aNode, zRoot, nRoot);
     memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
@@ -128721,7 +127562,7 @@ static int fts3SegmentMerge(
 
   if( iLevel==FTS3_SEGCURSOR_ALL ){
     /* This call is to merge all segments in the database to a single
-    ** segment. The level of the new segment is equal to the the numerically 
+    ** segment. The level of the new segment is equal to the numerically
     ** greatest segment level currently present in the database for this
     ** index. The idx of the new segment is always 0.  */
     if( csr.nSegment==1 ){
@@ -128928,7 +127769,12 @@ static void fts3UpdateDocTotals(
   }else{
     memset(a, 0, sizeof(u32)*(nStat) );
   }
-  sqlite3_reset(pStmt);
+  rc = sqlite3_reset(pStmt);
+  if( rc!=SQLITE_OK ){
+    sqlite3_free(a);
+    *pRC = rc;
+    return;
+  }
   if( nChng<0 && a[0]<(u32)(-nChng) ){
     a[0] = 0;
   }else{
@@ -129346,7 +128192,7 @@ static int fts3IncrmergePush(
         pNode->key.n = nTerm;
       }
     }else{
-      /* Otherwise, flush the the current node of layer iLayer to disk.
+      /* Otherwise, flush the current node of layer iLayer to disk.
       ** Then allocate a new, empty sibling node. The key will be written
       ** into the parent of this node. */
       rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
@@ -130793,6 +129639,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
   return rc;
 }
 
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
 /*
 ** Delete all cached deferred doclists. Deferred doclists are cached
 ** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
@@ -130930,6 +129777,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
 
   return SQLITE_OK;
 }
+#endif
 
 /*
 ** SQLite value pRowid contains the rowid of a row that may or may not be
@@ -132651,6 +131499,769 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo(
 #endif
 
 /************** End of fts3_snippet.c ****************************************/
+/************** Begin file fts3_unicode.c ************************************/
+/*
+** 2012 May 24
+**
+** 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.
+**
+******************************************************************************
+**
+** Implementation of the "unicode" full-text-search tokenizer.
+*/
+
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <stdio.h> */
+/* #include <string.h> */
+
+
+/*
+** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
+** from the sqlite3 source file utf.c. If this file is compiled as part
+** of the amalgamation, they are not required.
+*/
+#ifndef SQLITE_AMALGAMATION
+
+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 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; }        \
+  }
+
+#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);                   \
+  }                                                    \
+}
+
+#endif /* ifndef SQLITE_AMALGAMATION */
+
+typedef struct unicode_tokenizer unicode_tokenizer;
+typedef struct unicode_cursor unicode_cursor;
+
+struct unicode_tokenizer {
+  sqlite3_tokenizer base;
+  int bRemoveDiacritic;
+  int nException;
+  int *aiException;
+};
+
+struct unicode_cursor {
+  sqlite3_tokenizer_cursor base;
+  const unsigned char *aInput;    /* Input text being tokenized */
+  int nInput;                     /* Size of aInput[] in bytes */
+  int iOff;                       /* Current offset within aInput[] */
+  int iToken;                     /* Index of next token to be returned */
+  char *zToken;                   /* storage for current token */
+  int nAlloc;                     /* space allocated at zToken */
+};
+
+
+/*
+** Destroy a tokenizer allocated by unicodeCreate().
+*/
+static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
+  if( pTokenizer ){
+    unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer;
+    sqlite3_free(p->aiException);
+    sqlite3_free(p);
+  }
+  return SQLITE_OK;
+}
+
+/*
+** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE
+** statement has specified that the tokenizer for this table shall consider
+** all characters in string zIn/nIn to be separators (if bAlnum==0) or
+** token characters (if bAlnum==1).
+**
+** For each codepoint in the zIn/nIn string, this function checks if the
+** sqlite3FtsUnicodeIsalnum() function already returns the desired result.
+** If so, no action is taken. Otherwise, the codepoint is added to the 
+** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
+** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
+** codepoints in the aiException[] array.
+**
+** 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
+** to these codepoints.
+*/
+static int unicodeAddExceptions(
+  unicode_tokenizer *p,           /* Tokenizer to add exceptions to */
+  int bAlnum,                     /* Replace Isalnum() return value with this */
+  const char *zIn,                /* Array of characters to make exceptions */
+  int nIn                         /* Length of z in bytes */
+){
+  const unsigned char *z = (const unsigned char *)zIn;
+  const unsigned char *zTerm = &z[nIn];
+  int iCode;
+  int nEntry = 0;
+
+  assert( bAlnum==0 || bAlnum==1 );
+
+  while( z<zTerm ){
+    READ_UTF8(z, zTerm, iCode);
+    assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
+    if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum 
+     && sqlite3FtsUnicodeIsdiacritic(iCode)==0 
+    ){
+      nEntry++;
+    }
+  }
+
+  if( nEntry ){
+    int *aNew;                    /* New aiException[] array */
+    int nNew;                     /* Number of valid entries in array aNew[] */
+
+    aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
+    if( aNew==0 ) return SQLITE_NOMEM;
+    nNew = p->nException;
+
+    z = (const unsigned char *)zIn;
+    while( z<zTerm ){
+      READ_UTF8(z, zTerm, iCode);
+      if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum 
+       && sqlite3FtsUnicodeIsdiacritic(iCode)==0
+      ){
+        int i, j;
+        for(i=0; i<nNew && aNew[i]<iCode; i++);
+        for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
+        aNew[i] = iCode;
+        nNew++;
+      }
+    }
+    p->aiException = aNew;
+    p->nException = nNew;
+  }
+
+  return SQLITE_OK;
+}
+
+/*
+** Return true if the p->aiException[] array contains the value iCode.
+*/
+static int unicodeIsException(unicode_tokenizer *p, int iCode){
+  if( p->nException>0 ){
+    int *a = p->aiException;
+    int iLo = 0;
+    int iHi = p->nException-1;
+
+    while( iHi>=iLo ){
+      int iTest = (iHi + iLo) / 2;
+      if( iCode==a[iTest] ){
+        return 1;
+      }else if( iCode>a[iTest] ){
+        iLo = iTest+1;
+      }else{
+        iHi = iTest-1;
+      }
+    }
+  }
+
+  return 0;
+}
+
+/*
+** Return true if, for the purposes of tokenization, codepoint iCode is
+** considered a token character (not a separator).
+*/
+static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){
+  assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
+  return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode);
+}
+
+/*
+** Create a new tokenizer instance.
+*/
+static int unicodeCreate(
+  int nArg,                       /* Size of array argv[] */
+  const char * const *azArg,      /* Tokenizer creation arguments */
+  sqlite3_tokenizer **pp          /* OUT: New tokenizer handle */
+){
+  unicode_tokenizer *pNew;        /* New tokenizer object */
+  int i;
+  int rc = SQLITE_OK;
+
+  pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
+  if( pNew==NULL ) return SQLITE_NOMEM;
+  memset(pNew, 0, sizeof(unicode_tokenizer));
+  pNew->bRemoveDiacritic = 1;
+
+  for(i=0; rc==SQLITE_OK && i<nArg; i++){
+    const char *z = azArg[i];
+    int n = strlen(z);
+
+    if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
+      pNew->bRemoveDiacritic = 1;
+    }
+    else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
+      pNew->bRemoveDiacritic = 0;
+    }
+    else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
+      rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
+    }
+    else if( n>=11 && memcmp("separators=", z, 11)==0 ){
+      rc = unicodeAddExceptions(pNew, 0, &z[11], n-11);
+    }
+    else{
+      /* Unrecognized argument */
+      rc  = SQLITE_ERROR;
+    }
+  }
+
+  if( rc!=SQLITE_OK ){
+    unicodeDestroy((sqlite3_tokenizer *)pNew);
+    pNew = 0;
+  }
+  *pp = (sqlite3_tokenizer *)pNew;
+  return rc;
+}
+
+/*
+** Prepare to begin tokenizing a particular string.  The input
+** string to be tokenized is pInput[0..nBytes-1].  A cursor
+** used to incrementally tokenize this string is returned in 
+** *ppCursor.
+*/
+static int unicodeOpen(
+  sqlite3_tokenizer *p,           /* The tokenizer */
+  const char *aInput,             /* Input string */
+  int nInput,                     /* Size of string aInput in bytes */
+  sqlite3_tokenizer_cursor **pp   /* OUT: New cursor object */
+){
+  unicode_cursor *pCsr;
+
+  pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor));
+  if( pCsr==0 ){
+    return SQLITE_NOMEM;
+  }
+  memset(pCsr, 0, sizeof(unicode_cursor));
+
+  pCsr->aInput = (const unsigned char *)aInput;
+  if( aInput==0 ){
+    pCsr->nInput = 0;
+  }else if( nInput<0 ){
+    pCsr->nInput = (int)strlen(aInput);
+  }else{
+    pCsr->nInput = nInput;
+  }
+
+  *pp = &pCsr->base;
+  UNUSED_PARAMETER(p);
+  return SQLITE_OK;
+}
+
+/*
+** Close a tokenization cursor previously opened by a call to
+** simpleOpen() above.
+*/
+static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){
+  unicode_cursor *pCsr = (unicode_cursor *) pCursor;
+  sqlite3_free(pCsr->zToken);
+  sqlite3_free(pCsr);
+  return SQLITE_OK;
+}
+
+/*
+** Extract the next token from a tokenization cursor.  The cursor must
+** have been opened by a prior call to simpleOpen().
+*/
+static int unicodeNext(
+  sqlite3_tokenizer_cursor *pC,   /* Cursor returned by simpleOpen */
+  const char **paToken,           /* OUT: Token text */
+  int *pnToken,                   /* OUT: Number of bytes at *paToken */
+  int *piStart,                   /* OUT: Starting offset of token */
+  int *piEnd,                     /* OUT: Ending offset of token */
+  int *piPos                      /* OUT: Position integer of token */
+){
+  unicode_cursor *pCsr = (unicode_cursor *)pC;
+  unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
+  int iCode;
+  char *zOut;
+  const unsigned char *z = &pCsr->aInput[pCsr->iOff];
+  const unsigned char *zStart = z;
+  const unsigned char *zEnd;
+  const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
+
+  /* Scan past any delimiter characters before the start of the next token.
+  ** Return SQLITE_DONE early if this takes us all the way to the end of 
+  ** the input.  */
+  while( z<zTerm ){
+    READ_UTF8(z, zTerm, iCode);
+    if( unicodeIsAlnum(p, iCode) ) break;
+    zStart = z;
+  }
+  if( zStart>=zTerm ) return SQLITE_DONE;
+
+  zOut = pCsr->zToken;
+  do {
+    int iOut;
+
+    /* Grow the output buffer if required. */
+    if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
+      char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
+      if( !zNew ) return SQLITE_NOMEM;
+      zOut = &zNew[zOut - pCsr->zToken];
+      pCsr->zToken = zNew;
+      pCsr->nAlloc += 64;
+    }
+
+    /* Write the folded case of the last character read to the output */
+    zEnd = z;
+    iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
+    if( iOut ){
+      WRITE_UTF8(zOut, iOut);
+    }
+
+    /* If the cursor is not at EOF, read the next character */
+    if( z>=zTerm ) break;
+    READ_UTF8(z, zTerm, iCode);
+  }while( unicodeIsAlnum(p, iCode) 
+       || sqlite3FtsUnicodeIsdiacritic(iCode)
+  );
+
+  /* Set the output variables and return. */
+  pCsr->iOff = (z - pCsr->aInput);
+  *paToken = pCsr->zToken;
+  *pnToken = zOut - pCsr->zToken;
+  *piStart = (zStart - pCsr->aInput);
+  *piEnd = (zEnd - pCsr->aInput);
+  *piPos = pCsr->iToken++;
+  return SQLITE_OK;
+}
+
+/*
+** Set *ppModule to a pointer to the sqlite3_tokenizer_module 
+** structure for the unicode tokenizer.
+*/
+SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){
+  static const sqlite3_tokenizer_module module = {
+    0,
+    unicodeCreate,
+    unicodeDestroy,
+    unicodeOpen,
+    unicodeClose,
+    unicodeNext,
+    0,
+  };
+  *ppModule = &module;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */
+
+/************** End of fts3_unicode.c ****************************************/
+/************** Begin file fts3_unicode2.c ***********************************/
+/*
+** 2012 May 25
+**
+** 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.
+**
+******************************************************************************
+*/
+
+/*
+** DO NOT EDIT THIS MACHINE GENERATED FILE.
+*/
+
+#if defined(SQLITE_ENABLE_FTS4_UNICODE61)
+#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
+
+/* #include <assert.h> */
+
+/*
+** Return true if the argument corresponds to a unicode codepoint
+** classified as either a letter or a number. Otherwise false.
+**
+** The results are undefined if the value passed to this function
+** is less than zero.
+*/
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
+  /* Each unsigned integer in the following array corresponds to a contiguous
+  ** range of unicode codepoints that are not either letters or numbers (i.e.
+  ** codepoints for which this function should return 0).
+  **
+  ** The most significant 22 bits in each 32-bit value contain the first 
+  ** codepoint in the range. The least significant 10 bits are used to store
+  ** the size of the range (always at least 1). In other words, the value 
+  ** ((C<<22) + N) represents a range of N codepoints starting with codepoint 
+  ** C. It is not possible to represent a range larger than 1023 codepoints 
+  ** using this format.
+  */
+  const static unsigned int aEntry[] = {
+    0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
+    0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
+    0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
+    0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
+    0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
+    0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
+    0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
+    0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
+    0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
+    0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
+    0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
+    0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
+    0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
+    0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
+    0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
+    0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
+    0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
+    0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
+    0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
+    0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
+    0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
+    0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
+    0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
+    0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
+    0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
+    0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
+    0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
+    0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
+    0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
+    0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
+    0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
+    0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
+    0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
+    0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
+    0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
+    0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
+    0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
+    0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
+    0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
+    0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
+    0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
+    0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
+    0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
+    0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
+    0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
+    0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
+    0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
+    0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
+    0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
+    0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
+    0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
+    0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
+    0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
+    0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
+    0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
+    0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
+    0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
+    0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
+    0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
+    0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
+    0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
+    0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
+    0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
+    0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
+    0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
+    0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
+    0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
+    0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
+    0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
+    0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
+    0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
+    0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
+    0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
+    0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
+    0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
+    0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
+    0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
+    0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
+    0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
+    0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
+    0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
+    0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
+    0x43FFF401,
+  };
+  static const unsigned int aAscii[4] = {
+    0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
+  };
+
+  if( c<128 ){
+    return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
+  }else if( c<(1<<22) ){
+    unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
+    int iRes;
+    int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
+    int iLo = 0;
+    while( iHi>=iLo ){
+      int iTest = (iHi + iLo) / 2;
+      if( key >= aEntry[iTest] ){
+        iRes = iTest;
+        iLo = iTest+1;
+      }else{
+        iHi = iTest-1;
+      }
+    }
+    assert( aEntry[0]<key );
+    assert( key>=aEntry[iRes] );
+    return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
+  }
+  return 1;
+}
+
+
+/*
+** If the argument is a codepoint corresponding to a lowercase letter
+** in the ASCII range with a diacritic added, return the codepoint
+** of the ASCII letter only. For example, if passed 235 - "LATIN
+** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
+** E"). The resuls of passing a codepoint that corresponds to an
+** uppercase letter are undefined.
+*/
+static int remove_diacritic(int c){
+  unsigned short aDia[] = {
+        0,  1797,  1848,  1859,  1891,  1928,  1940,  1995, 
+     2024,  2040,  2060,  2110,  2168,  2206,  2264,  2286, 
+     2344,  2383,  2472,  2488,  2516,  2596,  2668,  2732, 
+     2782,  2842,  2894,  2954,  2984,  3000,  3028,  3336, 
+     3456,  3696,  3712,  3728,  3744,  3896,  3912,  3928, 
+     3968,  4008,  4040,  4106,  4138,  4170,  4202,  4234, 
+     4266,  4296,  4312,  4344,  4408,  4424,  4472,  4504, 
+     6148,  6198,  6264,  6280,  6360,  6429,  6505,  6529, 
+    61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, 
+    61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, 
+    62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, 
+    62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, 
+    62924, 63050, 63082, 63274, 63390, 
+  };
+  char aChar[] = {
+    '\0', 'a',  'c',  'e',  'i',  'n',  'o',  'u',  'y',  'y',  'a',  'c',  
+    'd',  'e',  'e',  'g',  'h',  'i',  'j',  'k',  'l',  'n',  'o',  'r',  
+    's',  't',  'u',  'u',  'w',  'y',  'z',  'o',  'u',  'a',  'i',  'o',  
+    'u',  'g',  'k',  'o',  'j',  'g',  'n',  'a',  'e',  'i',  'o',  'r',  
+    'u',  's',  't',  'h',  'a',  'e',  'o',  'y',  '\0', '\0', '\0', '\0', 
+    '\0', '\0', '\0', '\0', 'a',  'b',  'd',  'd',  'e',  'f',  'g',  'h',  
+    'h',  'i',  'k',  'l',  'l',  'm',  'n',  'p',  'r',  'r',  's',  't',  
+    'u',  'v',  'w',  'w',  'x',  'y',  'z',  'h',  't',  'w',  'y',  'a',  
+    'e',  'i',  'o',  'u',  'y',  
+  };
+
+  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
+  int iRes = 0;
+  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
+  int iLo = 0;
+  while( iHi>=iLo ){
+    int iTest = (iHi + iLo) / 2;
+    if( key >= aDia[iTest] ){
+      iRes = iTest;
+      iLo = iTest+1;
+    }else{
+      iHi = iTest-1;
+    }
+  }
+  assert( key>=aDia[iRes] );
+  return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
+};
+
+
+/*
+** Return true if the argument interpreted as a unicode codepoint
+** is a diacritical modifier character.
+*/
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){
+  unsigned int mask0 = 0x08029FDF;
+  unsigned int mask1 = 0x000361F8;
+  if( c<768 || c>817 ) return 0;
+  return (c < 768+32) ?
+      (mask0 & (1 << (c-768))) :
+      (mask1 & (1 << (c-768-32)));
+}
+
+
+/*
+** Interpret the argument as a unicode codepoint. If the codepoint
+** is an upper case character that has a lower case equivalent,
+** return the codepoint corresponding to the lower case version.
+** Otherwise, return a copy of the argument.
+**
+** The results are undefined if the value passed to this function
+** is less than zero.
+*/
+SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
+  /* Each entry in the following array defines a rule for folding a range
+  ** of codepoints to lower case. The rule applies to a range of nRange
+  ** codepoints starting at codepoint iCode.
+  **
+  ** If the least significant bit in flags is clear, then the rule applies
+  ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
+  ** need to be folded). Or, if it is set, then the rule only applies to
+  ** every second codepoint in the range, starting with codepoint C.
+  **
+  ** The 7 most significant bits in flags are an index into the aiOff[]
+  ** array. If a specific codepoint C does require folding, then its lower
+  ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
+  **
+  ** The contents of this array are generated by parsing the CaseFolding.txt
+  ** file distributed as part of the "Unicode Character Database". See
+  ** http://www.unicode.org for details.
+  */
+  static const struct TableEntry {
+    unsigned short iCode;
+    unsigned char flags;
+    unsigned char nRange;
+  } aEntry[] = {
+    {65, 14, 26},          {181, 64, 1},          {192, 14, 23},
+    {216, 14, 7},          {256, 1, 48},          {306, 1, 6},
+    {313, 1, 16},          {330, 1, 46},          {376, 116, 1},
+    {377, 1, 6},           {383, 104, 1},         {385, 50, 1},
+    {386, 1, 4},           {390, 44, 1},          {391, 0, 1},
+    {393, 42, 2},          {395, 0, 1},           {398, 32, 1},
+    {399, 38, 1},          {400, 40, 1},          {401, 0, 1},
+    {403, 42, 1},          {404, 46, 1},          {406, 52, 1},
+    {407, 48, 1},          {408, 0, 1},           {412, 52, 1},
+    {413, 54, 1},          {415, 56, 1},          {416, 1, 6},
+    {422, 60, 1},          {423, 0, 1},           {425, 60, 1},
+    {428, 0, 1},           {430, 60, 1},          {431, 0, 1},
+    {433, 58, 2},          {435, 1, 4},           {439, 62, 1},
+    {440, 0, 1},           {444, 0, 1},           {452, 2, 1},
+    {453, 0, 1},           {455, 2, 1},           {456, 0, 1},
+    {458, 2, 1},           {459, 1, 18},          {478, 1, 18},
+    {497, 2, 1},           {498, 1, 4},           {502, 122, 1},
+    {503, 134, 1},         {504, 1, 40},          {544, 110, 1},
+    {546, 1, 18},          {570, 70, 1},          {571, 0, 1},
+    {573, 108, 1},         {574, 68, 1},          {577, 0, 1},
+    {579, 106, 1},         {580, 28, 1},          {581, 30, 1},
+    {582, 1, 10},          {837, 36, 1},          {880, 1, 4},
+    {886, 0, 1},           {902, 18, 1},          {904, 16, 3},
+    {908, 26, 1},          {910, 24, 2},          {913, 14, 17},
+    {931, 14, 9},          {962, 0, 1},           {975, 4, 1},
+    {976, 140, 1},         {977, 142, 1},         {981, 146, 1},
+    {982, 144, 1},         {984, 1, 24},          {1008, 136, 1},
+    {1009, 138, 1},        {1012, 130, 1},        {1013, 128, 1},
+    {1015, 0, 1},          {1017, 152, 1},        {1018, 0, 1},
+    {1021, 110, 3},        {1024, 34, 16},        {1040, 14, 32},
+    {1120, 1, 34},         {1162, 1, 54},         {1216, 6, 1},
+    {1217, 1, 14},         {1232, 1, 88},         {1329, 22, 38},
+    {4256, 66, 38},        {4295, 66, 1},         {4301, 66, 1},
+    {7680, 1, 150},        {7835, 132, 1},        {7838, 96, 1},
+    {7840, 1, 96},         {7944, 150, 8},        {7960, 150, 6},
+    {7976, 150, 8},        {7992, 150, 8},        {8008, 150, 6},
+    {8025, 151, 8},        {8040, 150, 8},        {8072, 150, 8},
+    {8088, 150, 8},        {8104, 150, 8},        {8120, 150, 2},
+    {8122, 126, 2},        {8124, 148, 1},        {8126, 100, 1},
+    {8136, 124, 4},        {8140, 148, 1},        {8152, 150, 2},
+    {8154, 120, 2},        {8168, 150, 2},        {8170, 118, 2},
+    {8172, 152, 1},        {8184, 112, 2},        {8186, 114, 2},
+    {8188, 148, 1},        {8486, 98, 1},         {8490, 92, 1},
+    {8491, 94, 1},         {8498, 12, 1},         {8544, 8, 16},
+    {8579, 0, 1},          {9398, 10, 26},        {11264, 22, 47},
+    {11360, 0, 1},         {11362, 88, 1},        {11363, 102, 1},
+    {11364, 90, 1},        {11367, 1, 6},         {11373, 84, 1},
+    {11374, 86, 1},        {11375, 80, 1},        {11376, 82, 1},
+    {11378, 0, 1},         {11381, 0, 1},         {11390, 78, 2},
+    {11392, 1, 100},       {11499, 1, 4},         {11506, 0, 1},
+    {42560, 1, 46},        {42624, 1, 24},        {42786, 1, 14},
+    {42802, 1, 62},        {42873, 1, 4},         {42877, 76, 1},
+    {42878, 1, 10},        {42891, 0, 1},         {42893, 74, 1},
+    {42896, 1, 4},         {42912, 1, 10},        {42922, 72, 1},
+    {65313, 14, 26},       
+  };
+  static const unsigned short aiOff[] = {
+   1,     2,     8,     15,    16,    26,    28,    32,    
+   37,    38,    40,    48,    63,    64,    69,    71,    
+   79,    80,    116,   202,   203,   205,   206,   207,   
+   209,   210,   211,   213,   214,   217,   218,   219,   
+   775,   7264,  10792, 10795, 23228, 23256, 30204, 54721, 
+   54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, 
+   57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, 
+   65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, 
+   65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, 
+   65514, 65521, 65527, 65528, 65529, 
+  };
+
+  int ret = c;
+
+  assert( c>=0 );
+  assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
+
+  if( c<128 ){
+    if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
+  }else if( c<65536 ){
+    int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
+    int iLo = 0;
+    int iRes = -1;
+
+    while( iHi>=iLo ){
+      int iTest = (iHi + iLo) / 2;
+      int cmp = (c - aEntry[iTest].iCode);
+      if( cmp>=0 ){
+        iRes = iTest;
+        iLo = iTest+1;
+      }else{
+        iHi = iTest-1;
+      }
+    }
+    assert( iRes<0 || c>=aEntry[iRes].iCode );
+
+    if( iRes>=0 ){
+      const struct TableEntry *p = &aEntry[iRes];
+      if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
+        ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
+        assert( ret>0 );
+      }
+    }
+
+    if( bRemoveDiacritic ) ret = remove_diacritic(ret);
+  }
+  
+  else if( c>=66560 && c<66600 ){
+    ret = c + 40;
+  }
+
+  return ret;
+}
+#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
+#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */
+
+/************** End of fts3_unicode2.c ***************************************/
 /************** Begin file rtree.c *******************************************/
 /*
 ** 2001 September 15
@@ -135392,6 +135003,36 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
 }
 
 /*
+** Rounding constants for float->double conversion.
+*/
+#define RNDTOWARDS  (1.0 - 1.0/8388608.0)  /* Round towards zero */
+#define RNDAWAY     (1.0 + 1.0/8388608.0)  /* Round away from zero */
+
+#if !defined(SQLITE_RTREE_INT_ONLY)
+/*
+** Convert an sqlite3_value into an RtreeValue (presumably a float)
+** while taking care to round toward negative or positive, respectively.
+*/
+static RtreeValue rtreeValueDown(sqlite3_value *v){
+  double d = sqlite3_value_double(v);
+  float f = (float)d;
+  if( f>d ){
+    f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS));
+  }
+  return f;
+}
+static RtreeValue rtreeValueUp(sqlite3_value *v){
+  double d = sqlite3_value_double(v);
+  float f = (float)d;
+  if( f<d ){
+    f = (float)(d*(d<0 ? RNDTOWARDS : RNDAWAY));
+  }
+  return f;
+}
+#endif /* !defined(SQLITE_RTREE_INT_ONLY) */
+
+
+/*
 ** The xUpdate method for rtree module virtual tables.
 */
 static int rtreeUpdate(
@@ -135427,8 +135068,8 @@ static int rtreeUpdate(
 #ifndef SQLITE_RTREE_INT_ONLY
     if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
       for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-        cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]);
-        cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]);
+        cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
+        cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
         if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
           rc = SQLITE_CONSTRAINT;
           goto constraint;
@@ -136681,7 +136322,7 @@ static int icuNext(
 
     while( iStart<iEnd ){
       int iWhite = iStart;
-      U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
+      U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
       if( u_isspace(c) ){
         iStart = iWhite;
       }else{
diff --git a/libgda/sqlite/sqlite-src/sqlite3.h b/libgda/sqlite/sqlite-src/sqlite3.h
index a198489..5a1f9d4 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.12.1"
-#define SQLITE_VERSION_NUMBER 3007012
-#define SQLITE_SOURCE_ID      "2012-05-22 02:45:53 6d326d44fd1d626aae0e8456e5fa2049f1ce0789"
+#define SQLITE_VERSION        "3.7.14.1"
+#define SQLITE_VERSION_NUMBER 3007014
+#define SQLITE_SOURCE_ID      "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -219,7 +219,8 @@ SQLITE_API int sqlite3_threadsafe(void);
 ** the opaque structure named "sqlite3".  It is useful to think of an sqlite3
 ** pointer as an object.  The [sqlite3_open()], [sqlite3_open16()], and
 ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
-** is its destructor.  There are many other interfaces (such as
+** and [sqlite3_close_v2()] are its destructors.  There are many other
+** interfaces (such as
 ** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
 ** [sqlite3_busy_timeout()] to name but three) that are methods on an
 ** sqlite3 object.
@@ -266,28 +267,46 @@ typedef sqlite_uint64 sqlite3_uint64;
 /*
 ** CAPI3REF: Closing A Database Connection
 **
-** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.
-** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is
-** successfully destroyed and all associated resources are deallocated.
-**
-** Applications must [sqlite3_finalize | finalize] all [prepared statements]
-** and [sqlite3_blob_close | close] all [BLOB handles] associated with
-** the [sqlite3] object prior to attempting to close the object.  ^If
+** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
+** for the [sqlite3] object.
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
+** the [sqlite3] object is successfully destroyed and all associated
+** resources are deallocated.
+**
+** ^If the database connection is associated with unfinalized prepared
+** statements or unfinished sqlite3_backup objects then sqlite3_close()
+** will leave the database connection open and return [SQLITE_BUSY].
+** ^If sqlite3_close_v2() is called with unfinalized prepared statements
+** and unfinished sqlite3_backups, then the database connection becomes
+** an unusable "zombie" which will automatically be deallocated when the
+** last prepared statement is finalized or the last sqlite3_backup is
+** finished.  The sqlite3_close_v2() interface is intended for use with
+** host languages that are garbage collected, and where the order in which
+** destructors are called is arbitrary.
+**
+** Applications should [sqlite3_finalize | finalize] all [prepared statements],
+** [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
-** outstanding [prepared statements] or [BLOB handles], then it returns
-** SQLITE_BUSY.
+** 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],
+** and [sqlite3_backup] objects are also destroyed.
 **
-** ^If [sqlite3_close()] is invoked while a transaction is open,
+** ^If an [sqlite3] object is destroyed while a transaction is open,
 ** the transaction is automatically rolled back.
 **
-** The C parameter to [sqlite3_close(C)] must be either a NULL
+** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
+** must be either a NULL
 ** pointer or an [sqlite3] object pointer obtained
 ** from [sqlite3_open()], [sqlite3_open16()], or
 ** [sqlite3_open_v2()], and not previously closed.
-** ^Calling sqlite3_close() with a NULL pointer argument is a 
-** harmless no-op.
+** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
+** argument is a harmless no-op.
 */
-SQLITE_API int sqlite3_close(sqlite3 *);
+SQLITE_API int sqlite3_close(sqlite3*);
+SQLITE_API int sqlite3_close_v2(sqlite3*);
 
 /*
 ** The type for a callback function.
@@ -478,6 +497,7 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_OPEN_EXCLUSIVE        0x00000010  /* VFS only */
 #define SQLITE_OPEN_AUTOPROXY        0x00000020  /* VFS only */
 #define SQLITE_OPEN_URI              0x00000040  /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MEMORY           0x00000080  /* Ok for sqlite3_open_v2() */
 #define SQLITE_OPEN_MAIN_DB          0x00000100  /* VFS only */
 #define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
 #define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
@@ -497,7 +517,7 @@ SQLITE_API int sqlite3_exec(
 ** CAPI3REF: Device Characteristics
 **
 ** The xDeviceCharacteristics method of the [sqlite3_io_methods]
-** object returns an integer which is a vector of the these
+** object returns an integer which is a vector of these
 ** bit values expressing I/O characteristics of the mass storage
 ** device that holds the file that the [sqlite3_io_methods]
 ** refers to.
@@ -2169,12 +2189,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
 ** implementation of these routines to be omitted.  That capability
 ** is no longer provided.  Only built-in memory allocators can be used.
 **
-** The Windows OS interface layer calls
+** Prior to SQLite version 3.7.10, the Windows OS interface layer called
 ** the system malloc() and free() directly when converting
 ** filenames between the UTF-8 encoding used by SQLite
 ** and whatever filename encoding is used by the particular Windows
-** installation.  Memory allocation errors are detected, but
-** they are reported back as [SQLITE_CANTOPEN] or
+** installation.  Memory allocation errors were detected, but
+** they were reported back as [SQLITE_CANTOPEN] or
 ** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
 **
 ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
@@ -2575,18 +2595,20 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     present, then the VFS specified by the option takes precedence over
 **     the value passed as the fourth parameter to sqlite3_open_v2().
 **
-**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
-**     "rwc". Attempting to set it to any other value is an error)^. 
+**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
+**     "rwc", or "memory". Attempting to set it to any other value is
+**     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 
 **     "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 
-**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is 
-**     used, it is an error to specify a value for the mode parameter that is 
-**     less restrictive than that specified by the flags passed as the third 
-**     parameter.
+**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.  ^If the mode option is
+**     set to "memory" then a pure [in-memory database] that never reads
+**     or writes from disk is used. ^It is an error to specify a value for
+**     the mode parameter that is less restrictive than that specified by
+**     the flags passed in the third parameter to sqlite3_open_v2().
 **
 **   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
 **     "private". ^Setting it to "shared" is equivalent to setting the
@@ -2645,6 +2667,12 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** codepage is currently defined.  Filenames containing international
 ** characters must be converted to UTF-8 prior to passing them into
 ** sqlite3_open() or sqlite3_open_v2().
+**
+** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
+** prior to calling sqlite3_open() or sqlite3_open_v2().  Otherwise, various
+** features that require the use of temporary files may fail.
+**
+** See also: [sqlite3_temp_directory]
 */
 SQLITE_API int sqlite3_open(
   const char *filename,   /* Database filename (UTF-8) */
@@ -3137,8 +3165,11 @@ typedef struct sqlite3_context sqlite3_context;
 ** ^(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
 ** number of <u>bytes</u> in the value, not the number of characters.)^
-** ^If the fourth parameter is negative, the length of the string is
+** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** is negative, then the length of the string is
 ** the number of bytes up to the first zero terminator.
+** If the fourth parameter to sqlite3_bind_blob() is negative, then
+** the behavior is undefined.
 ** If a non-negative fourth parameter is provided to sqlite3_bind_text()
 ** or sqlite3_bind_text16() then that parameter must be the byte offset
 ** where the NUL terminator would occur assuming the string were NUL
@@ -4135,11 +4166,11 @@ typedef void (*sqlite3_destructor_type)(void*);
 ** the error code is SQLITE_ERROR.  ^A subsequent call to sqlite3_result_error()
 ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
 **
-** ^The sqlite3_result_toobig() interface causes SQLite to throw an error
-** indicating that a string or BLOB is too long to represent.
+** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
+** error indicating that a string or BLOB is too long to represent.
 **
-** ^The sqlite3_result_nomem() interface causes SQLite to throw an error
-** indicating that a memory allocation failed.
+** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
+** error indicating that a memory allocation failed.
 **
 ** ^The sqlite3_result_int() interface sets the return value
 ** of the application-defined function to be the 32-bit signed integer
@@ -4446,10 +4477,62 @@ SQLITE_API int sqlite3_sleep(int);
 ** Hence, if this variable is modified directly, either it should be
 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
 ** or else the use of the [temp_store_directory pragma] should be avoided.
+**
+** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
+** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
+** features that require the use of temporary files may fail.  Here is an
+** example of how to do this using C++ with the Windows Runtime:
+**
+** <blockquote><pre>
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+** &nbsp;     TemporaryFolder->Path->Data();
+** char zPathBuf&#91;MAX_PATH + 1&#93;;
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+** &nbsp;     NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** </pre></blockquote>
 */
 SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory;
 
 /*
+** CAPI3REF: Name Of The Folder Holding Database Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all database files
+** specified with a relative pathname and created or accessed by
+** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
+** to be relative to that directory.)^ ^If this variable is a NULL
+** pointer, then SQLite assumes that all database files specified
+** with a relative pathname are relative to the current directory
+** for the process.  Only the windows VFS makes use of this global
+** variable; it is ignored by the unix VFS.
+**
+** Changing the value of this variable while a database connection is
+** open can result in a corrupt database.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time.  It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [data_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
+** the [data_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from 
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [data_store_directory pragma] should be avoided.
+*/
+SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
+
+/*
 ** CAPI3REF: Test For Auto-Commit Mode
 ** KEYWORDS: {autocommit mode}
 **
@@ -4627,7 +4710,6 @@ SQLITE_API void *sqlite3_update_hook(
 
 /*
 ** CAPI3REF: Enable Or Disable Shared Pager Cache
-** KEYWORDS: {shared cache}
 **
 ** ^(This routine enables or disables the sharing of the database cache
 ** and schema data structures between [database connection | connections]
@@ -5455,7 +5537,6 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** implementations are available in the SQLite core:
 **
 ** <ul>
-** <li>   SQLITE_MUTEX_OS2
 ** <li>   SQLITE_MUTEX_PTHREADS
 ** <li>   SQLITE_MUTEX_W32
 ** <li>   SQLITE_MUTEX_NOOP
@@ -5463,9 +5544,9 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 **
 ** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
 ** that does no real locking and is appropriate for use in
-** a single-threaded application.  ^The SQLITE_MUTEX_OS2,
-** SQLITE_MUTEX_PTHREADS, and SQLITE_MUTEX_W32 implementations
-** are appropriate for use on OS/2, Unix, and Windows.
+** a single-threaded application.  ^The SQLITE_MUTEX_PTHREADS and
+** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
+** and Windows.
 **
 ** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
 ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
diff --git a/providers/sqlcipher/sqlcipher.patch b/providers/sqlcipher/sqlcipher.patch
index 5452e53..81128dc 100644
--- a/providers/sqlcipher/sqlcipher.patch
+++ b/providers/sqlcipher/sqlcipher.patch
@@ -1,6 +1,6 @@
---- sqlite3.c.sqlite	2012-08-27 14:56:39.000000000 +0200
-+++ sqlite3.c	2012-08-27 14:56:17.000000000 +0200
-@@ -12218,9 +12218,47 @@
+--- 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 @@
  #endif /* _SQLITEINT_H_ */
  
  /************** End of sqliteInt.h *******************************************/
@@ -50,7 +50,7 @@
  **
  ** The author disclaims copyright to this source code.  In place of
  ** a legal notice, here is a blessing:
-@@ -12230,220 +12268,2261 @@
+@@ -12329,220 +12367,2496 @@
  **    May you share freely, never taking more than you give.
  **
  *************************************************************************
@@ -732,6 +732,7 @@
 +#ifndef SQLITE_OMIT_INCRBLOB
 +  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
 +#endif
++  u8 hints;                             /* As configured by CursorSetHints() */
 +  i16 iPage;                            /* Index of current page in apPage */
 +  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
 +  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
@@ -924,7 +925,7 @@
 +#define FILE_HEADER_SZ 16
 +
 +#ifndef CIPHER_VERSION
-+#define CIPHER_VERSION "2.0.6"
++#define CIPHER_VERSION "2.1.1"
 +#endif
 +
 +#ifndef CIPHER
@@ -942,10 +943,16 @@
 +#define PBKDF2_ITER 4000
 +#endif
 +
-+#ifndef DEFAULT_USE_HMAC
-+#define DEFAULT_USE_HMAC 1
++/* possible flags for cipher_ctx->flags */
++#define CIPHER_FLAG_HMAC          0x01
++#define CIPHER_FLAG_LE_PGNO       0x02
++#define CIPHER_FLAG_BE_PGNO       0x04
++
++#ifndef DEFAULT_CIPHER_FLAGS
++#define DEFAULT_CIPHER_FLAGS CIPHER_FLAG_HMAC | CIPHER_FLAG_LE_PGNO
 +#endif
 +
++
 +/* by default, sqlcipher will use a reduced number of iterations to generate
 +   the HMAC key / or transform a raw cipher key 
 +   */
@@ -1019,13 +1026,15 @@
 +typedef struct codec_ctx codec_ctx;
 +
 +/* utility functions */
-+int sqlcipher_ismemset(const unsigned char *a0, unsigned char value, int len);
-+int sqlcipher_memcmp(const unsigned char *a0, const unsigned char *a1, int len);
++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();
 +int sqlcipher_codec_ctx_init(codec_ctx **, Db *, Pager *, sqlite3_file *, const void *, int);
 +void sqlcipher_codec_ctx_free(codec_ctx **);
 +int sqlcipher_codec_key_derive(codec_ctx *);
@@ -1045,19 +1054,33 @@
 +int sqlcipher_codec_ctx_get_reservesize(codec_ctx *);
 +
 +int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int, int);
++int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx, int);
++
 +void* sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx);
 +
 +int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *, int, int);
++int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *, int);
 +
 +int sqlcipher_codec_ctx_set_cipher(codec_ctx *, const char *, int);
++const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx, int for_ctx);
 +
 +void* sqlcipher_codec_ctx_get_data(codec_ctx *);
 +
 +void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **);
 +
 +void sqlcipher_set_default_use_hmac(int use);
++int sqlcipher_get_default_use_hmac();
++
++void sqlcipher_set_hmac_salt_mask(unsigned char mask);
++unsigned char sqlcipher_get_hmac_salt_mask();
 +
 +int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use);
++int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx, int for_ctx);
++
++int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag);
++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
@@ -1067,6 +1090,10 @@
 +/************** End of crypto.h **********************************************/
 +/************** Continuing where we left off in crypto.c *********************/
 +
++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){
 +  Vdbe *v = sqlite3GetVdbe(pParse);
@@ -1076,30 +1103,6 @@
 +  sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
 +}
 +
-+int codec_set_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) {
-+  struct Db *pDb = &db->aDb[nDb];
-+  CODEC_TRACE(("codec_set_kdf_iter: entered db=%p nDb=%d kdf_iter=%d for_ctx=%d\n", db, nDb, kdf_iter, for_ctx));
-+
-+  if(pDb->pBt) {
-+    codec_ctx *ctx;
-+    sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+    if(ctx) return sqlcipher_codec_ctx_set_kdf_iter(ctx, kdf_iter, for_ctx);
-+  }
-+  return SQLITE_ERROR;
-+}
-+
-+int codec_set_fast_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) {
-+  struct Db *pDb = &db->aDb[nDb];
-+  CODEC_TRACE(("codec_set_kdf_iter: entered db=%p nDb=%d kdf_iter=%d for_ctx=%d\n", db, nDb, kdf_iter, for_ctx));
-+
-+  if(pDb->pBt) {
-+    codec_ctx *ctx;
-+    sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+    if(ctx) return sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, kdf_iter, for_ctx);
-+  }
-+  return SQLITE_ERROR;
-+}
-+
 +static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ctx) {
 +  int rc, page_sz, reserve_sz; 
 +
@@ -1118,76 +1121,154 @@
 +  return rc;
 +}
 +
-+void codec_set_default_use_hmac(int use) {
-+  sqlcipher_set_default_use_hmac(use);
-+}
-+
-+int codec_set_use_hmac(sqlite3* db, int nDb, int use) {
++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_use_hmac: entered db=%p nDb=%d use=%d\n", db, nDb, use));
-+
++  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) {
-+    int rc;
 +    codec_ctx *ctx;
 +    sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+    if(ctx) {
-+      rc = sqlcipher_codec_ctx_set_use_hmac(ctx, use);
-+      if(rc != SQLITE_OK) return rc;
-+      /* since the use of hmac has changed, the page size may also change */
-+      return codec_set_btree_to_codec_pagesize(db, pDb, ctx);
-+    }
++    if(ctx) return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx);
 +  }
 +  return SQLITE_ERROR;
-+}
++} 
 +
-+int codec_set_page_size(sqlite3* db, int nDb, int size) {
-+  struct Db *pDb = &db->aDb[nDb];
-+  CODEC_TRACE(("codec_set_page_size: entered db=%p nDb=%d size=%d\n", db, nDb, size));
++int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
++  struct Db *pDb = &db->aDb[iDb];
++  codec_ctx *ctx = NULL;
++  int rc;
 +
 +  if(pDb->pBt) {
-+    int rc;
-+    codec_ctx *ctx;
 +    sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+
-+    if(ctx) {
-+      rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
-+      if(rc != SQLITE_OK) return rc;
-+      return codec_set_btree_to_codec_pagesize(db, pDb, ctx);
-+    }
 +  }
-+  return SQLITE_ERROR;
-+}
 +
-+/**
-+  * 
-+  * when for_ctx == 0 then it will change for read
-+  * when for_ctx == 1 then it will change for write
-+  * when for_ctx == 2 then it will change for both
-+  */
-+int codec_set_cipher_name(sqlite3* db, int nDb, const char *cipher_name, int for_ctx) {
-+  struct Db *pDb = &db->aDb[nDb];
-+  CODEC_TRACE(("codec_set_cipher_name: entered db=%p nDb=%d cipher_name=%s for_ctx=%d\n", db, nDb, cipher_name, for_ctx));
++  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(pDb->pBt) {
-+    codec_ctx *ctx;
-+    sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+    if(ctx) return sqlcipher_codec_ctx_set_cipher(ctx, cipher_name, for_ctx);
++  if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){
++    codec_vdbe_return_static_string(pParse, "cipher_version", codec_get_cipher_version());
++  }else
++  if( sqlite3StrICmp(zLeft, "cipher")==0 ){
++    if(ctx) {
++      if( zRight ) {
++        sqlcipher_codec_ctx_set_cipher(ctx, zRight, 2); // change cipher for both
++      }else {
++        codec_vdbe_return_static_string(pParse, "cipher",
++          sqlcipher_codec_ctx_get_cipher(ctx, 2));
++      }
++    }
++  }else
++  if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
++    if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 1); // change write cipher only 
++  }else
++  if( sqlite3StrICmp(zLeft, "kdf_iter")==0 ){
++    if(ctx) {
++      if( zRight ) {
++        sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration 
++      } else {
++        char *kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_kdf_iter(ctx, 2));
++        codec_vdbe_return_static_string(pParse, "kdf_iter", kdf_iter);
++        sqlite3_free(kdf_iter);
++      }
++    }
++  }else
++  if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0){
++    if(ctx) {
++      if( zRight ) {
++        sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration 
++      } else {
++        char *fast_kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_fast_kdf_iter(ctx, 2));
++        codec_vdbe_return_static_string(pParse, "fast_kdf_iter", fast_kdf_iter);
++        sqlite3_free(fast_kdf_iter);
++      }
++    }
++  }else
++  if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
++    if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 1); // write iterations only
++  }else
++  if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){
++    if(ctx) {
++      if( zRight ) {
++        int size = atoi(zRight);
++        rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
++        if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
++        rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
++        if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
++      } else {
++        char * page_size = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx));
++        codec_vdbe_return_static_string(pParse, "cipher_page_size", page_size);
++        sqlite3_free(page_size);
++      }
++    }
++  }else
++  if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){
++    if( zRight ) {
++      sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1));
++    } else {
++      char *default_use_hmac = sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac());
++      codec_vdbe_return_static_string(pParse, "cipher_default_use_hmac", default_use_hmac);
++      sqlite3_free(default_use_hmac);
++    }
++  }else
++  if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){
++    if(ctx) {
++      if( zRight ) {
++        rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlite3GetBoolean(zRight,1));
++        if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
++        /* since the use of hmac has changed, the page size may also change */
++        rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
++        if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
++      } else {
++        char *hmac_flag = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx, 2));
++        codec_vdbe_return_static_string(pParse, "cipher_use_hmac", hmac_flag);
++        sqlite3_free(hmac_flag);
++      }
++    }
++  }else
++  if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){
++    if(ctx) {
++      if(zRight) {
++        // clear both pgno endian flags
++        if(sqlite3StrICmp(zRight, "le") == 0) {
++          sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
++          sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
++        } else if(sqlite3StrICmp(zRight, "be") == 0) {
++          sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
++          sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
++        } else if(sqlite3StrICmp(zRight, "native") == 0) {
++          sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
++          sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
++        }
++      } else {
++        if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_LE_PGNO, 2)) {
++          codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "le");
++        } else if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_BE_PGNO, 2)) {
++          codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "be");
++        } else {
++          codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "native");
++        }
++      }
++    }
++  }else
++  if( sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){
++    if(ctx) {
++      if(zRight) {
++        if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) {
++          unsigned char mask = 0;
++          const char *hex = zRight+2;
++          cipher_hex2bin(hex,2,&mask);
++          sqlcipher_set_hmac_salt_mask(mask);
++        }
++      } else {
++          char *hmac_salt_mask = sqlite3_mprintf("%02x", sqlcipher_get_hmac_salt_mask());
++          codec_vdbe_return_static_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask);
++          sqlite3_free(hmac_salt_mask);
++      }
++    }
++  }else {
++    return 0;
 +  }
-+  return SQLITE_ERROR;
++  return 1;
 +}
 +
-+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) {
-+    codec_ctx *ctx;
-+    sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+    if(ctx) return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx);
-+  }
-+  return SQLITE_ERROR;
-+} 
-+
 +/*
 + * sqlite3Codec can be called in multiple modes.
 + * encrypt mode - expected to return a pointer to the 
@@ -1245,6 +1326,7 @@
 +  codec_ctx *ctx = (codec_ctx *) pCodecArg;
 +  if(pCodecArg == NULL) return;
 +  sqlcipher_codec_ctx_free(&ctx); // wipe and free allocated memory for the context 
++  sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */
 +}
 +
 +SQLITE_PRIVATE int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
@@ -1252,7 +1334,6 @@
 +
 +  CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey));
 +
-+  sqlcipher_activate();
 +
 +  if(nKey && zKey && pDb->pBt) {
 +    int rc;
@@ -1260,9 +1341,15 @@
 +    sqlite3_file *fd = sqlite3Pager_get_fd(pPager);
 +    codec_ctx *ctx;
 +
++    sqlcipher_activate(); /* perform internal initialization for sqlcipher */
++
 +    /* 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);
@@ -1275,7 +1362,6 @@
 +    /* if fd is null, then this is an in-memory database and
 +       we dont' want to overwrite the AutoVacuum settings
 +       if not null, then set to the default */
-+    sqlite3_mutex_enter(db->mutex);
 +    if(fd != NULL) { 
 +      sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
 +    }
@@ -1292,8 +1378,7 @@
 +  CODEC_TRACE(("sqlite3_key: entered db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
 +  /* attach key if db and pKey are not null and nKey is > 0 */
 +  if(db && pKey && nKey) {
-+    sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db 
-+    return SQLITE_OK;
++    return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db 
 +  }
 +  return SQLITE_ERROR;
 +}
@@ -1310,7 +1395,6 @@
 +*/
 +SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
 +  CODEC_TRACE(("sqlite3_rekey: entered db=%p pKey=%s, nKey=%d\n", db, (char *)pKey, nKey));
-+  sqlcipher_activate();
 +  if(db && pKey && nKey) {
 +    struct Db *pDb = &db->aDb[0];
 +    CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb));
@@ -1459,7 +1543,7 @@
 +  int pass_sz;
 +  int reserve_sz;
 +  int hmac_sz;
-+  int use_hmac;
++  unsigned int flags;
 +  unsigned char *key;
 +  unsigned char *hmac_key;
 +  char *pass;
@@ -1475,7 +1559,11 @@
 +/* prototype for pager HMAC function */
 +int sqlcipher_page_hmac(cipher_ctx *, Pgno, unsigned char *, int, unsigned char *);
 +
-+static int default_use_hmac = DEFAULT_USE_HMAC;
++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;
 +
 +struct codec_ctx {
 +  int kdf_salt_sz;
@@ -1488,31 +1576,93 @@
 +  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. 
++*/
 +void sqlcipher_activate() {
 +  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+  if(EVP_get_cipherbyname(CIPHER) == NULL) {
-+    OpenSSL_add_all_algorithms();
++
++  /* 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();
++    }
++    openssl_init_count++; 
 +  } 
 +  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 +}
 +
-+/* fixed time zero memory check tests every position of a memory segement
-+   matches a single value (i.e. the memory is all zeros)*/
-+int sqlcipher_ismemset(const unsigned char *a0, unsigned char value, int len) {
-+  int i = 0, noMatch = 0;
-+  for(i = 0; i < len; i++) noMatch = (noMatch || (a0[i] != value)); 
-+  return noMatch;
++/* 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();
++    }
++  }
++  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
++}
++
++/* 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)
++*/
++void* sqlcipher_memset(void *v, unsigned char value, int len) {
++  int i = 0;
++  volatile unsigned char *a = v;
++
++  if (v == NULL) return v;
++
++  for(i = 0; i < len; i++) {
++    a[i] = value;
++  }
++
++  return v;
++}
++
++/* 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;
++
++  for(i = 0; i < len; i++) {
++    result |= a[i] ^ value;
++  }
++
++  return (result != 0);
 +}
 +
-+/* fixed time memory comparison routine */
-+int sqlcipher_memcmp(const unsigned char *a0, const unsigned char *a1, int len) {
-+  int i = 0, noMatch = 0;
++/* 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;
 +
 +  for(i = 0; i < len; i++) {
-+    noMatch = (noMatch || (a0[i] != a1[i]));
++    result |= a0[i] ^ a1[i];
 +  }
 +  
-+  return noMatch;
++  return (result != 0);
 +}
 +
 +/* generate a defined number of pseudorandom bytes */
@@ -1522,7 +1672,7 @@
 +
 +/**
 +  * Free and wipe memory. Uses SQLites internal sqlite3_free so that memory
-+  * can be countend and memory leak detection works in the tet suite. 
++  * can be countend and memory leak detection works in the test suite. 
 +  * If ptr is not null memory will be freed. 
 +  * If sz is greater than zero, the memory will be overwritten with zero before it is freed
 +  * If sz is > 0, and not compiled with OMIT_MEMLOCK, system will attempt to unlock the
@@ -1531,7 +1681,7 @@
 +void sqlcipher_free(void *ptr, int sz) {
 +  if(ptr) {
 +    if(sz > 0) {
-+      memset(ptr, 0, sz);
++      sqlcipher_memset(ptr, 0, sz);
 +#ifndef OMIT_MEMLOCK
 +#if defined(__unix__) || defined(__APPLE__) 
 +      munlock(ptr, sz);
@@ -1551,6 +1701,7 @@
 +  */
 +void* sqlcipher_malloc(int sz) {
 +  void *ptr = sqlite3Malloc(sz);
++  sqlcipher_memset(ptr, 0, sz);
 +#ifndef OMIT_MEMLOCK
 +  if(ptr) {
 +#if defined(__unix__) || defined(__APPLE__) 
@@ -1565,7 +1716,7 @@
 +
 +
 +/**
-+  * Initialize a a new cipher_ctx struct. This function will allocate memory
++  * Initialize new cipher_ctx struct. This function will allocate memory
 +  * for the cipher context and for the key
 +  * 
 +  * returns SQLITE_OK if initialization was successful
@@ -1576,11 +1727,15 @@
 +  *iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx));
 +  ctx = *iCtx;
 +  if(ctx == NULL) return SQLITE_NOMEM;
-+  memset(ctx, 0, sizeof(cipher_ctx)); 
++
 +  ctx->key = (unsigned char *) sqlcipher_malloc(EVP_MAX_KEY_LENGTH);
 +  ctx->hmac_key = (unsigned char *) sqlcipher_malloc(EVP_MAX_KEY_LENGTH);
 +  if(ctx->key == NULL) return SQLITE_NOMEM;
 +  if(ctx->hmac_key == NULL) return SQLITE_NOMEM;
++
++  /* setup default flags */
++  ctx->flags = default_flags;
++
 +  return SQLITE_OK;
 +}
 +
@@ -1612,7 +1767,7 @@
 +    && c1->fast_kdf_iter == c2->fast_kdf_iter
 +    && c1->key_sz == c2->key_sz
 +    && c1->pass_sz == c2->pass_sz
-+    && c1->use_hmac == c2->use_hmac
++    && c1->flags == c2->flags
 +    && c1->hmac_sz == c2->hmac_sz
 +    && (
 +      c1->pass == c2->pass
@@ -1705,6 +1860,12 @@
 +  return SQLITE_OK;
 +}
 +
++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);
++}
++
 +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;
@@ -1719,6 +1880,11 @@
 +  return SQLITE_OK;
 +}
 +
++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;
++}
++
 +int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *ctx, int fast_kdf_iter, int for_ctx) {
 +  cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
 +  int rc;
@@ -1733,9 +1899,27 @@
 +  return SQLITE_OK;
 +}
 +
++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;
++}
++
 +/* set the global default flag for HMAC */
 +void sqlcipher_set_default_use_hmac(int use) {
-+  default_use_hmac = use;
++  if(use) default_flags |= CIPHER_FLAG_HMAC; 
++  else default_flags &= ~CIPHER_FLAG_HMAC; 
++}
++
++int sqlcipher_get_default_use_hmac() {
++  return (default_flags & CIPHER_FLAG_HMAC) != 0;
++}
++
++void sqlcipher_set_hmac_salt_mask(unsigned char mask) {
++  hmac_salt_mask = mask;
++}
++
++unsigned char sqlcipher_get_hmac_salt_mask() {
++  return hmac_salt_mask;
 +}
 +
 +/* set the codec flag for whether this individual database should be using hmac */
@@ -1752,22 +1936,46 @@
 +  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)); 
 +
-+  ctx->write_ctx->use_hmac = ctx->read_ctx->use_hmac = use;
++  
++  if(use) {
++    sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_HMAC);
++  } else {
++    sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_HMAC);
++  } 
++  
 +  ctx->write_ctx->reserve_sz = ctx->read_ctx->reserve_sz = reserve;
 +
 +  return SQLITE_OK;
 +}
 +
++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;
++}
++
++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;
++}
++
++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;
++}
++
++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;
++}
++
 +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_pagesize(codec_ctx *ctx) {
-+  return ctx->page_sz;
-+}
-+
 +int sqlcipher_codec_ctx_get_reservesize(codec_ctx *ctx) {
 +  return ctx->read_ctx->reserve_sz;
 +}
@@ -1799,6 +2007,10 @@
 +  return SQLITE_OK;
 +}
 +
++int sqlcipher_codec_ctx_get_pagesize(codec_ctx *ctx) {
++  return ctx->page_sz;
++}
++
 +int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_file *fd, const void *zKey, int nKey) {
 +  int rc;
 +  codec_ctx *ctx;
@@ -1807,7 +2019,6 @@
 +
 +  if(ctx == NULL) return SQLITE_NOMEM;
 +
-+  memset(ctx, 0, sizeof(codec_ctx)); /* initialize all pointers and values to 0 */
 +  ctx->pBt = pDb->pBt; /* assign pointer to database btree structure */
 +
 +  /* allocate space for salt data. Then read the first 16 bytes 
@@ -1845,9 +2056,9 @@
 +  if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
 +  if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc;
 +
-+  /* Use HMAC signatures by default. Note that codec_set_use_hmac will implicity call
-+     codec_set_page_size to set the default */
-+  if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_use_hmac)) != SQLITE_OK) return rc;
++  /* Note that use_hmac is a special case that requires recalculation of page size
++     so we call set_use_hmac to perform setup */
++  if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_flags & CIPHER_FLAG_HMAC)) != SQLITE_OK) return rc;
 +
 +  if((rc = sqlcipher_cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx)) != SQLITE_OK) return rc;
 +
@@ -1869,16 +2080,40 @@
 +  sqlcipher_free(ctx, sizeof(codec_ctx)); 
 +}
 +
++/** convert a 32bit unsigned integer to little endian byte ordering */
++static void sqlcipher_put4byte_le(unsigned char *p, u32 v) { 
++  p[0] = (u8)v;
++  p[1] = (u8)(v>>8);
++  p[2] = (u8)(v>>16);
++  p[3] = (u8)(v>>24);
++}
++
 +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. 
++
++     Note: The public release of sqlcipher 2.0.0 to 2.0.6 had a bug where the bytes of pgno 
++     were used directly in the MAC. SQLCipher convert's to little endian by default to preserve
++     backwards compatibility on the most popular platforms, but can optionally be configured
++     to use either big endian or native byte ordering via pragma. */
++
++  if(ctx->flags & CIPHER_FLAG_LE_PGNO) { /* compute hmac using little endian pgno*/
++    sqlcipher_put4byte_le(pgno_raw, pgno);
++  } else if(ctx->flags & CIPHER_FLAG_BE_PGNO) { /* compute hmac using big endian pgno */
++    sqlite3Put4byte(pgno_raw, pgno); /* sqlite3Put4byte converts 32bit uint to big endian  */
++  } else { /* use native byte ordering */
++    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, sizeof(Pgno));
++  HMAC_Update(&ctx->hctx, (const unsigned char*) pgno_raw, sizeof(pgno)); 
 +  HMAC_Final(&ctx->hctx, out, NULL);
 +  HMAC_CTX_cleanup(&ctx->hctx);
 +  return SQLITE_OK; 
@@ -1903,7 +2138,7 @@
 +  iv_in = in + size;
 +
 +  /* hmac will be written immediately after the initialization vector. the remainder of the page reserve will contain
-+     random bytes. note, these pointers are only valid when use_hmac is true */
++     random bytes. note, these pointers are only valid when using hmac */
 +  hmac_in = in + size + c_ctx->iv_sz; 
 +  hmac_out = out + size + c_ctx->iv_sz;
 +  out_start = out; /* note the original position of the output buffer pointer, as out will be rewritten during encryption */
@@ -1914,7 +2149,7 @@
 +  /* the key size should never be zero. If it is, error out. */
 +  if(c_ctx->key_sz == 0) {
 +    CODEC_TRACE(("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno));
-+    memset(out, 0, page_sz); 
++    sqlcipher_memset(out, 0, page_sz); 
 +    return SQLITE_ERROR;
 +  } 
 +
@@ -1925,9 +2160,9 @@
 +    memcpy(iv_out, iv_in, c_ctx->iv_sz); /* copy the iv from the input to output buffer */
 +  } 
 +
-+  if(c_ctx->use_hmac && (mode == CIPHER_DECRYPT)) {
++  if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT)) {
 +    if(sqlcipher_page_hmac(c_ctx, pgno, in, size + c_ctx->iv_sz, hmac_out) != SQLITE_OK) {
-+      memset(out, 0, page_sz); 
++      sqlcipher_memset(out, 0, page_sz); 
 +      CODEC_TRACE(("codec_cipher: hmac operations failed for pgno=%d\n", pgno));
 +      return SQLITE_ERROR;
 +    }
@@ -1940,14 +2175,14 @@
 +           short read failures must be ignored for autovaccum mode to work so wipe the output buffer 
 +           and return SQLITE_OK to skip the decryption step. */
 +        CODEC_TRACE(("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno));
-+        memset(out, 0, page_sz); 
++        sqlcipher_memset(out, 0, page_sz); 
 +  	return SQLITE_OK;
 +      } else {
 +	/* if the page memory is not all zeros, it means the there was data and a hmac on the page. 
 +           since the check failed, the page was either tampered with or corrupted. wipe the output buffer,
 +           and return SQLITE_ERROR to the caller */
 +      	CODEC_TRACE(("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno));
-+        memset(out, 0, page_sz); 
++        sqlcipher_memset(out, 0, page_sz); 
 +      	return SQLITE_ERROR;
 +      }
 +    }
@@ -1964,7 +2199,7 @@
 +  EVP_CIPHER_CTX_cleanup(&c_ctx->ectx);
 +  assert(size == csz);
 +
-+  if(c_ctx->use_hmac && (mode == CIPHER_ENCRYPT)) {
++  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); 
 +  }
 +
@@ -2009,7 +2244,7 @@
 +    /* if this context is setup to use hmac checks, generate a seperate and different 
 +       key for HMAC. In this case, we use the output of the previous KDF as the input to 
 +       this KDF run. This ensures a distinct but predictable HMAC key. */
-+    if(c_ctx->use_hmac) {
++    if(c_ctx->flags & CIPHER_FLAG_HMAC) {
 +      int i;
 +
 +      /* start by copying the kdf key into the hmac salt slot
@@ -2019,7 +2254,7 @@
 +         to generate the encryption key */ 
 +      memcpy(ctx->hmac_kdf_salt, ctx->kdf_salt, ctx->kdf_salt_sz);
 +      for(i = 0; i < ctx->kdf_salt_sz; i++) {
-+        ctx->hmac_kdf_salt[i] ^= HMAC_SALT_MASK;
++        ctx->hmac_kdf_salt[i] ^= hmac_salt_mask;
 +      } 
 +
 +      CODEC_TRACE(("codec_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n", 
@@ -2490,7 +2725,7 @@
  ** The author disclaims copyright to this source code.  In place of
  ** a legal notice, here is a blessing:
  **
-@@ -24967,7 +27046,7 @@
+@@ -22677,7 +24991,7 @@
  #include <sys/time.h>
  #include <errno.h>
  #ifndef SQLITE_OMIT_WAL
@@ -2499,41 +2734,10 @@
  #endif
  
  
-@@ -45561,24 +47640,56 @@
- }
- #endif
+@@ -43883,6 +46197,38 @@
+ 
+ #endif /* SQLITE_OMIT_DISKIO */
  
--#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.
--*/
--SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
--  void *aData = 0;
--  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
--  return aData;
-+#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.
-+*/
-+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 */
-+
-+#endif /* !SQLITE_OMIT_WAL */
-+
-+#endif /* SQLITE_OMIT_DISKIO */
-+
 +/* BEGIN CRYPTO */
 +#ifdef SQLITE_HAS_CODEC
 +SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx) {
@@ -2560,64 +2764,339 @@
 +
 +SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetError( Pager *pPager, int error) {
 +  pPager->errCode = error;
- }
--#endif /* SQLITE_HAS_CODEC */
- 
--#endif /* !SQLITE_OMIT_WAL */
++}
++
 +#endif
 +/* END CRYPTO */
- 
--#endif /* SQLITE_OMIT_DISKIO */
- 
++
++
  /************** End of pager.c ***********************************************/
  /************** Begin file wal.c *********************************************/
-@@ -46100,3253 +48211,2590 @@
- static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
-   int rc = SQLITE_OK;
- 
--  /* Enlarge the pWal->apWiData[] array if required */
--  if( pWal->nWiData<=iPage ){
--    int nByte = sizeof(u32*)*(iPage+1);
--    volatile u32 **apNew;
--    apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
--    if( !apNew ){
--      *ppPage = 0;
--      return SQLITE_NOMEM;
--    }
--    memset((void*)&apNew[pWal->nWiData], 0,
--           sizeof(u32*)*(iPage+1-pWal->nWiData));
--    pWal->apWiData = apNew;
--    pWal->nWiData = iPage+1;
--  }
--
--  /* Request a pointer to the required page from the VFS */
--  if( pWal->apWiData[iPage]==0 ){
--    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
--      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
--      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
--    }else{
--      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
--          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
--      );
--      if( rc==SQLITE_READONLY ){
--        pWal->readOnly |= WAL_SHM_RDONLY;
--        rc = SQLITE_OK;
--      }
--    }
--  }
+ /*
+@@ -44127,3533 +46473,2869 @@
+ ** that correspond to frames greater than the new K value are removed
+ ** from the hash table at this point.
+ */
+-#ifndef SQLITE_OMIT_WAL
 -
--  *ppPage = pWal->apWiData[iPage];
--  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
--  return rc;
--}
 -
 -/*
--** Return a pointer to the WalCkptInfo structure in the wal-index.
+-** Trace output macros
 -*/
--static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
--  assert( pWal->nWiData>0 && pWal->apWiData[0] );
--  return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
--}
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+-SQLITE_PRIVATE int sqlite3WalTrace = 0;
+-# define WALTRACE(X)  if(sqlite3WalTrace) sqlite3DebugPrintf X
+-#else
+-# define WALTRACE(X)
+-#endif
+-
+-/*
+-** The maximum (and only) versions of the wal and wal-index formats
+-** that may be interpreted by this version of SQLite.
+-**
+-** If a client begins recovering a WAL file and finds that (a) the checksum
+-** values in the wal-header are correct and (b) the version field is not
+-** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
+-**
+-** Similarly, if a client successfully reads a wal-index header (i.e. the 
+-** 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.
+-*/
+-#define WAL_MAX_VERSION      3007000
+-#define WALINDEX_MAX_VERSION 3007000
+-
+-/*
+-** Indices of various locking bytes.   WAL_NREADER is the number
+-** of available reader locks and should be at least 3.
+-*/
+-#define WAL_WRITE_LOCK         0
+-#define WAL_ALL_BUT_WRITE      1
+-#define WAL_CKPT_LOCK          1
+-#define WAL_RECOVER_LOCK       2
+-#define WAL_READ_LOCK(I)       (3+(I))
+-#define WAL_NREADER            (SQLITE_SHM_NLOCK-3)
+-
+-
+-/* Object declarations */
+-typedef struct WalIndexHdr WalIndexHdr;
+-typedef struct WalIterator WalIterator;
+-typedef struct WalCkptInfo WalCkptInfo;
+-
+-
+-/*
+-** 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.
+-**
+-** 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.  
+-*/
+-struct WalIndexHdr {
+-  u32 iVersion;                   /* Wal-index version */
+-  u32 unused;                     /* Unused (padding) field */
+-  u32 iChange;                    /* Counter incremented each transaction */
+-  u8 isInit;                      /* 1 when initialized */
+-  u8 bigEndCksum;                 /* True if checksums in WAL are big-endian */
+-  u16 szPage;                     /* Database page size in bytes. 1==64K */
+-  u32 mxFrame;                    /* Index of last valid frame in the WAL */
+-  u32 nPage;                      /* Size of database in pages */
+-  u32 aFrameCksum[2];             /* Checksum of last frame in log */
+-  u32 aSalt[2];                   /* Two salt values copied from WAL header */
+-  u32 aCksum[2];                  /* Checksum over all prior fields */
+-};
+-
+-/*
+-** 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.
+-**
+-** nBackfill is the number of frames in the WAL that have been written
+-** back into the database. (We call the act of moving content from WAL to
+-** database "backfilling".)  The nBackfill number is never greater than
+-** WalIndexHdr.mxFrame.  nBackfill can only be increased by threads
+-** 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.
+-**
+-** 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)
+-** for any aReadMark[] means that entry is unused.  aReadMark[0] is 
+-** a special case; its value is never used and it exists as a place-holder
+-** 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.
+-**
+-** 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 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
+-** WAL_READ_LOCK(j)).  New readers (usually) pick the aReadMark[] with the
+-** largest value and will increase an unused aReadMark[] to mxFrame if there
+-** is not already an aReadMark[] equal to mxFrame.  The exception to the
+-** previous sentence is when nBackfill equals mxFrame (meaning that everything
+-** in the WAL has been backfilled into the database) then new readers
+-** 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.
+-**
+-** 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.
+-**
+-** We assume that 32-bit loads are atomic and so no locks are needed in
+-** order to read from any aReadMark[] entries.
+-*/
+-struct WalCkptInfo {
+-  u32 nBackfill;                  /* Number of WAL frames backfilled into DB */
+-  u32 aReadMark[WAL_NREADER];     /* Reader marks */
+-};
+-#define READMARK_NOT_USED  0xffffffff
+-
+-
+-/* 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
+-** from the region of the file on which locks are applied.
+-*/
+-#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
+-
+-/* Size of write ahead log header, including checksum. */
+-/* #define WAL_HDRSIZE 24 */
+-#define WAL_HDRSIZE 32
+-
+-/* 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.
+-**
+-** If the LSB is set, then the checksums for each frame within the WAL
+-** file are calculated by treating all data as an array of 32-bit 
+-** big-endian words. Otherwise, they are calculated by interpreting 
+-** all data as 32-bit little-endian words.
+-*/
+-#define WAL_MAGIC 0x377f0682
+-
+-/*
+-** Return the offset of frame iFrame in the write-ahead log file, 
+-** assuming a database page size of szPage bytes. The offset returned
+-** is to the start of the write-ahead log frame-header.
+-*/
+-#define walFrameOffset(iFrame, szPage) (                               \
+-  WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE)         \
+-)
+-
+-/*
+-** An open write-ahead log file is represented by an instance of the
+-** following object.
+-*/
+-struct Wal {
+-  sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
+-  sqlite3_file *pDbFd;       /* File handle for the database file */
+-  sqlite3_file *pWalFd;      /* File handle for WAL file */
+-  u32 iCallback;             /* Value to pass to log callback (or 0) */
+-  i64 mxWalSize;             /* Truncate WAL to this size upon reset */
+-  int nWiData;               /* Size of array apWiData */
+-  int szFirstBlock;          /* Size of first block written to WAL file */
+-  volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
+-  u32 szPage;                /* Database page size */
+-  i16 readLock;              /* Which read lock is being held.  -1 for none */
+-  u8 syncFlags;              /* Flags to use to sync header writes */
+-  u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
+-  u8 writeLock;              /* True if in a write transaction */
+-  u8 ckptLock;               /* True if holding a checkpoint lock */
+-  u8 readOnly;               /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
+-  u8 truncateOnCommit;       /* True to truncate WAL file on commit */
+-  u8 syncHeader;             /* Fsync the WAL header if true */
+-  u8 padToSectorBoundary;    /* Pad transactions out to the next sector */
+-  WalIndexHdr hdr;           /* Wal-index header for current transaction */
+-  const char *zWalName;      /* Name of WAL file */
+-  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
+-#ifdef SQLITE_DEBUG
+-  u8 lockError;              /* True if a locking error has occurred */
+-#endif
+-};
+-
+-/*
+-** Candidate values for Wal.exclusiveMode.
+-*/
+-#define WAL_NORMAL_MODE     0
+-#define WAL_EXCLUSIVE_MODE  1     
+-#define WAL_HEAPMEMORY_MODE 2
+-
+-/*
+-** Possible values for WAL.readOnly
+-*/
+-#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 */
+-
+-/*
+-** Each page of the wal-index mapping contains a hash-table made up of
+-** an array of HASHTABLE_NSLOT elements of the following type.
+-*/
+-typedef u16 ht_slot;
+-
+-/*
+-** 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 
+-** frame most recently written to the WAL (in other words, the frame with
+-** the largest index).
+-**
+-** The internals of this structure are only accessed by:
+-**
+-**   walIteratorInit() - Create a new iterator,
+-**   walIteratorNext() - Step an iterator,
+-**   walIteratorFree() - Free an iterator.
+-**
+-** This functionality is used by the checkpoint code (see walCheckpoint()).
+-*/
+-struct WalIterator {
+-  int iPrior;                     /* Last result returned from the iterator */
+-  int nSegment;                   /* Number of entries in aSegment[] */
+-  struct WalSegment {
+-    int iNext;                    /* Next slot in aIndex[] not yet returned */
+-    ht_slot *aIndex;              /* i0, i1, i2... such that aPgno[iN] ascend */
+-    u32 *aPgno;                   /* Array of page numbers. */
+-    int nEntry;                   /* Nr. of entries in aPgno[] and aIndex[] */
+-    int iZero;                    /* Frame number associated with aPgno[0] */
+-  } aSegment[1];                  /* One for every 32KB page in the wal-index */
+-};
+-
+-/*
+-** 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.
+-**
+-** Changing any of these constants will alter the wal-index format and
+-** create incompatibilities.
+-*/
+-#define HASHTABLE_NPAGE      4096                 /* Must be power of 2 */
+-#define HASHTABLE_HASH_1     383                  /* Should be prime */
+-#define HASHTABLE_NSLOT      (HASHTABLE_NPAGE*2)  /* Must be a power of 2 */
+-
+-/* 
+-** 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.
+-*/
+-#define HASHTABLE_NPAGE_ONE  (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
+-
+-/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
+-#define WALINDEX_PGSZ   (                                         \
+-    sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
+-)
+-
+-/*
+-** 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.
+-**
+-** 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.
+-*/
+-static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
+-  int rc = SQLITE_OK;
+-
+-  /* Enlarge the pWal->apWiData[] array if required */
+-  if( pWal->nWiData<=iPage ){
+-    int nByte = sizeof(u32*)*(iPage+1);
+-    volatile u32 **apNew;
+-    apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
+-    if( !apNew ){
+-      *ppPage = 0;
+-      return SQLITE_NOMEM;
+-    }
+-    memset((void*)&apNew[pWal->nWiData], 0,
+-           sizeof(u32*)*(iPage+1-pWal->nWiData));
+-    pWal->apWiData = apNew;
+-    pWal->nWiData = iPage+1;
+-  }
+-
+-  /* Request a pointer to the required page from the VFS */
+-  if( pWal->apWiData[iPage]==0 ){
+-    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+-      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
+-      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
+-    }else{
+-      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
+-          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
+-      );
+-      if( rc==SQLITE_READONLY ){
+-        pWal->readOnly |= WAL_SHM_RDONLY;
+-        rc = SQLITE_OK;
+-      }
+-    }
+-  }
+-
+-  *ppPage = pWal->apWiData[iPage];
+-  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
+-  return rc;
+-}
+-
+-/*
+-** Return a pointer to the WalCkptInfo structure in the wal-index.
+-*/
+-static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
+-  assert( pWal->nWiData>0 && pWal->apWiData[0] );
+-  return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
+-}
 -
 -/*
 -** Return a pointer to the WalIndexHdr structure in the wal-index.
@@ -2798,13 +3277,15 @@
 -  *pnTruncate = sqlite3Get4byte(&aFrame[4]);
 -  return 1;
 -}
--
--
++#ifndef SQLITE_OMIT_WAL
+ 
+ 
 -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
--/*
+ /*
 -** Names of locks.  This routine is used to provide debugging output and is not
 -** a part of an ordinary build.
--*/
++** Trace output macros
+ */
 -static const char *walLockName(int lockIdx){
 -  if( lockIdx==WAL_WRITE_LOCK ){
 -    return "WRITE-LOCK";
@@ -2821,14 +3302,30 @@
 -}
 -#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
 -    
--
--/*
++#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
++SQLITE_PRIVATE int sqlite3WalTrace = 0;
++# define WALTRACE(X)  if(sqlite3WalTrace) sqlite3DebugPrintf X
++#else
++# define WALTRACE(X)
++#endif
+ 
+ /*
 -** 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.
--**
++** The maximum (and only) versions of the wal and wal-index formats
++** that may be interpreted by this version of SQLite.
+ **
 -** In locking_mode=EXCLUSIVE, all of these routines become no-ops.
--*/
++** If a client begins recovering a WAL file and finds that (a) the checksum
++** values in the wal-header are correct and (b) the version field is not
++** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
++**
++** Similarly, if a client successfully reads a wal-index header (i.e. the 
++** 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.
+ */
 -static int walLockShared(Wal *pWal, int lockIdx){
 -  int rc;
 -  if( pWal->exclusiveMode ) return SQLITE_OK;
@@ -2862,8 +3359,10 @@
 -  WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
 -             walLockName(lockIdx), n));
 -}
--
--/*
++#define WAL_MAX_VERSION      3007000
++#define WALINDEX_MAX_VERSION 3007000
+ 
+ /*
 -** 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.
@@ -2890,7 +3389,9 @@
 -**
 -** Finally, set *paPgno so that *paPgno[1] is the page number of the
 -** first frame indexed by the hash table, frame (*piZero+1).
--*/
++** Indices of various locking bytes.   WAL_NREADER is the number
++** of available reader locks and should be at least 3.
+ */
 -static int walHashGet(
 -  Wal *pWal,                      /* WAL handle */
 -  int iHash,                      /* Find the iHash'th table */
@@ -2903,11 +3404,17 @@
 -
 -  rc = walIndexPage(pWal, iHash, &aPgno);
 -  assert( rc==SQLITE_OK || iHash>0 );
--
++#define WAL_WRITE_LOCK         0
++#define WAL_ALL_BUT_WRITE      1
++#define WAL_CKPT_LOCK          1
++#define WAL_RECOVER_LOCK       2
++#define WAL_READ_LOCK(I)       (3+(I))
++#define WAL_NREADER            (SQLITE_SHM_NLOCK-3)
+ 
 -  if( rc==SQLITE_OK ){
 -    u32 iZero;
 -    volatile ht_slot *aHash;
--
+ 
 -    aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE];
 -    if( iHash==0 ){
 -      aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
@@ -2922,7 +3429,11 @@
 -  }
 -  return rc;
 -}
--
++/* Object declarations */
++typedef struct WalIndexHdr WalIndexHdr;
++typedef struct WalIterator WalIterator;
++typedef struct WalCkptInfo WalCkptInfo;
+ 
 -/*
 -** Return the number of the wal-index page that contains the hash-table
 -** and page-number array that contain entries corresponding to WAL frame
@@ -2939,10 +3450,18 @@
 -  );
 -  return iHash;
 -}
--
--/*
+ 
+ /*
 -** Return the page number associated with frame iFrame in this WAL.
--*/
++** 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.
++**
++** 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.  
+ */
 -static u32 walFramePgno(Wal *pWal, u32 iFrame){
 -  int iHash = walFramePage(iFrame);
 -  if( iHash==0 ){
@@ -2950,19 +3469,77 @@
 -  }
 -  return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE];
 -}
--
--/*
++struct WalIndexHdr {
++  u32 iVersion;                   /* Wal-index version */
++  u32 unused;                     /* Unused (padding) field */
++  u32 iChange;                    /* Counter incremented each transaction */
++  u8 isInit;                      /* 1 when initialized */
++  u8 bigEndCksum;                 /* True if checksums in WAL are big-endian */
++  u16 szPage;                     /* Database page size in bytes. 1==64K */
++  u32 mxFrame;                    /* Index of last valid frame in the WAL */
++  u32 nPage;                      /* Size of database in pages */
++  u32 aFrameCksum[2];             /* Checksum of last frame in log */
++  u32 aSalt[2];                   /* Two salt values copied from WAL header */
++  u32 aCksum[2];                  /* Checksum over all prior fields */
++};
+ 
+ /*
 -** Remove entries from the hash table that point to WAL slots greater
 -** than pWal->hdr.mxFrame.
--**
++** 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.
+ **
 -** This function is called whenever pWal->hdr.mxFrame is decreased due
 -** to a rollback or savepoint.
--**
++** nBackfill is the number of frames in the WAL that have been written
++** back into the database. (We call the act of moving content from WAL to
++** database "backfilling".)  The nBackfill number is never greater than
++** WalIndexHdr.mxFrame.  nBackfill can only be increased by threads
++** 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.
+ **
 -** At most only the hash table containing pWal->hdr.mxFrame needs to be
 -** updated.  Any later hash tables will be automatically cleared when
 -** pWal->hdr.mxFrame advances to the point where those hash tables are
 -** actually needed.
--*/
++** 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)
++** for any aReadMark[] means that entry is unused.  aReadMark[0] is 
++** a special case; its value is never used and it exists as a place-holder
++** 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.
++**
++** 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 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
++** WAL_READ_LOCK(j)).  New readers (usually) pick the aReadMark[] with the
++** largest value and will increase an unused aReadMark[] to mxFrame if there
++** is not already an aReadMark[] equal to mxFrame.  The exception to the
++** previous sentence is when nBackfill equals mxFrame (meaning that everything
++** in the WAL has been backfilled into the database) then new readers
++** 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.
++**
++** 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.
++**
++** We assume that 32-bit loads are atomic and so no locks are needed in
++** order to read from any aReadMark[] entries.
+ */
 -static void walCleanupHash(Wal *pWal){
 -  volatile ht_slot *aHash = 0;    /* Pointer to hash table to clear */
 -  volatile u32 *aPgno = 0;        /* Page number array for hash table */
@@ -2975,9 +3552,14 @@
 -  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
 -  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
 -  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );
--
++struct WalCkptInfo {
++  u32 nBackfill;                  /* Number of WAL frames backfilled into DB */
++  u32 aReadMark[WAL_NREADER];     /* Reader marks */
++};
++#define READMARK_NOT_USED  0xffffffff
+ 
 -  if( pWal->hdr.mxFrame==0 ) return;
--
+ 
 -  /* Obtain pointers to the hash-table and page-number array containing 
 -  ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
 -  ** that the page said hash-table and array reside on is already mapped.
@@ -2985,7 +3567,15 @@
 -  assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
 -  assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
 -  walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero);
--
++/* 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
++** from the region of the file on which locks are applied.
++*/
++#define WALINDEX_LOCK_OFFSET   (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
++#define WALINDEX_LOCK_RESERVED 16
++#define WALINDEX_HDR_SIZE      (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
+ 
 -  /* Zero all hash-table entries that correspond to frame numbers greater
 -  ** than pWal->hdr.mxFrame.
 -  */
@@ -3002,7 +3592,9 @@
 -  */
 -  nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
 -  memset((void *)&aPgno[iLimit+1], 0, nByte);
--
++/* Size of header before each frame in wal */
++#define WAL_FRAME_HDRSIZE 24
+ 
 -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
 -  /* Verify that the every entry in the mapping region is still reachable
 -  ** via the hash table even after the cleanup.
@@ -3019,12 +3611,28 @@
 -  }
 -#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
 -}
--
--
--/*
++/* Size of write ahead log header, including checksum. */
++/* #define WAL_HDRSIZE 24 */
++#define WAL_HDRSIZE 32
+ 
++/* 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.
++**
++** If the LSB is set, then the checksums for each frame within the WAL
++** file are calculated by treating all data as an array of 32-bit 
++** big-endian words. Otherwise, they are calculated by interpreting 
++** all data as 32-bit little-endian words.
++*/
++#define WAL_MAGIC 0x377f0682
+ 
+ /*
 -** Set an entry in the wal-index that will map database page number
 -** pPage into WAL frame iFrame.
--*/
++** Return the offset of frame iFrame in the write-ahead log file, 
++** assuming a database page size of szPage bytes. The offset returned
++** is to the start of the write-ahead log frame-header.
+ */
 -static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
 -  int rc;                         /* Return code */
 -  u32 iZero = 0;                  /* One less than frame number of aPgno[1] */
@@ -3040,7 +3648,10 @@
 -    int iKey;                     /* Hash table key */
 -    int idx;                      /* Value to write to hash-table slot */
 -    int nCollide;                 /* Number of hash collisions */
--
++#define walFrameOffset(iFrame, szPage) (                               \
++  WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE)         \
++)
+ 
 -    idx = iFrame - iZero;
 -    assert( idx <= HASHTABLE_NSLOT/2 + 1 );
 -    
@@ -3051,7 +3662,37 @@
 -      int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
 -      memset((void*)&aPgno[1], 0, nByte);
 -    }
--
++/*
++** An open write-ahead log file is represented by an instance of the
++** following object.
++*/
++struct Wal {
++  sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
++  sqlite3_file *pDbFd;       /* File handle for the database file */
++  sqlite3_file *pWalFd;      /* File handle for WAL file */
++  u32 iCallback;             /* Value to pass to log callback (or 0) */
++  i64 mxWalSize;             /* Truncate WAL to this size upon reset */
++  int nWiData;               /* Size of array apWiData */
++  int szFirstBlock;          /* Size of first block written to WAL file */
++  volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
++  u32 szPage;                /* Database page size */
++  i16 readLock;              /* Which read lock is being held.  -1 for none */
++  u8 syncFlags;              /* Flags to use to sync header writes */
++  u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
++  u8 writeLock;              /* True if in a write transaction */
++  u8 ckptLock;               /* True if holding a checkpoint lock */
++  u8 readOnly;               /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
++  u8 truncateOnCommit;       /* True to truncate WAL file on commit */
++  u8 syncHeader;             /* Fsync the WAL header if true */
++  u8 padToSectorBoundary;    /* Pad transactions out to the next sector */
++  WalIndexHdr hdr;           /* Wal-index header for current transaction */
++  const char *zWalName;      /* Name of WAL file */
++  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
++#ifdef SQLITE_DEBUG
++  u8 lockError;              /* True if a locking error has occurred */
++#endif
++};
+ 
 -    /* If the entry in aPgno[] is already set, then the previous writer
 -    ** must have exited unexpectedly in the middle of a transaction (after
 -    ** writing one or more dirty pages to the WAL to free up memory). 
@@ -3062,7 +3703,13 @@
 -      walCleanupHash(pWal);
 -      assert( !aPgno[idx] );
 -    }
--
++/*
++** Candidate values for Wal.exclusiveMode.
++*/
++#define WAL_NORMAL_MODE     0
++#define WAL_EXCLUSIVE_MODE  1     
++#define WAL_HEAPMEMORY_MODE 2
+ 
 -    /* Write the aPgno[] array entry and the hash-table slot. */
 -    nCollide = idx;
 -    for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
@@ -3070,7 +3717,13 @@
 -    }
 -    aPgno[idx] = iPage;
 -    aHash[iKey] = (ht_slot)idx;
--
++/*
++** Possible values for WAL.readOnly
++*/
++#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 */
+ 
 -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
 -    /* Verify that the number of entries in the hash table exactly equals
 -    ** the number of entries in the mapping region.
@@ -3080,20 +3733,12 @@
 -      int nEntry = 0;  /* Number of entries in the hash table */
 -      for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
 -      assert( nEntry==idx );
-+  /* Enlarge the pWal->apWiData[] array if required */
-+  if( pWal->nWiData<=iPage ){
-+    int nByte = sizeof(u32*)*(iPage+1);
-+    volatile u32 **apNew;
-+    apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
-+    if( !apNew ){
-+      *ppPage = 0;
-+      return SQLITE_NOMEM;
-     }
-+    memset((void*)&apNew[pWal->nWiData], 0,
-+           sizeof(u32*)*(iPage+1-pWal->nWiData));
-+    pWal->apWiData = apNew;
-+    pWal->nWiData = iPage+1;
-+  }
+-    }
++/*
++** Each page of the wal-index mapping contains a hash-table made up of
++** an array of HASHTABLE_NSLOT elements of the following type.
++*/
++typedef u16 ht_slot;
  
 -    /* Verify that the every entry in the mapping region is reachable
 -    ** via the hash table.  This turns out to be a really, really expensive
@@ -3107,47 +3752,78 @@
 -          if( aHash[iKey]==i ) break;
 -        }
 -        assert( aHash[iKey]==i );
-+  /* Request a pointer to the required page from the VFS */
-+  if( pWal->apWiData[iPage]==0 ){
-+    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
-+      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
-+      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
-+    }else{
-+      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
-+          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
-+      );
-+      if( rc==SQLITE_READONLY ){
-+        pWal->readOnly |= WAL_SHM_RDONLY;
-+        rc = SQLITE_OK;
-       }
-     }
+-      }
+-    }
 -#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
-   }
- 
--
-+  *ppPage = pWal->apWiData[iPage];
-+  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
-   return rc;
- }
+-  }
++/*
++** 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 
++** frame most recently written to the WAL (in other words, the frame with
++** the largest index).
++**
++** The internals of this structure are only accessed by:
++**
++**   walIteratorInit() - Create a new iterator,
++**   walIteratorNext() - Step an iterator,
++**   walIteratorFree() - Free an iterator.
++**
++** This functionality is used by the checkpoint code (see walCheckpoint()).
++*/
++struct WalIterator {
++  int iPrior;                     /* Last result returned from the iterator */
++  int nSegment;                   /* Number of entries in aSegment[] */
++  struct WalSegment {
++    int iNext;                    /* Next slot in aIndex[] not yet returned */
++    ht_slot *aIndex;              /* i0, i1, i2... such that aPgno[iN] ascend */
++    u32 *aPgno;                   /* Array of page numbers. */
++    int nEntry;                   /* Nr. of entries in aPgno[] and aIndex[] */
++    int iZero;                    /* Frame number associated with aPgno[0] */
++  } aSegment[1];                  /* One for every 32KB page in the wal-index */
++};
  
 +/*
-+** Return a pointer to the WalCkptInfo structure in the wal-index.
++** 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.
++**
++** Changing any of these constants will alter the wal-index format and
++** create incompatibilities.
 +*/
-+static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
-+  assert( pWal->nWiData>0 && pWal->apWiData[0] );
-+  return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
-+}
++#define HASHTABLE_NPAGE      4096                 /* Must be power of 2 */
++#define HASHTABLE_HASH_1     383                  /* Should be prime */
++#define HASHTABLE_NSLOT      (HASHTABLE_NPAGE*2)  /* Must be a power of 2 */
+ 
+-  return rc;
+-}
++/* 
++** 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.
++*/
++#define HASHTABLE_NPAGE_ONE  (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
+ 
++/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
++#define WALINDEX_PGSZ   (                                         \
++    sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
++)
  
  /*
 -** Recover the wal-index by reading the write-ahead log file. 
--**
++** 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.
+ **
 -** This routine first tries to establish an exclusive lock on the
 -** wal-index to prevent other threads/processes from doing anything
 -** with the WAL or wal-index while recovery is running.  The
 -** WAL_RECOVER_LOCK is also held so that other threads will know
 -** that this thread is running recovery.  If unable to establish
 -** the necessary locks, this routine returns SQLITE_BUSY.
-+** Return a pointer to the WalIndexHdr structure in the wal-index.
++** 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.
  */
 -static int walIndexRecover(Wal *pWal){
 -  int rc;                         /* Return Code */
@@ -3155,11 +3831,7 @@
 -  u32 aFrameCksum[2] = {0, 0};
 -  int iLock;                      /* Lock offset to lock for checkpoint */
 -  int nLock;                      /* Number of locks to hold */
-+static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
-+  assert( pWal->nWiData>0 && pWal->apWiData[0] );
-+  return (volatile WalIndexHdr*)pWal->apWiData[0];
-+}
- 
+-
 -  /* 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.
@@ -3177,47 +3849,27 @@
 -    return rc;
 -  }
 -  WALTRACE(("WAL%p: recovery begin...\n", pWal));
-+/*
-+** The argument to this macro must be of type u32. On a little-endian
-+** architecture, it returns the u32 value that results from interpreting
-+** the 4 bytes as a big-endian value. On a big-endian architecture, it
-+** returns the value that would be produced by intepreting the 4 bytes
-+** of the input value as a little-endian integer.
-+*/
-+#define BYTESWAP32(x) ( \
-+    (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)  \
-+  + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24) \
-+)
- 
+-
 -  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
-+/*
-+** 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 checksum is written back into aOut[] before returning.
-+**
-+** nByte must be a positive multiple of 8.
-+*/
-+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 */
-+){
-+  u32 s1, s2;
-+  u32 *aData = (u32 *)a;
-+  u32 *aEnd = (u32 *)&a[nByte];
++static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
++  int rc = SQLITE_OK;
  
 -  rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
 -  if( rc!=SQLITE_OK ){
 -    goto recovery_error;
-+  if( aIn ){
-+    s1 = aIn[0];
-+    s2 = aIn[1];
-+  }else{
-+    s1 = s2 = 0;
++  /* Enlarge the pWal->apWiData[] array if required */
++  if( pWal->nWiData<=iPage ){
++    int nByte = sizeof(u32*)*(iPage+1);
++    volatile u32 **apNew;
++    apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
++    if( !apNew ){
++      *ppPage = 0;
++      return SQLITE_NOMEM;
++    }
++    memset((void*)&apNew[pWal->nWiData], 0,
++           sizeof(u32*)*(iPage+1-pWal->nWiData));
++    pWal->apWiData = apNew;
++    pWal->nWiData = iPage+1;
    }
  
 -  if( nSize>WAL_HDRSIZE ){
@@ -3236,8 +3888,22 @@
 -    rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
 -    if( rc!=SQLITE_OK ){
 -      goto recovery_error;
--    }
--
++  /* Request a pointer to the required page from the VFS */
++  if( pWal->apWiData[iPage]==0 ){
++    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
++      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
++      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
++    }else{
++      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
++          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
++      );
++      if( rc==SQLITE_READONLY ){
++        pWal->readOnly |= WAL_SHM_RDONLY;
++        rc = SQLITE_OK;
++      }
+     }
++  }
+ 
 -    /* If the database page size is not a power of two, or is greater than
 -    ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid 
 -    ** data. Similarly, if the 'magic' value is invalid, ignore the whole
@@ -3256,7 +3922,11 @@
 -    pWal->szPage = szPage;
 -    pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
 -    memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
--
++  *ppPage = pWal->apWiData[iPage];
++  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
++  return rc;
++}
+ 
 -    /* Verify that the WAL header checksum is correct */
 -    walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, 
 -        aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
@@ -3266,7 +3936,14 @@
 -    ){
 -      goto finished;
 -    }
--
++/*
++** Return a pointer to the WalCkptInfo structure in the wal-index.
++*/
++static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
++  assert( pWal->nWiData>0 && pWal->apWiData[0] );
++  return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
++}
+ 
 -    /* Verify that the version number on the WAL format is one that
 -    ** are able to understand */
 -    version = sqlite3Get4byte(&aBuf[4]);
@@ -3274,7 +3951,14 @@
 -      rc = SQLITE_CANTOPEN_BKPT;
 -      goto finished;
 -    }
--
++/*
++** 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];
++}
+ 
 -    /* Malloc a buffer to read frames into. */
 -    szFrame = szPage + WAL_FRAME_HDRSIZE;
 -    aFrame = (u8 *)sqlite3_malloc(szFrame);
@@ -3283,13 +3967,43 @@
 -      goto recovery_error;
 -    }
 -    aData = &aFrame[WAL_FRAME_HDRSIZE];
--
++/*
++** The argument to this macro must be of type u32. On a little-endian
++** architecture, it returns the u32 value that results from interpreting
++** the 4 bytes as a big-endian value. On a big-endian architecture, it
++** returns the value that would be produced by intepreting the 4 bytes
++** of the input value as a little-endian integer.
++*/
++#define BYTESWAP32(x) ( \
++    (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)  \
++  + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24) \
++)
+ 
 -    /* 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 */
--
++/*
++** 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 checksum is written back into aOut[] before returning.
++**
++** nByte must be a positive multiple of 8.
++*/
++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 */
++){
++  u32 s1, s2;
++  u32 *aData = (u32 *)a;
++  u32 *aEnd = (u32 *)&a[nByte];
+ 
 -      /* Read and decode the next log frame. */
 -      iFrame++;
 -      rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
@@ -3298,7 +4012,13 @@
 -      if( !isValid ) break;
 -      rc = walIndexAppend(pWal, iFrame, pgno);
 -      if( rc!=SQLITE_OK ) break;
--
++  if( aIn ){
++    s1 = aIn[0];
++    s2 = aIn[1];
++  }else{
++    s1 = s2 = 0;
++  }
+ 
 -      /* If nTruncate is non-zero, this is a commit record. */
 -      if( nTruncate ){
 -        pWal->hdr.mxFrame = iFrame;
@@ -3343,6 +4063,7 @@
 -    pInfo->nBackfill = 0;
 -    pInfo->aReadMark[0] = 0;
 -    for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+-    if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
 +  aOut[0] = s1;
 +  aOut[1] = s2;
 +}
@@ -3505,31 +4226,18 @@
 -  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;
-   }
++  }
  
--  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));
+-  /* 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 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 
@@ -3544,25 +4252,25 @@
 +    /* Checksum failed. */
 +    return 0;
    }
--  return rc;
-+
+ 
+-  if( rc!=SQLITE_OK ){
+-    walIndexClose(pRet, 0);
+-    sqlite3OsClose(pRet->pWalFd);
+-    sqlite3_free(pRet);
 +  /* 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";
@@ -3570,59 +4278,35 @@
 +    return "CKPT-LOCK";
 +  }else if( lockIdx==WAL_RECOVER_LOCK ){
 +    return "RECOVER-LOCK";
-+  }else{
+   }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));
 +    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) */
 +    
  
  /*
--** 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.
+-** Change the size to which the WAL file is trucated on each reset.
 +** 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.
  */
--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){
+-SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
+-  if( pWal ) pWal->mxWalSize = iLimit;
++static int walLockShared(Wal *pWal, int lockIdx){
 +  int rc;
 +  if( pWal->exclusiveMode ) return SQLITE_OK;
 +  rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
@@ -3657,6 +4341,56 @@
  }
  
  /*
+-** 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
@@ -3674,19 +4408,6 @@
 -** 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
@@ -4170,12 +4891,7 @@
 +  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.
@@ -4194,10 +4910,15 @@
 +  }
 +  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;
@@ -4231,7 +4952,7 @@
 -      assert( y<=pWal->hdr.mxFrame );
 -      rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
 -      if( rc==SQLITE_OK ){
--        pInfo->aReadMark[i] = READMARK_NOT_USED;
+-        pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
 -        walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
 -      }else if( rc==SQLITE_BUSY ){
 -        mxSafeFrame = y;
@@ -4401,6 +5122,7 @@
 +    pInfo->nBackfill = 0;
 +    pInfo->aReadMark[0] = 0;
 +    for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
++    if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
 +
 +    /* If more than one frame was recovered from the log file, report an
 +    ** event via sqlite3_log(). This is to help with identifying performance
@@ -4425,7 +5147,8 @@
  /*
 -** 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;
@@ -4437,23 +5160,55 @@
 -  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.
-+** Close an open wal-index.
++/* 
++** 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.
  */
 -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
@@ -4491,30 +5246,71 @@
 -        }
 -      }
 -    }
--
++  assert( zWalName && zWalName[0] );
++  assert( pDbFd );
+ 
 -    walIndexClose(pWal, isDelete);
 -    sqlite3OsClose(pWal->pWalFd);
 -    if( isDelete ){
 -      sqlite3BeginBenignMalloc();
 -      sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
 -      sqlite3EndBenignMalloc();
-+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;
++  /* 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;
      }
 -    WALTRACE(("WAL%p: closed\n", pWal));
 -    sqlite3_free((void *)pWal->apWiData);
 -    sqlite3_free(pWal);
-+  }else{
-+    sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
++    *ppWal = pRet;
++    WALTRACE(("WAL%d: opened\n", pRet));
    }
--  return rc;
+   return rc;
  }
  
--/*
+ /*
 -** Try to read the wal-index header.  Return 0 on success and 1 if
 -** there is a problem.
 -**
@@ -4523,47 +5319,23 @@
 -** 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.
-+** 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.
++** Change the size to which the WAL file is trucated on each reset.
  */
 -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
@@ -4573,53 +5345,43 @@
 -  ** 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));
-+#ifdef WIN_SHM_BASE
-+  assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
-+#endif
-+#ifdef UNIX_SHM_BASE
-+  assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
-+#endif
++SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
++  if( pWal ) pWal->mxWalSize = iLimit;
++}
  
 -  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 */
-+
-+  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;
-   }
+-  }
++/*
++** 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 */
  
 -  if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
 -    *pChanged = 1;
@@ -4627,49 +5389,59 @@
 -    pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
 -    testcase( pWal->szPage<=32768 );
 -    testcase( pWal->szPage>=65536 );
-+  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;
++  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++;
 +    }
-+    *ppWal = pRet;
-+    WALTRACE(("WAL%d: opened\n", pRet));
    }
-+  return rc;
-+}
  
 -  /* The header was successfully read. Return zero. */
 -  return 0;
-+/*
-+** 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;
++  *piPage = p->iPrior = iRet;
++  return (iRet==0xFFFFFFFF);
  }
  
  /*
 -** 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.
-+** 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.
++** 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:
  **
 -** If the wal-index header is successfully read, return SQLITE_OK. 
 -** Otherwise an SQLite error code.
-+** Return 0 on success.  If there are no pages in the WAL with a page
-+** number larger than *piPage, then return 1.
++**        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 int walIndexReadHdr(Wal *pWal, int *pChanged){
 -  int rc;                         /* Return code */
@@ -4685,21 +5457,30 @@
 -    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);
-+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 */
++  assert( nLeft>0 && nRight>0 );
++  while( iRight<nRight || iLeft<nLeft ){
++    ht_slot logpage;
++    Pgno dbpage;
  
 -  /* If the first attempt failed, it might have been due to a race
 -  ** with a writer.  So get a WRITE lock and try again.
@@ -4722,71 +5503,10 @@
 -          */
 -          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]])
 +    ){
@@ -5276,30 +5996,11 @@
 -      if( walFramePgno(pWal, iTest)==pgno ){
 -        iRead2 = iTest;
 -        break;
--      }
--    }
--    assert( iRead==iRead2 );
--  }
--#endif
 +  for(i=0; rc==SQLITE_OK && i<nSegment; i++){
 +    volatile ht_slot *aHash;
 +    u32 iZero;
 +    volatile u32 *aPgno;
- 
--  /* 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);
++
 +    rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero);
 +    if( rc==SQLITE_OK ){
 +      int j;                      /* Counter variable */
@@ -5317,21 +6018,38 @@
 +  
 +      for(j=0; j<nEntry; j++){
 +        aIndex[j] = (ht_slot)j;
-+      }
+       }
 +      walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
 +      p->aSegment[i].iZero = iZero;
 +      p->aSegment[i].nEntry = nEntry;
 +      p->aSegment[i].aIndex = aIndex;
 +      p->aSegment[i].aPgno = (u32 *)aPgno;
-+    }
+     }
+-    assert( iRead==iRead2 );
    }
+-#endif
 +  sqlite3ScratchFree(aTmp);
  
--  *pInWal = 0;
--  return SQLITE_OK;
+-  /* 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);
 +  if( rc!=SQLITE_OK ){
 +    walIteratorFree(p);
-+  }
+   }
+-
+-  *pInWal = 0;
+-  return SQLITE_OK;
 +  *pp = p;
 +  return rc;
  }
@@ -5414,10 +6132,6 @@
  */
 -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 */
@@ -5437,31 +6151,26 @@
 +  volatile WalCkptInfo *pInfo;    /* The checkpoint status information */
 +  int (*xBusy)(void*) = 0;        /* Function to call when waiting for locks */
  
--  if( pWal->readOnly ){
--    return SQLITE_READONLY;
--  }
+-  /* Cannot start a write transaction without first holding a read
+-  ** transaction. */
+-  assert( pWal->readLock>=0 );
 +  szPage = walPagesize(pWal);
 +  testcase( szPage<=32768 );
 +  testcase( szPage>=65536 );
 +  pInfo = walCkptInfo(pWal);
 +  if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
  
--  /* 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 ){
+-  if( pWal->readOnly ){
+-    return SQLITE_READONLY;
 +  /* Allocate the iterator */
 +  rc = walIteratorInit(pWal, &pIter);
 +  if( rc!=SQLITE_OK ){
-     return rc;
++    return rc;
    }
--  pWal->writeLock = 1;
 +  assert( pIter );
  
--  /* 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.
+-  /* Only one writer allowed at a time.  Get the write lock.  Return
+-  ** SQLITE_BUSY if unable.
 +  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
 +
 +  /* Compute in mxSafeFrame the index of the last frame of the WAL that is
@@ -5469,10 +6178,9 @@
 +  ** overwrite database pages that are in use by active readers and thus
 +  ** cannot be backfilled from the WAL.
    */
--  if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
--    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
--    pWal->writeLock = 0;
--    rc = SQLITE_BUSY;
+-  rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+-  if( rc ){
+-    return rc;
 +  mxSafeFrame = pWal->hdr.mxFrame;
 +  mxPage = pWal->hdr.nPage;
 +  for(i=1; i<WAL_NREADER; i++){
@@ -5481,7 +6189,7 @@
 +      assert( y<=pWal->hdr.mxFrame );
 +      rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
 +      if( rc==SQLITE_OK ){
-+        pInfo->aReadMark[i] = READMARK_NOT_USED;
++        pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
 +        walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
 +      }else if( rc==SQLITE_BUSY ){
 +        mxSafeFrame = y;
@@ -5491,109 +6199,33 @@
 +      }
 +    }
    }
+-  pWal->writeLock = 1;
  
--  return rc;
--}
+-  /* 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( 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 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 file 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);
 +      }
-     }
--    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;
@@ -5608,9 +6240,7 @@
 +      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 ){
@@ -5625,61 +6255,26 @@
 +        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 ){
@@ -5687,91 +6282,28 @@
 +    }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 ){
--        /* 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;
--        for(i=1; 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 );
++      if( rc==SQLITE_OK ){
++        walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
++      }
++    }
    }
-+
+ 
 + walcheckpoint_out:
 +  walIteratorFree(pIter);
    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.
+-** End a write transaction.  The commit has already been done.  This
+-** routine merely releases the lock.
 +** 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.
  */
--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;
+-SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
+-  if( pWal->writeLock ){
+-    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+-    pWal->writeLock = 0;
+-    pWal->truncateOnCommit = 0;
 +static void walLimitSize(Wal *pWal, i64 nMax){
 +  i64 sz;
 +  int rx;
@@ -5784,39 +6316,36 @@
 +  if( rx ){
 +    sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
    }
--  rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
--  return rc;
+-  return SQLITE_OK;
  }
  
  /*
--** Write out a single frame of the WAL
+-** 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.
 +** Close a connection to a log file.
  */
--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 sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
 +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;                         /* 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;
++){
+   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( pWal ){
 +    int isDelete = 0;             /* True to unlink wal and wal-index files */
 +
@@ -5827,7 +6356,8 @@
 +    ** 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 ){
@@ -5857,24 +6387,45 @@
 +        }
 +      }
 +    }
-+
+ 
+-    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;
  }
  
 -/* 
--** Write a set of frames to the log. The caller must hold the write-lock
--** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
+-** 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()).
 +/*
 +** Try to read the wal-index header.  Return 0 on success and 1 if
 +** there is a problem.
@@ -5892,35 +6443,31 @@
 +** If the checksum cannot be verified return non-zero. If the header
 +** is read successfully and the checksum verified, return zero.
  */
--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 */
+-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;
+-}
 +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 */
  
--  assert( pList );
--  assert( pWal->writeLock );
+-/* 
+-** 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;
 +  /* The first page of the wal-index must be mapped at this point. */
 +  assert( pWal->nWiData>0 && pWal->apWiData[0] );
  
--  /* 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->writeLock );
+-  assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame );
 +  /* 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
@@ -5936,10 +6483,13 @@
 +  walShmBarrier(pWal);
 +  memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
  
--#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( 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( memcmp(&h1, &h2, sizeof(h1))!=0 ){
 +    return 1;   /* Dirty read */
 +  }  
@@ -5950,13 +6500,12 @@
 +  if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
 +    return 1;   /* Checksum does not match */
    }
--#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;
+-  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( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
 +    *pChanged = 1;
 +    memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
@@ -5965,37 +6514,64 @@
 +    testcase( pWal->szPage>=65536 );
    }
  
--  /* 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.
+-  return rc;
 +  /* 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.
 +** 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 */
 +  /* 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.
-   */
--  iFrame = pWal->hdr.mxFrame;
--  if( iFrame==0 ){
--    u8 aWalHdr[WAL_HDRSIZE];      /* Buffer to assemble wal-header in */
--    u32 aCksum[2];                /* Checksum for wal-header */
++  */
 +  assert( pChanged );
 +  rc = walIndexPage(pWal, 0, &page0);
 +  if( rc!=SQLITE_OK ){
@@ -6003,32 +6579,25 @@
 +  };
 +  assert( page0 || pWal->writeLock==0 );
  
--    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;
+-        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 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);
- 
--    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;
++
 +  /* If the first attempt failed, it might have been due to a race
 +  ** with a writer.  So get a WRITE lock and try again.
 +  */
@@ -6051,23 +6620,63 @@
 +          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;
  
--    /* 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;
--    }
+-/*
+-** 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 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.
@@ -6075,38 +6684,42 @@
 +  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
 +    rc = SQLITE_CANTOPEN_BKPT;
    }
--  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;
-+  return rc;
-+}
+-  rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
++
+   return rc;
+ }
  
--  /* 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;
--  }
-+/*
+ /*
+-** Write out a single frame of the WAL
 +** 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)
  
--  /* If this is the end of a transaction, then we might need to pad
--  ** the transaction and/or sync the WAL file.
+-/* 
+-** 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
@@ -6156,21 +6769,49 @@
 +** update values of the aReadMark[] array in the header, but if it does
 +** 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) */
+-){
+-  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 );
+-
+-  /* 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) );
 +static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
 +  volatile WalCkptInfo *pInfo;    /* Checkpoint information in wal-index */
 +  u32 mxReadMark;                 /* Largest aReadMark[] value */
 +  int mxI;                        /* Index of largest aReadMark[] value */
 +  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"));
+-  }
+-#endif
 +  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.
 +  /* Take steps to avoid spinning forever if there is a protocol error.
-   **
--  ** 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.
++  **
 +  ** 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 
@@ -6178,13 +6819,7 @@
 +  ** paged out or take a page-fault that is time-consuming to resolve, 
 +  ** during the few nanoseconds that it is holding the lock.  In that case,
 +  ** it might take longer than normal for the lock to free.
-   **
--  ** 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.
++  **
 +  ** After 5 RETRYs, we begin calling sqlite3OsSleep().  The first few
 +  ** calls to sqlite3OsSleep() have a delay of 1 microsecond.  Really this
 +  ** is more of a scheduler yield than an actual delay.  But on the 10th
@@ -6192,15 +6827,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( 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++;
+-  if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
+-    return rc;
 +  if( cnt>5 ){
 +    int nDelay = 1;                      /* Pause time in microseconds */
 +    if( cnt>100 ){
@@ -6209,8 +6837,35 @@
 +    }
 +    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 ){
@@ -6236,28 +6891,27 @@
 +        rc = WAL_RETRY;
 +      }else if( rc==SQLITE_BUSY ){
 +        rc = SQLITE_BUSY_RECOVERY;
-       }
--    }else{
--      rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
++      }
 +    }
-+    if( rc!=SQLITE_OK ){
-+      return rc;
+     if( rc!=SQLITE_OK ){
+       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( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){
--    i64 sz = pWal->mxWalSize;
--    if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){
--      sz = walFrameOffset(iFrame+nExtra+1, szPage);
+-    /* 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 ){
@@ -6283,28 +6937,60 @@
 +    }else if( rc!=SQLITE_BUSY ){
 +      return rc;
      }
--    walLimitSize(pWal, sz);
--    pWal->truncateOnCommit = 0;
    }
+-  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;
+-  }
  
--  /* 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 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.
 +  /* 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.
    */
--  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( 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++){
@@ -6313,7 +6999,7 @@
 +      assert( thisMark!=READMARK_NOT_USED );
 +      mxReadMark = thisMark;
 +      mxI = i;
-+    }
+     }
    }
 +  /* There was once an "if" here. The extra "{" is to preserve indentation. */
 +  {
@@ -6337,23 +7023,18 @@
 +      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
 +    }
  
--  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 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);
 +    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
 +    if( rc ){
 +      return rc==SQLITE_BUSY ? WAL_RETRY : rc;
-     }
--    /* If this is a commit, update the wal-index header too. */
--    if( isCommit ){
--      walIndexWriteHdr(pWal);
--      pWal->iCallback = iFrame;
++    }
 +    /* Now that the read-lock has been obtained, check that neither the
 +    ** value in the aReadMark[] array or the contents of the wal-index
 +    ** header have changed.
@@ -6384,11 +7065,27 @@
 +      assert( mxReadMark<=pWal->hdr.mxFrame );
 +      pWal->readLock = (i16)mxI;
      }
+-    walLimitSize(pWal, sz);
+-    pWal->truncateOnCommit = 0;
    }
 +  return rc;
 +}
  
--  WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
+-  /* 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);
+-  }
 +/*
 +** Begin a read transaction on the database.
 +**
@@ -6406,7 +7103,22 @@
 +SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
 +  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;
+-    }
 +  do{
 +    rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
 +  }while( rc==WAL_RETRY );
@@ -6414,15 +7126,9 @@
 +  testcase( (rc&0xff)==SQLITE_IOERR );
 +  testcase( rc==SQLITE_PROTOCOL );
 +  testcase( rc==SQLITE_OK );
-   return rc;
- }
- 
--/* 
--** This routine is called to implement sqlite3_wal_checkpoint() and
--** related interfaces.
--**
--** Obtain a CHECKPOINT lock and then backfill as much information as
--** we can from WAL into the database.
++  return rc;
++}
++
 +/*
 +** Finish with a read transaction.  All this does is release the
 +** read-lock.
@@ -6432,9 +7138,18 @@
 +  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;
+ }
+ 
+-/* 
+-** This routine is called to implement sqlite3_wal_checkpoint() and
+-** related interfaces.
+-**
+-** 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.  
@@ -6746,7 +7461,7 @@
 -#endif
 -
 -#endif /* #ifndef SQLITE_OMIT_WAL */
--
+ 
 -/************** End of wal.c *************************************************/
 -/************** Begin file btmutex.c *****************************************/
 -/*
@@ -6971,7 +7686,6 @@
 -**    SIZE    DESCRIPTION
 -**      4     Page number of next overflow page
 -**      *     Data
-+
 +  /* Only one writer allowed at a time.  Get the write lock.  Return
 +  ** SQLITE_BUSY if unable.
 +  */
@@ -7174,7 +7888,8 @@
 +        aSalt[1] = salt1;
 +        walIndexWriteHdr(pWal);
 +        pInfo->nBackfill = 0;
-+        for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
++        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 ){
@@ -7347,40 +8062,7 @@
 -#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) );
@@ -7390,19 +8072,8 @@
 +    WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
 +              pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
 +  }
- #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
++#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.
 +  */
@@ -7550,6 +8221,80 @@
 +      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.
@@ -7580,23 +8325,12 @@
 -**
 -**     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 */
@@ -7630,20 +8364,16 @@
 -#endif
 -  u8 *pTmpSpace;        /* BtShared.pageSize bytes of space for tmp use */
 -};
-+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() */
++  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;
  
 -/*
 -** Allowed values for BtShared.btsFlags
@@ -7655,8 +8385,24 @@
 -#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 */
-+  assert( pWal->ckptLock==0 );
-+  assert( pWal->writeLock==0 );
++  /* 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;
++    }
++  }
  
 -/*
 -** An instance of the following structure is used to hold information
@@ -7674,16 +8420,10 @@
 -  u16 iOverflow; /* Offset to overflow page number.  Zero if no overflow */
 -  u16 nSize;     /* Size of the cell content on the main b-tree page */
 -};
-+  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;
++  /* Read the wal-index header. */
++  if( rc==SQLITE_OK ){
++    rc = walIndexReadHdr(pWal, &isChanged);
 +  }
-+  pWal->ckptLock = 1;
  
 -/*
 -** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
@@ -7695,24 +8435,13 @@
 -** assumed that the database is corrupt.
 -*/
 -#define BTCURSOR_MAX_DEPTH 20
-+  /* 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;
++  /* 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);
 +    }
-+  }
  
 -/*
 -** A cursor is a pointer to a particular entry within a particular
@@ -7749,13 +8478,16 @@
 -#ifndef SQLITE_OMIT_INCRBLOB
 -  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
 -#endif
+-  u8 hints;                             /* As configured by CursorSetHints() */
 -  i16 iPage;                            /* Index of current page in apPage */
 -  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
 -  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
 -};
-+  /* Read the wal-index header. */
-+  if( rc==SQLITE_OK ){
-+    rc = walIndexReadHdr(pWal, &isChanged);
++    /* 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);
++    }
 +  }
  
 -/*
@@ -7787,24 +8519,27 @@
 -#define CURSOR_VALID             1
 -#define CURSOR_REQUIRESEEK       2
 -#define CURSOR_FAULT             3
-+  /* 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( 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));
++  }
  
 -/* 
 -** The database page the PENDING_BYTE occupies. This page is never used.
 -*/
 -# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
-+    /* 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);
-+    }
-+  }
++  /* 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);
++}
  
 -/*
 -** These macros define the location of the pointer-map entry for a 
@@ -7820,24 +8555,6 @@
 -** 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
@@ -8036,7 +8753,7 @@
  #ifndef SQLITE_OMIT_SHARED_CACHE
  #if SQLITE_THREADSAFE
  
-@@ -87992,10 +89440,16 @@
+@@ -86559,10 +88241,16 @@
  */
  SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
    int rc = sqlite3_overload_function(db, "MATCH", 2);
@@ -8053,7 +8770,34 @@
  }
  
  /*
-@@ -93389,60 +94843,6 @@
+@@ -91386,6 +93074,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 **/
++#ifdef SQLITE_HAS_CODEC
++  extern int codec_pragma(sqlite3*, int, Parse *, const char *, const char *);
++#endif
++/** END CRYPTO **/
++
+ 
+   if( v==0 ) return;
+   sqlite3VdbeRunOnlyOnce(v);
+@@ -91445,6 +93139,13 @@
+     pParse->rc = rc;
+   }else
+                             
++/** BEGIN CRYPTO **/
++#ifdef SQLITE_HAS_CODEC
++  if(codec_pragma(db, iDb, pParse, zLeft, zRight)) { 
++    /* codec_pragma executes internal */
++  }else
++  #endif
++/** END CRYPTO **/
+  
+ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
+   /*
+@@ -92000,60 +93701,6 @@
  
  #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
    /*
@@ -8114,48 +8858,3 @@
    **   PRAGMA table_info(<table>)
    **
    ** Return a single row for each column of the named table. The columns of
-@@ -94090,6 +95490,44 @@
-       sqlite3_rekey(db, zKey, i/2);
-     }
-   }else
-+/** BEGIN CRYPTO **/
-+  if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){
-+    extern void codec_vdbe_return_static_string(Parse *pParse, const char *zLabel, const char *value);
-+    codec_vdbe_return_static_string(pParse, "cipher_version", CIPHER_VERSION);
-+  }else
-+  if( sqlite3StrICmp(zLeft, "cipher")==0 && zRight ){
-+    extern int codec_set_cipher_name(sqlite3*, int, const char *, int);
-+    codec_set_cipher_name(db, iDb, zRight, 2); // change cipher for both
-+  }else
-+  if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
-+    extern int codec_set_cipher_name(sqlite3*, int, const char *, int); 
-+    codec_set_cipher_name(db, iDb, zRight, 1); // change write cipher only
-+  }else
-+  if( sqlite3StrICmp(zLeft, "kdf_iter")==0 && zRight ){
-+    extern int codec_set_kdf_iter(sqlite3*, int, int, int);
-+    codec_set_kdf_iter(db, iDb, atoi(zRight), 2); // change of RW PBKDF2 iteration
-+  }else
-+  if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0 && zRight ){
-+    extern int codec_set_fast_kdf_iter(sqlite3*, int, int, int);
-+    codec_set_fast_kdf_iter(db, iDb, atoi(zRight), 2); // change of RW PBKDF2 iteration
-+  }else
-+  if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
-+    extern int codec_set_kdf_iter(sqlite3*, int, int, int); 
-+    codec_set_kdf_iter(db, iDb, atoi(zRight), 1); // change # if W iterations
-+  }else
-+  if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){
-+    extern int codec_set_page_size(sqlite3*, int, int); 
-+    codec_set_page_size(db, iDb, atoi(zRight)); // change page size
-+  }else
-+  if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){
-+    extern void codec_set_default_use_hmac(int);
-+    codec_set_default_use_hmac(sqlite3GetBoolean(zRight,1));
-+  }else
-+  if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){
-+    extern int codec_set_use_hmac(sqlite3*, int, int);
-+    codec_set_use_hmac(db, iDb, sqlite3GetBoolean(zRight,1));
-+  }else
-+/** END CRYPTO **/
- #endif
- #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-   if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){



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