Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update sqlite to 3.7.7.1 while here remove compat
Baptiste Daroussin committed 14 years ago
commit 7454ae132d5959e8841380949fedec1b4d07624a
parent 146165a
3 files changed +5324 -2677
deleted compat/pkg_updating
@@ -1,78 +0,0 @@
-
#!/bin/sh
-

-
usage() {
-
	echo "usage: $0 [-h] [-d YYYYMMDD] [-f file] [portname ...]" >&2
-
	# Respects EX_USAGE (sysexit.h)
-
	exit 64
-
}
-

-
while getopts "d:f:h" OPTS; do
-
	case ${OPTS} in
-
		d)
-
		DATE=${OPTARG}
-
		echo ${DATE} | egrep -q "^[0-9]{8}$"
-
		if [ $? -ne 0 ]; then
-
			echo "${DATE}: Bad date format" >&2
-
			usage
-
		fi
-
		shift; shift
-
		;;
-
		f)
-
		FILE=${OPTARG}
-
		test -f ${FILE} || (echo "${FILE}: No such file or directory" >&2; usage)
-
		test -r ${FILE} || (echo "${FILE}: Not readable" >&2; usage)
-
		shift; shift
-
		;;
-
		h)
-
		usage
-
		;;
-
		*)
-
		usage
-
		;;
-
	esac
-
done
-

-
: ${FILE:=/usr/ports/UPDATING}
-

-
if [ $# -eq 0 ]; then
-
#TODO: REPLACE with PKG_info
-
	ALLPORTS=`pkg_info -qoa | xargs echo`
-
else
-
	for PKG in "$*";do
-
		ORIGIN=`pkg_info -qo ${PKG}-*`
-
		if [ $? -eq 0 ]; then
-
			ALLPORTS="${ALLPORTS} ${ORIGIN}"
-
		else
-
			echo "${PKG}: No such packages installed" >&2
-
		fi
-
		unset ORIGIN
-
	done
-
fi
-
awk -v PORTS="${ALLPORTS}" 'BEGIN {
-
	split(PORTS,portorigin, " ");
-
	date_line="";
-
}
-
{
-
	if ($0 ~ /^\ \ AFFECTS.*$/) {
-
		for (i in portorigin) {
-
			if ( match($0, portorigin[i]) ) {
-
				found=1;
-
				print date_line
-
				print $0
-
				break;
-
			}
-
		}
-
	} else {
-
	date_line=$0;
-
	if ( found == 1) {
-
		if ($0 ~ /^[0-9]/) {
-
			found=0
-
		} else {
-
			print $0
-
		}
-
	}
-
}
-
}
-
' $FILE
-
#echo ${ALLPORTS}
-
exit 0
modified external/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-
** version 3.7.6.2.  By combining all the individual C code files into this 
+
** version 3.7.7.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
@@ -650,9 +650,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.7.6.2"
-
#define SQLITE_VERSION_NUMBER 3007006
-
#define SQLITE_SOURCE_ID      "2011-04-17 17:25:17 154ddbc17120be2915eb03edc52af1225eb7cb5e"
+
#define SQLITE_VERSION        "3.7.7.1"
+
#define SQLITE_VERSION_NUMBER 3007007
+
#define SQLITE_SOURCE_ID      "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -853,7 +853,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** argument.  ^If the callback function of the 3rd argument to
** sqlite3_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements.  ^The 4th argument to
-
** to sqlite3_exec() is relayed through to the 1st argument of each
+
** sqlite3_exec() is relayed through to the 1st argument of each
** callback invocation.  ^If the callback pointer to sqlite3_exec()
** is NULL, then no callback is ever invoked and result rows are
** ignored.
@@ -918,7 +918,8 @@ SQLITE_API int sqlite3_exec(
**
** New error codes may be added in future versions of SQLite.
**
-
** See also: [SQLITE_IOERR_READ | extended result codes]
+
** See also: [SQLITE_IOERR_READ | extended result codes],
+
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
*/
#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
@@ -995,17 +996,21 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SHMOPEN           (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
+
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
+
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
+
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
+
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
+
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
-
** in the 4th parameter to the xOpen method of the
-
** [sqlite3_vfs] object.
+
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
*/
#define SQLITE_OPEN_READONLY         0x00000001  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE        0x00000002  /* Ok for sqlite3_open_v2() */
@@ -1013,6 +1018,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_DELETEONCLOSE    0x00000008  /* VFS only */
#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_MAIN_DB          0x00000100  /* VFS only */
#define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
@@ -1123,17 +1129,18 @@ struct sqlite3_file {
/*
** CAPI3REF: OS Interface File Virtual Methods Object
**
-
** Every file opened by the [sqlite3_vfs] xOpen method populates an
+
** Every file opened by the [sqlite3_vfs.xOpen] method populates an
** [sqlite3_file] object (or, more commonly, a subclass of the
** [sqlite3_file] object) with a pointer to an instance of this object.
** This object defines the methods used to perform various operations
** against the open file represented by the [sqlite3_file] object.
**
-
** If the xOpen method sets the sqlite3_file.pMethods element 
+
** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element 
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
-
** may be invoked even if the xOpen reported that it failed.  The
-
** only way to prevent a call to xClose following a failed xOpen
-
** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
+
** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed.  The
+
** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
+
** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
+
** to NULL.
**
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
** [SQLITE_SYNC_FULL].  The first choice is the normal fsync().
@@ -1305,7 +1312,8 @@ typedef struct sqlite3_mutex sqlite3_mutex;
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
-
** in the name of the object stands for "virtual file system".
+
** in the name of the object stands for "virtual file system".  See
+
** the [VFS | VFS documentation] for further information.
**
** The value of the iVersion field is initially 1 but may be larger in
** future versions of SQLite.  Additional fields may be appended to this
@@ -1334,6 +1342,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** The zName field holds the name of the VFS module.  The name must
** be unique across all VFS modules.
**
+
** [[sqlite3_vfs.xOpen]]
** ^SQLite guarantees that the zFilename parameter to xOpen
** is either a NULL pointer or string obtained
** from xFullPathname() with an optional suffix added.
@@ -1411,6 +1420,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** element will be valid after xOpen returns regardless of the success
** or failure of the xOpen call.
**
+
** [[sqlite3_vfs.xAccess]]
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
@@ -1435,7 +1445,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** method returns a Julian Day Number for the current date and time as
** a floating point value.
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
-
** Day Number multipled by 86400000 (the number of milliseconds in 
+
** Day Number multiplied by 86400000 (the number of milliseconds in 
** a 24-hour day).  
** ^SQLite will use the xCurrentTimeInt64() method to get the current
** date and time if that method is available (if iVersion is 2 or 
@@ -1657,9 +1667,9 @@ SQLITE_API int sqlite3_os_end(void);
** implementation of an application-defined [sqlite3_os_init()].
**
** The first argument to sqlite3_config() is an integer
-
** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
+
** [configuration option] that determines
** what property of SQLite is to be configured.  Subsequent arguments
-
** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
+
** vary depending on the [configuration option]
** in the first argument.
**
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
@@ -1769,6 +1779,7 @@ struct sqlite3_mem_methods {

/*
** CAPI3REF: Configuration Options
+
** KEYWORDS: {configuration option}
**
** These constants are the available integer configuration options that
** can be passed as the first argument to the [sqlite3_config()] interface.
@@ -1781,7 +1792,7 @@ struct sqlite3_mem_methods {
** is invoked.
**
** <dl>
-
** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
+
** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
** <dd>There are no arguments to this option.  ^This option sets the
** [threading mode] to Single-thread.  In other words, it disables
** all mutexing and puts SQLite into a mode where it can only be used
@@ -1792,7 +1803,7 @@ struct sqlite3_mem_methods {
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
** configuration option.</dd>
**
-
** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
+
** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
** <dd>There are no arguments to this option.  ^This option sets the
** [threading mode] to Multi-thread.  In other words, it disables
** mutexing on [database connection] and [prepared statement] objects.
@@ -1806,7 +1817,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
**
-
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
+
** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option.  ^This option sets the
** [threading mode] to Serialized. In other words, this option enables
** all mutexes including the recursive
@@ -1822,7 +1833,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
**
-
** <dt>SQLITE_CONFIG_MALLOC</dt>
+
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mem_methods] structure.  The argument specifies
** alternative low-level memory allocation routines to be used in place of
@@ -1830,7 +1841,7 @@ struct sqlite3_mem_methods {
** its own private copy of the content of the [sqlite3_mem_methods] structure
** before the [sqlite3_config()] call returns.</dd>
**
-
** <dt>SQLITE_CONFIG_GETMALLOC</dt>
+
** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mem_methods] structure.  The [sqlite3_mem_methods]
** structure is filled with the currently defined memory allocation routines.)^
@@ -1838,7 +1849,7 @@ struct sqlite3_mem_methods {
** routines with a wrapper that simulations memory allocation failure or
** tracks memory usage, for example. </dd>
**
-
** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
+
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^This option takes single argument of type int, interpreted as a 
** boolean, which enables or disables the collection of memory allocation 
** statistics. ^(When memory allocation statistics are disabled, the 
@@ -1854,7 +1865,7 @@ struct sqlite3_mem_methods {
** allocation statistics are disabled by default.
** </dd>
**
-
** <dt>SQLITE_CONFIG_SCRATCH</dt>
+
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
** scratch memory.  There are three arguments:  A pointer an 8-byte
** aligned memory buffer from which the scratch allocations will be
@@ -1870,9 +1881,9 @@ struct sqlite3_mem_methods {
** scratch memory beyond what is provided by this configuration option, then 
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
**
-
** <dt>SQLITE_CONFIG_PAGECACHE</dt>
+
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
-
** the database page cache with the default page cache implemenation.  
+
** the database page cache with the default page cache implementation.  
** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1891,7 +1902,7 @@ struct sqlite3_mem_methods {
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
** will be undefined.</dd>
**
-
** <dt>SQLITE_CONFIG_HEAP</dt>
+
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
** <dd> ^This option specifies a static memory buffer that SQLite will use
** for all of its dynamic memory allocation needs beyond those provided
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
@@ -1908,7 +1919,7 @@ struct sqlite3_mem_methods {
** The minimum allocation size is capped at 2^12. Reasonable values
** for the minimum allocation size are 2^5 through 2^8.</dd>
**
-
** <dt>SQLITE_CONFIG_MUTEX</dt>
+
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure.  The argument specifies
** alternative low-level mutex routines to be used in place
@@ -1920,7 +1931,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
** return [SQLITE_ERROR].</dd>
**
-
** <dt>SQLITE_CONFIG_GETMUTEX</dt>
+
** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure.  The
** [sqlite3_mutex_methods]
@@ -1933,7 +1944,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
** return [SQLITE_ERROR].</dd>
**
-
** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
** <dd> ^(This option takes two arguments that determine the default
** memory allocation for the lookaside memory allocator on each
** [database connection].  The first argument is the
@@ -1943,18 +1954,18 @@ struct sqlite3_mem_methods {
** verb to [sqlite3_db_config()] can be used to change the lookaside
** configuration on individual connections.)^ </dd>
**
-
** <dt>SQLITE_CONFIG_PCACHE</dt>
+
** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
** <dd> ^(This option takes a single argument which is a pointer to
** an [sqlite3_pcache_methods] object.  This object specifies the interface
** to a custom page cache implementation.)^  ^SQLite makes a copy of the
** object and uses it for page cache memory allocations.</dd>
**
-
** <dt>SQLITE_CONFIG_GETPCACHE</dt>
+
** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** [sqlite3_pcache_methods] object.  SQLite copies of the current
** page cache implementation into that object.)^ </dd>
**
-
** <dt>SQLITE_CONFIG_LOG</dt>
+
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
** function with a call signature of void(*)(void*,int,const char*), 
** and a pointer to void. ^If the function pointer is not NULL, it is
@@ -1972,6 +1983,18 @@ struct sqlite3_mem_methods {
** In a multi-threaded application, the application-defined logger
** function must be threadsafe. </dd>
**
+
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
+
** <dd> This option takes a single argument of type int. If non-zero, then
+
** URI handling is globally enabled. If the parameter is zero, then URI handling
+
** is globally disabled. If URI handling is globally enabled, all filenames
+
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
+
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
+
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
+
** connection is opened. If it is globally disabled, filenames are
+
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
+
** database connection is opened. By default, URI handling is globally
+
** disabled. The default value may be changed by compiling with the
+
** [SQLITE_USE_URI] symbol defined.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -1990,6 +2013,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
+
#define SQLITE_CONFIG_URI          17  /* int */

/*
** CAPI3REF: Database Connection Configuration Options
@@ -2075,13 +2099,17 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
**
** ^This routine returns the [rowid] of the most recent
** successful [INSERT] into the database from the [database connection]
-
** in the first argument.  ^If no successful [INSERT]s
+
** in the first argument.  ^As of SQLite version 3.7.7, this routines
+
** records the last insert rowid of both ordinary tables and [virtual tables].
+
** ^If no successful [INSERT]s
** have ever occurred on that database connection, zero is returned.
**
-
** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
-
** row is returned by this routine as long as the trigger is running.
-
** But once the trigger terminates, the value returned by this routine
-
** reverts to the last value inserted before the trigger fired.)^
+
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
+
** method, then this routine will return the [rowid] of the inserted
+
** row as long as the trigger or virtual table method is running.
+
** But once the trigger or virtual table method ends, the value returned 
+
** by this routine reverts to what it was before the trigger or virtual
+
** table method began.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
@@ -2744,6 +2772,9 @@ SQLITE_API int sqlite3_set_authorizer(
** to signal SQLite whether or not the action is permitted.  See the
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
+
**
+
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
+
** from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */
@@ -2866,7 +2897,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
** CAPI3REF: Opening A New Database Connection
**
-
** ^These routines open an SQLite database file whose name is given by the
+
** ^These routines open an SQLite database file as specified by the 
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
@@ -2893,7 +2924,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** sqlite3_open_v2() can take one of
** the following three values, optionally combined with the 
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
-
** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
+
** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
**
** <dl>
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
@@ -2912,9 +2943,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** </dl>
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
-
** combinations shown above or one of the combinations shown above combined
-
** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
-
** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
+
** combinations shown above optionally combined with other
+
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined.
**
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
@@ -2929,6 +2959,11 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**
+
** ^The fourth parameter to sqlite3_open_v2() is the name of the
+
** [sqlite3_vfs] object that defines the operating system interface that
+
** the new database connection should use.  ^If the fourth parameter is
+
** a NULL pointer then the default [sqlite3_vfs] object is used.
+
**
** ^If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection.  ^This in-memory database will vanish when
** the database connection is closed.  Future versions of SQLite might
@@ -2941,10 +2976,111 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** on-disk database will be created.  ^This private database will be
** automatically deleted as soon as the database connection is closed.
**
-
** ^The fourth parameter to sqlite3_open_v2() is the name of the
-
** [sqlite3_vfs] object that defines the operating system interface that
-
** the new database connection should use.  ^If the fourth parameter is
-
** a NULL pointer then the default [sqlite3_vfs] object is used.
+
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
+
**
+
** ^If [URI filename] interpretation is enabled, and the filename argument
+
** begins with "file:", then the filename is interpreted as a URI. ^URI
+
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
+
** set in the fourth argument to sqlite3_open_v2(), or if it has
+
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
+
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
+
** As of SQLite version 3.7.7, URI filename interpretation is turned off
+
** by default, but future releases of SQLite might enable URI filename
+
** interpretation by default.  See "[URI filenames]" for additional
+
** information.
+
**
+
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
+
** authority, then it must be either an empty string or the string 
+
** "localhost". ^If the authority is not an empty string or "localhost", an 
+
** error is returned to the caller. ^The fragment component of a URI, if 
+
** present, is ignored.
+
**
+
** ^SQLite uses the path component of the URI as the name of the disk file
+
** which contains the database. ^If the path begins with a '/' character, 
+
** then it is interpreted as an absolute path. ^If the path does not begin 
+
** with a '/' (meaning that the authority section is omitted from the URI)
+
** then the path is interpreted as a relative path. 
+
** ^On windows, the first component of an absolute path 
+
** is a drive specification (e.g. "C:").
+
**
+
** [[core URI query parameters]]
+
** The query component of a URI may contain parameters that are interpreted
+
** either by SQLite itself, or by a [VFS | custom VFS implementation].
+
** SQLite interprets the following three query parameters:
+
**
+
** <ul>
+
**   <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
+
**     a VFS object that provides the operating system interface that should
+
**     be used to access the database file on disk. ^If this option is set to
+
**     an empty string the default VFS object is used. ^Specifying an unknown
+
**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
+
**     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)^. 
+
**     ^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.
+
**
+
**   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
+
**     "private". ^Setting it to "shared" is equivalent to setting the
+
**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
+
**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
+
**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
+
**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
+
**     a URI filename, its value overrides any behaviour requested by setting
+
**     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+
** </ul>
+
**
+
** ^Specifying an unknown parameter in the query component of a URI is not an
+
** error.  Future versions of SQLite might understand additional query
+
** parameters.  See "[query parameters with special meaning to SQLite]" for
+
** additional information.
+
**
+
** [[URI filename examples]] <h3>URI filename examples</h3>
+
**
+
** <table border="1" align=center cellpadding=5>
+
** <tr><th> URI filenames <th> Results
+
** <tr><td> file:data.db <td> 
+
**          Open the file "data.db" in the current directory.
+
** <tr><td> file:/home/fred/data.db<br>
+
**          file:///home/fred/data.db <br> 
+
**          file://localhost/home/fred/data.db <br> <td> 
+
**          Open the database file "/home/fred/data.db".
+
** <tr><td> file://darkstar/home/fred/data.db <td> 
+
**          An error. "darkstar" is not a recognized authority.
+
** <tr><td style="white-space:nowrap"> 
+
**          file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
+
**     <td> Windows only: Open the file "data.db" on fred's desktop on drive
+
**          C:. Note that the %20 escaping in this example is not strictly 
+
**          necessary - space characters can be used literally
+
**          in URI filenames.
+
** <tr><td> file:data.db?mode=ro&cache=private <td> 
+
**          Open file "data.db" in the current directory for read-only access.
+
**          Regardless of whether or not shared-cache mode is enabled by
+
**          default, use a private cache.
+
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
+
**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+
** <tr><td> file:data.db?mode=readonly <td> 
+
**          An error. "readonly" is not a valid option for the "mode" parameter.
+
** </table>
+
**
+
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
+
** query components of a URI. A hexadecimal escape sequence consists of a
+
** percent sign - "%" - followed by exactly two hexadecimal digits 
+
** specifying an octet value. ^Before the path or query components of a
+
** URI filename are interpreted, they are encoded using UTF-8 and all 
+
** hexadecimal escape sequences replaced by a single byte containing the
+
** corresponding octet. If this process generates an invalid UTF-8 encoding,
+
** the results are undefined.
**
** <b>Note to Windows users:</b>  The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
@@ -2968,6 +3104,26 @@ SQLITE_API int sqlite3_open_v2(
);

/*
+
** CAPI3REF: Obtain Values For URI Parameters
+
**
+
** This is a utility routine, useful to VFS implementations, that checks
+
** to see if a database file was a URI that contained a specific query 
+
** parameter, and if so obtains the value of the query parameter.
+
**
+
** The zFilename argument is the filename pointer passed into the xOpen()
+
** method of a VFS implementation.  The zParam argument is the name of the
+
** query parameter we seek.  This routine returns the value of the zParam
+
** parameter if it exists.  If the parameter does not exist, this routine
+
** returns a NULL pointer.
+
**
+
** If the zFilename argument to this function is not a pointer that SQLite
+
** passed into the xOpen VFS method, then the behavior of this routine
+
** is undefined and probably undesirable.
+
*/
+
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+

+

+
/*
** CAPI3REF: Error Codes And Messages
**
** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -3082,43 +3238,45 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** Additional information is available at [limits | Limits in SQLite].
**
** <dl>
-
** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
+
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
+
** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
+
** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
** <dd>The maximum number of columns in a table definition or in the
** result set of a [SELECT] or the maximum number of columns in an index
** or in an ORDER BY or GROUP BY clause.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
+
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
+
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
+
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
** <dd>The maximum number of instructions in a virtual machine program
** used to implement an SQL statement.  This limit is not currently
** enforced, though that might be added in some future release of
** SQLite.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
+
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
** <dd>The maximum number of arguments on a function.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
+
** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
**
+
** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
** <dd>The maximum length of the pattern argument to the [LIKE] or
** [GLOB] operators.</dd>)^
**
+
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
-
** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
+
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^
** </dl>
*/
@@ -3647,7 +3805,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
** database locks it needs to do its job.  ^If the statement is a [COMMIT]
** or occurs outside of an explicit transaction, then you can retry the
-
** statement.  If the statement is not a [COMMIT] and occurs within a
+
** statement.  If the statement is not a [COMMIT] and occurs within an
** explicit transaction then you should rollback the transaction before
** continuing.
**
@@ -3926,7 +4084,7 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
** CAPI3REF: Destroy A Prepared Statement Object
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
-
** ^If the most recent evaluation of the statement encountered no errors or
+
** ^If the most recent evaluation of the statement encountered no errors
** or if the statement is never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK.  ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
@@ -5153,6 +5311,11 @@ struct sqlite3_module {
                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
                       void **ppArg);
  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+
  /* The methods above are in version 1 of the sqlite_module object. Those 
+
  ** below are for version 2 and greater. */
+
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+
  int (*xRelease)(sqlite3_vtab *pVTab, int);
+
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};

/*
@@ -5835,7 +5998,7 @@ struct sqlite3_mutex_methods {
**
** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
** the routine should return 1.   This seems counter-intuitive since
-
** clearly the mutex cannot be held if it does not exist.  But the
+
** clearly the mutex cannot be held if it does not exist.  But
** the reason the mutex does not exist is because the build is not
** using mutexes.  And we do not want the assert() containing the
** call to sqlite3_mutex_held() to fail, so a non-zero return is
@@ -5958,7 +6121,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_PGHDRSZ                 17
#define SQLITE_TESTCTRL_SCRATCHMALLOC           18
-
#define SQLITE_TESTCTRL_LAST                    18
+
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         19
+
#define SQLITE_TESTCTRL_LAST                    19

/*
** CAPI3REF: SQLite Runtime Status
@@ -5967,7 +6131,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for
** the specific parameter to measure.  ^(Recognized integer codes
-
** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
+
** are of the form [status parameters | SQLITE_STATUS_...].)^
** ^The current value of the parameter is returned into *pCurrent.
** ^The highest recorded value is returned in *pHighwater.  ^If the
** resetFlag is true, then the highest record value is reset after
@@ -5994,12 +6158,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF

/*
** CAPI3REF: Status Parameters
+
** KEYWORDS: {status parameters}
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite3_status()].
**
** <dl>
-
** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
+
** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
** <dd>This parameter is the current amount of memory checked out
** using [sqlite3_malloc()], either directly or indirectly.  The
** figure includes calls made to [sqlite3_malloc()] by the application
@@ -6009,23 +6174,24 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** this parameter.  The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+
** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
** internal equivalents).  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
+
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
** <dd>This parameter records the number of separate memory allocations
** currently checked out.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
+
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
** [pagecache memory allocator] that was configured using 
** [SQLITE_CONFIG_PAGECACHE].  The
** value returned is in pages, not in bytes.</dd>)^
**
+
** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] 
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of page cache
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
@@ -6035,13 +6201,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
+
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [pagecache memory allocator].  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
+
** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
** <dd>This parameter returns the number of allocations used out of the
** [scratch memory allocator] configured using
** [SQLITE_CONFIG_SCRATCH].  The value returned is in allocations, not
@@ -6049,7 +6215,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** outstanding at time, this parameter also reports the number of threads
** using scratch memory at the same time.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
+
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of scratch memory
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
** buffer and where forced to overflow to [sqlite3_malloc()].  The values
@@ -6059,13 +6225,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** slots were available.
** </dd>)^
**
-
** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
+
** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [scratch memory allocator].  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
+
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
** <dd>This parameter records the deepest parser stack.  It is only
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
** </dl>
@@ -6090,9 +6256,9 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** about a single [database connection].  ^The first argument is the
** database connection object to be interrogated.  ^The second argument
** is an integer constant, taken from the set of
-
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
+
** [SQLITE_DBSTATUS options], that
** determines the parameter to interrogate.  The set of 
-
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
+
** [SQLITE_DBSTATUS options] is likely
** to grow in future releases of SQLite.
**
** ^The current value of the requested parameter is written into *pCur
@@ -6109,6 +6275,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r

/*
** CAPI3REF: Status Parameters for database connections
+
** KEYWORDS: {SQLITE_DBSTATUS options}
**
** These constants are the available integer "verbs" that can be passed as
** the second argument to the [sqlite3_db_status()] interface.
@@ -6120,15 +6287,16 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** if a discontinued or unsupported verb is invoked.
**
** <dl>
-
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
-
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
+
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were 
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
+
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
@@ -6136,6 +6304,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
+
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
@@ -6143,12 +6312,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
-
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
+
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
-
** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
+
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^ 
@@ -6157,7 +6326,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
-
** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
+
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
@@ -6179,7 +6348,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** CAPI3REF: Prepared Statement Status
**
** ^(Each prepared statement maintains various
-
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
+
** [SQLITE_STMTSTATUS counters] that measure the number
** of times it has performed specific operations.)^  These counters can
** be used to monitor the performance characteristics of the prepared
** statements.  For example, if the number of table steps greatly exceeds
@@ -6190,7 +6359,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** ^(This interface is used to retrieve and reset counter values from
** a [prepared statement].  The first argument is the prepared statement
** object to be interrogated.  The second argument
-
** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
+
** is an integer code for a specific [SQLITE_STMTSTATUS counter]
** to be interrogated.)^
** ^The current value of the requested counter is returned.
** ^If the resetFlg is true, then the counter is reset to zero after this
@@ -6202,24 +6371,25 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);

/*
** CAPI3REF: Status Parameters for prepared statements
+
** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite3_stmt_status()] interface.
** The meanings of the various counters are as follows:
**
** <dl>
-
** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
+
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan.  Large numbers for this counter
** may indicate opportunities for performance improvement through 
** careful use of indices.</dd>
**
-
** <dt>SQLITE_STMTSTATUS_SORT</dt>
+
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
** improvement performance through careful use of indices.</dd>
**
-
** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
+
** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
** <dd>^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
@@ -6270,6 +6440,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** the application may discard the parameter after the call to
** [sqlite3_config()] returns.)^
**
+
** [[the xInit() page cache method]]
** ^(The xInit() method is called once for each effective 
** call to [sqlite3_initialize()])^
** (usually only once during the lifetime of the process). ^(The xInit()
@@ -6280,6 +6451,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** built-in default page cache is used instead of the application defined
** page cache.)^
**
+
** [[the xShutdown() page cache method]]
** ^The xShutdown() method is called by [sqlite3_shutdown()].
** It can be used to clean up 
** any outstanding resources before process shutdown, if required.
@@ -6294,6 +6466,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^SQLite will never invoke xInit() more than once without an intervening
** call to xShutdown().
**
+
** [[the xCreate() page cache methods]]
** ^SQLite invokes the xCreate() method to construct a new cache instance.
** SQLite will typically create one cache instance for each open database file,
** though this is not guaranteed. ^The
@@ -6318,6 +6491,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^Hence, a cache created with bPurgeable false will
** never contain any unpinned pages.
**
+
** [[the xCachesize() page cache method]]
** ^(The xCachesize() method may be called at any time by SQLite to set the
** suggested maximum cache-size (number of pages stored by) the cache
** instance passed as the first argument. This is the value configured using
@@ -6325,14 +6499,16 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** parameter, the implementation is not required to do anything with this
** value; it is advisory only.
**
+
** [[the xPagecount() page cache methods]]
** The xPagecount() method must return the number of pages currently
** stored in the cache, both pinned and unpinned.
** 
+
** [[the xFetch() page cache methods]]
** The xFetch() method locates a page in the cache and returns a pointer to 
** the page, or a NULL pointer.
** A "page", in this context, means a buffer of szPage bytes aligned at an
** 8-byte boundary. The page to be fetched is determined by the key. ^The
-
** mimimum key value is 1.  After it has been retrieved using xFetch, the page 
+
** minimum key value is 1.  After it has been retrieved using xFetch, the page 
** is considered to be "pinned".
**
** If the requested page is already in the page cache, then the page cache
@@ -6356,6 +6532,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
+
** [[the xUnpin() page cache method]]
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument.  If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
@@ -6368,6 +6545,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** call to xUnpin() unpins the page regardless of the number of prior calls 
** to xFetch().
**
+
** [[the xRekey() page cache methods]]
** The xRekey() method is used to change the key value associated with the
** page passed as the second argument. If the cache
** previously contains an entry associated with newKey, it must be
@@ -6380,6 +6558,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** of these pages are pinned, they are implicitly unpinned, meaning that
** they can be safely discarded.
**
+
** [[the xDestroy() page cache method]]
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
** All resources associated with the specified cache should be freed. ^After
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
@@ -6442,7 +6621,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** There should be exactly one call to sqlite3_backup_finish() for each
** successful call to sqlite3_backup_init().
**
-
** <b>sqlite3_backup_init()</b>
+
** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
**
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the 
** [database connection] associated with the destination database 
@@ -6469,7 +6648,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** sqlite3_backup_finish() functions to perform the specified backup 
** operation.
**
-
** <b>sqlite3_backup_step()</b>
+
** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
**
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between 
** the source and destination databases specified by [sqlite3_backup] object B.
@@ -6526,7 +6705,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
-
** <b>sqlite3_backup_finish()</b>
+
** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
**
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the 
** application wishes to abandon the backup operation, the application
@@ -6549,7 +6728,8 @@ typedef struct sqlite3_backup sqlite3_backup;
** is not a permanent error and does not affect the return value of
** sqlite3_backup_finish().
**
-
** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
+
** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
+
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
**
** ^Each call to sqlite3_backup_step() sets two values inside
** the [sqlite3_backup] object: the number of pages still to be backed
@@ -6935,6 +7115,93 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
#define SQLITE_CHECKPOINT_FULL    1
#define SQLITE_CHECKPOINT_RESTART 2

+
/*
+
** CAPI3REF: Virtual Table Interface Configuration
+
**
+
** This function may be called by either the [xConnect] or [xCreate] method
+
** of a [virtual table] implementation to configure
+
** various facets of the virtual table interface.
+
**
+
** If this interface is invoked outside the context of an xConnect or
+
** xCreate virtual table method then the behavior is undefined.
+
**
+
** At present, there is only one option that may be configured using
+
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].)  Further options
+
** may be added in the future.
+
*/
+
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+

+
/*
+
** CAPI3REF: Virtual Table Configuration Options
+
**
+
** These macros define the various options to the
+
** [sqlite3_vtab_config()] interface that [virtual table] implementations
+
** can use to customize and optimize their behavior.
+
**
+
** <dl>
+
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
+
** <dd>Calls of the form
+
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
+
** where X is an integer.  If X is zero, then the [virtual table] whose
+
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
+
** support constraints.  In this configuration (which is the default) if
+
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
+
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
+
** specified as part of the users SQL statement, regardless of the actual
+
** ON CONFLICT mode specified.
+
**
+
** If X is non-zero, then the virtual table implementation guarantees
+
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
+
** any modifications to internal or persistent data structures have been made.
+
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite 
+
** is able to roll back a statement or database transaction, and abandon
+
** or continue processing the current SQL statement as appropriate. 
+
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
+
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
+
** had been ABORT.
+
**
+
** Virtual table implementations that are required to handle OR REPLACE
+
** must do so within the [xUpdate] method. If a call to the 
+
** [sqlite3_vtab_on_conflict()] function indicates that the current ON 
+
** CONFLICT policy is REPLACE, the virtual table implementation should 
+
** silently replace the appropriate rows within the xUpdate callback and
+
** return SQLITE_OK. Or, if this is not possible, it may return
+
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
+
** constraint handling.
+
** </dl>
+
*/
+
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+

+
/*
+
** CAPI3REF: Determine The Virtual Table Conflict Policy
+
**
+
** This function may only be called from within a call to the [xUpdate] method
+
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
+
** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
+
** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
+
** of the SQL statement that triggered the call to the [xUpdate] method of the
+
** [virtual table].
+
*/
+
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+

+
/*
+
** CAPI3REF: Conflict resolution modes
+
**
+
** These constants are returned by [sqlite3_vtab_on_conflict()] to
+
** inform a [virtual table] implementation what the [ON CONFLICT] mode
+
** is for the SQL statement being evaluated.
+
**
+
** Note that the [SQLITE_IGNORE] constant is also used as a potential
+
** return value from the [sqlite3_set_authorizer()] callback and that
+
** [SQLITE_ABORT] is also a [result code].
+
*/
+
#define SQLITE_ROLLBACK 1
+
/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
+
#define SQLITE_FAIL     3
+
/* #define SQLITE_ABORT 4  // Also an error code */
+
#define SQLITE_REPLACE  5
+

+


/*
** Undo the hack that converts floating point types to integer for
@@ -7601,6 +7868,7 @@ typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
+
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
@@ -7657,6 +7925,7 @@ typedef struct BtShared BtShared;


SQLITE_PRIVATE int sqlite3BtreeOpen(
+
  sqlite3_vfs *pVfs,       /* VFS to use with this b-tree */
  const char *zFilename,   /* Name of database file to open */
  sqlite3 *db,             /* Associated database connection */
  Btree **ppBtree,         /* Return open Btree* here */
@@ -8217,6 +8486,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
+
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
@@ -8230,7 +8500,7 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
-
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
+
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
@@ -8239,6 +8509,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int);
SQLITE_PRIVATE   void sqlite3VdbeTrace(Vdbe*,FILE*);
#endif
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
+
SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
@@ -9015,7 +9286,7 @@ struct Db {
** A thread must be holding a mutex on the corresponding Btree in order
** to access Schema content.  This implies that the thread must also be
** holding a mutex on the sqlite3 connection pointer that owns the Btree.
-
** For a TEMP Schema, on the connection mutex is required.
+
** For a TEMP Schema, only the connection mutex is required.
*/
struct Schema {
  int schema_cookie;   /* Database schema version number for this file */
@@ -9136,7 +9407,7 @@ struct sqlite3 {
  int nDb;                      /* Number of backends currently in use */
  Db *aDb;                      /* All backends */
  int flags;                    /* Miscellaneous flags. See below */
-
  int openFlags;                /* Flags passed to sqlite3_vfs.xOpen() */
+
  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u8 autoCommit;                /* The auto-commit flag. */
@@ -9145,6 +9416,7 @@ struct sqlite3 {
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
+
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  int nextPagesize;             /* Pagesize after VACUUM if >0 */
  int nTable;                   /* Number of tables in the database */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
@@ -9203,7 +9475,7 @@ struct sqlite3 {
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  Hash aModule;                 /* populated by sqlite3_create_module() */
-
  Table *pVTab;                 /* vtab with active Connect/Create method */
+
  VtabCtx *pVtabCtx;            /* Context for active vtab connect/create */
  VTable **aVTrans;             /* Virtual tables with open transactions */
  int nVTrans;                  /* Allocated size of aVTrans */
  VTable *pDisconnect;    /* Disconnect these in next sqlite3_prepare() */
@@ -9287,6 +9559,7 @@ struct sqlite3 {
#define SQLITE_IndexCover     0x10        /* Disable index covering table */
#define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
+
#define SQLITE_IdxRealAsInt   0x80        /* Store REAL as INT in indices */
#define SQLITE_OptMask        0xff        /* Mask of all disablable opts */

/*
@@ -9566,6 +9839,8 @@ struct VTable {
  Module *pMod;             /* Pointer to module implementation */
  sqlite3_vtab *pVtab;      /* Pointer to vtab instance */
  int nRef;                 /* Number of pointers to this structure */
+
  u8 bConstraint;           /* True if constraints are supported */
+
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */
};

@@ -10560,9 +10835,8 @@ struct Parse {
  ** each recursion */

  int nVar;            /* Number of '?' variables seen in the SQL so far */
-
  int nVarExpr;        /* Number of used slots in apVarExpr[] */
-
  int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
-
  Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */
+
  int nzVar;           /* Number of available slots in azVar[] */
+
  char **azVar;        /* Pointers to names of parameters */
  Vdbe *pReprepare;    /* VM being reprepared (sqlite3Reprepare()) */
  int nAlias;          /* Number of aliased result set columns */
  int nAliasAlloc;     /* Number of allocated slots for aAlias[] */
@@ -10754,6 +11028,7 @@ struct Sqlite3Config {
  int bMemstat;                     /* True to enable memory status */
  int bCoreMutex;                   /* True to enable core mutexing */
  int bFullMutex;                   /* True to enable full mutexing */
+
  int bOpenUri;                     /* True to interpret filenames as URIs */
  int mxStrlen;                     /* Maximum string length */
  int szLookaside;                  /* Default lookaside buffer size */
  int nLookaside;                   /* Default lookaside buffer count */
@@ -10782,6 +11057,7 @@ struct Sqlite3Config {
  int nRefInitMutex;                /* Number of users of pInitMutex */
  void (*xLog)(void*,int,const char*); /* Function for logging */
  void *pLogArg;                       /* First argument to xLog() */
+
  int bLocaltimeFault;              /* True to fail localtime() calls */
};

/*
@@ -11003,6 +11279,8 @@ SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
+
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
+
                    sqlite3_vfs**,char**,char **);

SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
@@ -11207,7 +11485,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
-
SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
+
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8*, const u8**);

/*
** Routines to read and write variable-length integers.  These used to
@@ -11253,6 +11531,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
+
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
@@ -11268,6 +11547,12 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3AbsInt32(int);
+
#ifdef SQLITE_ENABLE_8_3_NAMES
+
SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
+
#else
+
# define sqlite3FileSuffix3(X,Y)
+
#endif
+
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z);

SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
@@ -11377,6 +11662,7 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
#  define sqlite3VtabLock(X) 
#  define sqlite3VtabUnlock(X)
#  define sqlite3VtabUnlockList(X)
+
#  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
#else
SQLITE_PRIVATE    void sqlite3VtabClear(sqlite3 *db, Table*);
SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, char **);
@@ -11385,6 +11671,7 @@ SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
SQLITE_PRIVATE    void sqlite3VtabLock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlockList(sqlite3*);
+
SQLITE_PRIVATE    int sqlite3VtabSavepoint(sqlite3 *, int, int);
#  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
@@ -11691,7 +11978,9 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
};
#endif

-

+
#ifndef SQLITE_USE_URI
+
# define  SQLITE_USE_URI 0
+
#endif

/*
** The following singleton contains the global configuration for
@@ -11701,6 +11990,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE_THREADSAFE==1,      /* bFullMutex */
+
   SQLITE_USE_URI,            /* bOpenUri */
   0x7ffffffe,                /* mxStrlen */
   100,                       /* szLookaside */
   500,                       /* nLookaside */
@@ -11728,6 +12018,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   0,                         /* nRefInitMutex */
   0,                         /* xLog */
   0,                         /* pLogArg */
+
   0,                         /* bLocaltimeFault */
};


@@ -12480,11 +12771,11 @@ struct Vdbe {
  Mem *aVar;              /* Values for the OP_Variable opcode. */
  char **azVar;           /* Name of variables */
  ynVar nVar;             /* Number of entries in aVar[] */
+
  ynVar nzVar;            /* Number of entries in azVar[] */
  u32 cacheCtr;           /* VdbeCursor row cache generation counter */
  int pc;                 /* The program counter */
  int rc;                 /* Value to return */
  u8 errorAction;         /* Recovery action to do in case of an error */
-
  u8 okVar;               /* True if azVar[] has been initialized */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 expired;             /* True if the VM needs to be recompiled */
@@ -12878,22 +13169,6 @@ SQLITE_API int sqlite3_db_status(

#ifndef SQLITE_OMIT_DATETIME_FUNCS

-
/*
-
** On recent Windows platforms, the localtime_s() function is available
-
** as part of the "Secure CRT". It is essentially equivalent to 
-
** localtime_r() available under most POSIX platforms, except that the 
-
** order of the parameters is reversed.
-
**
-
** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
-
**
-
** If the user has not indicated to use localtime_r() or localtime_s()
-
** already, check for an MSVC build environment that provides 
-
** localtime_s().
-
*/
-
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
-
     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
-
#define HAVE_LOCALTIME_S 1
-
#endif

/*
** A structure for holding a single date and time.
@@ -13239,15 +13514,83 @@ static void clearYMD_HMS_TZ(DateTime *p){
  p->validTZ = 0;
}

+
/*
+
** On recent Windows platforms, the localtime_s() function is available
+
** as part of the "Secure CRT". It is essentially equivalent to 
+
** localtime_r() available under most POSIX platforms, except that the 
+
** order of the parameters is reversed.
+
**
+
** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
+
**
+
** If the user has not indicated to use localtime_r() or localtime_s()
+
** already, check for an MSVC build environment that provides 
+
** localtime_s().
+
*/
+
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
+
     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
+
#define HAVE_LOCALTIME_S 1
+
#endif
+

+
#ifndef SQLITE_OMIT_LOCALTIME
+
/*
+
** The following routine implements the rough equivalent of localtime_r()
+
** using whatever operating-system specific localtime facility that
+
** is available.  This routine returns 0 on success and
+
** non-zero on any kind of error.
+
**
+
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
+
** routine will always fail.
+
*/
+
static int osLocaltime(time_t *t, struct tm *pTm){
+
  int rc;
+
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
+
      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
+
  struct tm *pX;
+
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+
  sqlite3_mutex_enter(mutex);
+
  pX = localtime(t);
+
#ifndef SQLITE_OMIT_BUILTIN_TEST
+
  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
+
#endif
+
  if( pX ) *pTm = *pX;
+
  sqlite3_mutex_leave(mutex);
+
  rc = pX==0;
+
#else
+
#ifndef SQLITE_OMIT_BUILTIN_TEST
+
  if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
+
#endif
+
#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
+
  rc = localtime_r(t, pTm)==0;
+
#else
+
  rc = localtime_s(pTm, t);
+
#endif /* HAVE_LOCALTIME_R */
+
#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
+
  return rc;
+
}
+
#endif /* SQLITE_OMIT_LOCALTIME */
+

+

#ifndef SQLITE_OMIT_LOCALTIME
/*
-
** Compute the difference (in milliseconds)
-
** between localtime and UTC (a.k.a. GMT)
-
** for the time value p where p is in UTC.
+
** Compute the difference (in milliseconds) between localtime and UTC
+
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
+
** return this value and set *pRc to SQLITE_OK. 
+
**
+
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
+
** is undefined in this case.
*/
-
static sqlite3_int64 localtimeOffset(DateTime *p){
+
static sqlite3_int64 localtimeOffset(
+
  DateTime *p,                    /* Date at which to calculate offset */
+
  sqlite3_context *pCtx,          /* Write error here if one occurs */
+
  int *pRc                        /* OUT: Error code. SQLITE_OK or ERROR */
+
){
  DateTime x, y;
  time_t t;
+
  struct tm sLocal;
+

+
  /* Initialize the contents of sLocal to avoid a compiler warning. */
+
  memset(&sLocal, 0, sizeof(sLocal));
+

  x = *p;
  computeYMD_HMS(&x);
  if( x.Y<1971 || x.Y>=2038 ){
@@ -13265,47 +13608,23 @@ static sqlite3_int64 localtimeOffset(DateTime *p){
  x.validJD = 0;
  computeJD(&x);
  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
-
#ifdef HAVE_LOCALTIME_R
-
  {
-
    struct tm sLocal;
-
    localtime_r(&t, &sLocal);
-
    y.Y = sLocal.tm_year + 1900;
-
    y.M = sLocal.tm_mon + 1;
-
    y.D = sLocal.tm_mday;
-
    y.h = sLocal.tm_hour;
-
    y.m = sLocal.tm_min;
-
    y.s = sLocal.tm_sec;
-
  }
-
#elif defined(HAVE_LOCALTIME_S) && HAVE_LOCALTIME_S
-
  {
-
    struct tm sLocal;
-
    localtime_s(&sLocal, &t);
-
    y.Y = sLocal.tm_year + 1900;
-
    y.M = sLocal.tm_mon + 1;
-
    y.D = sLocal.tm_mday;
-
    y.h = sLocal.tm_hour;
-
    y.m = sLocal.tm_min;
-
    y.s = sLocal.tm_sec;
-
  }
-
#else
-
  {
-
    struct tm *pTm;
-
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-
    pTm = localtime(&t);
-
    y.Y = pTm->tm_year + 1900;
-
    y.M = pTm->tm_mon + 1;
-
    y.D = pTm->tm_mday;
-
    y.h = pTm->tm_hour;
-
    y.m = pTm->tm_min;
-
    y.s = pTm->tm_sec;
-
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+
  if( osLocaltime(&t, &sLocal) ){
+
    sqlite3_result_error(pCtx, "local time unavailable", -1);
+
    *pRc = SQLITE_ERROR;
+
    return 0;
  }
-
#endif
+
  y.Y = sLocal.tm_year + 1900;
+
  y.M = sLocal.tm_mon + 1;
+
  y.D = sLocal.tm_mday;
+
  y.h = sLocal.tm_hour;
+
  y.m = sLocal.tm_min;
+
  y.s = sLocal.tm_sec;
  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.validTZ = 0;
  computeJD(&y);
+
  *pRc = SQLITE_OK;
  return y.iJD - x.iJD;
}
#endif /* SQLITE_OMIT_LOCALTIME */
@@ -13329,9 +13648,12 @@ static sqlite3_int64 localtimeOffset(DateTime *p){
**     localtime
**     utc
**
-
** Return 0 on success and 1 if there is any kind of error.
+
** Return 0 on success and 1 if there is any kind of error. If the error
+
** is in a system call (i.e. localtime()), then an error message is written
+
** to context pCtx. If the error is an unrecognized modifier, no error is
+
** written to pCtx.
*/
-
static int parseModifier(const char *zMod, DateTime *p){
+
static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
  int rc = 1;
  int n;
  double r;
@@ -13351,9 +13673,8 @@ static int parseModifier(const char *zMod, DateTime *p){
      */
      if( strcmp(z, "localtime")==0 ){
        computeJD(p);
-
        p->iJD += localtimeOffset(p);
+
        p->iJD += localtimeOffset(p, pCtx, &rc);
        clearYMD_HMS_TZ(p);
-
        rc = 0;
      }
      break;
    }
@@ -13374,11 +13695,12 @@ static int parseModifier(const char *zMod, DateTime *p){
      else if( strcmp(z, "utc")==0 ){
        sqlite3_int64 c1;
        computeJD(p);
-
        c1 = localtimeOffset(p);
-
        p->iJD -= c1;
-
        clearYMD_HMS_TZ(p);
-
        p->iJD += c1 - localtimeOffset(p);
-
        rc = 0;
+
        c1 = localtimeOffset(p, pCtx, &rc);
+
        if( rc==SQLITE_OK ){
+
          p->iJD -= c1;
+
          clearYMD_HMS_TZ(p);
+
          p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
+
        }
      }
#endif
      break;
@@ -13559,9 +13881,8 @@ static int isDate(
    }
  }
  for(i=1; i<argc; i++){
-
    if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){
-
      return 1;
-
    }
+
    z = sqlite3_value_text(argv[i]);
+
    if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
  }
  return 0;
}
@@ -17950,7 +18271,7 @@ static int mallocWithAlarm(int n, void **pp){
  sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
  if( mem0.alarmCallback!=0 ){
    int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-
    if( nUsed+nFull >= mem0.alarmThreshold ){
+
    if( nUsed >= mem0.alarmThreshold - nFull ){
      mem0.nearlyFull = 1;
      sqlite3MallocAlarm(nFull);
    }else{
@@ -18191,7 +18512,7 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
** Change the size of an existing memory allocation
*/
SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
-
  int nOld, nNew;
+
  int nOld, nNew, nDiff;
  void *pNew;
  if( pOld==0 ){
    return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
@@ -18214,9 +18535,10 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
-
    if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= 
-
          mem0.alarmThreshold ){
-
      sqlite3MallocAlarm(nNew-nOld);
+
    nDiff = nNew - nOld;
+
    if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
+
          mem0.alarmThreshold-nDiff ){
+
      sqlite3MallocAlarm(nDiff);
    }
    assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
    assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
@@ -19801,7 +20123,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
        || (c&0xFFFFF800)==0xD800                          \
        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
  }
-
SQLITE_PRIVATE int sqlite3Utf8Read(
+
SQLITE_PRIVATE u32 sqlite3Utf8Read(
  const unsigned char *zIn,       /* First byte of UTF-8 character */
  const unsigned char **pzNext    /* Write first byte past UTF-8 char here */
){
@@ -21182,13 +21504,12 @@ SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){



-
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
-
static u8 hexToInt(int h){
+
SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
  h += 9*(1&(h>>6));
@@ -21198,7 +21519,6 @@ static u8 hexToInt(int h){
#endif
  return (u8)(h & 0xf);
}
-
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */

#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
@@ -21215,7 +21535,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
  n--;
  if( zBlob ){
    for(i=0; i<n; i+=2){
-
      zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
+
      zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
    }
    zBlob[i/2] = 0;
  }
@@ -21348,6 +21668,32 @@ SQLITE_PRIVATE int sqlite3AbsInt32(int x){
  return -x;
}

+
#ifdef SQLITE_ENABLE_8_3_NAMES
+
/*
+
** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
+
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
+
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
+
** three characters, then shorten the suffix on z[] to be the last three
+
** characters of the original suffix.
+
**
+
** Examples:
+
**
+
**     test.db-journal    =>   test.nal
+
**     test.db-wal        =>   test.wal
+
**     test.db-shm        =>   test.shm
+
*/
+
SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
+
  const char *zOk;
+
  zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
+
  if( zOk && sqlite3GetBoolean(zOk) ){
+
    int i, sz;
+
    sz = sqlite3Strlen30(z);
+
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
+
    if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
+
  }
+
}
+
#endif
+

/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
@@ -24054,6 +24400,10 @@ SQLITE_API int sqlite3_os_end(void){
# include <sys/mount.h>
#endif

+
#ifdef HAVE_UTIME
+
# include <utime.h>
+
#endif
+

/*
** Allowed values of unixFile.fsFlags
*/
@@ -24402,6 +24752,18 @@ SQLITE_API int sqlite3_open_file_count = 0;
#endif

/*
+
** Different Unix systems declare open() in different ways.  Same use
+
** open(const char*,int,mode_t).  Others use open(const char*,int,...).
+
** The difference is important when using a pointer to the function.
+
**
+
** The safest way to deal with the problem is to always use this wrapper
+
** which always has the same well-defined interface.
+
*/
+
static int posixOpen(const char *zFile, int flags, int mode){
+
  return open(zFile, flags, mode);
+
}
+

+
/*
** 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
@@ -24412,8 +24774,8 @@ static struct unix_syscall {
  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
  sqlite3_syscall_ptr pDefault; /* Default value */
} aSyscall[] = {
-
  { "open",         (sqlite3_syscall_ptr)open,       0  },
-
#define osOpen      ((int(*)(const char*,int,...))aSyscall[0].pCurrent)
+
  { "open",         (sqlite3_syscall_ptr)posixOpen,  0  },
+
#define osOpen      ((int(*)(const char*,int,int))aSyscall[0].pCurrent)

  { "close",        (sqlite3_syscall_ptr)close,      0  },
#define osClose     ((int(*)(int))aSyscall[1].pCurrent)
@@ -24450,7 +24812,7 @@ static struct unix_syscall {
  { "read",         (sqlite3_syscall_ptr)read,       0  },
#define osRead      ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)

-
#if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
+
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
  { "pread",        (sqlite3_syscall_ptr)pread,      0  },
#else
  { "pread",        (sqlite3_syscall_ptr)0,          0  },
@@ -24467,7 +24829,7 @@ static struct unix_syscall {
  { "write",        (sqlite3_syscall_ptr)write,      0  },
#define osWrite     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)

-
#if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
+
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
  { "pwrite",       (sqlite3_syscall_ptr)pwrite,     0  },
#else
  { "pwrite",       (sqlite3_syscall_ptr)0,          0  },
@@ -25053,7 +25415,7 @@ struct unixInodeInfo {
  UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
  unixInodeInfo *pPrev;           /*    .... doubly linked */
-
#if defined(SQLITE_ENABLE_LOCKING_STYLE)
+
#if SQLITE_ENABLE_LOCKING_STYLE
  unsigned long long sharedByte;  /* for AFP simulated shared lock */
#endif
#if OS_VXWORKS
@@ -26047,8 +26409,10 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
  */
  if( pFile->eFileLock > NO_LOCK ){
    pFile->eFileLock = eFileLock;
-
#if !OS_VXWORKS
    /* Always update the timestamp on the old file */
+
#ifdef HAVE_UTIME
+
    utime(zLockFile, NULL);
+
#else
    utimes(zLockFile, NULL);
#endif
    return SQLITE_OK;
@@ -27210,7 +27574,7 @@ static int unixWrite(
  SimulateDiskfullError(( wrote=0, amt=1 ));

  if( amt>0 ){
-
    if( wrote<0 ){
+
    if( wrote<0 && pFile->lastErrno!=ENOSPC ){
      /* lastErrno set by seekAndWrite */
      return SQLITE_IOERR_WRITE;
    }else{
@@ -27645,7 +28009,8 @@ struct unixShmNode {
  char *zFilename;           /* Name of the mmapped file */
  int h;                     /* Open file descriptor */
  int szRegion;              /* Size of shared-memory regions */
-
  int nRegion;               /* Size of array apRegion */
+
  u16 nRegion;               /* Size of array apRegion */
+
  u8 isReadonly;             /* True if read-only */
  char **apRegion;           /* Array of mapped shared-memory regions */
  int nRef;                  /* Number of unixShm objects pointing to this */
  unixShm *pFirst;           /* All unixShm objects pointing to this */
@@ -27877,6 +28242,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
                     (u32)sStat.st_ino, (u32)sStat.st_dev);
#else
    sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
+
    sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
#endif
    pShmNode->h = -1;
    pDbFd->pInode->pShmNode = pShmNode;
@@ -27891,8 +28257,17 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
                               (sStat.st_mode & 0777));
      if( pShmNode->h<0 ){
-
        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
-
        goto shm_open_err;
+
        const char *zRO;
+
        zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
+
        if( zRO && sqlite3GetBoolean(zRO) ){
+
          pShmNode->h = robust_open(zShmFilename, O_RDONLY,
+
                                    (sStat.st_mode & 0777));
+
          pShmNode->isReadonly = 1;
+
        }
+
        if( pShmNode->h<0 ){
+
          rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
+
          goto shm_open_err;
+
        }
      }
  
      /* Check to see if another process is holding the dead-man switch.
@@ -28031,11 +28406,12 @@ static int unixShmMap(
    while(pShmNode->nRegion<=iRegion){
      void *pMem;
      if( pShmNode->h>=0 ){
-
        pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
+
        pMem = mmap(0, szRegion,
+
            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
        );
        if( pMem==MAP_FAILED ){
-
          rc = SQLITE_IOERR;
+
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
      }else{
@@ -28057,6 +28433,7 @@ shmpage_out:
  }else{
    *pp = 0;
  }
+
  if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
  sqlite3_mutex_leave(pShmNode->mutex);
  return rc;
}
@@ -28910,6 +29287,11 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
** corresponding database file and sets *pMode to this value. Whenever 
** possible, WAL and journal files are created using the same permissions 
** as the associated database file.
+
**
+
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
+
** original filename is unavailable.  But 8_3_NAMES is only used for
+
** FAT filesystems and permissions do not matter there, so just use
+
** the default permissions.
*/
static int findCreateFileMode(
  const char *zPath,              /* Path of file (possibly) being created */
@@ -28917,6 +29299,7 @@ static int findCreateFileMode(
  mode_t *pMode                   /* OUT: Permissions to open file with */
){
  int rc = SQLITE_OK;             /* Return Code */
+
  *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
  if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
    char zDb[MAX_PATHNAME+1];     /* Database file path */
    int nDb;                      /* Number of valid bytes in zDb */
@@ -28928,15 +29311,15 @@ static int findCreateFileMode(
    **
    **   "<path to db>-journal"
    **   "<path to db>-wal"
-
    **   "<path to db>-journal-NNNN"
-
    **   "<path to db>-wal-NNNN"
+
    **   "<path to db>-journalNN"
+
    **   "<path to db>-walNN"
    **
-
    ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are 
+
    ** where NN is a 4 digit decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
-
    while( nDb>0 && zPath[nDb]!='l' ) nDb--;
-
    nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7);
+
    while( nDb>0 && zPath[nDb]!='-' ) nDb--;
+
    if( nDb==0 ) return SQLITE_OK;
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

@@ -28947,8 +29330,6 @@ static int findCreateFileMode(
    }
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
    *pMode = 0600;
-
  }else{
-
    *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
  }
  return rc;
}
@@ -31156,6 +31537,7 @@ struct winFile {
#endif
};

+

/*
** Forward prototypes.
*/
@@ -31323,7 +31705,7 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
** Convert UTF-8 to multibyte character string.  Space to hold the 
** returned string is obtained from malloc().
*/
-
static char *utf8ToMbcs(const char *zFilename){
+
SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
  char *zFilenameMbcs;
  WCHAR *zTmpWide;

@@ -31336,6 +31718,109 @@ static char *utf8ToMbcs(const char *zFilename){
  return zFilenameMbcs;
}

+

+
/*
+
** The return value of getLastErrorMsg
+
** is zero if the error message fits in the buffer, or non-zero
+
** otherwise (if the message was truncated).
+
*/
+
static int getLastErrorMsg(int nBuf, char *zBuf){
+
  /* FormatMessage returns 0 on failure.  Otherwise it
+
  ** returns the number of TCHARs written to the output
+
  ** buffer, excluding the terminating null char.
+
  */
+
  DWORD error = GetLastError();
+
  DWORD dwLen = 0;
+
  char *zOut = 0;
+

+
  if( isNT() ){
+
    WCHAR *zTempWide = NULL;
+
    dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+
                           NULL,
+
                           error,
+
                           0,
+
                           (LPWSTR) &zTempWide,
+
                           0,
+
                           0);
+
    if( dwLen > 0 ){
+
      /* allocate a buffer and convert to UTF8 */
+
      zOut = unicodeToUtf8(zTempWide);
+
      /* free the system buffer allocated by FormatMessage */
+
      LocalFree(zTempWide);
+
    }
+
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
+
** Since the ASCII 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{
+
    char *zTemp = NULL;
+
    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+
                           NULL,
+
                           error,
+
                           0,
+
                           (LPSTR) &zTemp,
+
                           0,
+
                           0);
+
    if( dwLen > 0 ){
+
      /* allocate a buffer and convert to UTF8 */
+
      zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
+
      /* free the system buffer allocated by FormatMessage */
+
      LocalFree(zTemp);
+
    }
+
#endif
+
  }
+
  if( 0 == dwLen ){
+
    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
+
  }else{
+
    /* copy a maximum of nBuf chars to output buffer */
+
    sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
+
    /* free the UTF8 buffer */
+
    free(zOut);
+
  }
+
  return 0;
+
}
+

+
/*
+
**
+
** This function - winLogErrorAtLine() - is only ever called via the macro
+
** winLogError().
+
**
+
** This routine is invoked after an error occurs in an OS function.
+
** It logs a message using sqlite3_log() containing the current value of
+
** error code and, if possible, the human-readable equivalent from 
+
** FormatMessage.
+
**
+
** The first argument passed to the macro should be the error code that
+
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). 
+
** The two subsequent arguments should be the name of the OS function that
+
** failed and the the associated file-system path, if any.
+
*/
+
#define winLogError(a,b,c)     winLogErrorAtLine(a,b,c,__LINE__)
+
static int winLogErrorAtLine(
+
  int errcode,                    /* SQLite error code */
+
  const char *zFunc,              /* Name of OS function that failed */
+
  const char *zPath,              /* File path associated with error */
+
  int iLine                       /* Source line number where error occurred */
+
){
+
  char zMsg[500];                 /* Human readable error text */
+
  int i;                          /* Loop counter */
+
  DWORD iErrno = GetLastError();  /* Error code */
+

+
  zMsg[0] = 0;
+
  getLastErrorMsg(sizeof(zMsg), zMsg);
+
  assert( errcode!=SQLITE_OK );
+
  if( zPath==0 ) zPath = "";
+
  for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
+
  zMsg[i] = 0;
+
  sqlite3_log(errcode,
+
      "os_win.c:%d: (%d) %s(%s) - %s",
+
      iLine, iErrno, zFunc, zPath, zMsg
+
  );
+

+
  return errcode;
+
}
+

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
@@ -31412,6 +31897,7 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
  pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
  if (!pFile->hMutex){
    pFile->lastErrno = GetLastError();
+
    winLogError(SQLITE_ERROR, "winceCreateLock1", zFilename);
    free(zName);
    return FALSE;
  }
@@ -31443,6 +31929,7 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
    /* If mapping failed, close the shared memory handle and erase it */
    if (!pFile->shared){
      pFile->lastErrno = GetLastError();
+
      winLogError(SQLITE_ERROR, "winceCreateLock2", zFilename);
      CloseHandle(pFile->hShared);
      pFile->hShared = NULL;
    }
@@ -31688,6 +32175,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
  dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
  if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
    pFile->lastErrno = GetLastError();
+
    winLogError(SQLITE_IOERR_SEEK, "seekWinFile", pFile->zPath);
    return 1;
  }

@@ -31733,7 +32221,8 @@ static int winClose(sqlite3_file *id){
#endif
  OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
  OpenCounter(-1);
-
  return rc ? SQLITE_OK : SQLITE_IOERR;
+
  return rc ? SQLITE_OK
+
            : winLogError(SQLITE_IOERR_CLOSE, "winClose", pFile->zPath);
}

/*
@@ -31759,7 +32248,7 @@ static int winRead(
  }
  if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
    pFile->lastErrno = GetLastError();
-
    return SQLITE_IOERR_READ;
+
    return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
  }
  if( nRead<(DWORD)amt ){
    /* Unread parts of the buffer must be zero-filled */
@@ -31807,10 +32296,11 @@ static int winWrite(
  }

  if( rc ){
-
    if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
+
    if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
+
       || ( pFile->lastErrno==ERROR_DISK_FULL )){
      return SQLITE_FULL;
    }
-
    return SQLITE_IOERR_WRITE;
+
    return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
  }
  return SQLITE_OK;
}
@@ -31838,10 +32328,10 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( seekWinFile(pFile, nByte) ){
-
    rc = SQLITE_IOERR_TRUNCATE;
+
    rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate1", pFile->zPath);
  }else if( 0==SetEndOfFile(pFile->h) ){
    pFile->lastErrno = GetLastError();
-
    rc = SQLITE_IOERR_TRUNCATE;
+
    rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate2", pFile->zPath);
  }

  OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
@@ -31863,6 +32353,7 @@ SQLITE_API int sqlite3_fullsync_count = 0;
static int winSync(sqlite3_file *id, int flags){
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
  winFile *pFile = (winFile*)id;
+
  BOOL rc;
#else
  UNUSED_PARAMETER(id);
#endif
@@ -31875,32 +32366,33 @@ static int winSync(sqlite3_file *id, int flags){

  OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));

+
  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
+
  ** line is to test that doing so does not cause any problems.
+
  */
+
  SimulateDiskfullError( return SQLITE_FULL );
+

#ifndef SQLITE_TEST
  UNUSED_PARAMETER(flags);
#else
-
  if( flags & SQLITE_SYNC_FULL ){
+
  if( (flags&0x0F)==SQLITE_SYNC_FULL ){
    sqlite3_fullsync_count++;
  }
  sqlite3_sync_count++;
#endif

-
  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
-
  ** line is to test that doing so does not cause any problems.
-
  */
-
  SimulateDiskfullError( return SQLITE_FULL );
-
  SimulateIOError( return SQLITE_IOERR; );
-

  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
  ** no-op
  */
#ifdef SQLITE_NO_SYNC
  return SQLITE_OK;
#else
-
  if( FlushFileBuffers(pFile->h) ){
+
  rc = FlushFileBuffers(pFile->h);
+
  SimulateIOError( rc=FALSE );
+
  if( rc ){
    return SQLITE_OK;
  }else{
    pFile->lastErrno = GetLastError();
-
    return SQLITE_IOERR;
+
    return winLogError(SQLITE_IOERR_FSYNC, "winSync", pFile->zPath);
  }
#endif
}
@@ -31921,7 +32413,7 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
     && ((error = GetLastError()) != NO_ERROR) )
  {
    pFile->lastErrno = error;
-
    return SQLITE_IOERR_FSTAT;
+
    return winLogError(SQLITE_IOERR_FSTAT, "winFileSize", pFile->zPath);
  }
  *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
  return SQLITE_OK;
@@ -31960,6 +32452,7 @@ static int getReadLock(winFile *pFile){
  }
  if( res == 0 ){
    pFile->lastErrno = GetLastError();
+
    /* No need to log a failure to lock */
  }
  return res;
}
@@ -31978,8 +32471,9 @@ static int unlockReadLock(winFile *pFile){
    res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
#endif
  }
-
  if( res == 0 ){
+
  if( res==0 && GetLastError()!=ERROR_NOT_LOCKED ){
    pFile->lastErrno = GetLastError();
+
    winLogError(SQLITE_IOERR_UNLOCK, "unlockReadLock", pFile->zPath);
  }
  return res;
}
@@ -32180,7 +32674,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
      /* This should never happen.  We should always be able to
      ** reacquire the read lock */
-
      rc = SQLITE_IOERR_UNLOCK;
+
      rc = winLogError(SQLITE_IOERR_UNLOCK, "winUnlock", pFile->zPath);
    }
  }
  if( type>=RESERVED_LOCK ){
@@ -32495,6 +32989,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
  memset(pNew, 0, sizeof(*pNew));
  pNew->zFilename = (char*)&pNew[1];
  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
+
  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); 

  /* Look to see if there is an existing winShmNode that can be used.
  ** If no matching winShmNode currently exists, create a new one.
@@ -32537,7 +33032,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
      if( rc!=SQLITE_OK ){
-
        rc = SQLITE_IOERR_SHMOPEN;
+
        rc = winLogError(SQLITE_IOERR_SHMOPEN, "winOpenShm", pDbFd->zPath);
      }
    }
    if( rc==SQLITE_OK ){
@@ -32796,7 +33291,7 @@ static int winShmMap(
    */
    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
    if( rc!=SQLITE_OK ){
-
      rc = SQLITE_IOERR_SHMSIZE;
+
      rc = winLogError(SQLITE_IOERR_SHMSIZE, "winShmMap1", pDbFd->zPath);
      goto shmpage_out;
    }

@@ -32810,7 +33305,7 @@ static int winShmMap(
      if( !isWrite ) goto shmpage_out;
      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
      if( rc!=SQLITE_OK ){
-
        rc = SQLITE_IOERR_SHMSIZE;
+
        rc = winLogError(SQLITE_IOERR_SHMSIZE, "winShmMap2", pDbFd->zPath);
        goto shmpage_out;
      }
    }
@@ -32847,7 +33342,7 @@ static int winShmMap(
      }
      if( !pMap ){
        pShmNode->lastErrno = GetLastError();
-
        rc = SQLITE_IOERR;
+
        rc = winLogError(SQLITE_IOERR_SHMMAP, "winShmMap3", pDbFd->zPath);
        if( hMap ) CloseHandle(hMap);
        goto shmpage_out;
      }
@@ -32929,7 +33424,7 @@ static void *convertUtf8Filename(const char *zFilename){
*/
#if SQLITE_OS_WINCE==0
  }else{
-
    zConverted = utf8ToMbcs(zFilename);
+
    zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
#endif
  }
  /* caller will handle out of memory */
@@ -33010,68 +33505,6 @@ static int getTempname(int nBuf, char *zBuf){
}

/*
-
** The return value of getLastErrorMsg
-
** is zero if the error message fits in the buffer, or non-zero
-
** otherwise (if the message was truncated).
-
*/
-
static int getLastErrorMsg(int nBuf, char *zBuf){
-
  /* FormatMessage returns 0 on failure.  Otherwise it
-
  ** returns the number of TCHARs written to the output
-
  ** buffer, excluding the terminating null char.
-
  */
-
  DWORD error = GetLastError();
-
  DWORD dwLen = 0;
-
  char *zOut = 0;
-

-
  if( isNT() ){
-
    WCHAR *zTempWide = NULL;
-
    dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-
                           NULL,
-
                           error,
-
                           0,
-
                           (LPWSTR) &zTempWide,
-
                           0,
-
                           0);
-
    if( dwLen > 0 ){
-
      /* allocate a buffer and convert to UTF8 */
-
      zOut = unicodeToUtf8(zTempWide);
-
      /* free the system buffer allocated by FormatMessage */
-
      LocalFree(zTempWide);
-
    }
-
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
-
** Since the ASCII 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{
-
    char *zTemp = NULL;
-
    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-
                           NULL,
-
                           error,
-
                           0,
-
                           (LPSTR) &zTemp,
-
                           0,
-
                           0);
-
    if( dwLen > 0 ){
-
      /* allocate a buffer and convert to UTF8 */
-
      zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
-
      /* free the system buffer allocated by FormatMessage */
-
      LocalFree(zTemp);
-
    }
-
#endif
-
  }
-
  if( 0 == dwLen ){
-
    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
-
  }else{
-
    /* copy a maximum of nBuf chars to output buffer */
-
    sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
-
    /* free the UTF8 buffer */
-
    free(zOut);
-
  }
-
  return 0;
-
}
-

-
/*
** Open a file.
*/
static int winOpen(
@@ -33242,6 +33675,7 @@ static int winOpen(

  if( h==INVALID_HANDLE_VALUE ){
    pFile->lastErrno = GetLastError();
+
    winLogError(SQLITE_CANTOPEN, "winOpen", zUtf8Name);
    free(zConverted);
    if( isReadWrite ){
      return winOpen(pVfs, zName, id, 
@@ -33345,7 +33779,8 @@ static int winDelete(
         "ok" : "failed" ));
 
  return (   (rc == INVALID_FILE_ATTRIBUTES) 
-
          && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
+
          && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
+
                 winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
}

/*
@@ -33385,6 +33820,7 @@ static int winAccess(
      }
    }else{
      if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
+
        winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
        free(zConverted);
        return SQLITE_IOERR_ACCESS;
      }else{
@@ -33449,6 +33885,13 @@ static int winFullPathname(
  void *zConverted;
  char *zOut;

+
  /* If this path name begins with "/X:", where "X" is any alphabetic
+
  ** character, discard the initial "/" from the pathname.
+
  */
+
  if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
+
    zRelative++;
+
  }
+

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. This function could fail if, for example, the
@@ -34489,6 +34932,13 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
    }
    if( pPg ){
      int rc;
+
#ifdef SQLITE_LOG_CACHE_SPILL
+
      sqlite3_log(SQLITE_FULL, 
+
                  "spill page %d making room for %d - cache used: %d/%d",
+
                  pPg->pgno, pgno,
+
                  sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
+
                  pCache->nMax);
+
#endif
      rc = pCache->xStress(pCache->pStress, pPg);
      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
        return rc;
@@ -35399,7 +35849,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
      pGroup = (PGroup*)&pCache[1];
      pGroup->mxPinned = 10;
    }else{
-
      pGroup = &pcache1_g.grp;
+
      pGroup = &pcache1.grp;
    }
    pCache->pGroup = pGroup;
    pCache->szPage = szPage;
@@ -36260,6 +36710,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i

#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z)                   0
+
# define sqlite3WalLimit(x,y)
# define sqlite3WalClose(w,x,y,z)                0
# define sqlite3WalBeginReadTransaction(y,z)     0
# define sqlite3WalEndReadTransaction(z)
@@ -36285,9 +36736,12 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
typedef struct Wal Wal;

/* Open and close a connection to a write-ahead log. */
-
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
+
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);

+
/* Set the limiting size of a WAL file. */
+
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
+

/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
** snapshot is like a read-transaction.  It is the state of the database
** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
@@ -40636,6 +41090,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;  /* True to omit read-lock */
  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
+
  const char *zUri = 0;    /* URI args to copy */
+
  int nUri = 0;            /* Number of bytes of URI args at *zUri */

  /* Figure out how much space is required for each journal file-handle
  ** (there are two of them, the main journal and the sub-journal). This
@@ -40666,6 +41122,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
  ** leave both nPathname and zPathname set to 0.
  */
  if( zFilename && zFilename[0] ){
+
    const char *z;
    nPathname = pVfs->mxPathname+1;
    zPathname = sqlite3Malloc(nPathname*2);
    if( zPathname==0 ){
@@ -40674,6 +41131,12 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    nPathname = sqlite3Strlen30(zPathname);
+
    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
+
    while( *z ){
+
      z += sqlite3Strlen30(z)+1;
+
      z += sqlite3Strlen30(z)+1;
+
    }
+
    nUri = &z[1] - zUri;
    if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
      /* This branch is taken when the journal path required by
      ** the database being opened will be more than pVfs->mxPathname
@@ -40706,7 +41169,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
    ROUND8(pcacheSize) +           /* PCache object */
    ROUND8(pVfs->szOsFile) +       /* The main db file */
    journalFileSize * 2 +          /* The two journal files */ 
-
    nPathname + 1 +                /* zFilename */
+
    nPathname + 1 + nUri +         /* zFilename */
    nPathname + 8 + 1              /* zJournal */
#ifndef SQLITE_OMIT_WAL
    + nPathname + 4 + 1              /* zWal */
@@ -40728,14 +41191,17 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
  if( zPathname ){
    assert( nPathname>0 );
-
    pPager->zJournal =   (char*)(pPtr += nPathname + 1);
+
    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
    memcpy(pPager->zFilename, zPathname, nPathname);
+
    memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
    memcpy(pPager->zJournal, zPathname, nPathname);
    memcpy(&pPager->zJournal[nPathname], "-journal", 8);
+
    sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
#ifndef SQLITE_OMIT_WAL
    pPager->zWal = &pPager->zJournal[nPathname+8+1];
    memcpy(pPager->zWal, zPathname, nPathname);
    memcpy(&pPager->zWal[nPathname], "-wal", 4);
+
    sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
#endif
    sqlite3_free(zPathname);
  }
@@ -42072,11 +42538,21 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
  }else{
    if( pagerUseWal(pPager) ){
      PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
-
      if( pList ){
+
      PgHdr *pPageOne = 0;
+
      if( pList==0 ){
+
        /* Must have at least one page for the WAL commit flag.
+
        ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
+
        rc = sqlite3PagerGet(pPager, 1, &pPageOne);
+
        pList = pPageOne;
+
        pList->pDirty = 0;
+
      }
+
      assert( rc==SQLITE_OK );
+
      if( ALWAYS(pList) ){
        rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1, 
            (pPager->fullSync ? pPager->syncFlags : 0)
        );
      }
+
      sqlite3PagerUnref(pPageOne);
      if( rc==SQLITE_OK ){
        sqlite3PcacheCleanAll(pPager->pPCache);
      }
@@ -42934,6 +43410,7 @@ SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
  if( iLimit>=-1 ){
    pPager->journalSizeLimit = iLimit;
+
    sqlite3WalLimit(pPager->pWal, iLimit);
  }
  return pPager->journalSizeLimit;
}
@@ -43025,7 +43502,8 @@ static int pagerOpenWal(Pager *pPager){
  */
  if( rc==SQLITE_OK ){
    rc = sqlite3WalOpen(pPager->pVfs, 
-
        pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
+
        pPager->fd, pPager->zWal, pPager->exclusiveMode,
+
        pPager->journalSizeLimit, &pPager->pWal
    );
  }

@@ -43557,6 +44035,7 @@ struct Wal {
  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 */
  volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
  u32 szPage;                /* Database page size */
@@ -43564,7 +44043,7 @@ struct Wal {
  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;               /* True if the WAL file is open read-only */
+
  u8 readOnly;               /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
  WalIndexHdr hdr;           /* Wal-index header for current transaction */
  const char *zWalName;      /* Name of WAL file */
  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
@@ -43581,6 +44060,13 @@ struct Wal {
#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.
*/
@@ -43673,6 +44159,10 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
      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;
+
      }
    }
  }

@@ -44379,6 +44869,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
  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 */
@@ -44411,6 +44902,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
  pRet->pWalFd = (sqlite3_file *)&pRet[1];
  pRet->pDbFd = pDbFd;
  pRet->readLock = -1;
+
  pRet->mxWalSize = mxWalSize;
  pRet->zWalName = zWalName;
  pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);

@@ -44418,7 +44910,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
  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 = 1;
+
    pRet->readOnly = WAL_RDONLY;
  }

  if( rc!=SQLITE_OK ){
@@ -44433,6 +44925,13 @@ SQLITE_PRIVATE int sqlite3WalOpen(
}

/*
+
** 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;
+
}
+

+
/*
** 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
@@ -45052,21 +45551,28 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
  ** with a writer.  So get a WRITE lock and try again.
  */
  assert( badHdr==0 || pWal->writeLock==0 );
-
  if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
-
    pWal->writeLock = 1;
-
    if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
-
      badHdr = walIndexTryHdr(pWal, pChanged);
-
      if( badHdr ){
-
        /* If the wal-index header is still malformed even while holding
-
        ** a WRITE lock, it can only mean that the header is corrupted and
-
        ** needs to be reconstructed.  So run recovery to do exactly that.
-
        */
-
        rc = walIndexRecover(pWal);
-
        *pChanged = 1;
+
  if( badHdr ){
+
    if( pWal->readOnly & WAL_SHM_RDONLY ){
+
      if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
+
        walUnlockShared(pWal, WAL_WRITE_LOCK);
+
        rc = SQLITE_READONLY_RECOVERY;
+
      }
+
    }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
+
      pWal->writeLock = 1;
+
      if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
+
        badHdr = walIndexTryHdr(pWal, pChanged);
+
        if( badHdr ){
+
          /* If the wal-index header is still malformed even while holding
+
          ** a WRITE lock, it can only mean that the header is corrupted and
+
          ** needs to be reconstructed.  So run recovery to do exactly that.
+
          */
+
          rc = walIndexRecover(pWal);
+
          *pChanged = 1;
+
        }
      }
+
      pWal->writeLock = 0;
+
      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
    }
-
    pWal->writeLock = 0;
-
    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
  }

  /* If the header is read successfully, check the version number to make
@@ -45253,7 +45759,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
  }
  /* There was once an "if" here. The extra "{" is to preserve indentation. */
  {
-
    if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
+
    if( (pWal->readOnly & WAL_SHM_RDONLY)==0
+
     && (mxReadMark<pWal->hdr.mxFrame || mxI==0)
+
    ){
      for(i=1; i<WAL_NREADER; i++){
        rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
@@ -45267,8 +45775,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
      }
    }
    if( mxI==0 ){
-
      assert( rc==SQLITE_BUSY );
-
      return WAL_RETRY;
+
      assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
+
      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
    }

    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
@@ -45667,6 +46175,24 @@ static int walRestartLog(Wal *pWal){
        */
        int i;                    /* Loop counter */
        u32 *aSalt = pWal->hdr.aSalt;       /* Big-endian salt values */
+

+
        /* Limit the size of WAL file if the journal_size_limit PRAGMA is
+
        ** set to a non-negative value.  Log errors encountered
+
        ** during the truncation attempt. */
+
        if( pWal->mxWalSize>=0 ){
+
          i64 sz;
+
          int rx;
+
          sqlite3BeginBenignMalloc();
+
          rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
+
          if( rx==SQLITE_OK && (sz > pWal->mxWalSize) ){
+
            rx = sqlite3OsTruncate(pWal->pWalFd, pWal->mxWalSize);
+
          }
+
          sqlite3EndBenignMalloc();
+
          if( rx ){
+
            sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
+
          }
+
        }
+

        pWal->nCkpt++;
        pWal->hdr.mxFrame = 0;
        sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
@@ -45892,6 +46418,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
  assert( pWal->ckptLock==0 );
  assert( pWal->writeLock==0 );

+
  if( pWal->readOnly ) return SQLITE_READONLY;
  WALTRACE(("WAL%p: checkpoint begins\n", pWal));
  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  if( rc ){
@@ -47772,6 +48299,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
    *pRC = SQLITE_CORRUPT_BKPT;
    goto ptrmap_exit;
  }
+
  assert( offset <= (int)pBt->usableSize-5 );
  pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);

  if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
@@ -47811,6 +48339,11 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
  pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);

  offset = PTRMAP_PTROFFSET(iPtrmap, key);
+
  if( offset<0 ){
+
    sqlite3PagerUnref(pDbPage);
+
    return SQLITE_CORRUPT_BKPT;
+
  }
+
  assert( offset <= (int)pBt->usableSize-5 );
  assert( pEType!=0 );
  *pEType = pPtrmap[offset];
  if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
@@ -47835,6 +48368,8 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
*/
#define findCell(P,I) \
  ((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)])))
+
#define findCellv2(D,M,O,I) (D+(M&get2byte(D+(O+2*(I)))))
+


/*
** This a more complex version of findCell() that works for
@@ -48672,13 +49207,13 @@ static int btreeInvokeBusyHandler(void *pArg){
** to problems with locking.
*/
SQLITE_PRIVATE int sqlite3BtreeOpen(
+
  sqlite3_vfs *pVfs,      /* VFS to use for this b-tree */
  const char *zFilename,  /* Name of the file containing the BTree database */
  sqlite3 *db,            /* Associated database handle */
  Btree **ppBtree,        /* Pointer to new Btree object written here */
  int flags,              /* Options */
  int vfsFlags            /* Flags passed through to sqlite3_vfs.xOpen() */
){
-
  sqlite3_vfs *pVfs;             /* The VFS to use for this btree */
  BtShared *pBt = 0;             /* Shared part of btree structure */
  Btree *p;                      /* Handle to return */
  sqlite3_mutex *mutexOpen = 0;  /* Prevents a race condition. Ticket #3537 */
@@ -48700,6 +49235,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
#endif

  assert( db!=0 );
+
  assert( pVfs!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( (flags&0xff)==flags );   /* flags fit in 8 bits */

@@ -48718,7 +49254,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
  if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
    vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
  }
-
  pVfs = db->pVfs;
  p = sqlite3MallocZero(sizeof(Btree));
  if( !p ){
    return SQLITE_NOMEM;
@@ -51429,7 +51964,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
  }
  assert( pCur->apPage[0]->intKey || pIdxKey );
  for(;;){
-
    int lwr, upr;
+
    int lwr, upr, idx;
    Pgno chldPg;
    MemPage *pPage = pCur->apPage[pCur->iPage];
    int c;
@@ -51445,14 +51980,14 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
    lwr = 0;
    upr = pPage->nCell-1;
    if( biasRight ){
-
      pCur->aiIdx[pCur->iPage] = (u16)upr;
+
      pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
    }else{
-
      pCur->aiIdx[pCur->iPage] = (u16)((upr+lwr)/2);
+
      pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
    }
    for(;;){
-
      int idx = pCur->aiIdx[pCur->iPage]; /* Index of current cell in pPage */
      u8 *pCell;                          /* Pointer to current cell in pPage */

+
      assert( idx==pCur->aiIdx[pCur->iPage] );
      pCur->info.nSize = 0;
      pCell = findCell(pPage, idx) + pPage->childPtrSize;
      if( pPage->intKey ){
@@ -51535,7 +52070,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
      if( lwr>upr ){
        break;
      }
-
      pCur->aiIdx[pCur->iPage] = (u16)((lwr+upr)/2);
+
      pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
    }
    assert( lwr==upr+1 );
    assert( pPage->isInit );
@@ -52368,10 +52903,10 @@ static int fillInCell(
** "sz" must be the number of bytes in the cell.
*/
static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
-
  int i;          /* Loop counter */
  u32 pc;         /* Offset to cell content of cell being deleted */
  u8 *data;       /* pPage->aData */
  u8 *ptr;        /* Used to move bytes around within data[] */
+
  u8 *endPtr;     /* End of loop */
  int rc;         /* The return code */
  int hdr;        /* Beginning of the header.  0 most pages.  100 page 1 */

@@ -52396,9 +52931,11 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
    *pRC = rc;
    return;
  }
-
  for(i=idx+1; i<pPage->nCell; i++, ptr+=2){
-
    ptr[0] = ptr[2];
-
    ptr[1] = ptr[3];
+
  endPtr = &data[pPage->cellOffset + 2*pPage->nCell - 2];
+
  assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 );  /* ptr is always 2-byte aligned */
+
  while( ptr<endPtr ){
+
    *(u16*)ptr = *(u16*)&ptr[2];
+
    ptr += 2;
  }
  pPage->nCell--;
  put2byte(&data[hdr+3], pPage->nCell);
@@ -52438,6 +52975,7 @@ static void insertCell(
  int cellOffset;   /* Address of first cell pointer in data[] */
  u8 *data;         /* The content of the whole page */
  u8 *ptr;          /* Used for moving information around in data[] */
+
  u8 *endPtr;       /* End of the loop */

  int nSkip = (iChild ? 4 : 0);

@@ -52488,9 +53026,12 @@ static void insertCell(
    if( iChild ){
      put4byte(&data[idx], iChild);
    }
-
    for(j=end, ptr=&data[j]; j>ins; j-=2, ptr-=2){
-
      ptr[0] = ptr[-2];
-
      ptr[1] = ptr[-1];
+
    ptr = &data[end];
+
    endPtr = &data[ins];
+
    assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 );  /* ptr is always 2-byte aligned */
+
    while( ptr>endPtr ){
+
      *(u16*)ptr = *(u16*)&ptr[-2];
+
      ptr -= 2;
    }
    put2byte(&data[ins], idx);
    put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
@@ -52535,10 +53076,11 @@ static void assemblePage(
  pCellptr = &data[pPage->cellOffset + nCell*2];
  cellbody = nUsable;
  for(i=nCell-1; i>=0; i--){
+
    u16 sz = aSize[i];
    pCellptr -= 2;
-
    cellbody -= aSize[i];
+
    cellbody -= sz;
    put2byte(pCellptr, cellbody);
-
    memcpy(&data[cellbody], apCell[i], aSize[i]);
+
    memcpy(&data[cellbody], apCell[i], sz);
  }
  put2byte(&data[hdr+3], nCell);
  put2byte(&data[hdr+5], cellbody);
@@ -52992,12 +53534,24 @@ static int balance_nonroot(
    memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize);

    limit = pOld->nCell+pOld->nOverflow;
-
    for(j=0; j<limit; j++){
-
      assert( nCell<nMaxCells );
-
      apCell[nCell] = findOverflowCell(pOld, j);
-
      szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
-
      nCell++;
-
    }
+
    if( pOld->nOverflow>0 ){
+
      for(j=0; j<limit; j++){
+
        assert( nCell<nMaxCells );
+
        apCell[nCell] = findOverflowCell(pOld, j);
+
        szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
+
        nCell++;
+
      }
+
    }else{
+
      u8 *aData = pOld->aData;
+
      u16 maskPage = pOld->maskPage;
+
      u16 cellOffset = pOld->cellOffset;
+
      for(j=0; j<limit; j++){
+
        assert( nCell<nMaxCells );
+
        apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
+
        szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
+
        nCell++;
+
      }
+
    }       
    if( i<nOld-1 && !leafData){
      u16 sz = (u16)szNew[i];
      u8 *pTemp;
@@ -57146,13 +57700,6 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
-
  p->expired = 0;
-
  if( op==OP_ParseSchema ){
-
    /* Any program that uses the OP_ParseSchema opcode needs to lock
-
    ** all btrees. */
-
    int j;
-
    for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
-
  }
#ifdef SQLITE_DEBUG
  pOp->zComment = 0;
  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
@@ -57192,6 +57739,20 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4(
}

/*
+
** Add an OP_ParseSchema opcode.  This routine is broken out from
+
** sqlite3VdbeAddOp4() since it needs to also local all btrees.
+
**
+
** The zWhere string must have been obtained from sqlite3_malloc().
+
** This routine will take ownership of the allocated memory.
+
*/
+
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
+
  int j;
+
  int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
+
  sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
+
  for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
+
}
+

+
/*
** Add an opcode that includes the p4 value as an integer.
*/
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
@@ -58381,44 +58942,88 @@ static void *allocSpace(
}

/*
-
** Prepare a virtual machine for execution.  This involves things such
+
** Rewind the VDBE back to the beginning in preparation for
+
** running it.
+
*/
+
SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
+
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+
  int i;
+
#endif
+
  assert( p!=0 );
+
  assert( p->magic==VDBE_MAGIC_INIT );
+

+
  /* There should be at least one opcode.
+
  */
+
  assert( p->nOp>0 );
+

+
  /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
+
  p->magic = VDBE_MAGIC_RUN;
+

+
#ifdef SQLITE_DEBUG
+
  for(i=1; i<p->nMem; i++){
+
    assert( p->aMem[i].db==p->db );
+
  }
+
#endif
+
  p->pc = -1;
+
  p->rc = SQLITE_OK;
+
  p->errorAction = OE_Abort;
+
  p->magic = VDBE_MAGIC_RUN;
+
  p->nChange = 0;
+
  p->cacheCtr = 1;
+
  p->minWriteFileFormat = 255;
+
  p->iStatement = 0;
+
  p->nFkConstraint = 0;
+
#ifdef VDBE_PROFILE
+
  for(i=0; i<p->nOp; i++){
+
    p->aOp[i].cnt = 0;
+
    p->aOp[i].cycles = 0;
+
  }
+
#endif
+
}
+

+
/*
+
** Prepare a virtual machine for execution for the first time after
+
** creating the virtual machine.  This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().  
**
-
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
-
** VDBE_MAGIC_RUN.
+
** This function may be called exact once on a each virtual machine.
+
** After this routine is called the VM has been "packaged" and is ready
+
** to run.  After this routine is called, futher calls to 
+
** sqlite3VdbeAddOp() functions are prohibited.  This routine disconnects
+
** the Vdbe from the Parse object that helped generate it so that the
+
** the Vdbe becomes an independent entity and the Parse object can be
+
** destroyed.
**
-
** This function may be called more than once on a single virtual machine.
-
** The first call is made while compiling the SQL statement. Subsequent
-
** calls are made as part of the process of resetting a statement to be
-
** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor 
-
** and isExplain parameters are only passed correct values the first time
-
** the function is called. On subsequent calls, from sqlite3_reset(), nVar
-
** is passed -1 and nMem, nCursor and isExplain are all passed zero.
+
** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
+
** to its initial state after it has been run.
*/
SQLITE_PRIVATE void sqlite3VdbeMakeReady(
  Vdbe *p,                       /* The VDBE */
-
  int nVar,                      /* Number of '?' see in the SQL statement */
-
  int nMem,                      /* Number of memory cells to allocate */
-
  int nCursor,                   /* Number of cursors to allocate */
-
  int nArg,                      /* Maximum number of args in SubPrograms */
-
  int isExplain,                 /* True if the EXPLAIN keywords is present */
-
  int usesStmtJournal            /* True to set Vdbe.usesStmtJournal */
+
  Parse *pParse                  /* Parsing context */
){
-
  int n;
-
  sqlite3 *db = p->db;
+
  sqlite3 *db;                   /* The database connection */
+
  int nVar;                      /* Number of parameters */
+
  int nMem;                      /* Number of VM memory registers */
+
  int nCursor;                   /* Number of cursors required */
+
  int nArg;                      /* Number of arguments in subprograms */
+
  int n;                         /* Loop counter */
+
  u8 *zCsr;                      /* Memory available for allocation */
+
  u8 *zEnd;                      /* First byte past allocated memory */
+
  int nByte;                     /* How much extra memory is needed */

  assert( p!=0 );
-
  assert( p->magic==VDBE_MAGIC_INIT );
-

-
  /* There should be at least one opcode.
-
  */
  assert( p->nOp>0 );
-

-
  /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
-
  p->magic = VDBE_MAGIC_RUN;
-

+
  assert( pParse!=0 );
+
  assert( p->magic==VDBE_MAGIC_INIT );
+
  db = p->db;
+
  assert( db->mallocFailed==0 );
+
  nVar = pParse->nVar;
+
  nMem = pParse->nMem;
+
  nCursor = pParse->nTab;
+
  nArg = pParse->nMaxArg;
+
  
  /* For each cursor required, also allocate a memory cell. Memory
  ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
  ** the vdbe program. Instead they are used to allocate space for
@@ -58431,91 +59036,69 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
  nMem += nCursor;

  /* Allocate space for memory registers, SQL variables, VDBE cursors and 
-
  ** an array to marshal SQL function arguments in. This is only done the
-
  ** first time this function is called for a given VDBE, not when it is
-
  ** being called from sqlite3_reset() to reset the virtual machine.
-
  */
-
  if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){
-
    u8 *zCsr = (u8 *)&p->aOp[p->nOp];       /* Memory avaliable for alloation */
-
    u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc];  /* First byte past available mem */
-
    int nByte;                              /* How much extra memory needed */
-

-
    resolveP2Values(p, &nArg);
-
    p->usesStmtJournal = (u8)usesStmtJournal;
-
    if( isExplain && nMem<10 ){
-
      nMem = 10;
-
    }
-
    memset(zCsr, 0, zEnd-zCsr);
-
    zCsr += (zCsr - (u8*)0)&7;
-
    assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
-

-
    /* Memory for registers, parameters, cursor, etc, is allocated in two
-
    ** passes.  On the first pass, we try to reuse unused space at the 
-
    ** end of the opcode array.  If we are unable to satisfy all memory
-
    ** requirements by reusing the opcode array tail, then the second
-
    ** pass will fill in the rest using a fresh allocation.  
-
    **
-
    ** This two-pass approach that reuses as much memory as possible from
-
    ** the leftover space at the end of the opcode array can significantly
-
    ** reduce the amount of memory held by a prepared statement.
-
    */
-
    do {
-
      nByte = 0;
-
      p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
-
      p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
-
      p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
-
      p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
-
      p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
-
                            &zCsr, zEnd, &nByte);
-
      if( nByte ){
-
        p->pFree = sqlite3DbMallocZero(db, nByte);
-
      }
-
      zCsr = p->pFree;
-
      zEnd = &zCsr[nByte];
-
    }while( nByte && !db->mallocFailed );
+
  ** an array to marshal SQL function arguments in.
+
  */
+
  zCsr = (u8*)&p->aOp[p->nOp];       /* Memory avaliable for allocation */
+
  zEnd = (u8*)&p->aOp[p->nOpAlloc];  /* First byte past end of zCsr[] */

-
    p->nCursor = (u16)nCursor;
-
    if( p->aVar ){
-
      p->nVar = (ynVar)nVar;
-
      for(n=0; n<nVar; n++){
-
        p->aVar[n].flags = MEM_Null;
-
        p->aVar[n].db = db;
-
      }
+
  resolveP2Values(p, &nArg);
+
  p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
+
  if( pParse->explain && nMem<10 ){
+
    nMem = 10;
+
  }
+
  memset(zCsr, 0, zEnd-zCsr);
+
  zCsr += (zCsr - (u8*)0)&7;
+
  assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
+
  p->expired = 0;
+

+
  /* Memory for registers, parameters, cursor, etc, is allocated in two
+
  ** passes.  On the first pass, we try to reuse unused space at the 
+
  ** end of the opcode array.  If we are unable to satisfy all memory
+
  ** requirements by reusing the opcode array tail, then the second
+
  ** pass will fill in the rest using a fresh allocation.  
+
  **
+
  ** This two-pass approach that reuses as much memory as possible from
+
  ** the leftover space at the end of the opcode array can significantly
+
  ** reduce the amount of memory held by a prepared statement.
+
  */
+
  do {
+
    nByte = 0;
+
    p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
+
    p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
+
    p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
+
    p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
+
    p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
+
                          &zCsr, zEnd, &nByte);
+
    if( nByte ){
+
      p->pFree = sqlite3DbMallocZero(db, nByte);
    }
-
    if( p->aMem ){
-
      p->aMem--;                      /* aMem[] goes from 1..nMem */
-
      p->nMem = nMem;                 /*       not from 0..nMem-1 */
-
      for(n=1; n<=nMem; n++){
-
        p->aMem[n].flags = MEM_Null;
-
        p->aMem[n].db = db;
-
      }
+
    zCsr = p->pFree;
+
    zEnd = &zCsr[nByte];
+
  }while( nByte && !db->mallocFailed );
+

+
  p->nCursor = (u16)nCursor;
+
  if( p->aVar ){
+
    p->nVar = (ynVar)nVar;
+
    for(n=0; n<nVar; n++){
+
      p->aVar[n].flags = MEM_Null;
+
      p->aVar[n].db = db;
    }
  }
-
#ifdef SQLITE_DEBUG
-
  for(n=1; n<p->nMem; n++){
-
    assert( p->aMem[n].db==db );
+
  if( p->azVar ){
+
    p->nzVar = pParse->nzVar;
+
    memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
+
    memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
  }
-
#endif
-

-
  p->pc = -1;
-
  p->rc = SQLITE_OK;
-
  p->errorAction = OE_Abort;
-
  p->explain |= isExplain;
-
  p->magic = VDBE_MAGIC_RUN;
-
  p->nChange = 0;
-
  p->cacheCtr = 1;
-
  p->minWriteFileFormat = 255;
-
  p->iStatement = 0;
-
  p->nFkConstraint = 0;
-
#ifdef VDBE_PROFILE
-
  {
-
    int i;
-
    for(i=0; i<p->nOp; i++){
-
      p->aOp[i].cnt = 0;
-
      p->aOp[i].cycles = 0;
+
  if( p->aMem ){
+
    p->aMem--;                      /* aMem[] goes from 1..nMem */
+
    p->nMem = nMem;                 /*       not from 0..nMem-1 */
+
    for(n=1; n<=nMem; n++){
+
      p->aMem[n].flags = MEM_Null;
+
      p->aMem[n].db = db;
    }
  }
-
#endif
+
  p->explain = pParse->explain;
+
  sqlite3VdbeRewind(p);
}

/*
@@ -58789,6 +59372,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
      if( !zMaster ){
        return SQLITE_NOMEM;
      }
+
      sqlite3FileSuffix3(zMainFile, zMaster);
      rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
    }while( rc==SQLITE_OK && res );
    if( rc==SQLITE_OK ){
@@ -59003,6 +59587,15 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
    db->nStatement--;
    p->iStatement = 0;

+
    if( rc==SQLITE_OK ){
+
      if( eOp==SAVEPOINT_ROLLBACK ){
+
        rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
+
      }
+
      if( rc==SQLITE_OK ){
+
        rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
+
      }
+
    }
+

    /* If the statement transaction is being rolled back, also restore the 
    ** database handles deferred constraint counter to the value it had when 
    ** the statement transaction was opened.  */
@@ -59182,17 +59775,11 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
    ** do so. If this operation returns an error, and the current statement
    ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
    ** current statement error code.
-
    **
-
    ** Note that sqlite3VdbeCloseStatement() can only fail if eStatementOp
-
    ** is SAVEPOINT_ROLLBACK.  But if p->rc==SQLITE_OK then eStatementOp
-
    ** must be SAVEPOINT_RELEASE.  Hence the NEVER(p->rc==SQLITE_OK) in 
-
    ** the following code.
    */
    if( eStatementOp ){
      rc = sqlite3VdbeCloseStatement(p, eStatementOp);
      if( rc ){
-
        assert( eStatementOp==SAVEPOINT_ROLLBACK );
-
        if( NEVER(p->rc==SQLITE_OK) || p->rc==SQLITE_CONSTRAINT ){
+
        if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
          p->rc = rc;
          sqlite3DbFree(db, p->zErrMsg);
          p->zErrMsg = 0;
@@ -59385,6 +59972,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
*/
SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
  SubProgram *pSub, *pNext;
+
  int i;
  assert( p->db==0 || p->db==db );
  releaseMemArray(p->aVar, p->nVar);
  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
@@ -59393,6 +59981,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
    vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
    sqlite3DbFree(db, pSub);
  }
+
  for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
  vdbeFreeOpArray(db, p->aOp, p->nOp);
  sqlite3DbFree(db, p->aLabel);
  sqlite3DbFree(db, p->aColName);
@@ -59838,7 +60427,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
    idx += getVarint32(&aKey[idx], serial_type);
    pMem->enc = pKeyInfo->enc;
    pMem->db = pKeyInfo->db;
-
    pMem->flags = 0;
+
    /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
    pMem->zMalloc = 0;
    d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
    pMem++;
@@ -59853,6 +60442,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
** This routine destroys a UnpackedRecord object.
*/
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
+
#ifdef SQLITE_DEBUG
  int i;
  Mem *pMem;

@@ -59866,6 +60456,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
    */
    if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem);
  }
+
#endif
  if( p->flags & UNPACKED_NEED_FREE ){
    sqlite3DbFree(p->pKeyInfo->db, p);
  }
@@ -59919,7 +60510,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(

  /* Compilers may complain that mem1.u.i is potentially uninitialized.
  ** We could initialize it, as shown here, to silence those complaints.
-
  ** But in fact, mem1.u.i will never actually be used initialized, and doing 
+
  ** But in fact, mem1.u.i will never actually be used uninitialized, and doing 
  ** the unnecessary initialization has a measurable negative performance
  ** impact, since this routine is a very high runner.  And so, we choose
  ** to ignore the compiler warnings and leave this variable uninitialized.
@@ -60301,7 +60892,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){
    Vdbe *v = (Vdbe*)pStmt;
    sqlite3_mutex_enter(v->db->mutex);
    rc = sqlite3VdbeReset(v);
-
    sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0);
+
    sqlite3VdbeRewind(v);
    assert( (rc & (v->db->errMask))==rc );
    rc = sqlite3ApiExit(v->db, rc);
    sqlite3_mutex_leave(v->db->mutex);
@@ -60659,6 +61250,14 @@ end_of_step:
}

/*
+
** The maximum number of times that a statement will try to reparse
+
** itself before giving up and returning SQLITE_SCHEMA.
+
*/
+
#ifndef SQLITE_MAX_SCHEMA_RETRY
+
# define SQLITE_MAX_SCHEMA_RETRY 5
+
#endif
+

+
/*
** This is the top-level implementation of sqlite3_step().  Call
** sqlite3Step() to do most of the work.  If a schema error occurs,
** call sqlite3Reprepare() and try again.
@@ -60676,7 +61275,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
  db = v->db;
  sqlite3_mutex_enter(db->mutex);
  while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
-
         && cnt++ < 5
+
         && cnt++ < SQLITE_MAX_SCHEMA_RETRY
         && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
    sqlite3_reset(pStmt);
    v->expired = 0;
@@ -61367,32 +61966,6 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
}

/*
-
** Create a mapping from variable numbers to variable names
-
** in the Vdbe.azVar[] array, if such a mapping does not already
-
** exist.
-
*/
-
static void createVarMap(Vdbe *p){
-
  if( !p->okVar ){
-
    int j;
-
    Op *pOp;
-
    sqlite3_mutex_enter(p->db->mutex);
-
    /* The race condition here is harmless.  If two threads call this
-
    ** routine on the same Vdbe at the same time, they both might end
-
    ** up initializing the Vdbe.azVar[] array.  That is a little extra
-
    ** work but it results in the same answer.
-
    */
-
    for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
-
      if( pOp->opcode==OP_Variable ){
-
        assert( pOp->p1>0 && pOp->p1<=p->nVar );
-
        p->azVar[pOp->p1-1] = pOp->p4.z;
-
      }
-
    }
-
    p->okVar = 1;
-
    sqlite3_mutex_leave(p->db->mutex);
-
  }
-
}
-

-
/*
** Return the name of a wildcard parameter.  Return NULL if the index
** is out of range or if the wildcard is unnamed.
**
@@ -61400,10 +61973,9 @@ static void createVarMap(Vdbe *p){
*/
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
  Vdbe *p = (Vdbe*)pStmt;
-
  if( p==0 || i<1 || i>p->nVar ){
+
  if( p==0 || i<1 || i>p->nzVar ){
    return 0;
  }
-
  createVarMap(p);
  return p->azVar[i-1];
}

@@ -61417,9 +61989,8 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa
  if( p==0 ){
    return 0;
  }
-
  createVarMap(p); 
  if( zName ){
-
    for(i=0; i<p->nVar; i++){
+
    for(i=0; i<p->nzVar; i++){
      const char *z = p->azVar[i];
      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
        return i+1;
@@ -62334,6 +62905,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
  Mem *pOut = 0;             /* Output operand */
  int iCompare = 0;          /* Result of last OP_Compare operation */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */
+
  i64 lastRowid = db->lastRowid;  /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
@@ -62742,6 +63314,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
    } cm;
    struct OP_Trace_stack_vars {
      char *zTrace;
+
      char *z;
    } cn;
  } u;
  /* End automatically generated code
@@ -62975,7 +63548,7 @@ case OP_Yield: { /* in1 */

/* Opcode:  HaltIfNull  P1 P2 P3 P4 *
**
-
** Check the value in register P3.  If is is NULL then Halt using
+
** Check the value in register P3.  If it is NULL then Halt using
** parameter P1, P2, and P4 as if this were a Halt instruction.  If the
** value in register P3 is not NULL, then this routine is a no-op.
*/
@@ -63012,6 +63585,7 @@ case OP_Halt: {
    p->nFrame--;
    sqlite3VdbeSetChanges(db, p->nChange);
    pc = sqlite3VdbeFrameRestore(pFrame);
+
    lastRowid = db->lastRowid;
    if( pOp->p2==OE_Ignore ){
      /* Instruction pc is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
@@ -63167,6 +63741,7 @@ case OP_Variable: { /* out2-prerelease */
#endif /* local variables moved into u.ab */

  assert( pOp->p1>0 && pOp->p1<=p->nVar );
+
  assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
  u.ab.pVar = &p->aVar[pOp->p1 - 1];
  if( sqlite3VdbeMemTooBig(u.ab.pVar) ){
    goto too_big;
@@ -63584,16 +64159,9 @@ case OP_Function: {
    assert( pOp[-1].opcode==OP_CollSeq );
    u.ag.ctx.pColl = pOp[-1].p4.pColl;
  }
+
  db->lastRowid = lastRowid;
  (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
-
  if( db->mallocFailed ){
-
    /* Even though a malloc() has failed, the implementation of the
-
    ** user function may have called an sqlite3_result_XXX() function
-
    ** to return a value. The following call releases any resources
-
    ** associated with such a value.
-
    */
-
    sqlite3VdbeMemRelease(&u.ag.ctx.s);
-
    goto no_mem;
-
  }
+
  lastRowid = db->lastRowid;

  /* If any auxiliary data functions have been called by this user function,
  ** immediately call the destructor for any non-static values.
@@ -63604,6 +64172,16 @@ case OP_Function: {
    pOp->p4type = P4_VDBEFUNC;
  }

+
  if( db->mallocFailed ){
+
    /* Even though a malloc() has failed, the implementation of the
+
    ** user function may have called an sqlite3_result_XXX() function
+
    ** to return a value. The following call releases any resources
+
    ** associated with such a value.
+
    */
+
    sqlite3VdbeMemRelease(&u.ag.ctx.s);
+
    goto no_mem;
+
  }
+

  /* If the function returned an error, throw an exception */
  if( u.ag.ctx.isError ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ag.ctx.s));
@@ -63907,7 +64485,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is false.  If either operand is NULL then the result is true.
-
** If neither operand is NULL the the result is the same as it would be if
+
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Eq P1 P2 P3 P4 P5
@@ -63919,7 +64497,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is true.  If either operand is NULL then the result is false.
-
** If neither operand is NULL the the result is the same as it would be if
+
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Le P1 P2 P3 P4 P5
@@ -63957,7 +64535,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
  pIn3 = &aMem[pOp->p3];
  u.ai.flags1 = pIn1->flags;
  u.ai.flags3 = pIn3->flags;
-
  if( (pIn1->flags | pIn3->flags)&MEM_Null ){
+
  if( (u.ai.flags1 | u.ai.flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE_NULLEQ ){
      /* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -63965,7 +64543,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
      ** or not both operands are null.
      */
      assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
-
      u.ai.res = (pIn1->flags & pIn3->flags & MEM_Null)==0;
+
      u.ai.res = (u.ai.flags1 & u.ai.flags3 & MEM_Null)==0;
    }else{
      /* SQLITE_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
@@ -64204,13 +64782,13 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */

/* Opcode: If P1 P2 P3 * *
**
-
** Jump to P2 if the value in register P1 is true.  The value is
+
** Jump to P2 if the value in register P1 is true.  The value
** is considered true if it is numeric and non-zero.  If the value
** in P1 is NULL then take the jump if P3 is true.
*/
/* Opcode: IfNot P1 P2 P3 * *
**
-
** Jump to P2 if the value in register P1 is False.  The value is
+
** Jump to P2 if the value in register P1 is False.  The value
** is considered true if it has a numeric value of zero.  If the value
** in P1 is NULL then take the jump if P3 is true.
*/
@@ -64791,6 +65369,17 @@ case OP_Savepoint: {
    }else{
      u.aq.nName = sqlite3Strlen30(u.aq.zName);

+
#ifndef SQLITE_OMIT_VIRTUALTABLE
+
      /* This call is Ok even if this savepoint is actually a transaction
+
      ** savepoint (and therefore should not prompt xSavepoint()) callbacks.
+
      ** If this is a transaction savepoint being opened, it is guaranteed
+
      ** that the db->aVTrans[] array is empty.  */
+
      assert( db->autoCommit==0 || db->nVTrans==0 );
+
      rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN,
+
                                db->nStatement+db->nSavepoint);
+
      if( rc!=SQLITE_OK ) goto abort_due_to_error;
+
#endif
+

      /* Create a new savepoint structure. */
      u.aq.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.aq.nName+1);
      if( u.aq.pNew ){
@@ -64897,6 +65486,11 @@ case OP_Savepoint: {
      }else{
        db->nDeferredCons = u.aq.pSavepoint->nDeferredCons;
      }
+

+
      if( !isTransaction ){
+
        rc = sqlite3VtabSavepoint(db, u.aq.p1, u.aq.iSavepoint);
+
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
+
      }
    }
  }

@@ -65036,7 +65630,11 @@ case OP_Transaction: {
        db->nStatement++;
        p->iStatement = db->nSavepoint + db->nStatement;
      }
-
      rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement);
+

+
      rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
+
      if( rc==SQLITE_OK ){
+
        rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement);
+
      }

      /* Store the current value of the database handles deferred constraint
      ** counter. If the statement transaction needs to be rolled back,
@@ -65357,7 +65955,7 @@ case OP_OpenEphemeral: {
  u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( u.ax.pCx==0 ) goto no_mem;
  u.ax.pCx->nullRow = 1;
-
  rc = sqlite3BtreeOpen(0, db, &u.ax.pCx->pBt,
+
  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
                        BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(u.ax.pCx->pBt, 1);
@@ -65844,7 +66442,7 @@ case OP_IsUnique: { /* jump, in3 */

/* Opcode: NotExists P1 P2 P3 * *
**
-
** Use the content of register P3 as a integer key.  If a record 
+
** Use the content of register P3 as an integer key.  If a record 
** with that key does not exist in table of P1, then jump to P2. 
** If the record does exist, then fall through.  The cursor is left 
** pointing to the record if it exists.
@@ -65922,7 +66520,7 @@ case OP_Sequence: { /* out2-prerelease */
** If P3>0 then P3 is a register in the root frame of this VDBE that holds 
** the largest previously generated record number. No new record numbers are
** allowed to be less than this value. When this value reaches its maximum, 
-
** a SQLITE_FULL error is generated. The P3 register is updated with the '
+
** an SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
@@ -66031,7 +66629,7 @@ case OP_NewRowid: { /* out2-prerelease */
      assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                             ** an AUTOINCREMENT table. */
      /* on the first attempt, simply do one more than previous */
-
      u.be.v = db->lastRowid;
+
      u.be.v = lastRowid;
      u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
      u.be.v++; /* ensure non-zero */
      u.be.cnt = 0;
@@ -66143,7 +66741,7 @@ case OP_InsertInt: {
  }

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
-
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = u.bf.iKey;
+
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bf.iKey;
  if( u.bf.pData->flags & MEM_Null ){
    u.bf.pData->z = 0;
    u.bf.pData->n = 0;
@@ -66564,7 +67162,7 @@ case OP_Next: { /* jump */

/* Opcode: IdxInsert P1 P2 P3 * P5
**
-
** Register P2 holds a SQL index key made using the
+
** Register P2 holds an SQL index key made using the
** MakeRecord instructions.  This opcode writes that key
** into the index P1.  Data for the entry is nil.
**
@@ -67269,7 +67867,7 @@ case OP_Program: { /* jump */

  p->nFrame++;
  u.by.pFrame->pParent = p->pFrame;
-
  u.by.pFrame->lastRowid = db->lastRowid;
+
  u.by.pFrame->lastRowid = lastRowid;
  u.by.pFrame->nChange = p->nChange;
  p->nChange = 0;
  p->pFrame = u.by.pFrame;
@@ -68080,11 +68678,15 @@ case OP_VUpdate: {
  Mem *pX;
#endif /* local variables moved into u.cm */

+
  assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback
+
       || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
+
  );
  u.cm.pVtab = pOp->p4.pVtab->pVtab;
  u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
  u.cm.nArg = pOp->p2;
  assert( pOp->p4type==P4_VTAB );
  if( ALWAYS(u.cm.pModule->xUpdate) ){
+
    u8 vtabOnConflict = db->vtabOnConflict;
    u.cm.apArg = p->apArg;
    u.cm.pX = &aMem[pOp->p3];
    for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
@@ -68094,13 +68696,23 @@ case OP_VUpdate: {
      u.cm.apArg[u.cm.i] = u.cm.pX;
      u.cm.pX++;
    }
+
    db->vtabOnConflict = pOp->p5;
    rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
+
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.cm.pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
-
      db->lastRowid = u.cm.rowid;
+
      db->lastRowid = lastRowid = u.cm.rowid;
+
    }
+
    if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
+
      if( pOp->p5==OE_Ignore ){
+
        rc = SQLITE_OK;
+
      }else{
+
        p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
+
      }
+
    }else{
+
      p->nChange++;
    }
-
    p->nChange++;
  }
  break;
}
@@ -68152,21 +68764,21 @@ case OP_MaxPgcnt: { /* out2-prerelease */
case OP_Trace: {
#if 0  /* local variables moved into u.cn */
  char *zTrace;
+
  char *z;
#endif /* local variables moved into u.cn */

-
  u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
-
  if( u.cn.zTrace ){
-
    if( db->xTrace ){
-
      char *z = sqlite3VdbeExpandSql(p, u.cn.zTrace);
-
      db->xTrace(db->pTraceArg, z);
-
      sqlite3DbFree(db, z);
-
    }
+
  if( db->xTrace && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
+
    u.cn.z = sqlite3VdbeExpandSql(p, u.cn.zTrace);
+
    db->xTrace(db->pTraceArg, u.cn.z);
+
    sqlite3DbFree(db, u.cn.z);
+
  }
#ifdef SQLITE_DEBUG
-
    if( (db->flags & SQLITE_SqlTrace)!=0 ){
-
      sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace);
-
    }
-
#endif /* SQLITE_DEBUG */
+
  if( (db->flags & SQLITE_SqlTrace)!=0
+
   && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+
  ){
+
    sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace);
  }
+
#endif /* SQLITE_DEBUG */
  break;
}
#endif
@@ -68250,6 +68862,7 @@ vdbe_error_halt:
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
+
  db->lastRowid = lastRowid;
  sqlite3VdbeLeave(p);
  return rc;

@@ -68590,7 +69203,10 @@ SQLITE_API int sqlite3_blob_open(
      sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
      sqlite3VdbeChangeP2(v, 7, pTab->nCol);
      if( !db->mallocFailed ){
-
        sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
+
        pParse->nVar = 1;
+
        pParse->nMem = 1;
+
        pParse->nTab = 1;
+
        sqlite3VdbeMakeReady(v, pParse);
      }
    }
   
@@ -71157,53 +71773,53 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
    /* Wildcard of the form "?".  Assign the next variable number */
    assert( z[0]=='?' );
    pExpr->iColumn = (ynVar)(++pParse->nVar);
-
  }else if( z[0]=='?' ){
-
    /* Wildcard of the form "?nnn".  Convert "nnn" to an integer and
-
    ** use it as the variable number */
-
    i64 i;
-
    int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8);
-
    pExpr->iColumn = (ynVar)i;
-
    testcase( i==0 );
-
    testcase( i==1 );
-
    testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
-
    testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
-
    if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
-
      sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
-
          db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
-
    }
-
    if( i>pParse->nVar ){
-
      pParse->nVar = (int)i;
-
    }
  }else{
-
    /* Wildcards like ":aaa", "$aaa" or "@aaa".  Reuse the same variable
-
    ** number as the prior appearance of the same name, or if the name
-
    ** has never appeared before, reuse the same variable number
-
    */
-
    int i;
-
    u32 n;
-
    n = sqlite3Strlen30(z);
-
    for(i=0; i<pParse->nVarExpr; i++){
-
      Expr *pE = pParse->apVarExpr[i];
-
      assert( pE!=0 );
-
      if( memcmp(pE->u.zToken, z, n)==0 && pE->u.zToken[n]==0 ){
-
        pExpr->iColumn = pE->iColumn;
-
        break;
+
    ynVar x = 0;
+
    u32 n = sqlite3Strlen30(z);
+
    if( z[0]=='?' ){
+
      /* Wildcard of the form "?nnn".  Convert "nnn" to an integer and
+
      ** use it as the variable number */
+
      i64 i;
+
      int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
+
      pExpr->iColumn = x = (ynVar)i;
+
      testcase( i==0 );
+
      testcase( i==1 );
+
      testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
+
      testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
+
      if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
+
        sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
+
            db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
+
        x = 0;
+
      }
+
      if( i>pParse->nVar ){
+
        pParse->nVar = (int)i;
      }
+
    }else{
+
      /* Wildcards like ":aaa", "$aaa" or "@aaa".  Reuse the same variable
+
      ** number as the prior appearance of the same name, or if the name
+
      ** has never appeared before, reuse the same variable number
+
      */
+
      ynVar i;
+
      for(i=0; i<pParse->nzVar; i++){
+
        if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
+
          pExpr->iColumn = x = (ynVar)i+1;
+
          break;
+
        }
+
      }
+
      if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
    }
-
    if( i>=pParse->nVarExpr ){
-
      pExpr->iColumn = (ynVar)(++pParse->nVar);
-
      if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){
-
        pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10;
-
        pParse->apVarExpr =
-
            sqlite3DbReallocOrFree(
-
              db,
-
              pParse->apVarExpr,
-
              pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0])
-
            );
+
    if( x>0 ){
+
      if( x>pParse->nzVar ){
+
        char **a;
+
        a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
+
        if( a==0 ) return;  /* Error reported through db->mallocFailed */
+
        pParse->azVar = a;
+
        memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
+
        pParse->nzVar = x;
      }
-
      if( !db->mallocFailed ){
-
        assert( pParse->apVarExpr!=0 );
-
        pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
+
      if( z[0]!='?' || pParse->azVar[x-1]==0 ){
+
        sqlite3DbFree(db, pParse->azVar[x-1]);
+
        pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
      }
    }
  } 
@@ -72947,7 +73563,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
      assert( pExpr->u.zToken[0]!=0 );
      sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
      if( pExpr->u.zToken[1]!=0 ){
-
        sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, P4_TRANSIENT);
+
        assert( pExpr->u.zToken[0]=='?' 
+
             || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
+
        sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
      }
      break;
    }
@@ -74717,14 +75335,14 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
  /* Reload the table, index and permanent trigger schemas. */
  zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
  if( !zWhere ) return;
-
  sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
+
  sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);

#ifndef SQLITE_OMIT_TRIGGER
  /* Now, if the table is not stored in the temp database, reload any temp 
  ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. 
  */
  if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
-
    sqlite3VdbeAddOp4(v, OP_ParseSchema, 1, 0, 0, zWhere, P4_DYNAMIC);
+
    sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
  }
#endif
}
@@ -75978,8 +76596,12 @@ static void attachFunc(
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName;
  const char *zFile;
+
  char *zPath = 0;
+
  char *zErr = 0;
+
  unsigned int flags;
  Db *aNew;
  char *zErrDyn = 0;
+
  sqlite3_vfs *pVfs;

  UNUSED_PARAMETER(NotUsed);

@@ -76032,8 +76654,18 @@ static void attachFunc(
  ** it to obtain the database schema. At this point the schema may
  ** or may not be initialised.
  */
-
  rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
-
                        db->openFlags | SQLITE_OPEN_MAIN_DB);
+
  flags = db->openFlags;
+
  rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
+
  if( rc!=SQLITE_OK ){
+
    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+
    sqlite3_result_error(context, zErr, -1);
+
    sqlite3_free(zErr);
+
    return;
+
  }
+
  assert( pVfs );
+
  flags |= SQLITE_OPEN_MAIN_DB;
+
  rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
+
  sqlite3_free( zPath );
  db->nDb++;
  if( rc==SQLITE_CONSTRAINT ){
    rc = SQLITE_ERROR;
@@ -76904,9 +77536,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
    /* A minimum of one cursor is required if autoincrement is used
    *  See ticket [a696379c1f08866] */
    if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
-
    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
-
                         pParse->nTab, pParse->nMaxArg, pParse->explain,
-
                         pParse->isMultiWrite && pParse->mayAbort);
+
    sqlite3VdbeMakeReady(v, pParse);
    pParse->rc = SQLITE_DONE;
    pParse->colNamesSet = 0;
  }else{
@@ -78325,8 +78955,8 @@ SQLITE_PRIVATE void sqlite3EndTable(
#endif

    /* Reparse everything to update our internal data structures */
-
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
-
        sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P4_DYNAMIC);
+
    sqlite3VdbeAddParseSchemaOp(v, iDb,
+
               sqlite3MPrintf(db, "tbl_name='%q'", p->zName));
  }


@@ -79523,9 +80153,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
    if( pTblName ){
      sqlite3RefillIndex(pParse, pIndex, iMem);
      sqlite3ChangeCookie(pParse, iDb);
-
      sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
-
         sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 
-
         P4_DYNAMIC);
+
      sqlite3VdbeAddParseSchemaOp(v, iDb,
+
         sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
      sqlite3VdbeAddOp1(v, OP_Expire, 0);
    }
  }
@@ -80147,7 +80776,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
          SQLITE_OPEN_DELETEONCLOSE |
          SQLITE_OPEN_TEMP_DB;

-
    rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
+
    rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorMsg(pParse, "unable to open a temporary database "
        "file for storing temporary tables");
@@ -81323,6 +81952,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
      sqlite3VtabMakeWritable(pParse, pTab);
      sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
+
      sqlite3VdbeChangeP5(v, OE_Abort);
      sqlite3MayAbort(pParse);
    }else
#endif
@@ -81557,8 +82187,14 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
    }
  }
  if( doMakeRec ){
+
    const char *zAff;
+
    if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
+
      zAff = 0;
+
    }else{
+
      zAff = sqlite3IndexAffinityStr(v, pIdx);
+
    }
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
-
    sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
+
    sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
  return regBase;
@@ -82070,10 +82706,10 @@ struct compareInfo {
** whereas only characters less than 0x80 do in ASCII.
*/
#if defined(SQLITE_EBCDIC)
-
# define sqlite3Utf8Read(A,C)    (*(A++))
-
# define GlogUpperToLower(A)     A = sqlite3UpperToLower[A]
+
# define sqlite3Utf8Read(A,C)  (*(A++))
+
# define GlogUpperToLower(A)   A = sqlite3UpperToLower[A]
#else
-
# define GlogUpperToLower(A)     if( A<0x80 ){ A = sqlite3UpperToLower[A]; }
+
# define GlogUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
#endif

static const struct compareInfo globInfo = { '*', '?', '[', 0 };
@@ -82116,9 +82752,9 @@ static int patternCompare(
  const u8 *zPattern,              /* The glob pattern */
  const u8 *zString,               /* The string to compare against the glob */
  const struct compareInfo *pInfo, /* Information about how to do the compare */
-
  const int esc                    /* The escape character */
+
  u32 esc                          /* The escape character */
){
-
  int c, c2;
+
  u32 c, c2;
  int invert;
  int seen;
  u8 matchOne = pInfo->matchOne;
@@ -82172,7 +82808,7 @@ static int patternCompare(
        return 0;
      }
    }else if( c==matchSet ){
-
      int prior_c = 0;
+
      u32 prior_c = 0;
      assert( esc==0 );    /* This only occurs for GLOB, not LIKE */
      seen = 0;
      invert = 0;
@@ -82248,7 +82884,7 @@ static void likeFunc(
  sqlite3_value **argv
){
  const unsigned char *zA, *zB;
-
  int escape = 0;
+
  u32 escape = 0;
  int nPat;
  sqlite3 *db = sqlite3_context_db_handle(context);

@@ -82339,6 +82975,21 @@ static void sourceidFunc(
}

/*
+
** Implementation of the sqlite_log() function.  This is a wrapper around
+
** sqlite3_log().  The return value is NULL.  The function exists purely for
+
** its side-effects.
+
*/
+
static void errlogFunc(
+
  sqlite3_context *context,
+
  int argc,
+
  sqlite3_value **argv
+
){
+
  UNUSED_PARAMETER(argc);
+
  UNUSED_PARAMETER(context);
+
  sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
+
}
+

+
/*
** Implementation of the sqlite_compileoption_used() function.
** The result is an integer that identifies if the compiler option
** was used to build SQLite.
@@ -83105,6 +83756,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
    FUNCTION(nullif,             2, 0, 1, nullifFunc       ),
    FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
    FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
+
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
    FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
@@ -83543,13 +84195,25 @@ static void fkLookupParent(
      /* If the parent table is the same as the child table, and we are about
      ** to increment the constraint-counter (i.e. this is an INSERT operation),
      ** then check if the row being inserted matches itself. If so, do not
-
      ** increment the constraint-counter.  */
+
      ** increment the constraint-counter. 
+
      **
+
      ** If any of the parent-key values are NULL, then the row cannot match 
+
      ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
+
      ** of the parent-key values are NULL (at this point it is known that
+
      ** none of the child key values are).
+
      */
      if( pTab==pFKey->pFrom && nIncr==1 ){
        int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
        for(i=0; i<nCol; i++){
          int iChild = aiCol[i]+1+regData;
          int iParent = pIdx->aiColumn[i]+1+regData;
+
          assert( aiCol[i]!=pTab->iPKey );
+
          if( pIdx->aiColumn[i]==pTab->iPKey ){
+
            /* The parent key is a composite key that includes the IPK column */
+
            iParent = regData;
+
          }
          sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
+
          sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
        }
        sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
      }
@@ -85317,6 +85981,7 @@ SQLITE_PRIVATE void sqlite3Insert(
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
      sqlite3VtabMakeWritable(pParse, pTab);
      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
+
      sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
      sqlite3MayAbort(pParse);
    }else
#endif
@@ -86082,6 +86747,18 @@ static int xferOptimization(
    return 0;   /* Tables have different CHECK constraints.  Ticket #2252 */
  }
#endif
+
#ifndef SQLITE_OMIT_FOREIGN_KEY
+
  /* Disallow the transfer optimization if the destination table constains
+
  ** any foreign key constraints.  This is more restrictive than necessary.
+
  ** But the main beneficiary of the transfer optimization is the VACUUM 
+
  ** command, and the VACUUM command disables foreign key constraints.  So
+
  ** the extra complication to make this rule less restrictive is probably
+
  ** not worth the effort.  Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
+
  */
+
  if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
+
    return 0;
+
  }
+
#endif

  /* If we get this far, it means either:
  **
@@ -87414,10 +88091,6 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
** This file contains code used to implement the PRAGMA command.
*/

-
/* Ignore this whole file if pragmas are disabled
-
*/
-
#if !defined(SQLITE_OMIT_PRAGMA)
-

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
@@ -87450,10 +88123,16 @@ static u8 getSafetyLevel(const char *z){
/*
** Interpret the given string as a boolean value.
*/
-
static u8 getBoolean(const char *z){
+
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z){
  return getSafetyLevel(z)&1;
}

+
/* The sqlite3GetBoolean() function is used by other modules but the
+
** remainder of this file is specific to PRAGMA processing.  So omit
+
** the rest of the file if PRAGMAs are omitted from the build.
+
*/
+
#if !defined(SQLITE_OMIT_PRAGMA)
+

/*
** Interpret the given string as a locking mode value.
*/
@@ -87620,7 +88299,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
            mask &= ~(SQLITE_ForeignKeys);
          }

-
          if( getBoolean(zRight) ){
+
          if( sqlite3GetBoolean(zRight) ){
            db->flags |= mask;
          }else{
            db->flags &= ~mask;
@@ -87834,7 +88513,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
    int b = -1;
    assert( pBt!=0 );
    if( zRight ){
-
      b = getBoolean(zRight);
+
      b = sqlite3GetBoolean(zRight);
    }
    if( pId2->n==0 && b>=0 ){
      int ii;
@@ -88434,7 +89113,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
#ifndef NDEBUG
  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
    if( zRight ){
-
      if( getBoolean(zRight) ){
+
      if( sqlite3GetBoolean(zRight) ){
        sqlite3ParserTrace(stderr, "parser: ");
      }else{
        sqlite3ParserTrace(0, 0);
@@ -88448,7 +89127,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
  */
  if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
    if( zRight ){
-
      sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
+
      sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight));
    }
  }else

@@ -94026,11 +94705,13 @@ SQLITE_PRIVATE int sqlite3Select(
        ** and pKeyInfo to the KeyInfo structure required to navigate the
        ** index.
        **
+
        ** (2011-04-15) Do not do a full scan of an unordered index.
+
        **
        ** In practice the KeyInfo structure will not be used. It is only 
        ** passed to keep OP_OpenRead happy.
        */
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-
          if( !pBest || pIdx->nColumn<pBest->nColumn ){
+
          if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
            pBest = pIdx;
          }
        }
@@ -94752,9 +95433,8 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
       pTrig->table, z);
    sqlite3DbFree(db, z);
    sqlite3ChangeCookie(pParse, iDb);
-
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
-
        db, "type='trigger' AND name='%q'", zName), P4_DYNAMIC
-
    );
+
    sqlite3VdbeAddParseSchemaOp(v, iDb,
+
        sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
  }

  if( db->init.busy ){
@@ -95587,7 +96267,8 @@ static void updateVirtualTable(
  ExprList *pChanges,  /* The columns to change in the UPDATE statement */
  Expr *pRowidExpr,    /* Expression used to recompute the rowid */
  int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */
-
  Expr *pWhere         /* WHERE clause of the UPDATE statement */
+
  Expr *pWhere,        /* WHERE clause of the UPDATE statement */
+
  int onError          /* ON CONFLICT strategy */
);
#endif /* SQLITE_OMIT_VIRTUALTABLE */

@@ -95807,7 +96488,7 @@ SQLITE_PRIVATE void sqlite3Update(
  }
  for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
    int reg;
-
    if( chngRowid ){
+
    if( hasFK || chngRowid ){
      reg = ++pParse->nMem;
    }else{
      reg = 0;
@@ -95831,7 +96512,7 @@ SQLITE_PRIVATE void sqlite3Update(
  /* Virtual tables must be handled separately */
  if( IsVirtual(pTab) ){
    updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
-
                       pWhere);
+
                       pWhere, onError);
    pWhere = 0;
    pTabList = 0;
    goto update_cleanup;
@@ -96161,7 +96842,8 @@ static void updateVirtualTable(
  ExprList *pChanges,  /* The columns to change in the UPDATE statement */
  Expr *pRowid,        /* Expression used to recompute the rowid */
  int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */
-
  Expr *pWhere         /* WHERE clause of the UPDATE statement */
+
  Expr *pWhere,        /* WHERE clause of the UPDATE statement */
+
  int onError          /* ON CONFLICT strategy */
){
  Vdbe *v = pParse->pVdbe;  /* Virtual machine under construction */
  ExprList *pEList = 0;     /* The result set of the SELECT statement */
@@ -96218,6 +96900,7 @@ static void updateVirtualTable(
  }
  sqlite3VtabMakeWritable(pParse, pTab);
  sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
+
  sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
  sqlite3MayAbort(pParse);
  sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
  sqlite3VdbeJumpHere(v, addr);
@@ -96592,6 +97275,18 @@ end_of_vacuum:
#ifndef SQLITE_OMIT_VIRTUALTABLE

/*
+
** Before a virtual table xCreate() or xConnect() method is invoked, the
+
** sqlite3.pVtabCtx member variable is set to point to an instance of
+
** this struct allocated on the stack. It is used by the implementation of 
+
** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
+
** are invoked only from within xCreate and xConnect methods.
+
*/
+
struct VtabCtx {
+
  Table *pTab;
+
  VTable *pVTable;
+
};
+

+
/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
** sqlite3_create_module_v2() interfaces.
@@ -96619,13 +97314,13 @@ static int createModule(
    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;
    }
-
    sqlite3ResetInternalSchema(db, -1);
  }else if( xDestroy ){
    xDestroy(pAux);
  }
@@ -96948,7 +97643,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){

    sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
    zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
-
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
+
    sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
    sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, 
                         pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
  }
@@ -97011,6 +97706,7 @@ static int vtabCallConstructor(
  int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
  char **pzErr
){
+
  VtabCtx sCtx;
  VTable *pVTable;
  int rc;
  const char *const*azArg = (const char *const*)pTab->azModuleArg;
@@ -97030,12 +97726,14 @@ static int vtabCallConstructor(
  pVTable->db = db;
  pVTable->pMod = pMod;

-
  assert( !db->pVTab );
-
  assert( xConstruct );
-
  db->pVTab = pTab;
-

  /* Invoke the virtual table constructor */
+
  assert( &db->pVtabCtx );
+
  assert( xConstruct );
+
  sCtx.pTab = pTab;
+
  sCtx.pVTable = pVTable;
+
  db->pVtabCtx = &sCtx;
  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
+
  db->pVtabCtx = 0;
  if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;

  if( SQLITE_OK!=rc ){
@@ -97051,7 +97749,7 @@ static int vtabCallConstructor(
    ** the sqlite3_vtab object if successful.  */
    pVTable->pVtab->pModule = pMod->pModule;
    pVTable->nRef = 1;
-
    if( db->pVTab ){
+
    if( sCtx.pTab ){
      const char *zFormat = "vtable constructor did not declare schema: %s";
      *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
      sqlite3VtabUnlock(pVTable);
@@ -97099,7 +97797,6 @@ static int vtabCallConstructor(
  }

  sqlite3DbFree(db, zModuleName);
-
  db->pVTab = 0;
  return rc;
}

@@ -97140,11 +97837,11 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){

  return rc;
}
-

/*
-
** Add the virtual table pVTab to the array sqlite3.aVTrans[].
+
** Grow the db->aVTrans[] array so that there is room for at least one
+
** more v-table. Return SQLITE_NOMEM if a malloc fails, or SQLITE_OK otherwise.
*/
-
static int addToVTrans(sqlite3 *db, VTable *pVTab){
+
static int growVTrans(sqlite3 *db){
  const int ARRAY_INCR = 5;

  /* Grow the sqlite3.aVTrans array if required */
@@ -97159,10 +97856,17 @@ static int addToVTrans(sqlite3 *db, VTable *pVTab){
    db->aVTrans = aVTrans;
  }

+
  return SQLITE_OK;
+
}
+

+
/*
+
** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should
+
** have already been reserved using growVTrans().
+
*/
+
static void addToVTrans(sqlite3 *db, VTable *pVTab){
  /* Add pVtab to the end of sqlite3.aVTrans */
  db->aVTrans[db->nVTrans++] = pVTab;
  sqlite3VtabLock(pVTab);
-
  return SQLITE_OK;
}

/*
@@ -97200,7 +97904,10 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab,
  /* Justification of ALWAYS():  The xConstructor method is required to
  ** create a valid sqlite3_vtab if it returns SQLITE_OK. */
  if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){
-
      rc = addToVTrans(db, sqlite3GetVTable(db, pTab));
+
    rc = growVTrans(db);
+
    if( rc==SQLITE_OK ){
+
      addToVTrans(db, sqlite3GetVTable(db, pTab));
+
    }
  }

  return rc;
@@ -97219,8 +97926,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
  char *zErr = 0;

  sqlite3_mutex_enter(db->mutex);
-
  pTab = db->pVTab;
-
  if( !pTab ){
+
  if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
    sqlite3Error(db, SQLITE_MISUSE, 0);
    sqlite3_mutex_leave(db->mutex);
    return SQLITE_MISUSE_BKPT;
@@ -97247,7 +97953,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
        pParse->pNewTable->nCol = 0;
        pParse->pNewTable->aCol = 0;
      }
-
      db->pVTab = 0;
+
      db->pVtabCtx->pTab = 0;
    }else{
      sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
      sqlite3DbFree(db, zErr);
@@ -97317,6 +98023,7 @@ static void callFinaliser(sqlite3 *db, int offset){
        x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset);
        if( x ) x(p);
      }
+
      pVTab->iSavepoint = 0;
      sqlite3VtabUnlock(pVTab);
    }
    sqlite3DbFree(db, db->aVTrans);
@@ -97399,7 +98106,6 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
  if( pModule->xBegin ){
    int i;

-

    /* If pVtab is already in the aVTrans array, return early */
    for(i=0; i<db->nVTrans; i++){
      if( db->aVTrans[i]==pVTab ){
@@ -97407,10 +98113,62 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
      }
    }

-
    /* Invoke the xBegin method */
-
    rc = pModule->xBegin(pVTab->pVtab);
+
    /* Invoke the xBegin method. If successful, add the vtab to the 
+
    ** sqlite3.aVTrans[] array. */
+
    rc = growVTrans(db);
    if( rc==SQLITE_OK ){
-
      rc = addToVTrans(db, pVTab);
+
      rc = pModule->xBegin(pVTab->pVtab);
+
      if( rc==SQLITE_OK ){
+
        addToVTrans(db, pVTab);
+
      }
+
    }
+
  }
+
  return rc;
+
}
+

+
/*
+
** Invoke either the xSavepoint, xRollbackTo or xRelease method of all
+
** virtual tables that currently have an open transaction. Pass iSavepoint
+
** as the second argument to the virtual table method invoked.
+
**
+
** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
+
** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is 
+
** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
+
** an open transaction is invoked.
+
**
+
** If any virtual table method returns an error code other than SQLITE_OK, 
+
** processing is abandoned and the error returned to the caller of this
+
** function immediately. If all calls to virtual table methods are successful,
+
** SQLITE_OK is returned.
+
*/
+
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
+
  int rc = SQLITE_OK;
+

+
  assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
+
  assert( iSavepoint>=0 );
+
  if( db->aVTrans ){
+
    int i;
+
    for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
+
      VTable *pVTab = db->aVTrans[i];
+
      const sqlite3_module *pMod = pVTab->pMod->pModule;
+
      if( pMod->iVersion>=2 ){
+
        int (*xMethod)(sqlite3_vtab *, int);
+
        switch( op ){
+
          case SAVEPOINT_BEGIN:
+
            xMethod = pMod->xSavepoint;
+
            pVTab->iSavepoint = iSavepoint+1;
+
            break;
+
          case SAVEPOINT_ROLLBACK:
+
            xMethod = pMod->xRollbackTo;
+
            break;
+
          default:
+
            xMethod = pMod->xRelease;
+
            break;
+
        }
+
        if( xMethod && pVTab->iSavepoint>iSavepoint ){
+
          rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
+
        }
+
      }
    }
  }
  return rc;
@@ -97514,6 +98272,57 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
  }
}

+
/*
+
** Return the ON CONFLICT resolution mode in effect for the virtual
+
** table update operation currently in progress.
+
**
+
** The results of this routine are undefined unless it is called from
+
** within an xUpdate method.
+
*/
+
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
+
  static const unsigned char aMap[] = { 
+
    SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE 
+
  };
+
  assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
+
  assert( OE_Ignore==4 && OE_Replace==5 );
+
  assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
+
  return (int)aMap[db->vtabOnConflict-1];
+
}
+

+
/*
+
** Call from within the xCreate() or xConnect() methods to provide 
+
** the SQLite core with additional information about the behavior
+
** of the virtual table being implemented.
+
*/
+
SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
+
  va_list ap;
+
  int rc = SQLITE_OK;
+

+
  sqlite3_mutex_enter(db->mutex);
+

+
  va_start(ap, op);
+
  switch( op ){
+
    case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
+
      VtabCtx *p = db->pVtabCtx;
+
      if( !p ){
+
        rc = SQLITE_MISUSE_BKPT;
+
      }else{
+
        assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
+
        p->pVTable->bConstraint = (u8)va_arg(ap, int);
+
      }
+
      break;
+
    }
+
    default:
+
      rc = SQLITE_MISUSE_BKPT;
+
      break;
+
  }
+
  va_end(ap);
+

+
  if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0);
+
  sqlite3_mutex_leave(db->mutex);
+
  return rc;
+
}
+

#endif /* SQLITE_OMIT_VIRTUALTABLE */

/************** End of vtab.c ************************************************/
@@ -106561,13 +107370,12 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
      testcase( z[0]=='x' ); testcase( z[0]=='X' );
      if( z[1]=='\'' ){
        *tokenType = TK_BLOB;
-
        for(i=2; (c=z[i])!=0 && c!='\''; i++){
-
          if( !sqlite3Isxdigit(c) ){
-
            *tokenType = TK_ILLEGAL;
-
          }
+
        for(i=2; sqlite3Isxdigit(z[i]); i++){}
+
        if( z[i]!='\'' || i%2 ){
+
          *tokenType = TK_ILLEGAL;
+
          while( z[i] && z[i]!='\'' ){ i++; }
        }
-
        if( i%2 || !c ) *tokenType = TK_ILLEGAL;
-
        if( c ) i++;
+
        if( z[i] ) i++;
        return i;
      }
      /* Otherwise fall through to the next case */
@@ -106620,9 +107428,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
  assert( pParse->pNewTable==0 );
  assert( pParse->pNewTrigger==0 );
  assert( pParse->nVar==0 );
-
  assert( pParse->nVarExpr==0 );
-
  assert( pParse->nVarExprAlloc==0 );
-
  assert( pParse->apVarExpr==0 );
+
  assert( pParse->nzVar==0 );
+
  assert( pParse->azVar==0 );
  enableLookaside = db->lookaside.bEnabled;
  if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
  while( !db->mallocFailed && zSql[i]!=0 ){
@@ -106716,7 +107523,8 @@ abort_parse:
  }

  sqlite3DeleteTrigger(db, pParse->pNewTrigger);
-
  sqlite3DbFree(db, pParse->apVarExpr);
+
  for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
+
  sqlite3DbFree(db, pParse->azVar);
  sqlite3DbFree(db, pParse->aAlias);
  while( pParse->pAinc ){
    AutoincInfo *p = pParse->pAinc;
@@ -107536,6 +108344,11 @@ SQLITE_API int sqlite3_config(int op, ...){
      break;
    }

+
    case SQLITE_CONFIG_URI: {
+
      sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
+
      break;
+
    }
+

    default: {
      rc = SQLITE_ERROR;
      break;
@@ -108896,6 +109709,236 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
}

/*
+
** This function is used to parse both URIs and non-URI filenames passed by the
+
** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
+
** URIs specified as part of ATTACH statements.
+
**
+
** The first argument to this function is the name of the VFS to use (or
+
** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
+
** query parameter. The second argument contains the URI (or non-URI filename)
+
** itself. When this function is called the *pFlags variable should contain
+
** the default flags to open the database handle with. The value stored in
+
** *pFlags may be updated before returning if the URI filename contains 
+
** "cache=xxx" or "mode=xxx" query parameters.
+
**
+
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
+
** the VFS that should be used to open the database file. *pzFile is set to
+
** point to a buffer containing the name of the file to open. It is the 
+
** responsibility of the caller to eventually call sqlite3_free() to release
+
** this buffer.
+
**
+
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
+
** may be set to point to a buffer containing an English language error 
+
** message. It is the responsibility of the caller to eventually release
+
** this buffer by calling sqlite3_free().
+
*/
+
SQLITE_PRIVATE int sqlite3ParseUri(
+
  const char *zDefaultVfs,        /* VFS to use if no "vfs=xxx" query option */
+
  const char *zUri,               /* Nul-terminated URI to parse */
+
  unsigned int *pFlags,           /* IN/OUT: SQLITE_OPEN_XXX flags */
+
  sqlite3_vfs **ppVfs,            /* OUT: VFS to use */ 
+
  char **pzFile,                  /* OUT: Filename component of URI */
+
  char **pzErrMsg                 /* OUT: Error message (if rc!=SQLITE_OK) */
+
){
+
  int rc = SQLITE_OK;
+
  unsigned int flags = *pFlags;
+
  const char *zVfs = zDefaultVfs;
+
  char *zFile;
+
  char c;
+
  int nUri = sqlite3Strlen30(zUri);
+

+
  assert( *pzErrMsg==0 );
+

+
  if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) 
+
   && nUri>=5 && memcmp(zUri, "file:", 5)==0 
+
  ){
+
    char *zOpt;
+
    int eState;                   /* Parser state when parsing URI */
+
    int iIn;                      /* Input character index */
+
    int iOut = 0;                 /* Output character index */
+
    int nByte = nUri+2;           /* Bytes of space to allocate */
+

+
    /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen 
+
    ** method that there may be extra parameters following the file-name.  */
+
    flags |= SQLITE_OPEN_URI;
+

+
    for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
+
    zFile = sqlite3_malloc(nByte);
+
    if( !zFile ) return SQLITE_NOMEM;
+

+
    /* Discard the scheme and authority segments of the URI. */
+
    if( zUri[5]=='/' && zUri[6]=='/' ){
+
      iIn = 7;
+
      while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
+

+
      if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
+
        *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s", 
+
            iIn-7, &zUri[7]);
+
        rc = SQLITE_ERROR;
+
        goto parse_uri_out;
+
      }
+
    }else{
+
      iIn = 5;
+
    }
+

+
    /* Copy the filename and any query parameters into the zFile buffer. 
+
    ** Decode %HH escape codes along the way. 
+
    **
+
    ** Within this loop, variable eState may be set to 0, 1 or 2, depending
+
    ** on the parsing context. As follows:
+
    **
+
    **   0: Parsing file-name.
+
    **   1: Parsing name section of a name=value query parameter.
+
    **   2: Parsing value section of a name=value query parameter.
+
    */
+
    eState = 0;
+
    while( (c = zUri[iIn])!=0 && c!='#' ){
+
      iIn++;
+
      if( c=='%' 
+
       && sqlite3Isxdigit(zUri[iIn]) 
+
       && sqlite3Isxdigit(zUri[iIn+1]) 
+
      ){
+
        int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
+
        octet += sqlite3HexToInt(zUri[iIn++]);
+

+
        assert( octet>=0 && octet<256 );
+
        if( octet==0 ){
+
          /* This branch is taken when "%00" appears within the URI. In this
+
          ** case we ignore all text in the remainder of the path, name or
+
          ** value currently being parsed. So ignore the current character
+
          ** and skip to the next "?", "=" or "&", as appropriate. */
+
          while( (c = zUri[iIn])!=0 && c!='#' 
+
              && (eState!=0 || c!='?')
+
              && (eState!=1 || (c!='=' && c!='&'))
+
              && (eState!=2 || c!='&')
+
          ){
+
            iIn++;
+
          }
+
          continue;
+
        }
+
        c = octet;
+
      }else if( eState==1 && (c=='&' || c=='=') ){
+
        if( zFile[iOut-1]==0 ){
+
          /* An empty option name. Ignore this option altogether. */
+
          while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
+
          continue;
+
        }
+
        if( c=='&' ){
+
          zFile[iOut++] = '\0';
+
        }else{
+
          eState = 2;
+
        }
+
        c = 0;
+
      }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
+
        c = 0;
+
        eState = 1;
+
      }
+
      zFile[iOut++] = c;
+
    }
+
    if( eState==1 ) zFile[iOut++] = '\0';
+
    zFile[iOut++] = '\0';
+
    zFile[iOut++] = '\0';
+

+
    /* Check if there were any options specified that should be interpreted 
+
    ** here. Options that are interpreted here include "vfs" and those that
+
    ** correspond to flags that may be passed to the sqlite3_open_v2()
+
    ** method. */
+
    zOpt = &zFile[sqlite3Strlen30(zFile)+1];
+
    while( zOpt[0] ){
+
      int nOpt = sqlite3Strlen30(zOpt);
+
      char *zVal = &zOpt[nOpt+1];
+
      int nVal = sqlite3Strlen30(zVal);
+

+
      if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
+
        zVfs = zVal;
+
      }else{
+
        struct OpenMode {
+
          const char *z;
+
          int mode;
+
        } *aMode = 0;
+
        char *zModeType = 0;
+
        int mask = 0;
+
        int limit = 0;
+

+
        if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
+
          static struct OpenMode aCacheMode[] = {
+
            { "shared",  SQLITE_OPEN_SHAREDCACHE },
+
            { "private", SQLITE_OPEN_PRIVATECACHE },
+
            { 0, 0 }
+
          };
+

+
          mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
+
          aMode = aCacheMode;
+
          limit = mask;
+
          zModeType = "cache";
+
        }
+
        if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
+
          static struct OpenMode aOpenMode[] = {
+
            { "ro",  SQLITE_OPEN_READONLY },
+
            { "rw",  SQLITE_OPEN_READWRITE }, 
+
            { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
+
            { 0, 0 }
+
          };
+

+
          mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
+
          aMode = aOpenMode;
+
          limit = mask & flags;
+
          zModeType = "access";
+
        }
+

+
        if( aMode ){
+
          int i;
+
          int mode = 0;
+
          for(i=0; aMode[i].z; i++){
+
            const char *z = aMode[i].z;
+
            if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
+
              mode = aMode[i].mode;
+
              break;
+
            }
+
          }
+
          if( mode==0 ){
+
            *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
+
            rc = SQLITE_ERROR;
+
            goto parse_uri_out;
+
          }
+
          if( mode>limit ){
+
            *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
+
                                        zModeType, zVal);
+
            rc = SQLITE_PERM;
+
            goto parse_uri_out;
+
          }
+
          flags = (flags & ~mask) | mode;
+
        }
+
      }
+

+
      zOpt = &zVal[nVal+1];
+
    }
+

+
  }else{
+
    zFile = sqlite3_malloc(nUri+2);
+
    if( !zFile ) return SQLITE_NOMEM;
+
    memcpy(zFile, zUri, nUri);
+
    zFile[nUri] = '\0';
+
    zFile[nUri+1] = '\0';
+
  }
+

+
  *ppVfs = sqlite3_vfs_find(zVfs);
+
  if( *ppVfs==0 ){
+
    *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
+
    rc = SQLITE_ERROR;
+
  }
+
 parse_uri_out:
+
  if( rc!=SQLITE_OK ){
+
    sqlite3_free(zFile);
+
    zFile = 0;
+
  }
+
  *pFlags = flags;
+
  *pzFile = zFile;
+
  return rc;
+
}
+

+

+
/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
** is UTF-8 encoded.
@@ -108903,12 +109946,14 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb,        /* OUT: Returned database handle */
-
  unsigned flags,        /* Operational flags */
+
  unsigned int flags,    /* Operational flags */
  const char *zVfs       /* Name of the VFS to use */
){
-
  sqlite3 *db;
-
  int rc;
-
  int isThreadsafe;
+
  sqlite3 *db;                    /* Store allocated handle here */
+
  int rc;                         /* Return code */
+
  int isThreadsafe;               /* True for threadsafe connections */
+
  char *zOpen = 0;                /* Filename argument to pass to BtreeOpen() */
+
  char *zErrMsg = 0;              /* Error message from sqlite3ParseUri() */

  *ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
@@ -108932,7 +109977,7 @@ static int openDatabase(
  testcase( (1<<(flags&7))==0x02 ); /* READONLY */
  testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
  testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
-
  if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;
+
  if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;

  if( sqlite3GlobalConfig.bCoreMutex==0 ){
    isThreadsafe = 0;
@@ -109013,13 +110058,6 @@ static int openDatabase(
  sqlite3HashInit(&db->aModule);
#endif

-
  db->pVfs = sqlite3_vfs_find(zVfs);
-
  if( !db->pVfs ){
-
    rc = SQLITE_ERROR;
-
    sqlite3Error(db, rc, "no such vfs: %s", zVfs);
-
    goto opendb_out;
-
  }
-

  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** and UTF-16, so add a version for each to avoid any unnecessary
  ** conversions. The only error that can occur here is a malloc() failure.
@@ -109042,9 +110080,18 @@ static int openDatabase(
  createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
                  nocaseCollatingFunc, 0);

-
  /* Open the backend database driver */
+
  /* Parse the filename/URI argument. */
  db->openFlags = flags;
-
  rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,
+
  rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
+
  if( rc!=SQLITE_OK ){
+
    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+
    sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
+
    sqlite3_free(zErrMsg);
+
    goto opendb_out;
+
  }
+

+
  /* Open the backend database driver */
+
  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
                        flags | SQLITE_OPEN_MAIN_DB);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_IOERR_NOMEM ){
@@ -109137,6 +110184,7 @@ static int openDatabase(
  sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);

opendb_out:
+
  sqlite3_free(zOpen);
  if( db ){
    assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
    sqlite3_mutex_leave(db->mutex);
@@ -109168,7 +110216,7 @@ SQLITE_API int sqlite3_open_v2(
  int flags,              /* Flags */
  const char *zVfs        /* Name of VFS module to use */
){
-
  return openDatabase(filename, ppDb, flags, zVfs);
+
  return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
}

#ifndef SQLITE_OMIT_UTF16
@@ -109773,12 +110821,45 @@ SQLITE_API int sqlite3_test_control(int op, ...){
      break;
    }

+
    /*   sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
+
    **
+
    ** If parameter onoff is non-zero, configure the wrappers so that all
+
    ** subsequent calls to localtime() and variants fail. If onoff is zero,
+
    ** undo this setting.
+
    */
+
    case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
+
      sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
+
      break;
+
    }
+

  }
  va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
  return rc;
}

+
/*
+
** This is a utility routine, useful to VFS implementations, that checks
+
** to see if a database file was a URI that contained a specific query 
+
** parameter, and if so obtains the value of the query parameter.
+
**
+
** The zFilename argument is the filename pointer passed into the xOpen()
+
** method of a VFS implementation.  The zParam argument is the name of the
+
** query parameter we seek.  This routine returns the value of the zParam
+
** parameter if it exists.  If the parameter does not exist, this routine
+
** returns a NULL pointer.
+
*/
+
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
+
  zFilename += sqlite3Strlen30(zFilename) + 1;
+
  while( zFilename[0] ){
+
    int x = strcmp(zFilename, zParam);
+
    zFilename += sqlite3Strlen30(zFilename) + 1;
+
    if( x==0 ) return zFilename;
+
    zFilename += sqlite3Strlen30(zFilename) + 1;
+
  }
+
  return 0;
+
}
+

/************** End of main.c ************************************************/
/************** Begin file notify.c ******************************************/
/*
@@ -110408,12 +111489,6 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
** into a single segment.
*/

-
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-

-
#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
-
# define SQLITE_CORE 1
-
#endif
-

/************** Include fts3Int.h in the middle of fts3.c ********************/
/************** Begin file fts3Int.h *****************************************/
/*
@@ -110429,7 +111504,6 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
******************************************************************************
**
*/
-

#ifndef _FTSINT_H
#define _FTSINT_H

@@ -110437,6 +111511,16 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
# define NDEBUG 1
#endif

+
/*
+
** FTS4 is really an extension for FTS3.  It is enabled using the
+
** SQLITE_ENABLE_FTS3 macro.  But to avoid confusion we also all
+
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
+
*/
+
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
+
# define SQLITE_ENABLE_FTS3
+
#endif
+

+
#ifdef SQLITE_ENABLE_FTS3
/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
/************** Begin file fts3_tokenizer.h **********************************/
/*
@@ -110735,6 +111819,11 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
*/
#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))

+

+
#ifndef MIN
+
# define MIN(x,y) ((x)<(y)?(x):(y))
+
#endif
+

/*
** Maximum length of a varint encoded integer. The varint format is different
** from that used by SQLite, so the maximum length is 10, not 9.
@@ -110742,6 +111831,24 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
#define FTS3_VARINT_MAX 10

/*
+
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
+
** in the document set and zero or more prefix indexes. All indexes are stored
+
** as one or more b+-trees in the %_segments and %_segdir tables. 
+
**
+
** It is possible to determine which index a b+-tree belongs to based on the
+
** value stored in the "%_segdir.level" column. Given this value L, the index
+
** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with
+
** level values between 0 and 1023 (inclusive) belong to index 0, all levels
+
** between 1024 and 2047 to index 1, and so on.
+
**
+
** It is considered impossible for an index to use more than 1024 levels. In 
+
** theory though this may happen, but only after at least 
+
** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables.
+
*/
+
#define FTS3_SEGDIR_MAXLEVEL      1024
+
#define FTS3_SEGDIR_MAXLEVEL_STR "1024"
+

+
/*
** The testcase() macro is only used by the amalgamation.  If undefined,
** make it a no-op.
*/
@@ -110780,22 +111887,43 @@ typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
typedef short int i16;            /* 2-byte (or larger) signed integer */
typedef unsigned int u32;         /* 4-byte unsigned integer */
typedef sqlite3_uint64 u64;       /* 8-byte unsigned integer */
+

/*
** Macro used to suppress compiler warnings for unused parameters.
*/
#define UNUSED_PARAMETER(x) (void)(x)
+

+
/*
+
** Activate assert() only if SQLITE_TEST is enabled.
+
*/
+
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
+
# define NDEBUG 1
+
#endif
+

+
/*
+
** The TESTONLY macro is used to enclose variable declarations or
+
** other bits of code that are needed to support the arguments
+
** within testcase() and assert() macros.
+
*/
+
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+
# define TESTONLY(X)  X
+
#else
+
# define TESTONLY(X)
#endif

+
#endif /* SQLITE_AMALGAMATION */
+

typedef struct Fts3Table Fts3Table;
typedef struct Fts3Cursor Fts3Cursor;
typedef struct Fts3Expr Fts3Expr;
typedef struct Fts3Phrase Fts3Phrase;
typedef struct Fts3PhraseToken Fts3PhraseToken;

+
typedef struct Fts3Doclist Fts3Doclist;
typedef struct Fts3SegFilter Fts3SegFilter;
typedef struct Fts3DeferredToken Fts3DeferredToken;
typedef struct Fts3SegReader Fts3SegReader;
-
typedef struct Fts3SegReaderCursor Fts3SegReaderCursor;
+
typedef struct Fts3MultiSegReader Fts3MultiSegReader;

/*
** A connection to a fulltext index is an instance of the following
@@ -110816,7 +111944,7 @@ struct Fts3Table {
  /* Precompiled statements used by the implementation. Each of these 
  ** statements is run and reset within a single virtual table API call. 
  */
-
  sqlite3_stmt *aStmt[24];
+
  sqlite3_stmt *aStmt[27];

  char *zReadExprlist;
  char *zWriteExprlist;
@@ -110824,21 +111952,43 @@ struct Fts3Table {
  int nNodeSize;                  /* Soft limit for node size */
  u8 bHasStat;                    /* True if %_stat table exists */
  u8 bHasDocsize;                 /* True if %_docsize table exists */
+
  u8 bDescIdx;                    /* True if doclists are in reverse order */
  int nPgsz;                      /* Page size for host database */
  char *zSegmentsTbl;             /* Name of %_segments table */
  sqlite3_blob *pSegments;        /* Blob handle open on %_segments table */

-
  /* The following hash table is used to buffer pending index updates during
+
  /* TODO: Fix the first paragraph of this comment.
+
  **
+
  ** The following hash table is used to buffer pending index updates during
  ** transactions. Variable nPendingData estimates the memory size of the 
  ** pending data, including hash table overhead, but not malloc overhead. 
  ** When nPendingData exceeds nMaxPendingData, the buffer is flushed 
  ** automatically. Variable iPrevDocid is the docid of the most recently
  ** inserted record.
+
  **
+
  ** A single FTS4 table may have multiple full-text indexes. For each index
+
  ** there is an entry in the aIndex[] array. Index 0 is an index of all the
+
  ** terms that appear in the document set. Each subsequent index in aIndex[]
+
  ** is an index of prefixes of a specific length.
+
  */
+
  int nIndex;                     /* Size of aIndex[] */
+
  struct Fts3Index {
+
    int nPrefix;                  /* Prefix length (0 for main terms index) */
+
    Fts3Hash hPending;            /* Pending terms table for this index */
+
  } *aIndex;
+
  int nMaxPendingData;            /* Max pending data before flush to disk */
+
  int nPendingData;               /* Current bytes of pending data */
+
  sqlite_int64 iPrevDocid;        /* Docid of most recently inserted document */
+

+
#if defined(SQLITE_DEBUG)
+
  /* State variables used for validating that the transaction control
+
  ** methods of the virtual table are called at appropriate times.  These
+
  ** values do not contribution to the FTS computation; they are used for
+
  ** verifying the SQLite core.
  */
-
  int nMaxPendingData;
-
  int nPendingData;
-
  sqlite_int64 iPrevDocid;
-
  Fts3Hash pendingTerms;
+
  int inTransaction;     /* True after xBegin but before xCommit/xRollback */
+
  int mxSavepoint;       /* Largest valid xSavepoint integer */
+
#endif
};

/*
@@ -110859,8 +112009,10 @@ struct Fts3Cursor {
  char *pNextId;                  /* Pointer into the body of aDoclist */
  char *aDoclist;                 /* List of docids for full-text queries */
  int nDoclist;                   /* Size of buffer at aDoclist */
+
  u8 bDesc;                       /* True to sort in descending order */
  int eEvalmode;                  /* An FTS3_EVAL_XX constant */
  int nRowAvg;                    /* Average size of database rows, in pages */
+
  sqlite3_int64 nDoc;             /* Documents in table */

  int isMatchinfoNeeded;          /* True when aMatchinfo[] needs filling in */
  u32 *aMatchinfo;                /* Information about most recent match */
@@ -110891,47 +112043,70 @@ struct Fts3Cursor {
#define FTS3_DOCID_SEARCH    1    /* Lookup by rowid on %_content table */
#define FTS3_FULLTEXT_SEARCH 2    /* Full-text index search */

+

+
struct Fts3Doclist {
+
  char *aAll;                    /* Array containing doclist (or NULL) */
+
  int nAll;                      /* Size of a[] in bytes */
+
  char *pNextDocid;              /* Pointer to next docid */
+

+
  sqlite3_int64 iDocid;          /* Current docid (if pList!=0) */
+
  int bFreeList;                 /* True if pList should be sqlite3_free()d */
+
  char *pList;                   /* Pointer to position list following iDocid */
+
  int nList;                     /* Length of position list */
+
} doclist;
+

/*
** A "phrase" is a sequence of one or more tokens that must match in
** sequence.  A single token is the base case and the most common case.
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
** nToken will be the number of tokens in the string.
-
**
-
** The nDocMatch and nMatch variables contain data that may be used by the
-
** matchinfo() function. They are populated when the full-text index is 
-
** queried for hits on the phrase. If one or more tokens in the phrase
-
** are deferred, the nDocMatch and nMatch variables are populated based
-
** on the assumption that the 
*/
struct Fts3PhraseToken {
  char *z;                        /* Text of the token */
  int n;                          /* Number of bytes in buffer z */
  int isPrefix;                   /* True if token ends with a "*" character */
-
  int bFulltext;                  /* True if full-text index was used */
-
  Fts3SegReaderCursor *pSegcsr;   /* Segment-reader for this token */
+

+
  /* Variables above this point are populated when the expression is
+
  ** parsed (by code in fts3_expr.c). Below this point the variables are
+
  ** used when evaluating the expression. */
  Fts3DeferredToken *pDeferred;   /* Deferred token object for this token */
+
  Fts3MultiSegReader *pSegcsr;    /* Segment-reader for this token */
};

struct Fts3Phrase {
-
  /* Variables populated by fts3_expr.c when parsing a MATCH expression */
+
  /* Cache of doclist for this phrase. */
+
  Fts3Doclist doclist;
+
  int bIncr;                 /* True if doclist is loaded incrementally */
+
  int iDoclistToken;
+

+
  /* Variables below this point are populated by fts3_expr.c when parsing 
+
  ** a MATCH expression. Everything above is part of the evaluation phase. 
+
  */
  int nToken;                /* Number of tokens in the phrase */
  int iColumn;               /* Index of column this phrase must match */
-
  int isNot;                 /* Phrase prefixed by unary not (-) operator */
  Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
};

/*
** A tree of these objects forms the RHS of a MATCH operator.
**
-
** If Fts3Expr.eType is either FTSQUERY_NEAR or FTSQUERY_PHRASE and isLoaded
-
** is true, then aDoclist points to a malloced buffer, size nDoclist bytes, 
-
** containing the results of the NEAR or phrase query in FTS3 doclist
-
** format. As usual, the initial "Length" field found in doclists stored
-
** on disk is omitted from this buffer.
+
** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist 
+
** points to a malloced buffer, size nDoclist bytes, containing the results 
+
** of this phrase query in FTS3 doclist format. As usual, the initial 
+
** "Length" field found in doclists stored on disk is omitted from this 
+
** buffer.
+
**
+
** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global
+
** matchinfo data. If it is not NULL, it points to an array of size nCol*3,
+
** where nCol is the number of columns in the queried FTS table. The array
+
** is populated as follows:
+
**
+
**   aMI[iCol*3 + 0] = Undefined
+
**   aMI[iCol*3 + 1] = Number of occurrences
+
**   aMI[iCol*3 + 2] = Number of rows containing at least one instance
**
-
** Variable pCurrent always points to the start of a docid field within
-
** aDoclist. Since the doclist is usually scanned in docid order, this can
-
** be used to accelerate seeking to the required docid within the doclist.
+
** The aMI array is allocated using sqlite3_malloc(). It should be freed 
+
** when the expression node is.
*/
struct Fts3Expr {
  int eType;                 /* One of the FTSQUERY_XXX values defined below */
@@ -110941,12 +112116,13 @@ struct Fts3Expr {
  Fts3Expr *pRight;          /* Right operand */
  Fts3Phrase *pPhrase;       /* Valid if eType==FTSQUERY_PHRASE */

-
  int isLoaded;              /* True if aDoclist/nDoclist are initialized. */
-
  char *aDoclist;            /* Buffer containing doclist */
-
  int nDoclist;              /* Size of aDoclist in bytes */
+
  /* The following are used by the fts3_eval.c module. */
+
  sqlite3_int64 iDocid;      /* Current docid */
+
  u8 bEof;                   /* True this expression is at EOF already */
+
  u8 bStart;                 /* True if iDocid is valid */
+
  u8 bDeferred;              /* True if this expression is entirely deferred */

-
  sqlite3_int64 iCurrent;
-
  char *pCurrent;
+
  u32 *aMI;
};

/*
@@ -110974,12 +112150,12 @@ SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
  sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
-
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**);
+
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
+
  Fts3Table*,int,const char*,int,int,Fts3SegReader**);
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
-
SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *);
-
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, sqlite3_stmt **);
+
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
-
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*);
+
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);

SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
@@ -110988,17 +112164,18 @@ SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
-
SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *);
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);

-
#define FTS3_SEGCURSOR_PENDING -1
-
#define FTS3_SEGCURSOR_ALL     -2
+
/* Special values interpreted by sqlite3SegReaderCursor() */
+
#define FTS3_SEGCURSOR_PENDING        -1
+
#define FTS3_SEGCURSOR_ALL            -2
+

+
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
+
SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
+
SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);

-
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3SegReaderCursor*, Fts3SegFilter*);
-
SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3SegReaderCursor *);
-
SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3SegReaderCursor *);
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
-
    Fts3Table *, int, const char *, int, int, int, Fts3SegReaderCursor *);
+
    Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *);

/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
#define FTS3_SEGMENT_REQUIRE_POS   0x00000001
@@ -111015,7 +112192,7 @@ struct Fts3SegFilter {
  int flags;
};

-
struct Fts3SegReaderCursor {
+
struct Fts3MultiSegReader {
  /* Used internally by sqlite3Fts3SegReaderXXX() calls */
  Fts3SegReader **apSegment;      /* Array of Fts3SegReader objects */
  int nSegment;                   /* Size of apSegment array */
@@ -111024,8 +112201,12 @@ struct Fts3SegReaderCursor {
  char *aBuffer;                  /* Buffer to merge doclists in */
  int nBuffer;                    /* Allocated size of aBuffer[] in bytes */

-
  /* Cost of running this iterator. Used by fts3.c only. */
-
  int nCost;
+
  int iColFilter;                 /* If >=0, filter for this column */
+
  int bRestart;
+

+
  /* Used by fts3.c only. */
+
  int nCost;                      /* Cost of running iterator */
+
  int bLookup;                    /* True if a lookup of a single entry. */

  /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
  char *zTerm;                    /* Pointer to term buffer */
@@ -111040,11 +112221,9 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
+
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);

-
SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int);
-
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
-
SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
-
SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
+
SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);

/* fts3_tokenizer.c */
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
@@ -111068,15 +112247,45 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
+
SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
#endif

/* fts3_aux.c */
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);

+
SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
+
  Fts3Cursor *pCsr,               /* Virtual table cursor handle */
+
  const char *zTerm,              /* Term to query for */
+
  int nTerm,                      /* Size of zTerm in bytes */
+
  int isPrefix,                   /* True for a prefix search */
+
  Fts3MultiSegReader **ppSegcsr   /* OUT: Allocated seg-reader cursor */
+
);
+

+
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
+

+
SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
+
SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
+

+
SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
+
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
+
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
+
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
+
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol); 
+
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
+
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
+

+
SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
+

+
#endif /* SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

/************** End of fts3Int.h *********************************************/
/************** Continuing where we left off in fts3.c ***********************/
+
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+

+
#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
+
# define SQLITE_CORE 1
+
#endif


#ifndef SQLITE_CORE 
@@ -111190,17 +112399,31 @@ static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
}

/*
-
** As long as *pp has not reached its end (pEnd), then do the same
-
** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
-
** But if we have reached the end of the varint, just set *pp=0 and
-
** leave *pVal unchanged.
+
** When this function is called, *pp points to the first byte following a
+
** varint that is part of a doclist (or position-list, or any other list
+
** of varints). This function moves *pp to point to the start of that varint,
+
** and sets *pVal by the varint value.
+
**
+
** Argument pStart points to the first byte of the doclist that the
+
** varint is part of.
*/
-
static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
-
  if( *pp>=pEnd ){
-
    *pp = 0;
-
  }else{
-
    fts3GetDeltaVarint(pp, pVal);
-
  }
+
static void fts3GetReverseVarint(
+
  char **pp, 
+
  char *pStart, 
+
  sqlite3_int64 *pVal
+
){
+
  sqlite3_int64 iVal;
+
  char *p = *pp;
+

+
  /* Pointer p now points at the first byte past the varint we are 
+
  ** interested in. So, unless the doclist is corrupt, the 0x80 bit is
+
  ** clear on character p[-1]. */
+
  for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
+
  p++;
+
  *pp = p;
+

+
  sqlite3Fts3GetVarint(p, &iVal);
+
  *pVal = iVal;
}

/*
@@ -111294,6 +112517,8 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){
    char *zSql;                   /* SQL statement passed to declare_vtab() */
    char *zCols;                  /* List of user defined columns */

+
    sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
+

    /* Create a list of user columns for the virtual table */
    zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
    for(i=1; zCols && i<p->nColumn; i++){
@@ -111399,6 +112624,9 @@ static void fts3DatabasePageSize(int *pRc, Fts3Table *p){
        sqlite3_step(pStmt);
        p->nPgsz = sqlite3_column_int(pStmt, 0);
        rc = sqlite3_finalize(pStmt);
+
      }else if( rc==SQLITE_AUTH ){
+
        p->nPgsz = 1024;
+
        rc = SQLITE_OK;
      }
    }
    assert( p->nPgsz>0 || rc!=SQLITE_OK );
@@ -111572,6 +112800,58 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
  return zRet;
}

+
static int fts3GobbleInt(const char **pp, int *pnOut){
+
  const char *p = *pp;
+
  int nInt = 0;
+
  for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
+
    nInt = nInt * 10 + (p[0] - '0');
+
  }
+
  if( p==*pp ) return SQLITE_ERROR;
+
  *pnOut = nInt;
+
  *pp = p;
+
  return SQLITE_OK;
+
}
+

+

+
static int fts3PrefixParameter(
+
  const char *zParam,             /* ABC in prefix=ABC parameter to parse */
+
  int *pnIndex,                   /* OUT: size of *apIndex[] array */
+
  struct Fts3Index **apIndex,     /* OUT: Array of indexes for this table */
+
  struct Fts3Index **apFree       /* OUT: Free this with sqlite3_free() */
+
){
+
  struct Fts3Index *aIndex;
+
  int nIndex = 1;
+

+
  if( zParam && zParam[0] ){
+
    const char *p;
+
    nIndex++;
+
    for(p=zParam; *p; p++){
+
      if( *p==',' ) nIndex++;
+
    }
+
  }
+

+
  aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
+
  *apIndex = *apFree = aIndex;
+
  *pnIndex = nIndex;
+
  if( !aIndex ){
+
    return SQLITE_NOMEM;
+
  }
+

+
  memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
+
  if( zParam ){
+
    const char *p = zParam;
+
    int i;
+
    for(i=1; i<nIndex; i++){
+
      int nPrefix;
+
      if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
+
      aIndex[i].nPrefix = nPrefix;
+
      p++;
+
    }
+
  }
+

+
  return SQLITE_OK;
+
}
+

/*
** This function is the implementation of both the xConnect and xCreate
** methods of the FTS3 virtual table.
@@ -111604,12 +112884,19 @@ static int fts3InitVtab(
  int nDb;                        /* Bytes required to hold database name */
  int nName;                      /* Bytes required to hold table name */
  int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
-
  int bNoDocsize = 0;             /* True to omit %_docsize table */
  const char **aCol;              /* Array of column names */
  sqlite3_tokenizer *pTokenizer = 0;        /* Tokenizer for this table */

-
  char *zCompress = 0;
-
  char *zUncompress = 0;
+
  int nIndex;                     /* Size of aIndex[] array */
+
  struct Fts3Index *aIndex;       /* Array of indexes for this table */
+
  struct Fts3Index *aFree = 0;    /* Free this before returning */
+

+
  /* The results of parsing supported FTS4 key=value options: */
+
  int bNoDocsize = 0;             /* True to omit %_docsize table */
+
  int bDescIdx = 0;               /* True to store descending indexes */
+
  char *zPrefix = 0;              /* Prefix parameter value (or NULL) */
+
  char *zCompress = 0;            /* compress=? parameter (or NULL) */
+
  char *zUncompress = 0;          /* uncompress=? parameter (or NULL) */

  assert( strlen(argv[0])==4 );
  assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
@@ -111650,28 +112937,72 @@ static int fts3InitVtab(

    /* Check if it is an FTS4 special argument. */
    else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
+
      struct Fts4Option {
+
        const char *zOpt;
+
        int nOpt;
+
        char **pzVar;
+
      } aFts4Opt[] = {
+
        { "matchinfo",   9, 0 },            /* 0 -> MATCHINFO */
+
        { "prefix",      6, 0 },            /* 1 -> PREFIX */
+
        { "compress",    8, 0 },            /* 2 -> COMPRESS */
+
        { "uncompress", 10, 0 },            /* 3 -> UNCOMPRESS */
+
        { "order",       5, 0 }             /* 4 -> ORDER */
+
      };
+

+
      int iOpt;
      if( !zVal ){
        rc = SQLITE_NOMEM;
-
        goto fts3_init_out;
-
      }
-
      if( nKey==9 && 0==sqlite3_strnicmp(z, "matchinfo", 9) ){
-
        if( strlen(zVal)==4 && 0==sqlite3_strnicmp(zVal, "fts3", 4) ){
-
          bNoDocsize = 1;
-
        }else{
-
          *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
+
      }else{
+
        for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){
+
          struct Fts4Option *pOp = &aFts4Opt[iOpt];
+
          if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){
+
            break;
+
          }
+
        }
+
        if( iOpt==SizeofArray(aFts4Opt) ){
+
          *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
          rc = SQLITE_ERROR;
+
        }else{
+
          switch( iOpt ){
+
            case 0:               /* MATCHINFO */
+
              if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
+
                *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
+
                rc = SQLITE_ERROR;
+
              }
+
              bNoDocsize = 1;
+
              break;
+

+
            case 1:               /* PREFIX */
+
              sqlite3_free(zPrefix);
+
              zPrefix = zVal;
+
              zVal = 0;
+
              break;
+

+
            case 2:               /* COMPRESS */
+
              sqlite3_free(zCompress);
+
              zCompress = zVal;
+
              zVal = 0;
+
              break;
+

+
            case 3:               /* UNCOMPRESS */
+
              sqlite3_free(zUncompress);
+
              zUncompress = zVal;
+
              zVal = 0;
+
              break;
+

+
            case 4:               /* ORDER */
+
              if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) 
+
               && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 3)) 
+
              ){
+
                *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
+
                rc = SQLITE_ERROR;
+
              }
+
              bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
+
              break;
+
          }
        }
-
      }else if( nKey==8 && 0==sqlite3_strnicmp(z, "compress", 8) ){
-
        zCompress = zVal;
-
        zVal = 0;
-
      }else if( nKey==10 && 0==sqlite3_strnicmp(z, "uncompress", 10) ){
-
        zUncompress = zVal;
-
        zVal = 0;
-
      }else{
-
        *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
-
        rc = SQLITE_ERROR;
+
        sqlite3_free(zVal);
      }
-
      sqlite3_free(zVal);
    }

    /* Otherwise, the argument is a column name. */
@@ -111695,10 +113026,17 @@ static int fts3InitVtab(
  }
  assert( pTokenizer );

+
  rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
+
  if( rc==SQLITE_ERROR ){
+
    assert( zPrefix );
+
    *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
+
  }
+
  if( rc!=SQLITE_OK ) goto fts3_init_out;

  /* Allocate and populate the Fts3Table structure. */
-
  nByte = sizeof(Fts3Table) +              /* Fts3Table */
+
  nByte = sizeof(Fts3Table) +                  /* Fts3Table */
          nCol * sizeof(char *) +              /* azColumn */
+
          nIndex * sizeof(struct Fts3Index) +  /* aIndex */
          nName +                              /* zName */
          nDb +                                /* zDb */
          nString;                             /* Space for azColumn strings */
@@ -111713,14 +113051,22 @@ static int fts3InitVtab(
  p->nPendingData = 0;
  p->azColumn = (char **)&p[1];
  p->pTokenizer = pTokenizer;
-
  p->nNodeSize = 1000;
  p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
  p->bHasDocsize = (isFts4 && bNoDocsize==0);
  p->bHasStat = isFts4;
-
  fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1);
+
  p->bDescIdx = bDescIdx;
+
  TESTONLY( p->inTransaction = -1 );
+
  TESTONLY( p->mxSavepoint = -1 );
+

+
  p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
+
  memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
+
  p->nIndex = nIndex;
+
  for(i=0; i<nIndex; i++){
+
    fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
+
  }

  /* Fill in the zName and zDb fields of the vtab structure. */
-
  zCsr = (char *)&p->azColumn[nCol];
+
  zCsr = (char *)&p->aIndex[nIndex];
  p->zName = zCsr;
  memcpy(zCsr, argv[2], nName);
  zCsr += nName;
@@ -111731,7 +113077,7 @@ static int fts3InitVtab(
  /* Fill in the azColumn array */
  for(iCol=0; iCol<nCol; iCol++){
    char *z; 
-
    int n;
+
    int n = 0;
    z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
    memcpy(zCsr, z, n);
    zCsr[n] = '\0';
@@ -111758,15 +113104,16 @@ static int fts3InitVtab(
  }

  /* Figure out the page-size for the database. This is required in order to
-
  ** estimate the cost of loading large doclists from the database (see 
-
  ** function sqlite3Fts3SegReaderCost() for details).
-
  */
+
  ** estimate the cost of loading large doclists from the database.  */
  fts3DatabasePageSize(&rc, p);
+
  p->nNodeSize = p->nPgsz-35;

  /* Declare the table schema to SQLite. */
  fts3DeclareVtab(&rc, p);

fts3_init_out:
+
  sqlite3_free(zPrefix);
+
  sqlite3_free(aFree);
  sqlite3_free(zCompress);
  sqlite3_free(zUncompress);
  sqlite3_free((void *)aCol);
@@ -111777,6 +113124,7 @@ fts3_init_out:
      pTokenizer->pModule->xDestroy(pTokenizer);
    }
  }else{
+
    assert( p->pSegments==0 );
    *ppVTab = &p->base;
  }
  return rc;
@@ -111862,6 +113210,23 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
    pInfo->aConstraintUsage[iCons].argvIndex = 1;
    pInfo->aConstraintUsage[iCons].omit = 1;
  } 
+

+
  /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
+
  ** docid) order. Both ascending and descending are possible. 
+
  */
+
  if( pInfo->nOrderBy==1 ){
+
    struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
+
    if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){
+
      if( pOrder->desc ){
+
        pInfo->idxStr = "DESC";
+
      }else{
+
        pInfo->idxStr = "ASC";
+
      }
+
      pInfo->orderByConsumed = 1;
+
    }
+
  }
+

+
  assert( p->pSegments==0 );
  return SQLITE_OK;
}

@@ -111897,6 +113262,7 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
  sqlite3Fts3FreeDeferredTokens(pCsr);
  sqlite3_free(pCsr->aDoclist);
  sqlite3_free(pCsr->aMatchinfo);
+
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  sqlite3_free(pCsr);
  return SQLITE_OK;
}
@@ -111908,8 +113274,8 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
  if( pCsr->isRequireSeek ){
-
    pCsr->isRequireSeek = 0;
    sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
+
    pCsr->isRequireSeek = 0;
    if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
      return SQLITE_OK;
    }else{
@@ -111919,7 +113285,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
        ** table is missing a row that is present in the full-text index.
        ** The data structures are corrupt.
        */
-
        rc = SQLITE_CORRUPT;
+
        rc = SQLITE_CORRUPT_VTAB;
      }
      pCsr->isEof = 1;
      if( pContext ){
@@ -111979,7 +113345,7 @@ static int fts3ScanInteriorNode(
  zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
  zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
  if( zCsr>zEnd ){
-
    return SQLITE_CORRUPT;
+
    return SQLITE_CORRUPT_VTAB;
  }
  
  while( zCsr<zEnd && (piFirst || piLast) ){
@@ -111997,7 +113363,7 @@ static int fts3ScanInteriorNode(
    zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
    
    if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
-
      rc = SQLITE_CORRUPT;
+
      rc = SQLITE_CORRUPT_VTAB;
      goto finish_scan;
    }
    if( nPrefix+nSuffix>nAlloc ){
@@ -112090,7 +113456,7 @@ static int fts3SelectLeaf(
    int nBlob;                    /* Size of zBlob in bytes */

    if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
-
      rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob);
+
      rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
      if( rc==SQLITE_OK ){
        rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
      }
@@ -112100,7 +113466,7 @@ static int fts3SelectLeaf(
    }

    if( rc==SQLITE_OK ){
-
      rc = sqlite3Fts3ReadBlock(p, piLeaf ? *piLeaf : *piLeaf2, &zBlob, &nBlob);
+
      rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
    }
    if( rc==SQLITE_OK ){
      rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
@@ -112476,7 +113842,19 @@ static int fts3PoslistPhraseMerge(
}

/*
-
** Merge two position-lists as required by the NEAR operator.
+
** Merge two position-lists as required by the NEAR operator. The argument
+
** position lists correspond to the left and right phrases of an expression 
+
** like:
+
**
+
**     "phrase 1" NEAR "phrase number 2"
+
**
+
** Position list *pp1 corresponds to the left-hand side of the NEAR 
+
** expression and *pp2 to the right. As usual, the indexes in the position 
+
** lists are the offsets of the last token in each phrase (tokens "1" and "2" 
+
** in the example above).
+
**
+
** The output position list - written to *pp - is a copy of *pp2 with those
+
** entries that are not sufficiently NEAR entries in *pp1 removed.
*/
static int fts3PoslistNearMerge(
  char **pp,                      /* Output buffer */
@@ -112489,226 +113867,181 @@ static int fts3PoslistNearMerge(
  char *p1 = *pp1;
  char *p2 = *pp2;

-
  if( !pp ){
-
    if( fts3PoslistPhraseMerge(0, nRight, 0, 0, pp1, pp2) ) return 1;
-
    *pp1 = p1;
-
    *pp2 = p2;
-
    return fts3PoslistPhraseMerge(0, nLeft, 0, 0, pp2, pp1);
+
  char *pTmp1 = aTmp;
+
  char *pTmp2;
+
  char *aTmp2;
+
  int res = 1;
+

+
  fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
+
  aTmp2 = pTmp2 = pTmp1;
+
  *pp1 = p1;
+
  *pp2 = p2;
+
  fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
+
  if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
+
    fts3PoslistMerge(pp, &aTmp, &aTmp2);
+
  }else if( pTmp1!=aTmp ){
+
    fts3PoslistCopy(pp, &aTmp);
+
  }else if( pTmp2!=aTmp2 ){
+
    fts3PoslistCopy(pp, &aTmp2);
+
  }else{
+
    res = 0;
+
  }
+

+
  return res;
+
}
+

+
/* 
+
** A pointer to an instance of this structure is used as the context 
+
** argument to sqlite3Fts3SegReaderIterate()
+
*/
+
typedef struct TermSelect TermSelect;
+
struct TermSelect {
+
  int isReqPos;
+
  char *aaOutput[16];             /* Malloc'd output buffer */
+
  int anOutput[16];               /* Size of output in bytes */
+
};
+

+

+
static void fts3GetDeltaVarint3(
+
  char **pp, 
+
  char *pEnd, 
+
  int bDescIdx,
+
  sqlite3_int64 *pVal
+
){
+
  if( *pp>=pEnd ){
+
    *pp = 0;
  }else{
-
    char *pTmp1 = aTmp;
-
    char *pTmp2;
-
    char *aTmp2;
-
    int res = 1;
-

-
    fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
-
    aTmp2 = pTmp2 = pTmp1;
-
    *pp1 = p1;
-
    *pp2 = p2;
-
    fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
-
    if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
-
      fts3PoslistMerge(pp, &aTmp, &aTmp2);
-
    }else if( pTmp1!=aTmp ){
-
      fts3PoslistCopy(pp, &aTmp);
-
    }else if( pTmp2!=aTmp2 ){
-
      fts3PoslistCopy(pp, &aTmp2);
+
    sqlite3_int64 iVal;
+
    *pp += sqlite3Fts3GetVarint(*pp, &iVal);
+
    if( bDescIdx ){
+
      *pVal -= iVal;
    }else{
-
      res = 0;
+
      *pVal += iVal;
    }
+
  }
+
}

-
    return res;
+
static void fts3PutDeltaVarint3(
+
  char **pp,                      /* IN/OUT: Output pointer */
+
  int bDescIdx,                   /* True for descending docids */
+
  sqlite3_int64 *piPrev,          /* IN/OUT: Previous value written to list */
+
  int *pbFirst,                   /* IN/OUT: True after first int written */
+
  sqlite3_int64 iVal              /* Write this value to the list */
+
){
+
  sqlite3_int64 iWrite;
+
  if( bDescIdx==0 || *pbFirst==0 ){
+
    iWrite = iVal - *piPrev;
+
  }else{
+
    iWrite = *piPrev - iVal;
  }
+
  assert( *pbFirst || *piPrev==0 );
+
  assert( *pbFirst==0 || iWrite>0 );
+
  *pp += sqlite3Fts3PutVarint(*pp, iWrite);
+
  *piPrev = iVal;
+
  *pbFirst = 1;
}

-
/*
-
** Values that may be used as the first parameter to fts3DoclistMerge().
-
*/
-
#define MERGE_NOT        2        /* D + D -> D */
-
#define MERGE_AND        3        /* D + D -> D */
-
#define MERGE_OR         4        /* D + D -> D */
-
#define MERGE_POS_OR     5        /* P + P -> P */
-
#define MERGE_PHRASE     6        /* P + P -> D */
-
#define MERGE_POS_PHRASE 7        /* P + P -> P */
-
#define MERGE_NEAR       8        /* P + P -> D */
-
#define MERGE_POS_NEAR   9        /* P + P -> P */
+
#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))

-
/*
-
** Merge the two doclists passed in buffer a1 (size n1 bytes) and a2
-
** (size n2 bytes). The output is written to pre-allocated buffer aBuffer,
-
** which is guaranteed to be large enough to hold the results. The number
-
** of bytes written to aBuffer is stored in *pnBuffer before returning.
-
**
-
** If successful, SQLITE_OK is returned. Otherwise, if a malloc error
-
** occurs while allocating a temporary buffer as part of the merge operation,
-
** SQLITE_NOMEM is returned.
-
*/
-
static int fts3DoclistMerge(
-
  int mergetype,                  /* One of the MERGE_XXX constants */
-
  int nParam1,                    /* Used by MERGE_NEAR and MERGE_POS_NEAR */
-
  int nParam2,                    /* Used by MERGE_NEAR and MERGE_POS_NEAR */
-
  char *aBuffer,                  /* Pre-allocated output buffer */
-
  int *pnBuffer,                  /* OUT: Bytes written to aBuffer */
-
  char *a1,                       /* Buffer containing first doclist */
-
  int n1,                         /* Size of buffer a1 */
-
  char *a2,                       /* Buffer containing second doclist */
-
  int n2,                         /* Size of buffer a2 */
-
  int *pnDoc                      /* OUT: Number of docids in output */
+
static int fts3DoclistOrMerge(
+
  int bDescIdx,                   /* True if arguments are desc */
+
  char *a1, int n1,               /* First doclist */
+
  char *a2, int n2,               /* Second doclist */
+
  char **paOut, int *pnOut        /* OUT: Malloc'd doclist */
){
  sqlite3_int64 i1 = 0;
  sqlite3_int64 i2 = 0;
  sqlite3_int64 iPrev = 0;
-

-
  char *p = aBuffer;
-
  char *p1 = a1;
-
  char *p2 = a2;
  char *pEnd1 = &a1[n1];
  char *pEnd2 = &a2[n2];
-
  int nDoc = 0;
-

-
  assert( mergetype==MERGE_OR     || mergetype==MERGE_POS_OR 
-
       || mergetype==MERGE_AND    || mergetype==MERGE_NOT
-
       || mergetype==MERGE_PHRASE || mergetype==MERGE_POS_PHRASE
-
       || mergetype==MERGE_NEAR   || mergetype==MERGE_POS_NEAR
-
  );
-

-
  if( !aBuffer ){
-
    *pnBuffer = 0;
-
    return SQLITE_NOMEM;
-
  }
-

-
  /* Read the first docid from each doclist */
-
  fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
  fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-

-
  switch( mergetype ){
-
    case MERGE_OR:
-
    case MERGE_POS_OR:
-
      while( p1 || p2 ){
-
        if( p2 && p1 && i1==i2 ){
-
          fts3PutDeltaVarint(&p, &iPrev, i1);
-
          if( mergetype==MERGE_POS_OR ) fts3PoslistMerge(&p, &p1, &p2);
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }else if( !p2 || (p1 && i1<i2) ){
-
          fts3PutDeltaVarint(&p, &iPrev, i1);
-
          if( mergetype==MERGE_POS_OR ) fts3PoslistCopy(&p, &p1);
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
        }else{
-
          fts3PutDeltaVarint(&p, &iPrev, i2);
-
          if( mergetype==MERGE_POS_OR ) fts3PoslistCopy(&p, &p2);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }
-
      }
-
      break;
-

-
    case MERGE_AND:
-
      while( p1 && p2 ){
-
        if( i1==i2 ){
-
          fts3PutDeltaVarint(&p, &iPrev, i1);
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
          nDoc++;
-
        }else if( i1<i2 ){
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
        }else{
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }
-
      }
-
      break;
-

-
    case MERGE_NOT:
-
      while( p1 ){
-
        if( p2 && i1==i2 ){
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }else if( !p2 || i1<i2 ){
-
          fts3PutDeltaVarint(&p, &iPrev, i1);
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
        }else{
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }
-
      }
-
      break;
+
  char *p1 = a1;
+
  char *p2 = a2;
+
  char *p;
+
  char *aOut;
+
  int bFirstOut = 0;

-
    case MERGE_POS_PHRASE:
-
    case MERGE_PHRASE: {
-
      char **ppPos = (mergetype==MERGE_PHRASE ? 0 : &p);
-
      while( p1 && p2 ){
-
        if( i1==i2 ){
-
          char *pSave = p;
-
          sqlite3_int64 iPrevSave = iPrev;
-
          fts3PutDeltaVarint(&p, &iPrev, i1);
-
          if( 0==fts3PoslistPhraseMerge(ppPos, nParam1, 0, 1, &p1, &p2) ){
-
            p = pSave;
-
            iPrev = iPrevSave;
-
          }else{
-
            nDoc++;
-
          }
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }else if( i1<i2 ){
-
          fts3PoslistCopy(0, &p1);
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
        }else{
-
          fts3PoslistCopy(0, &p2);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }
-
      }
-
      break;
+
  *paOut = 0;
+
  *pnOut = 0;
+
  aOut = sqlite3_malloc(n1+n2);
+
  if( !aOut ) return SQLITE_NOMEM;
+

+
  p = aOut;
+
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
+
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
+
  while( p1 || p2 ){
+
    sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
+

+
    if( p2 && p1 && iDiff==0 ){
+
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+
      fts3PoslistMerge(&p, &p1, &p2);
+
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+
    }else if( !p2 || (p1 && iDiff<0) ){
+
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+
      fts3PoslistCopy(&p, &p1);
+
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+
    }else{
+
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
+
      fts3PoslistCopy(&p, &p2);
+
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
    }
+
  }

-
    default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); {
-
      char *aTmp = 0;
-
      char **ppPos = 0;
-

-
      if( mergetype==MERGE_POS_NEAR ){
-
        ppPos = &p;
-
        aTmp = sqlite3_malloc(2*(n1+n2+1));
-
        if( !aTmp ){
-
          return SQLITE_NOMEM;
-
        }
-
      }
-

-
      while( p1 && p2 ){
-
        if( i1==i2 ){
-
          char *pSave = p;
-
          sqlite3_int64 iPrevSave = iPrev;
-
          fts3PutDeltaVarint(&p, &iPrev, i1);
+
  *paOut = aOut;
+
  *pnOut = (p-aOut);
+
  return SQLITE_OK;
+
}

-
          if( !fts3PoslistNearMerge(ppPos, aTmp, nParam1, nParam2, &p1, &p2) ){
-
            iPrev = iPrevSave;
-
            p = pSave;
-
          }
+
static void fts3DoclistPhraseMerge(
+
  int bDescIdx,                   /* True if arguments are desc */
+
  int nDist,                      /* Distance from left to right (1=adjacent) */
+
  char *aLeft, int nLeft,         /* Left doclist */
+
  char *aRight, int *pnRight      /* IN/OUT: Right/output doclist */
+
){
+
  sqlite3_int64 i1 = 0;
+
  sqlite3_int64 i2 = 0;
+
  sqlite3_int64 iPrev = 0;
+
  char *pEnd1 = &aLeft[nLeft];
+
  char *pEnd2 = &aRight[*pnRight];
+
  char *p1 = aLeft;
+
  char *p2 = aRight;
+
  char *p;
+
  int bFirstOut = 0;
+
  char *aOut = aRight;
+

+
  assert( nDist>0 );
+

+
  p = aOut;
+
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
+
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
+

+
  while( p1 && p2 ){
+
    sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
+
    if( iDiff==0 ){
+
      char *pSave = p;
+
      sqlite3_int64 iPrevSave = iPrev;
+
      int bFirstOutSave = bFirstOut;

-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }else if( i1<i2 ){
-
          fts3PoslistCopy(0, &p1);
-
          fts3GetDeltaVarint2(&p1, pEnd1, &i1);
-
        }else{
-
          fts3PoslistCopy(0, &p2);
-
          fts3GetDeltaVarint2(&p2, pEnd2, &i2);
-
        }
-
      }
-
      sqlite3_free(aTmp);
-
      break;
+
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+
      if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
+
        p = pSave;
+
        iPrev = iPrevSave;
+
        bFirstOut = bFirstOutSave;
+
      }
+
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+
    }else if( iDiff<0 ){
+
      fts3PoslistCopy(0, &p1);
+
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+
    }else{
+
      fts3PoslistCopy(0, &p2);
+
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
    }
  }

-
  if( pnDoc ) *pnDoc = nDoc;
-
  *pnBuffer = (int)(p-aBuffer);
-
  return SQLITE_OK;
+
  *pnRight = p - aOut;
}

-
/* 
-
** A pointer to an instance of this structure is used as the context 
-
** argument to sqlite3Fts3SegReaderIterate()
-
*/
-
typedef struct TermSelect TermSelect;
-
struct TermSelect {
-
  int isReqPos;
-
  char *aaOutput[16];             /* Malloc'd output buffer */
-
  int anOutput[16];               /* Size of output in bytes */
-
};

/*
** Merge all doclists in the TermSelect.aaOutput[] array into a single
@@ -112719,8 +114052,7 @@ struct TermSelect {
** the responsibility of the caller to free any doclists left in the
** TermSelect.aaOutput[] array.
*/
-
static int fts3TermSelectMerge(TermSelect *pTS){
-
  int mergetype = (pTS->isReqPos ? MERGE_POS_OR : MERGE_OR);
+
static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
  char *aOut = 0;
  int nOut = 0;
  int i;
@@ -112735,15 +114067,17 @@ static int fts3TermSelectMerge(TermSelect *pTS){
        nOut = pTS->anOutput[i];
        pTS->aaOutput[i] = 0;
      }else{
-
        int nNew = nOut + pTS->anOutput[i];
-
        char *aNew = sqlite3_malloc(nNew);
-
        if( !aNew ){
+
        int nNew;
+
        char *aNew;
+

+
        int rc = fts3DoclistOrMerge(p->bDescIdx, 
+
            pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
+
        );
+
        if( rc!=SQLITE_OK ){
          sqlite3_free(aOut);
-
          return SQLITE_NOMEM;
+
          return rc;
        }
-
        fts3DoclistMerge(mergetype, 0, 0,
-
            aNew, &nNew, pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, 0
-
        );
+

        sqlite3_free(pTS->aaOutput[i]);
        sqlite3_free(aOut);
        pTS->aaOutput[i] = 0;
@@ -112779,9 +114113,7 @@ static int fts3TermSelectCb(

  if( pTS->aaOutput[0]==0 ){
    /* If this is the first term selected, copy the doclist to the output
-
    ** buffer using memcpy(). TODO: Add a way to transfer control of the
-
    ** aDoclist buffer from the caller so as to avoid the memcpy().
-
    */
+
    ** buffer using memcpy(). */
    pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
    pTS->anOutput[0] = nDoclist;
    if( pTS->aaOutput[0] ){
@@ -112790,126 +114122,100 @@ static int fts3TermSelectCb(
      return SQLITE_NOMEM;
    }
  }else{
-
    int mergetype = (pTS->isReqPos ? MERGE_POS_OR : MERGE_OR);
    char *aMerge = aDoclist;
    int nMerge = nDoclist;
    int iOut;

    for(iOut=0; iOut<SizeofArray(pTS->aaOutput); iOut++){
-
      char *aNew;
-
      int nNew;
      if( pTS->aaOutput[iOut]==0 ){
        assert( iOut>0 );
        pTS->aaOutput[iOut] = aMerge;
        pTS->anOutput[iOut] = nMerge;
        break;
-
      }
+
      }else{
+
        char *aNew;
+
        int nNew;

-
      nNew = nMerge + pTS->anOutput[iOut];
-
      aNew = sqlite3_malloc(nNew);
-
      if( !aNew ){
-
        if( aMerge!=aDoclist ){
-
          sqlite3_free(aMerge);
+
        int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge, 
+
            pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
+
        );
+
        if( rc!=SQLITE_OK ){
+
          if( aMerge!=aDoclist ) sqlite3_free(aMerge);
+
          return rc;
        }
-
        return SQLITE_NOMEM;
-
      }
-
      fts3DoclistMerge(mergetype, 0, 0, aNew, &nNew, 
-
          pTS->aaOutput[iOut], pTS->anOutput[iOut], aMerge, nMerge, 0
-
      );

-
      if( iOut>0 ) sqlite3_free(aMerge);
-
      sqlite3_free(pTS->aaOutput[iOut]);
-
      pTS->aaOutput[iOut] = 0;
-

-
      aMerge = aNew;
-
      nMerge = nNew;
-
      if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
-
        pTS->aaOutput[iOut] = aMerge;
-
        pTS->anOutput[iOut] = nMerge;
+
        if( aMerge!=aDoclist ) sqlite3_free(aMerge);
+
        sqlite3_free(pTS->aaOutput[iOut]);
+
        pTS->aaOutput[iOut] = 0;
+
  
+
        aMerge = aNew;
+
        nMerge = nNew;
+
        if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
+
          pTS->aaOutput[iOut] = aMerge;
+
          pTS->anOutput[iOut] = nMerge;
+
        }
      }
    }
  }
  return SQLITE_OK;
}

-
static int fts3DeferredTermSelect(
-
  Fts3DeferredToken *pToken,      /* Phrase token */
-
  int isTermPos,                  /* True to include positions */
-
  int *pnOut,                     /* OUT: Size of list */
-
  char **ppOut                    /* OUT: Body of list */
-
){
-
  char *aSource;
-
  int nSource;
-

-
  aSource = sqlite3Fts3DeferredDoclist(pToken, &nSource);
-
  if( !aSource ){
-
    *pnOut = 0;
-
    *ppOut = 0;
-
  }else if( isTermPos ){
-
    *ppOut = sqlite3_malloc(nSource);
-
    if( !*ppOut ) return SQLITE_NOMEM;
-
    memcpy(*ppOut, aSource, nSource);
-
    *pnOut = nSource;
-
  }else{
-
    sqlite3_int64 docid;
-
    *pnOut = sqlite3Fts3GetVarint(aSource, &docid);
-
    *ppOut = sqlite3_malloc(*pnOut);
-
    if( !*ppOut ) return SQLITE_NOMEM;
-
    sqlite3Fts3PutVarint(*ppOut, docid);
+
/*
+
** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
+
*/
+
static int fts3SegReaderCursorAppend(
+
  Fts3MultiSegReader *pCsr, 
+
  Fts3SegReader *pNew
+
){
+
  if( (pCsr->nSegment%16)==0 ){
+
    Fts3SegReader **apNew;
+
    int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
+
    apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
+
    if( !apNew ){
+
      sqlite3Fts3SegReaderFree(pNew);
+
      return SQLITE_NOMEM;
+
    }
+
    pCsr->apSegment = apNew;
  }
-

+
  pCsr->apSegment[pCsr->nSegment++] = pNew;
  return SQLITE_OK;
}

-
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
+
static int fts3SegReaderCursor(
  Fts3Table *p,                   /* FTS3 table handle */
+
  int iIndex,                     /* Index to search (from 0 to p->nIndex-1) */
  int iLevel,                     /* Level of segments to scan */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
  int isScan,                     /* True to scan from zTerm to EOF */
-
  Fts3SegReaderCursor *pCsr       /* Cursor object to populate */
+
  Fts3MultiSegReader *pCsr       /* Cursor object to populate */
){
  int rc = SQLITE_OK;
  int rc2;
-
  int iAge = 0;
  sqlite3_stmt *pStmt = 0;
-
  Fts3SegReader *pPending = 0;
-

-
  assert( iLevel==FTS3_SEGCURSOR_ALL 
-
      ||  iLevel==FTS3_SEGCURSOR_PENDING 
-
      ||  iLevel>=0
-
  );
-
  assert( FTS3_SEGCURSOR_PENDING<0 );
-
  assert( FTS3_SEGCURSOR_ALL<0 );
-
  assert( iLevel==FTS3_SEGCURSOR_ALL || (zTerm==0 && isPrefix==1) );
-
  assert( isPrefix==0 || isScan==0 );
-

-

-
  memset(pCsr, 0, sizeof(Fts3SegReaderCursor));

-
  /* If iLevel is less than 0, include a seg-reader for the pending-terms. */
-
  assert( isScan==0 || fts3HashCount(&p->pendingTerms)==0 );
-
  if( iLevel<0 && isScan==0 ){
-
    rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &pPending);
-
    if( rc==SQLITE_OK && pPending ){
-
      int nByte = (sizeof(Fts3SegReader *) * 16);
-
      pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
-
      if( pCsr->apSegment==0 ){
-
        rc = SQLITE_NOMEM;
-
      }else{
-
        pCsr->apSegment[0] = pPending;
-
        pCsr->nSegment = 1;
-
        pPending = 0;
-
      }
+
  /* If iLevel is less than 0 and this is not a scan, include a seg-reader 
+
  ** for the pending-terms. If this is a scan, then this call must be being
+
  ** made by an fts4aux module, not an FTS table. In this case calling
+
  ** Fts3SegReaderPending might segfault, as the data structures used by 
+
  ** fts4aux are not completely populated. So it's easiest to filter these
+
  ** calls out here.  */
+
  if( iLevel<0 && p->aIndex ){
+
    Fts3SegReader *pSeg = 0;
+
    rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
+
    if( rc==SQLITE_OK && pSeg ){
+
      rc = fts3SegReaderCursorAppend(pCsr, pSeg);
    }
  }

  if( iLevel!=FTS3_SEGCURSOR_PENDING ){
    if( rc==SQLITE_OK ){
-
      rc = sqlite3Fts3AllSegdirs(p, iLevel, &pStmt);
+
      rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt);
    }
+

    while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
+
      Fts3SegReader *pSeg = 0;

      /* Read the values returned by the SELECT into local variables. */
      sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
@@ -112918,18 +114224,6 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
      int nRoot = sqlite3_column_bytes(pStmt, 4);
      char const *zRoot = sqlite3_column_blob(pStmt, 4);

-
      /* If nSegment is a multiple of 16 the array needs to be extended. */
-
      if( (pCsr->nSegment%16)==0 ){
-
        Fts3SegReader **apNew;
-
        int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
-
        apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
-
        if( !apNew ){
-
          rc = SQLITE_NOMEM;
-
          goto finished;
-
        }
-
        pCsr->apSegment = apNew;
-
      }
-

      /* If zTerm is not NULL, and this segment is not stored entirely on its
      ** root node, the range of leaves scanned can be reduced. Do this. */
      if( iStartBlock && zTerm ){
@@ -112939,53 +114233,117 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
        if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
      }
 
-
      rc = sqlite3Fts3SegReaderNew(iAge, iStartBlock, iLeavesEndBlock,
-
          iEndBlock, zRoot, nRoot, &pCsr->apSegment[pCsr->nSegment]
+
      rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, 
+
          iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg
      );
      if( rc!=SQLITE_OK ) goto finished;
-
      pCsr->nSegment++;
-
      iAge++;
+
      rc = fts3SegReaderCursorAppend(pCsr, pSeg);
    }
  }

 finished:
  rc2 = sqlite3_reset(pStmt);
  if( rc==SQLITE_DONE ) rc = rc2;
-
  sqlite3Fts3SegReaderFree(pPending);

  return rc;
}

+
/*
+
** Set up a cursor object for iterating through a full-text index or a 
+
** single level therein.
+
*/
+
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
+
  Fts3Table *p,                   /* FTS3 table handle */
+
  int iIndex,                     /* Index to search (from 0 to p->nIndex-1) */
+
  int iLevel,                     /* Level of segments to scan */
+
  const char *zTerm,              /* Term to query for */
+
  int nTerm,                      /* Size of zTerm in bytes */
+
  int isPrefix,                   /* True for a prefix search */
+
  int isScan,                     /* True to scan from zTerm to EOF */
+
  Fts3MultiSegReader *pCsr       /* Cursor object to populate */
+
){
+
  assert( iIndex>=0 && iIndex<p->nIndex );
+
  assert( iLevel==FTS3_SEGCURSOR_ALL
+
      ||  iLevel==FTS3_SEGCURSOR_PENDING 
+
      ||  iLevel>=0
+
  );
+
  assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
+
  assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
+
  assert( isPrefix==0 || isScan==0 );
+

+
  /* "isScan" is only set to true by the ft4aux module, an ordinary
+
  ** full-text tables. */
+
  assert( isScan==0 || p->aIndex==0 );
+

+
  memset(pCsr, 0, sizeof(Fts3MultiSegReader));
+

+
  return fts3SegReaderCursor(
+
      p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
+
  );
+
}
+

+
static int fts3SegReaderCursorAddZero(
+
  Fts3Table *p,
+
  const char *zTerm,
+
  int nTerm,
+
  Fts3MultiSegReader *pCsr
+
){
+
  return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
+
}
+


-
static int fts3TermSegReaderCursor(
+
SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
  Fts3Cursor *pCsr,               /* Virtual table cursor handle */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
-
  Fts3SegReaderCursor **ppSegcsr  /* OUT: Allocated seg-reader cursor */
+
  Fts3MultiSegReader **ppSegcsr   /* OUT: Allocated seg-reader cursor */
){
-
  Fts3SegReaderCursor *pSegcsr;   /* Object to allocate and return */
+
  Fts3MultiSegReader *pSegcsr;   /* Object to allocate and return */
  int rc = SQLITE_NOMEM;          /* Return code */

-
  pSegcsr = sqlite3_malloc(sizeof(Fts3SegReaderCursor));
+
  pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
  if( pSegcsr ){
-
    Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
    int i;
-
    int nCost = 0;
-
    rc = sqlite3Fts3SegReaderCursor(
-
        p, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr);
-
  
-
    for(i=0; rc==SQLITE_OK && i<pSegcsr->nSegment; i++){
-
      rc = sqlite3Fts3SegReaderCost(pCsr, pSegcsr->apSegment[i], &nCost);
+
    int bFound = 0;               /* True once an index has been found */
+
    Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
+

+
    if( isPrefix ){
+
      for(i=1; bFound==0 && i<p->nIndex; i++){
+
        if( p->aIndex[i].nPrefix==nTerm ){
+
          bFound = 1;
+
          rc = sqlite3Fts3SegReaderCursor(
+
              p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr);
+
          pSegcsr->bLookup = 1;
+
        }
+
      }
+

+
      for(i=1; bFound==0 && i<p->nIndex; i++){
+
        if( p->aIndex[i].nPrefix==nTerm+1 ){
+
          bFound = 1;
+
          rc = sqlite3Fts3SegReaderCursor(
+
              p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
+
          );
+
          if( rc==SQLITE_OK ){
+
            rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr);
+
          }
+
        }
+
      }
+
    }
+

+
    if( bFound==0 ){
+
      rc = sqlite3Fts3SegReaderCursor(
+
          p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
+
      );
+
      pSegcsr->bLookup = !isPrefix;
    }
-
    pSegcsr->nCost = nCost;
  }

  *ppSegcsr = pSegcsr;
  return rc;
}

-
static void fts3SegReaderCursorFree(Fts3SegReaderCursor *pSegcsr){
+
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
  sqlite3Fts3SegReaderFinish(pSegcsr);
  sqlite3_free(pSegcsr);
}
@@ -113010,7 +114368,7 @@ static int fts3TermSelect(
  char **ppOut                    /* OUT: Malloced result buffer */
){
  int rc;                         /* Return code */
-
  Fts3SegReaderCursor *pSegcsr;   /* Seg-reader cursor for this term */
+
  Fts3MultiSegReader *pSegcsr;   /* Seg-reader cursor for this term */
  TermSelect tsc;                 /* Context object for fts3TermSelectCb() */
  Fts3SegFilter filter;           /* Segment term filter configuration */

@@ -113036,7 +114394,7 @@ static int fts3TermSelect(
  }

  if( rc==SQLITE_OK ){
-
    rc = fts3TermSelectMerge(&tsc);
+
    rc = fts3TermSelectMerge(p, &tsc);
  }
  if( rc==SQLITE_OK ){
    *ppOut = tsc.aaOutput[0];
@@ -113087,660 +114445,6 @@ static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
}

/*
-
** Call sqlite3Fts3DeferToken() for each token in the expression pExpr.
-
*/
-
static int fts3DeferExpression(Fts3Cursor *pCsr, Fts3Expr *pExpr){
-
  int rc = SQLITE_OK;
-
  if( pExpr ){
-
    rc = fts3DeferExpression(pCsr, pExpr->pLeft);
-
    if( rc==SQLITE_OK ){
-
      rc = fts3DeferExpression(pCsr, pExpr->pRight);
-
    }
-
    if( pExpr->eType==FTSQUERY_PHRASE ){
-
      int iCol = pExpr->pPhrase->iColumn;
-
      int i;
-
      for(i=0; rc==SQLITE_OK && i<pExpr->pPhrase->nToken; i++){
-
        Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
-
        if( pToken->pDeferred==0 ){
-
          rc = sqlite3Fts3DeferToken(pCsr, pToken, iCol);
-
        }
-
      }
-
    }
-
  }
-
  return rc;
-
}
-

-
/*
-
** This function removes the position information from a doclist. When
-
** called, buffer aList (size *pnList bytes) contains a doclist that includes
-
** position information. This function removes the position information so
-
** that aList contains only docids, and adjusts *pnList to reflect the new
-
** (possibly reduced) size of the doclist.
-
*/
-
static void fts3DoclistStripPositions(
-
  char *aList,                    /* IN/OUT: Buffer containing doclist */
-
  int *pnList                     /* IN/OUT: Size of doclist in bytes */
-
){
-
  if( aList ){
-
    char *aEnd = &aList[*pnList]; /* Pointer to one byte after EOF */
-
    char *p = aList;              /* Input cursor */
-
    char *pOut = aList;           /* Output cursor */
-
  
-
    while( p<aEnd ){
-
      sqlite3_int64 delta;
-
      p += sqlite3Fts3GetVarint(p, &delta);
-
      fts3PoslistCopy(0, &p);
-
      pOut += sqlite3Fts3PutVarint(pOut, delta);
-
    }
-

-
    *pnList = (int)(pOut - aList);
-
  }
-
}
-

-
/* 
-
** Return a DocList corresponding to the phrase *pPhrase.
-
**
-
** If this function returns SQLITE_OK, but *pnOut is set to a negative value,
-
** then no tokens in the phrase were looked up in the full-text index. This
-
** is only possible when this function is called from within xFilter(). The
-
** caller should assume that all documents match the phrase. The actual
-
** filtering will take place in xNext().
-
*/
-
static int fts3PhraseSelect(
-
  Fts3Cursor *pCsr,               /* Virtual table cursor handle */
-
  Fts3Phrase *pPhrase,            /* Phrase to return a doclist for */
-
  int isReqPos,                   /* True if output should contain positions */
-
  char **paOut,                   /* OUT: Pointer to malloc'd result buffer */
-
  int *pnOut                      /* OUT: Size of buffer at *paOut */
-
){
-
  char *pOut = 0;
-
  int nOut = 0;
-
  int rc = SQLITE_OK;
-
  int ii;
-
  int iCol = pPhrase->iColumn;
-
  int isTermPos = (pPhrase->nToken>1 || isReqPos);
-
  Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
-
  int isFirst = 1;
-

-
  int iPrevTok = 0;
-
  int nDoc = 0;
-

-
  /* If this is an xFilter() evaluation, create a segment-reader for each
-
  ** phrase token. Or, if this is an xNext() or snippet/offsets/matchinfo
-
  ** evaluation, only create segment-readers if there are no Fts3DeferredToken
-
  ** objects attached to the phrase-tokens.
-
  */
-
  for(ii=0; ii<pPhrase->nToken; ii++){
-
    Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
-
    if( pTok->pSegcsr==0 ){
-
      if( (pCsr->eEvalmode==FTS3_EVAL_FILTER)
-
       || (pCsr->eEvalmode==FTS3_EVAL_NEXT && pCsr->pDeferred==0) 
-
       || (pCsr->eEvalmode==FTS3_EVAL_MATCHINFO && pTok->bFulltext) 
-
      ){
-
        rc = fts3TermSegReaderCursor(
-
            pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr
-
        );
-
        if( rc!=SQLITE_OK ) return rc;
-
      }
-
    }
-
  }
-

-
  for(ii=0; ii<pPhrase->nToken; ii++){
-
    Fts3PhraseToken *pTok;        /* Token to find doclist for */
-
    int iTok = 0;                 /* The token being queried this iteration */
-
    char *pList = 0;              /* Pointer to token doclist */
-
    int nList = 0;                /* Size of buffer at pList */
-

-
    /* Select a token to process. If this is an xFilter() call, then tokens 
-
    ** are processed in order from least to most costly. Otherwise, tokens 
-
    ** are processed in the order in which they occur in the phrase.
-
    */
-
    if( pCsr->eEvalmode==FTS3_EVAL_MATCHINFO ){
-
      assert( isReqPos );
-
      iTok = ii;
-
      pTok = &pPhrase->aToken[iTok];
-
      if( pTok->bFulltext==0 ) continue;
-
    }else if( pCsr->eEvalmode==FTS3_EVAL_NEXT || isReqPos ){
-
      iTok = ii;
-
      pTok = &pPhrase->aToken[iTok];
-
    }else{
-
      int nMinCost = 0x7FFFFFFF;
-
      int jj;
-

-
      /* Find the remaining token with the lowest cost. */
-
      for(jj=0; jj<pPhrase->nToken; jj++){
-
        Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[jj].pSegcsr;
-
        if( pSegcsr && pSegcsr->nCost<nMinCost ){
-
          iTok = jj;
-
          nMinCost = pSegcsr->nCost;
-
        }
-
      }
-
      pTok = &pPhrase->aToken[iTok];
-

-
      /* This branch is taken if it is determined that loading the doclist
-
      ** for the next token would require more IO than loading all documents
-
      ** currently identified by doclist pOut/nOut. No further doclists will
-
      ** be loaded from the full-text index for this phrase.
-
      */
-
      if( nMinCost>nDoc && ii>0 ){
-
        rc = fts3DeferExpression(pCsr, pCsr->pExpr);
-
        break;
-
      }
-
    }
-

-
    if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){
-
      rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList);
-
    }else{
-
      if( pTok->pSegcsr ){
-
        rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList);
-
      }
-
      pTok->bFulltext = 1;
-
    }
-
    assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pSegcsr==0 );
-
    if( rc!=SQLITE_OK ) break;
-

-
    if( isFirst ){
-
      pOut = pList;
-
      nOut = nList;
-
      if( pCsr->eEvalmode==FTS3_EVAL_FILTER && pPhrase->nToken>1 ){
-
        nDoc = fts3DoclistCountDocids(1, pOut, nOut);
-
      }
-
      isFirst = 0;
-
      iPrevTok = iTok;
-
    }else{
-
      /* Merge the new term list and the current output. */
-
      char *aLeft, *aRight;
-
      int nLeft, nRight;
-
      int nDist;
-
      int mt;
-

-
      /* If this is the final token of the phrase, and positions were not
-
      ** requested by the caller, use MERGE_PHRASE instead of POS_PHRASE.
-
      ** This drops the position information from the output list.
-
      */
-
      mt = MERGE_POS_PHRASE;
-
      if( ii==pPhrase->nToken-1 && !isReqPos ) mt = MERGE_PHRASE;
-

-
      assert( iPrevTok!=iTok );
-
      if( iPrevTok<iTok ){
-
        aLeft = pOut;
-
        nLeft = nOut;
-
        aRight = pList;
-
        nRight = nList;
-
        nDist = iTok-iPrevTok;
-
        iPrevTok = iTok;
-
      }else{
-
        aRight = pOut;
-
        nRight = nOut;
-
        aLeft = pList;
-
        nLeft = nList;
-
        nDist = iPrevTok-iTok;
-
      }
-
      pOut = aRight;
-
      fts3DoclistMerge(
-
          mt, nDist, 0, pOut, &nOut, aLeft, nLeft, aRight, nRight, &nDoc
-
      );
-
      sqlite3_free(aLeft);
-
    }
-
    assert( nOut==0 || pOut!=0 );
-
  }
-

-
  if( rc==SQLITE_OK ){
-
    if( ii!=pPhrase->nToken ){
-
      assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
-
      fts3DoclistStripPositions(pOut, &nOut);
-
    }
-
    *paOut = pOut;
-
    *pnOut = nOut;
-
  }else{
-
    sqlite3_free(pOut);
-
  }
-
  return rc;
-
}
-

-
/*
-
** This function merges two doclists according to the requirements of a
-
** NEAR operator.
-
**
-
** Both input doclists must include position information. The output doclist 
-
** includes position information if the first argument to this function
-
** is MERGE_POS_NEAR, or does not if it is MERGE_NEAR.
-
*/
-
static int fts3NearMerge(
-
  int mergetype,                  /* MERGE_POS_NEAR or MERGE_NEAR */
-
  int nNear,                      /* Parameter to NEAR operator */
-
  int nTokenLeft,                 /* Number of tokens in LHS phrase arg */
-
  char *aLeft,                    /* Doclist for LHS (incl. positions) */
-
  int nLeft,                      /* Size of LHS doclist in bytes */
-
  int nTokenRight,                /* As nTokenLeft */
-
  char *aRight,                   /* As aLeft */
-
  int nRight,                     /* As nRight */
-
  char **paOut,                   /* OUT: Results of merge (malloced) */
-
  int *pnOut                      /* OUT: Sized of output buffer */
-
){
-
  char *aOut;                     /* Buffer to write output doclist to */
-
  int rc;                         /* Return code */
-

-
  assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR );
-

-
  aOut = sqlite3_malloc(nLeft+nRight+1);
-
  if( aOut==0 ){
-
    rc = SQLITE_NOMEM;
-
  }else{
-
    rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft, 
-
      aOut, pnOut, aLeft, nLeft, aRight, nRight, 0
-
    );
-
    if( rc!=SQLITE_OK ){
-
      sqlite3_free(aOut);
-
      aOut = 0;
-
    }
-
  }
-

-
  *paOut = aOut;
-
  return rc;
-
}
-

-
/*
-
** This function is used as part of the processing for the snippet() and
-
** offsets() functions.
-
**
-
** Both pLeft and pRight are expression nodes of type FTSQUERY_PHRASE. Both
-
** have their respective doclists (including position information) loaded
-
** in Fts3Expr.aDoclist/nDoclist. This function removes all entries from
-
** each doclist that are not within nNear tokens of a corresponding entry
-
** in the other doclist.
-
*/
-
SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){
-
  int rc;                         /* Return code */
-

-
  assert( pLeft->eType==FTSQUERY_PHRASE );
-
  assert( pRight->eType==FTSQUERY_PHRASE );
-
  assert( pLeft->isLoaded && pRight->isLoaded );
-

-
  if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){
-
    sqlite3_free(pLeft->aDoclist);
-
    sqlite3_free(pRight->aDoclist);
-
    pRight->aDoclist = 0;
-
    pLeft->aDoclist = 0;
-
    rc = SQLITE_OK;
-
  }else{
-
    char *aOut;                   /* Buffer in which to assemble new doclist */
-
    int nOut;                     /* Size of buffer aOut in bytes */
-

-
    rc = fts3NearMerge(MERGE_POS_NEAR, nNear, 
-
        pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
-
        pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
-
        &aOut, &nOut
-
    );
-
    if( rc!=SQLITE_OK ) return rc;
-
    sqlite3_free(pRight->aDoclist);
-
    pRight->aDoclist = aOut;
-
    pRight->nDoclist = nOut;
-

-
    rc = fts3NearMerge(MERGE_POS_NEAR, nNear, 
-
        pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
-
        pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
-
        &aOut, &nOut
-
    );
-
    sqlite3_free(pLeft->aDoclist);
-
    pLeft->aDoclist = aOut;
-
    pLeft->nDoclist = nOut;
-
  }
-
  return rc;
-
}
-

-

-
/*
-
** Allocate an Fts3SegReaderArray for each token in the expression pExpr. 
-
** The allocated objects are stored in the Fts3PhraseToken.pArray member
-
** variables of each token structure.
-
*/
-
static int fts3ExprAllocateSegReaders(
-
  Fts3Cursor *pCsr,               /* FTS3 table */
-
  Fts3Expr *pExpr,                /* Expression to create seg-readers for */
-
  int *pnExpr                     /* OUT: Number of AND'd expressions */
-
){
-
  int rc = SQLITE_OK;             /* Return code */
-

-
  assert( pCsr->eEvalmode==FTS3_EVAL_FILTER );
-
  if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
-
    (*pnExpr)++;
-
    pnExpr = 0;
-
  }
-

-
  if( pExpr->eType==FTSQUERY_PHRASE ){
-
    Fts3Phrase *pPhrase = pExpr->pPhrase;
-
    int ii;
-

-
    for(ii=0; rc==SQLITE_OK && ii<pPhrase->nToken; ii++){
-
      Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
-
      if( pTok->pSegcsr==0 ){
-
        rc = fts3TermSegReaderCursor(
-
            pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr
-
        );
-
      }
-
    }
-
  }else{ 
-
    rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pLeft, pnExpr);
-
    if( rc==SQLITE_OK ){
-
      rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pRight, pnExpr);
-
    }
-
  }
-
  return rc;
-
}
-

-
/*
-
** Free the Fts3SegReaderArray objects associated with each token in the
-
** expression pExpr. In other words, this function frees the resources
-
** allocated by fts3ExprAllocateSegReaders().
-
*/
-
static void fts3ExprFreeSegReaders(Fts3Expr *pExpr){
-
  if( pExpr ){
-
    Fts3Phrase *pPhrase = pExpr->pPhrase;
-
    if( pPhrase ){
-
      int kk;
-
      for(kk=0; kk<pPhrase->nToken; kk++){
-
        fts3SegReaderCursorFree(pPhrase->aToken[kk].pSegcsr);
-
        pPhrase->aToken[kk].pSegcsr = 0;
-
      }
-
    }
-
    fts3ExprFreeSegReaders(pExpr->pLeft);
-
    fts3ExprFreeSegReaders(pExpr->pRight);
-
  }
-
}
-

-
/*
-
** Return the sum of the costs of all tokens in the expression pExpr. This
-
** function must be called after Fts3SegReaderArrays have been allocated
-
** for all tokens using fts3ExprAllocateSegReaders().
-
*/
-
static int fts3ExprCost(Fts3Expr *pExpr){
-
  int nCost;                      /* Return value */
-
  if( pExpr->eType==FTSQUERY_PHRASE ){
-
    Fts3Phrase *pPhrase = pExpr->pPhrase;
-
    int ii;
-
    nCost = 0;
-
    for(ii=0; ii<pPhrase->nToken; ii++){
-
      Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[ii].pSegcsr;
-
      if( pSegcsr ) nCost += pSegcsr->nCost;
-
    }
-
  }else{
-
    nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight);
-
  }
-
  return nCost;
-
}
-

-
/*
-
** The following is a helper function (and type) for fts3EvalExpr(). It
-
** must be called after Fts3SegReaders have been allocated for every token
-
** in the expression. See the context it is called from in fts3EvalExpr()
-
** for further explanation.
-
*/
-
typedef struct ExprAndCost ExprAndCost;
-
struct ExprAndCost {
-
  Fts3Expr *pExpr;
-
  int nCost;
-
};
-
static void fts3ExprAssignCosts(
-
  Fts3Expr *pExpr,                /* Expression to create seg-readers for */
-
  ExprAndCost **ppExprCost        /* OUT: Write to *ppExprCost */
-
){
-
  if( pExpr->eType==FTSQUERY_AND ){
-
    fts3ExprAssignCosts(pExpr->pLeft, ppExprCost);
-
    fts3ExprAssignCosts(pExpr->pRight, ppExprCost);
-
  }else{
-
    (*ppExprCost)->pExpr = pExpr;
-
    (*ppExprCost)->nCost = fts3ExprCost(pExpr);
-
    (*ppExprCost)++;
-
  }
-
}
-

-
/*
-
** Evaluate the full-text expression pExpr against FTS3 table pTab. Store
-
** the resulting doclist in *paOut and *pnOut. This routine mallocs for
-
** the space needed to store the output. The caller is responsible for
-
** freeing the space when it has finished.
-
**
-
** This function is called in two distinct contexts:
-
**
-
**   * From within the virtual table xFilter() method. In this case, the
-
**     output doclist contains entries for all rows in the table, based on
-
**     data read from the full-text index.
-
**
-
**     In this case, if the query expression contains one or more tokens that 
-
**     are very common, then the returned doclist may contain a superset of 
-
**     the documents that actually match the expression.
-
**
-
**   * From within the virtual table xNext() method. This call is only made
-
**     if the call from within xFilter() found that there were very common 
-
**     tokens in the query expression and did return a superset of the 
-
**     matching documents. In this case the returned doclist contains only
-
**     entries that correspond to the current row of the table. Instead of
-
**     reading the data for each token from the full-text index, the data is
-
**     already available in-memory in the Fts3PhraseToken.pDeferred structures.
-
**     See fts3EvalDeferred() for how it gets there.
-
**
-
** In the first case above, Fts3Cursor.doDeferred==0. In the second (if it is
-
** required) Fts3Cursor.doDeferred==1.
-
**
-
** If the SQLite invokes the snippet(), offsets() or matchinfo() function
-
** as part of a SELECT on an FTS3 table, this function is called on each
-
** individual phrase expression in the query. If there were very common tokens
-
** found in the xFilter() call, then this function is called once for phrase
-
** for each row visited, and the returned doclist contains entries for the
-
** current row only. Otherwise, if there were no very common tokens, then this
-
** function is called once only for each phrase in the query and the returned
-
** doclist contains entries for all rows of the table.
-
**
-
** Fts3Cursor.doDeferred==1 when this function is called on phrases as a
-
** result of a snippet(), offsets() or matchinfo() invocation.
-
*/
-
static int fts3EvalExpr(
-
  Fts3Cursor *p,                  /* Virtual table cursor handle */
-
  Fts3Expr *pExpr,                /* Parsed fts3 expression */
-
  char **paOut,                   /* OUT: Pointer to malloc'd result buffer */
-
  int *pnOut,                     /* OUT: Size of buffer at *paOut */
-
  int isReqPos                    /* Require positions in output buffer */
-
){
-
  int rc = SQLITE_OK;             /* Return code */
-

-
  /* Zero the output parameters. */
-
  *paOut = 0;
-
  *pnOut = 0;
-

-
  if( pExpr ){
-
    assert( pExpr->eType==FTSQUERY_NEAR   || pExpr->eType==FTSQUERY_OR     
-
         || pExpr->eType==FTSQUERY_AND    || pExpr->eType==FTSQUERY_NOT
-
         || pExpr->eType==FTSQUERY_PHRASE
-
    );
-
    assert( pExpr->eType==FTSQUERY_PHRASE || isReqPos==0 );
-

-
    if( pExpr->eType==FTSQUERY_PHRASE ){
-
      rc = fts3PhraseSelect(p, pExpr->pPhrase,
-
          isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
-
          paOut, pnOut
-
      );
-
      fts3ExprFreeSegReaders(pExpr);
-
    }else if( p->eEvalmode==FTS3_EVAL_FILTER && pExpr->eType==FTSQUERY_AND ){
-
      ExprAndCost *aExpr = 0;     /* Array of AND'd expressions and costs */
-
      int nExpr = 0;              /* Size of aExpr[] */
-
      char *aRet = 0;             /* Doclist to return to caller */
-
      int nRet = 0;               /* Length of aRet[] in bytes */
-
      int nDoc = 0x7FFFFFFF;
-

-
      assert( !isReqPos );
-

-
      rc = fts3ExprAllocateSegReaders(p, pExpr, &nExpr);
-
      if( rc==SQLITE_OK ){
-
        assert( nExpr>1 );
-
        aExpr = sqlite3_malloc(sizeof(ExprAndCost) * nExpr);
-
        if( !aExpr ) rc = SQLITE_NOMEM;
-
      }
-
      if( rc==SQLITE_OK ){
-
        int ii;                   /* Used to iterate through expressions */
-

-
        fts3ExprAssignCosts(pExpr, &aExpr);
-
        aExpr -= nExpr;
-
        for(ii=0; ii<nExpr; ii++){
-
          char *aNew;
-
          int nNew;
-
          int jj;
-
          ExprAndCost *pBest = 0;
-
  
-
          for(jj=0; jj<nExpr; jj++){
-
            ExprAndCost *pCand = &aExpr[jj];
-
            if( pCand->pExpr && (pBest==0 || pCand->nCost<pBest->nCost) ){
-
              pBest = pCand;
-
            }
-
          }
-
  
-
          if( pBest->nCost>nDoc ){
-
            rc = fts3DeferExpression(p, p->pExpr);
-
            break;
-
          }else{
-
            rc = fts3EvalExpr(p, pBest->pExpr, &aNew, &nNew, 0);
-
            if( rc!=SQLITE_OK ) break;
-
            pBest->pExpr = 0;
-
            if( ii==0 ){
-
              aRet = aNew;
-
              nRet = nNew;
-
              nDoc = fts3DoclistCountDocids(0, aRet, nRet);
-
            }else{
-
              fts3DoclistMerge(
-
                  MERGE_AND, 0, 0, aRet, &nRet, aRet, nRet, aNew, nNew, &nDoc
-
              );
-
              sqlite3_free(aNew);
-
            }
-
          }
-
        }
-
      }
-

-
      if( rc==SQLITE_OK ){
-
        *paOut = aRet;
-
        *pnOut = nRet;
-
      }else{
-
        assert( *paOut==0 );
-
        sqlite3_free(aRet);
-
      }
-
      sqlite3_free(aExpr);
-
      fts3ExprFreeSegReaders(pExpr);
-

-
    }else{
-
      char *aLeft;
-
      char *aRight;
-
      int nLeft;
-
      int nRight;
-

-
      assert( pExpr->eType==FTSQUERY_NEAR 
-
           || pExpr->eType==FTSQUERY_OR
-
           || pExpr->eType==FTSQUERY_NOT
-
           || (pExpr->eType==FTSQUERY_AND && p->eEvalmode==FTS3_EVAL_NEXT)
-
      );
-

-
      if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
-
       && 0==(rc = fts3EvalExpr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
-
      ){
-
        switch( pExpr->eType ){
-
          case FTSQUERY_NEAR: {
-
            Fts3Expr *pLeft;
-
            Fts3Expr *pRight;
-
            int mergetype = MERGE_NEAR;
-
            if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
-
              mergetype = MERGE_POS_NEAR;
-
            }
-
            pLeft = pExpr->pLeft;
-
            while( pLeft->eType==FTSQUERY_NEAR ){ 
-
              pLeft=pLeft->pRight;
-
            }
-
            pRight = pExpr->pRight;
-
            assert( pRight->eType==FTSQUERY_PHRASE );
-
            assert( pLeft->eType==FTSQUERY_PHRASE );
-

-
            rc = fts3NearMerge(mergetype, pExpr->nNear, 
-
                pLeft->pPhrase->nToken, aLeft, nLeft,
-
                pRight->pPhrase->nToken, aRight, nRight,
-
                paOut, pnOut
-
            );
-
            sqlite3_free(aLeft);
-
            break;
-
          }
-

-
          case FTSQUERY_OR: {
-
            /* Allocate a buffer for the output. The maximum size is the
-
            ** sum of the sizes of the two input buffers. The +1 term is
-
            ** so that a buffer of zero bytes is never allocated - this can
-
            ** cause fts3DoclistMerge() to incorrectly return SQLITE_NOMEM.
-
            */
-
            char *aBuffer = sqlite3_malloc(nRight+nLeft+1);
-
            rc = fts3DoclistMerge(MERGE_OR, 0, 0, aBuffer, pnOut,
-
                aLeft, nLeft, aRight, nRight, 0
-
            );
-
            *paOut = aBuffer;
-
            sqlite3_free(aLeft);
-
            break;
-
          }
-

-
          default: {
-
            assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND );
-
            fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut,
-
                aLeft, nLeft, aRight, nRight, 0
-
            );
-
            *paOut = aLeft;
-
            break;
-
          }
-
        }
-
      }
-
      sqlite3_free(aRight);
-
    }
-
  }
-

-
  assert( rc==SQLITE_OK || *paOut==0 );
-
  return rc;
-
}
-

-
/*
-
** This function is called from within xNext() for each row visited by
-
** an FTS3 query. If evaluating the FTS3 query expression within xFilter()
-
** was able to determine the exact set of matching rows, this function sets
-
** *pbRes to true and returns SQLITE_IO immediately.
-
**
-
** Otherwise, if evaluating the query expression within xFilter() returned a
-
** superset of the matching documents instead of an exact set (this happens
-
** when the query includes very common tokens and it is deemed too expensive to
-
** load their doclists from disk), this function tests if the current row
-
** really does match the FTS3 query.
-
**
-
** If an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK
-
** is returned and *pbRes is set to true if the current row matches the
-
** FTS3 query (and should be included in the results returned to SQLite), or
-
** false otherwise.
-
*/
-
static int fts3EvalDeferred(
-
  Fts3Cursor *pCsr,               /* FTS3 cursor pointing at row to test */
-
  int *pbRes                      /* OUT: Set to true if row is a match */
-
){
-
  int rc = SQLITE_OK;
-
  if( pCsr->pDeferred==0 ){
-
    *pbRes = 1;
-
  }else{
-
    rc = fts3CursorSeek(0, pCsr);
-
    if( rc==SQLITE_OK ){
-
      sqlite3Fts3FreeDeferredDoclists(pCsr);
-
      rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
-
    }
-
    if( rc==SQLITE_OK ){
-
      char *a = 0;
-
      int n = 0;
-
      rc = fts3EvalExpr(pCsr, pCsr->pExpr, &a, &n, 0);
-
      assert( n>=0 );
-
      *pbRes = (n>0);
-
      sqlite3_free(a);
-
    }
-
  }
-
  return rc;
-
}
-

-
/*
** Advance the cursor to the next row in the %_content table that
** matches the search criteria.  For a MATCH search, this will be
** the next row that matches. For a full-table scan, this will be
@@ -113752,31 +114456,20 @@ static int fts3EvalDeferred(
** subsequently to determine whether or not an EOF was hit.
*/
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
-
  int res;
-
  int rc = SQLITE_OK;             /* Return code */
+
  int rc;
  Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
-

-
  pCsr->eEvalmode = FTS3_EVAL_NEXT;
-
  do {
-
    if( pCsr->aDoclist==0 ){
-
      if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
-
        pCsr->isEof = 1;
-
        rc = sqlite3_reset(pCsr->pStmt);
-
        break;
-
      }
-
      pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
+
  if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
+
    if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
+
      pCsr->isEof = 1;
+
      rc = sqlite3_reset(pCsr->pStmt);
    }else{
-
      if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
-
        pCsr->isEof = 1;
-
        break;
-
      }
-
      sqlite3_reset(pCsr->pStmt);
-
      fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
-
      pCsr->isRequireSeek = 1;
-
      pCsr->isMatchinfoNeeded = 1;
+
      pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
+
      rc = SQLITE_OK;
    }
-
  }while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
-

+
  }else{
+
    rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
+
  }
+
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  return rc;
}

@@ -113803,11 +114496,7 @@ static int fts3FilterMethod(
  int nVal,                       /* Number of elements in apVal */
  sqlite3_value **apVal           /* Arguments for the indexing scheme */
){
-
  const char *azSql[] = {
-
    "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
-
    "SELECT %s FROM %Q.'%q_content' AS x ",                /* full-scan */
-
  };
-
  int rc;                         /* Return code */
+
  int rc;
  char *zSql;                     /* SQL statement used to access %_content */
  Fts3Table *p = (Fts3Table *)pCursor->pVtab;
  Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
@@ -113826,6 +114515,13 @@ static int fts3FilterMethod(
  sqlite3Fts3ExprFree(pCsr->pExpr);
  memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));

+
  if( idxStr ){
+
    pCsr->bDesc = (idxStr[0]=='D');
+
  }else{
+
    pCsr->bDesc = p->bDescIdx;
+
  }
+
  pCsr->eSearch = (i16)idxNum;
+

  if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
    int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
    const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
@@ -113839,8 +114535,8 @@ static int fts3FilterMethod(
    );
    if( rc!=SQLITE_OK ){
      if( rc==SQLITE_ERROR ){
-
        p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]",
-
                                          zQuery);
+
        static const char *zErr = "malformed MATCH expression: [%s]";
+
        p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
      }
      return rc;
    }
@@ -113848,7 +114544,8 @@ static int fts3FilterMethod(
    rc = sqlite3Fts3ReadLock(p);
    if( rc!=SQLITE_OK ) return rc;

-
    rc = fts3EvalExpr(pCsr, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
+
    rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
+

    sqlite3Fts3SegmentsClose(p);
    if( rc!=SQLITE_OK ) return rc;
    pCsr->pNextId = pCsr->aDoclist;
@@ -113860,20 +114557,24 @@ static int fts3FilterMethod(
  ** full-text query or docid lookup, the statement retrieves a single
  ** row by docid.
  */
-
  zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH];
-
  zSql = sqlite3_mprintf(zSql, p->zReadExprlist, p->zDb, p->zName);
-
  if( !zSql ){
-
    rc = SQLITE_NOMEM;
+
  if( idxNum==FTS3_FULLSCAN_SEARCH ){
+
    const char *zSort = (pCsr->bDesc ? "DESC" : "ASC");
+
    const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s";
+
    zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName, zSort);
  }else{
-
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
-
    sqlite3_free(zSql);
+
    const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?";
+
    zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName);
  }
-
  if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
+
  if( !zSql ) return SQLITE_NOMEM;
+
  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
+
  sqlite3_free(zSql);
+
  if( rc!=SQLITE_OK ) return rc;
+

+
  if( idxNum==FTS3_DOCID_SEARCH ){
    rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
+
    if( rc!=SQLITE_OK ) return rc;
  }
-
  pCsr->eSearch = (i16)idxNum;

-
  if( rc!=SQLITE_OK ) return rc;
  return fts3NextMethod(pCursor);
}

@@ -113893,16 +114594,7 @@ static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
*/
static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
-
  if( pCsr->aDoclist ){
-
    *pRowid = pCsr->iPrevId;
-
  }else{
-
    /* This branch runs if the query is implemented using a full-table scan
-
    ** (not using the full-text index). In this case grab the rowid from the
-
    ** SELECT statement.
-
    */
-
    assert( pCsr->isRequireSeek==0 );
-
    *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
-
  }
+
  *pRowid = pCsr->iPrevId;
  return SQLITE_OK;
}

@@ -113915,7 +114607,7 @@ static int fts3ColumnMethod(
  sqlite3_context *pContext,      /* Context for sqlite3_result_xxx() calls */
  int iCol                        /* Index of column to read value from */
){
-
  int rc;                         /* Return Code */
+
  int rc = SQLITE_OK;             /* Return Code */
  Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
  Fts3Table *p = (Fts3Table *)pCursor->pVtab;

@@ -113926,21 +114618,20 @@ static int fts3ColumnMethod(
    /* This call is a request for the "docid" column. Since "docid" is an 
    ** alias for "rowid", use the xRowid() method to obtain the value.
    */
-
    sqlite3_int64 iRowid;
-
    rc = fts3RowidMethod(pCursor, &iRowid);
-
    sqlite3_result_int64(pContext, iRowid);
+
    sqlite3_result_int64(pContext, pCsr->iPrevId);
  }else if( iCol==p->nColumn ){
    /* The extra column whose name is the same as the table.
    ** Return a blob which is a pointer to the cursor.
    */
    sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
-
    rc = SQLITE_OK;
  }else{
    rc = fts3CursorSeek(0, pCsr);
    if( rc==SQLITE_OK ){
      sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
    }
  }
+

+
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  return rc;
}

@@ -113972,8 +114663,13 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method. This is a no-op.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
+
  TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  UNUSED_PARAMETER(pVtab);
-
  assert( ((Fts3Table *)pVtab)->nPendingData==0 );
+
  assert( p->pSegments==0 );
+
  assert( p->nPendingData==0 );
+
  assert( p->inTransaction!=1 );
+
  TESTONLY( p->inTransaction = 1 );
+
  TESTONLY( p->mxSavepoint = -1; );
  return SQLITE_OK;
}

@@ -113983,8 +114679,13 @@ static int fts3BeginMethod(sqlite3_vtab *pVtab){
** by fts3SyncMethod().
*/
static int fts3CommitMethod(sqlite3_vtab *pVtab){
+
  TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  UNUSED_PARAMETER(pVtab);
-
  assert( ((Fts3Table *)pVtab)->nPendingData==0 );
+
  assert( p->nPendingData==0 );
+
  assert( p->inTransaction!=0 );
+
  assert( p->pSegments==0 );
+
  TESTONLY( p->inTransaction = 0 );
+
  TESTONLY( p->mxSavepoint = -1; );
  return SQLITE_OK;
}

@@ -113993,93 +114694,31 @@ static int fts3CommitMethod(sqlite3_vtab *pVtab){
** hash-table. Any changes made to the database are reverted by SQLite.
*/
static int fts3RollbackMethod(sqlite3_vtab *pVtab){
-
  sqlite3Fts3PendingTermsClear((Fts3Table *)pVtab);
+
  Fts3Table *p = (Fts3Table*)pVtab;
+
  sqlite3Fts3PendingTermsClear(p);
+
  assert( p->inTransaction!=0 );
+
  TESTONLY( p->inTransaction = 0 );
+
  TESTONLY( p->mxSavepoint = -1; );
  return SQLITE_OK;
}

/*
-
** Load the doclist associated with expression pExpr to pExpr->aDoclist.
-
** The loaded doclist contains positions as well as the document ids.
-
** This is used by the matchinfo(), snippet() and offsets() auxillary
-
** functions.
+
** When called, *ppPoslist must point to the byte immediately following the
+
** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
+
** moves *ppPoslist so that it instead points to the first byte of the
+
** same position list.
*/
-
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *pCsr, Fts3Expr *pExpr){
-
  int rc;
-
  assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
-
  assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
-
  rc = fts3EvalExpr(pCsr, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
-
  return rc;
-
}
+
static void fts3ReversePoslist(char *pStart, char **ppPoslist){
+
  char *p = &(*ppPoslist)[-2];
+
  char c;

-
SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(
-
  Fts3Cursor *pCsr, 
-
  Fts3Expr *pExpr,
-
  char **paDoclist,
-
  int *pnDoclist
-
){
-
  int rc;
-
  assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
-
  assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
-
  pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
-
  rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
-
  pCsr->eEvalmode = FTS3_EVAL_NEXT;
-
  return rc;
-
}
-

-
/*
-
** After ExprLoadDoclist() (see above) has been called, this function is
-
** used to iterate/search through the position lists that make up the doclist
-
** stored in pExpr->aDoclist.
-
*/
-
SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
-
  Fts3Expr *pExpr,                /* Access this expressions doclist */
-
  sqlite3_int64 iDocid,           /* Docid associated with requested pos-list */
-
  int iCol                        /* Column of requested pos-list */
-
){
-
  assert( pExpr->isLoaded );
-
  if( pExpr->aDoclist ){
-
    char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
-
    char *pCsr;
-

-
    if( pExpr->pCurrent==0 ){
-
      pExpr->pCurrent = pExpr->aDoclist;
-
      pExpr->iCurrent = 0;
-
      pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent);
-
    }
-
    pCsr = pExpr->pCurrent;
-
    assert( pCsr );
-

-
    while( pCsr<pEnd ){
-
      if( pExpr->iCurrent<iDocid ){
-
        fts3PoslistCopy(0, &pCsr);
-
        if( pCsr<pEnd ){
-
          fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
-
        }
-
        pExpr->pCurrent = pCsr;
-
      }else{
-
        if( pExpr->iCurrent==iDocid ){
-
          int iThis = 0;
-
          if( iCol<0 ){
-
            /* If iCol is negative, return a pointer to the start of the
-
            ** position-list (instead of a pointer to the start of a list
-
            ** of offsets associated with a specific column).
-
            */
-
            return pCsr;
-
          }
-
          while( iThis<iCol ){
-
            fts3ColumnlistCopy(0, &pCsr);
-
            if( *pCsr==0x00 ) return 0;
-
            pCsr++;
-
            pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis);
-
          }
-
          if( iCol==iThis && (*pCsr&0xFE) ) return pCsr;
-
        }
-
        return 0;
-
      }
-
    }
+
  while( p>pStart && (c=*p--)==0 );
+
  while( p>pStart && (*p & 0x80) | c ){ 
+
    c = *p--; 
  }
-

-
  return 0;
+
  if( p>pStart ){ p = &p[2]; }
+
  while( *p++&0x80 );
+
  *ppPoslist = p;
}

/*
@@ -114312,8 +114951,34 @@ static int fts3RenameMethod(
  return rc;
}

+
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
+
  UNUSED_PARAMETER(iSavepoint);
+
  assert( ((Fts3Table *)pVtab)->inTransaction );
+
  assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
+
  TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
+
  return fts3SyncMethod(pVtab);
+
}
+
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
+
  TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
+
  UNUSED_PARAMETER(iSavepoint);
+
  UNUSED_PARAMETER(pVtab);
+
  assert( p->inTransaction );
+
  assert( p->mxSavepoint >= iSavepoint );
+
  TESTONLY( p->mxSavepoint = iSavepoint-1 );
+
  return SQLITE_OK;
+
}
+
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
+
  Fts3Table *p = (Fts3Table*)pVtab;
+
  UNUSED_PARAMETER(iSavepoint);
+
  assert( p->inTransaction );
+
  assert( p->mxSavepoint >= iSavepoint );
+
  TESTONLY( p->mxSavepoint = iSavepoint );
+
  sqlite3Fts3PendingTermsClear(p);
+
  return SQLITE_OK;
+
}
+

static const sqlite3_module fts3Module = {
-
  /* iVersion      */ 0,
+
  /* iVersion      */ 2,
  /* xCreate       */ fts3CreateMethod,
  /* xConnect      */ fts3ConnectMethod,
  /* xBestIndex    */ fts3BestIndexMethod,
@@ -114333,6 +114998,9 @@ static const sqlite3_module fts3Module = {
  /* xRollback     */ fts3RollbackMethod,
  /* xFindFunction */ fts3FindFunctionMethod,
  /* xRename */       fts3RenameMethod,
+
  /* xSavepoint    */ fts3SavepointMethod,
+
  /* xRelease      */ fts3ReleaseMethod,
+
  /* xRollbackTo   */ fts3RollbackToMethod,
};

/*
@@ -114379,6 +115047,11 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
  sqlite3Fts3IcuTokenizerModule(&pIcu);
#endif

+
#ifdef SQLITE_TEST
+
  rc = sqlite3Fts3InitTerm(db);
+
  if( rc!=SQLITE_OK ) return rc;
+
#endif
+

  rc = sqlite3Fts3InitAux(db);
  if( rc!=SQLITE_OK ) return rc;

@@ -114454,6 +115127,1308 @@ SQLITE_API int sqlite3_extension_init(
}
#endif

+

+
/*
+
** Allocate an Fts3MultiSegReader for each token in the expression headed
+
** by pExpr. 
+
**
+
** An Fts3SegReader object is a cursor that can seek or scan a range of
+
** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
+
** Fts3SegReader objects internally to provide an interface to seek or scan
+
** within the union of all segments of a b-tree. Hence the name.
+
**
+
** If the allocated Fts3MultiSegReader just seeks to a single entry in a
+
** segment b-tree (if the term is not a prefix or it is a prefix for which
+
** there exists prefix b-tree of the right length) then it may be traversed
+
** and merged incrementally. Otherwise, it has to be merged into an in-memory 
+
** doclist and then traversed.
+
*/
+
static void fts3EvalAllocateReaders(
+
  Fts3Cursor *pCsr, 
+
  Fts3Expr *pExpr, 
+
  int *pnToken,                   /* OUT: Total number of tokens in phrase. */
+
  int *pnOr,                      /* OUT: Total number of OR nodes in expr. */
+
  int *pRc
+
){
+
  if( pExpr && SQLITE_OK==*pRc ){
+
    if( pExpr->eType==FTSQUERY_PHRASE ){
+
      int i;
+
      int nToken = pExpr->pPhrase->nToken;
+
      *pnToken += nToken;
+
      for(i=0; i<nToken; i++){
+
        Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
+
        int rc = sqlite3Fts3TermSegReaderCursor(pCsr, 
+
            pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
+
        );
+
        if( rc!=SQLITE_OK ){
+
          *pRc = rc;
+
          return;
+
        }
+
      }
+
      assert( pExpr->pPhrase->iDoclistToken==0 );
+
      pExpr->pPhrase->iDoclistToken = -1;
+
    }else{
+
      *pnOr += (pExpr->eType==FTSQUERY_OR);
+
      fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
+
      fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
+
    }
+
  }
+
}
+

+
static void fts3EvalPhraseMergeToken(
+
  Fts3Table *pTab,
+
  Fts3Phrase *p,
+
  int iToken,
+
  char *pList,
+
  int nList
+
){
+
  assert( iToken!=p->iDoclistToken );
+

+
  if( pList==0 ){
+
    sqlite3_free(p->doclist.aAll);
+
    p->doclist.aAll = 0;
+
    p->doclist.nAll = 0;
+
  }
+

+
  else if( p->iDoclistToken<0 ){
+
    p->doclist.aAll = pList;
+
    p->doclist.nAll = nList;
+
  }
+

+
  else if( p->doclist.aAll==0 ){
+
    sqlite3_free(pList);
+
  }
+

+
  else {
+
    char *pLeft;
+
    char *pRight;
+
    int nLeft;
+
    int nRight;
+
    int nDiff;
+

+
    if( p->iDoclistToken<iToken ){
+
      pLeft = p->doclist.aAll;
+
      nLeft = p->doclist.nAll;
+
      pRight = pList;
+
      nRight = nList;
+
      nDiff = iToken - p->iDoclistToken;
+
    }else{
+
      pRight = p->doclist.aAll;
+
      nRight = p->doclist.nAll;
+
      pLeft = pList;
+
      nLeft = nList;
+
      nDiff = p->iDoclistToken - iToken;
+
    }
+

+
    fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
+
    sqlite3_free(pLeft);
+
    p->doclist.aAll = pRight;
+
    p->doclist.nAll = nRight;
+
  }
+

+
  if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
+
}
+

+
static int fts3EvalPhraseLoad(
+
  Fts3Cursor *pCsr, 
+
  Fts3Phrase *p
+
){
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
  int iToken;
+
  int rc = SQLITE_OK;
+

+
  for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
+
    Fts3PhraseToken *pToken = &p->aToken[iToken];
+
    assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
+

+
    if( pToken->pSegcsr ){
+
      int nThis = 0;
+
      char *pThis = 0;
+
      rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
+
      if( rc==SQLITE_OK ){
+
        fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
+
      }
+
    }
+
    assert( pToken->pSegcsr==0 );
+
  }
+

+
  return rc;
+
}
+

+
static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
+
  int iToken;
+
  int rc = SQLITE_OK;
+

+
  int nMaxUndeferred = pPhrase->iDoclistToken;
+
  char *aPoslist = 0;
+
  int nPoslist = 0;
+
  int iPrev = -1;
+

+
  assert( pPhrase->doclist.bFreeList==0 );
+

+
  for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
+
    Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
+
    Fts3DeferredToken *pDeferred = pToken->pDeferred;
+

+
    if( pDeferred ){
+
      char *pList;
+
      int nList;
+
      rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
+
      if( rc!=SQLITE_OK ) return rc;
+

+
      if( pList==0 ){
+
        sqlite3_free(aPoslist);
+
        pPhrase->doclist.pList = 0;
+
        pPhrase->doclist.nList = 0;
+
        return SQLITE_OK;
+

+
      }else if( aPoslist==0 ){
+
        aPoslist = pList;
+
        nPoslist = nList;
+

+
      }else{
+
        char *aOut = pList;
+
        char *p1 = aPoslist;
+
        char *p2 = aOut;
+

+
        assert( iPrev>=0 );
+
        fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
+
        sqlite3_free(aPoslist);
+
        aPoslist = pList;
+
        nPoslist = aOut - aPoslist;
+
        if( nPoslist==0 ){
+
          sqlite3_free(aPoslist);
+
          pPhrase->doclist.pList = 0;
+
          pPhrase->doclist.nList = 0;
+
          return SQLITE_OK;
+
        }
+
      }
+
      iPrev = iToken;
+
    }
+
  }
+

+
  if( iPrev>=0 ){
+
    if( nMaxUndeferred<0 ){
+
      pPhrase->doclist.pList = aPoslist;
+
      pPhrase->doclist.nList = nPoslist;
+
      pPhrase->doclist.iDocid = pCsr->iPrevId;
+
      pPhrase->doclist.bFreeList = 1;
+
    }else{
+
      int nDistance;
+
      char *p1;
+
      char *p2;
+
      char *aOut;
+

+
      if( nMaxUndeferred>iPrev ){
+
        p1 = aPoslist;
+
        p2 = pPhrase->doclist.pList;
+
        nDistance = nMaxUndeferred - iPrev;
+
      }else{
+
        p1 = pPhrase->doclist.pList;
+
        p2 = aPoslist;
+
        nDistance = iPrev - nMaxUndeferred;
+
      }
+

+
      aOut = (char *)sqlite3_malloc(nPoslist+8);
+
      if( !aOut ){
+
        sqlite3_free(aPoslist);
+
        return SQLITE_NOMEM;
+
      }
+
      
+
      pPhrase->doclist.pList = aOut;
+
      if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
+
        pPhrase->doclist.bFreeList = 1;
+
        pPhrase->doclist.nList = (aOut - pPhrase->doclist.pList);
+
      }else{
+
        sqlite3_free(aOut);
+
        pPhrase->doclist.pList = 0;
+
        pPhrase->doclist.nList = 0;
+
      }
+
      sqlite3_free(aPoslist);
+
    }
+
  }
+

+
  return SQLITE_OK;
+
}
+

+
/*
+
** This function is called for each Fts3Phrase in a full-text query 
+
** expression to initialize the mechanism for returning rows. Once this
+
** function has been called successfully on an Fts3Phrase, it may be
+
** used with fts3EvalPhraseNext() to iterate through the matching docids.
+
*/
+
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
+
  int rc;
+
  Fts3PhraseToken *pFirst = &p->aToken[0];
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+

+
  if( pCsr->bDesc==pTab->bDescIdx 
+
   && bOptOk==1 
+
   && p->nToken==1 
+
   && pFirst->pSegcsr 
+
   && pFirst->pSegcsr->bLookup 
+
  ){
+
    /* Use the incremental approach. */
+
    int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
+
    rc = sqlite3Fts3MsrIncrStart(
+
        pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
+
    p->bIncr = 1;
+

+
  }else{
+
    /* Load the full doclist for the phrase into memory. */
+
    rc = fts3EvalPhraseLoad(pCsr, p);
+
    p->bIncr = 0;
+
  }
+

+
  assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
+
  return rc;
+
}
+

+
/*
+
** This function is used to iterate backwards (from the end to start) 
+
** through doclists.
+
*/
+
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
+
  int bDescIdx,                   /* True if the doclist is desc */
+
  char *aDoclist,                 /* Pointer to entire doclist */
+
  int nDoclist,                   /* Length of aDoclist in bytes */
+
  char **ppIter,                  /* IN/OUT: Iterator pointer */
+
  sqlite3_int64 *piDocid,         /* IN/OUT: Docid pointer */
+
  int *pnList,                    /* IN/OUT: List length pointer */
+
  u8 *pbEof                       /* OUT: End-of-file flag */
+
){
+
  char *p = *ppIter;
+

+
  assert( nDoclist>0 );
+
  assert( *pbEof==0 );
+
  assert( p || *piDocid==0 );
+
  assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
+

+
  if( p==0 ){
+
    sqlite3_int64 iDocid = 0;
+
    char *pNext = 0;
+
    char *pDocid = aDoclist;
+
    char *pEnd = &aDoclist[nDoclist];
+
    int iMul = 1;
+

+
    while( pDocid<pEnd ){
+
      sqlite3_int64 iDelta;
+
      pDocid += sqlite3Fts3GetVarint(pDocid, &iDelta);
+
      iDocid += (iMul * iDelta);
+
      pNext = pDocid;
+
      fts3PoslistCopy(0, &pDocid);
+
      while( pDocid<pEnd && *pDocid==0 ) pDocid++;
+
      iMul = (bDescIdx ? -1 : 1);
+
    }
+

+
    *pnList = pEnd - pNext;
+
    *ppIter = pNext;
+
    *piDocid = iDocid;
+
  }else{
+
    int iMul = (bDescIdx ? -1 : 1);
+
    sqlite3_int64 iDelta;
+
    fts3GetReverseVarint(&p, aDoclist, &iDelta);
+
    *piDocid -= (iMul * iDelta);
+

+
    if( p==aDoclist ){
+
      *pbEof = 1;
+
    }else{
+
      char *pSave = p;
+
      fts3ReversePoslist(aDoclist, &p);
+
      *pnList = (pSave - p);
+
    }
+
    *ppIter = p;
+
  }
+
}
+

+
/*
+
** Attempt to move the phrase iterator to point to the next matching docid. 
+
** If an error occurs, return an SQLite error code. Otherwise, return 
+
** SQLITE_OK.
+
**
+
** If there is no "next" entry and no error occurs, then *pbEof is set to
+
** 1 before returning. Otherwise, if no error occurs and the iterator is
+
** successfully advanced, *pbEof is set to 0.
+
*/
+
static int fts3EvalPhraseNext(
+
  Fts3Cursor *pCsr, 
+
  Fts3Phrase *p, 
+
  u8 *pbEof
+
){
+
  int rc = SQLITE_OK;
+
  Fts3Doclist *pDL = &p->doclist;
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+

+
  if( p->bIncr ){
+
    assert( p->nToken==1 );
+
    assert( pDL->pNextDocid==0 );
+
    rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, 
+
        &pDL->iDocid, &pDL->pList, &pDL->nList
+
    );
+
    if( rc==SQLITE_OK && !pDL->pList ){
+
      *pbEof = 1;
+
    }
+
  }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
+
    sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, 
+
        &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
+
    );
+
    pDL->pList = pDL->pNextDocid;
+
  }else{
+
    char *pIter;                            /* Used to iterate through aAll */
+
    char *pEnd = &pDL->aAll[pDL->nAll];     /* 1 byte past end of aAll */
+
    if( pDL->pNextDocid ){
+
      pIter = pDL->pNextDocid;
+
    }else{
+
      pIter = pDL->aAll;
+
    }
+

+
    if( pIter>=pEnd ){
+
      /* We have already reached the end of this doclist. EOF. */
+
      *pbEof = 1;
+
    }else{
+
      sqlite3_int64 iDelta;
+
      pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
+
      if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
+
        pDL->iDocid += iDelta;
+
      }else{
+
        pDL->iDocid -= iDelta;
+
      }
+
      pDL->pList = pIter;
+
      fts3PoslistCopy(0, &pIter);
+
      pDL->nList = (pIter - pDL->pList);
+

+
      /* pIter now points just past the 0x00 that terminates the position-
+
      ** list for document pDL->iDocid. However, if this position-list was
+
      ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
+
      ** point to the start of the next docid value. The following line deals
+
      ** with this case by advancing pIter past the zero-padding added by
+
      ** fts3EvalNearTrim2().  */
+
      while( pIter<pEnd && *pIter==0 ) pIter++;
+

+
      pDL->pNextDocid = pIter;
+
      assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
+
      *pbEof = 0;
+
    }
+
  }
+

+
  return rc;
+
}
+

+
static void fts3EvalStartReaders(
+
  Fts3Cursor *pCsr, 
+
  Fts3Expr *pExpr, 
+
  int bOptOk,
+
  int *pRc
+
){
+
  if( pExpr && SQLITE_OK==*pRc ){
+
    if( pExpr->eType==FTSQUERY_PHRASE ){
+
      int i;
+
      int nToken = pExpr->pPhrase->nToken;
+
      for(i=0; i<nToken; i++){
+
        if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
+
      }
+
      pExpr->bDeferred = (i==nToken);
+
      *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
+
    }else{
+
      fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
+
      fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
+
      pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
+
    }
+
  }
+
}
+

+
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
+
struct Fts3TokenAndCost {
+
  Fts3Phrase *pPhrase;            /* The phrase the token belongs to */
+
  int iToken;                     /* Position of token in phrase */
+
  Fts3PhraseToken *pToken;        /* The token itself */
+
  Fts3Expr *pRoot; 
+
  int nOvfl;
+
  int iCol;                       /* The column the token must match */
+
};
+

+
static void fts3EvalTokenCosts(
+
  Fts3Cursor *pCsr, 
+
  Fts3Expr *pRoot, 
+
  Fts3Expr *pExpr, 
+
  Fts3TokenAndCost **ppTC,
+
  Fts3Expr ***ppOr,
+
  int *pRc
+
){
+
  if( *pRc==SQLITE_OK && pExpr ){
+
    if( pExpr->eType==FTSQUERY_PHRASE ){
+
      Fts3Phrase *pPhrase = pExpr->pPhrase;
+
      int i;
+
      for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
+
        Fts3TokenAndCost *pTC = (*ppTC)++;
+
        pTC->pPhrase = pPhrase;
+
        pTC->iToken = i;
+
        pTC->pRoot = pRoot;
+
        pTC->pToken = &pPhrase->aToken[i];
+
        pTC->iCol = pPhrase->iColumn;
+
        *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
+
      }
+
    }else if( pExpr->eType!=FTSQUERY_NOT ){
+
      if( pExpr->eType==FTSQUERY_OR ){
+
        pRoot = pExpr->pLeft;
+
        **ppOr = pRoot;
+
        (*ppOr)++;
+
      }
+
      fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc);
+
      if( pExpr->eType==FTSQUERY_OR ){
+
        pRoot = pExpr->pRight;
+
        **ppOr = pRoot;
+
        (*ppOr)++;
+
      }
+
      fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
+
    }
+
  }
+
}
+

+
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
+
  if( pCsr->nRowAvg==0 ){
+
    /* The average document size, which is required to calculate the cost
+
     ** of each doclist, has not yet been determined. Read the required 
+
     ** data from the %_stat table to calculate it.
+
     **
+
     ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 
+
     ** varints, where nCol is the number of columns in the FTS3 table.
+
     ** The first varint is the number of documents currently stored in
+
     ** the table. The following nCol varints contain the total amount of
+
     ** data stored in all rows of each column of the table, from left
+
     ** to right.
+
     */
+
    int rc;
+
    Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
+
    sqlite3_stmt *pStmt;
+
    sqlite3_int64 nDoc = 0;
+
    sqlite3_int64 nByte = 0;
+
    const char *pEnd;
+
    const char *a;
+

+
    rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
+
    if( rc!=SQLITE_OK ) return rc;
+
    a = sqlite3_column_blob(pStmt, 0);
+
    assert( a );
+

+
    pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
+
    a += sqlite3Fts3GetVarint(a, &nDoc);
+
    while( a<pEnd ){
+
      a += sqlite3Fts3GetVarint(a, &nByte);
+
    }
+
    if( nDoc==0 || nByte==0 ){
+
      sqlite3_reset(pStmt);
+
      return SQLITE_CORRUPT_VTAB;
+
    }
+

+
    pCsr->nDoc = nDoc;
+
    pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
+
    assert( pCsr->nRowAvg>0 ); 
+
    rc = sqlite3_reset(pStmt);
+
    if( rc!=SQLITE_OK ) return rc;
+
  }
+

+
  *pnPage = pCsr->nRowAvg;
+
  return SQLITE_OK;
+
}
+

+
static int fts3EvalSelectDeferred(
+
  Fts3Cursor *pCsr,
+
  Fts3Expr *pRoot,
+
  Fts3TokenAndCost *aTC,
+
  int nTC
+
){
+
  int nDocSize = 0;
+
  int nDocEst = 0;
+
  int rc = SQLITE_OK;
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
  int ii;
+

+
  int nOvfl = 0;
+
  int nTerm = 0;
+

+
  for(ii=0; ii<nTC; ii++){
+
    if( aTC[ii].pRoot==pRoot ){
+
      nOvfl += aTC[ii].nOvfl;
+
      nTerm++;
+
    }
+
  }
+
  if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
+

+
  rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
+

+
  for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
+
    int jj;
+
    Fts3TokenAndCost *pTC = 0;
+

+
    for(jj=0; jj<nTC; jj++){
+
      if( aTC[jj].pToken && aTC[jj].pRoot==pRoot 
+
       && (!pTC || aTC[jj].nOvfl<pTC->nOvfl) 
+
      ){
+
        pTC = &aTC[jj];
+
      }
+
    }
+
    assert( pTC );
+

+
    /* At this point pTC points to the cheapest remaining token. */
+
    if( ii==0 ){
+
      if( pTC->nOvfl ){
+
        nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
+
      }else{
+
        Fts3PhraseToken *pToken = pTC->pToken;
+
        int nList = 0;
+
        char *pList = 0;
+
        rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
+
        assert( rc==SQLITE_OK || pList==0 );
+

+
        if( rc==SQLITE_OK ){
+
          nDocEst = fts3DoclistCountDocids(1, pList, nList);
+
          fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
+
        }
+
      }
+
    }else{
+
      if( pTC->nOvfl>=(nDocEst*nDocSize) ){
+
        Fts3PhraseToken *pToken = pTC->pToken;
+
        rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
+
        fts3SegReaderCursorFree(pToken->pSegcsr);
+
        pToken->pSegcsr = 0;
+
      }
+
      nDocEst = 1 + (nDocEst/4);
+
    }
+
    pTC->pToken = 0;
+
  }
+

+
  return rc;
+
}
+

+
SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
  int rc = SQLITE_OK;
+
  int nToken = 0;
+
  int nOr = 0;
+

+
  /* Allocate a MultiSegReader for each token in the expression. */
+
  fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
+

+
  /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
+
  ** This call will eventually also be responsible for determining which
+
  ** tokens are 'deferred' until the document text is loaded into memory.
+
  **
+
  ** Each token in each phrase is dealt with using one of the following
+
  ** three strategies:
+
  **
+
  **   1. Entire doclist loaded into memory as part of the
+
  **      fts3EvalStartReaders() call.
+
  **
+
  **   2. Doclist loaded into memory incrementally, as part of each
+
  **      sqlite3Fts3EvalNext() call.
+
  **
+
  **   3. Token doclist is never loaded. Instead, documents are loaded into
+
  **      memory and scanned for the token as part of the sqlite3Fts3EvalNext()
+
  **      call. This is known as a "deferred" token.
+
  */
+

+
  /* If bOptOk is true, check if there are any tokens that should be deferred.
+
  */
+
  if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
+
    Fts3TokenAndCost *aTC;
+
    Fts3Expr **apOr;
+
    aTC = (Fts3TokenAndCost *)sqlite3_malloc(
+
        sizeof(Fts3TokenAndCost) * nToken
+
      + sizeof(Fts3Expr *) * nOr * 2
+
    );
+
    apOr = (Fts3Expr **)&aTC[nToken];
+

+
    if( !aTC ){
+
      rc = SQLITE_NOMEM;
+
    }else{
+
      int ii;
+
      Fts3TokenAndCost *pTC = aTC;
+
      Fts3Expr **ppOr = apOr;
+

+
      fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
+
      nToken = pTC-aTC;
+
      nOr = ppOr-apOr;
+

+
      if( rc==SQLITE_OK ){
+
        rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
+
        for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
+
          rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
+
        }
+
      }
+

+
      sqlite3_free(aTC);
+
    }
+
  }
+

+
  fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
+
  return rc;
+
}
+

+
static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
+
  if( pPhrase->doclist.bFreeList ){
+
    sqlite3_free(pPhrase->doclist.pList);
+
  }
+
  pPhrase->doclist.pList = 0;
+
  pPhrase->doclist.nList = 0;
+
  pPhrase->doclist.bFreeList = 0;
+
}
+

+
static int fts3EvalNearTrim2(
+
  int nNear,
+
  char *aTmp,                     /* Temporary space to use */
+
  char **paPoslist,               /* IN/OUT: Position list */
+
  int *pnToken,                   /* IN/OUT: Tokens in phrase of *paPoslist */
+
  Fts3Phrase *pPhrase             /* The phrase object to trim the doclist of */
+
){
+
  int nParam1 = nNear + pPhrase->nToken;
+
  int nParam2 = nNear + *pnToken;
+
  int nNew;
+
  char *p2; 
+
  char *pOut; 
+
  int res;
+

+
  assert( pPhrase->doclist.pList );
+

+
  p2 = pOut = pPhrase->doclist.pList;
+
  res = fts3PoslistNearMerge(
+
    &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
+
  );
+
  if( res ){
+
    nNew = (pOut - pPhrase->doclist.pList) - 1;
+
    assert( pPhrase->doclist.pList[nNew]=='\0' );
+
    assert( nNew<=pPhrase->doclist.nList && nNew>0 );
+
    memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
+
    pPhrase->doclist.nList = nNew;
+
    *paPoslist = pPhrase->doclist.pList;
+
    *pnToken = pPhrase->nToken;
+
  }
+

+
  return res;
+
}
+

+
static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
+
  int res = 1;
+

+
  /* The following block runs if pExpr is the root of a NEAR query.
+
  ** For example, the query:
+
  **
+
  **         "w" NEAR "x" NEAR "y" NEAR "z"
+
  **
+
  ** which is represented in tree form as:
+
  **
+
  **                               |
+
  **                          +--NEAR--+      <-- root of NEAR query
+
  **                          |        |
+
  **                     +--NEAR--+   "z"
+
  **                     |        |
+
  **                +--NEAR--+   "y"
+
  **                |        |
+
  **               "w"      "x"
+
  **
+
  ** The right-hand child of a NEAR node is always a phrase. The 
+
  ** left-hand child may be either a phrase or a NEAR node. There are
+
  ** no exceptions to this.
+
  */
+
  if( *pRc==SQLITE_OK 
+
   && pExpr->eType==FTSQUERY_NEAR 
+
   && pExpr->bEof==0
+
   && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
+
  ){
+
    Fts3Expr *p; 
+
    int nTmp = 0;                 /* Bytes of temp space */
+
    char *aTmp;                   /* Temp space for PoslistNearMerge() */
+

+
    /* Allocate temporary working space. */
+
    for(p=pExpr; p->pLeft; p=p->pLeft){
+
      nTmp += p->pRight->pPhrase->doclist.nList;
+
    }
+
    nTmp += p->pPhrase->doclist.nList;
+
    aTmp = sqlite3_malloc(nTmp*2);
+
    if( !aTmp ){
+
      *pRc = SQLITE_NOMEM;
+
      res = 0;
+
    }else{
+
      char *aPoslist = p->pPhrase->doclist.pList;
+
      int nToken = p->pPhrase->nToken;
+

+
      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
+
        Fts3Phrase *pPhrase = p->pRight->pPhrase;
+
        int nNear = p->nNear;
+
        res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+
      }
+
  
+
      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+
      nToken = pExpr->pRight->pPhrase->nToken;
+
      for(p=pExpr->pLeft; p && res; p=p->pLeft){
+
        int nNear = p->pParent->nNear;
+
        Fts3Phrase *pPhrase = (
+
            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+
        );
+
        res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+
      }
+
    }
+

+
    sqlite3_free(aTmp);
+
  }
+

+
  return res;
+
}
+

+
/*
+
** This macro is used by the fts3EvalNext() function. The two arguments are
+
** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
+
** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
+
** it returns (i2 - i1). This allows the same code to be used for merging
+
** doclists in ascending or descending order.
+
*/
+
#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
+

+
static void fts3EvalNext(
+
  Fts3Cursor *pCsr, 
+
  Fts3Expr *pExpr, 
+
  int *pRc
+
){
+
  if( *pRc==SQLITE_OK ){
+
    assert( pExpr->bEof==0 );
+
    pExpr->bStart = 1;
+

+
    switch( pExpr->eType ){
+
      case FTSQUERY_NEAR:
+
      case FTSQUERY_AND: {
+
        Fts3Expr *pLeft = pExpr->pLeft;
+
        Fts3Expr *pRight = pExpr->pRight;
+
        assert( !pLeft->bDeferred || !pRight->bDeferred );
+
        if( pLeft->bDeferred ){
+
          fts3EvalNext(pCsr, pRight, pRc);
+
          pExpr->iDocid = pRight->iDocid;
+
          pExpr->bEof = pRight->bEof;
+
        }else if( pRight->bDeferred ){
+
          fts3EvalNext(pCsr, pLeft, pRc);
+
          pExpr->iDocid = pLeft->iDocid;
+
          pExpr->bEof = pLeft->bEof;
+
        }else{
+
          fts3EvalNext(pCsr, pLeft, pRc);
+
          fts3EvalNext(pCsr, pRight, pRc);
+

+
          while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
+
            sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+
            if( iDiff==0 ) break;
+
            if( iDiff<0 ){
+
              fts3EvalNext(pCsr, pLeft, pRc);
+
            }else{
+
              fts3EvalNext(pCsr, pRight, pRc);
+
            }
+
          }
+

+
          pExpr->iDocid = pLeft->iDocid;
+
          pExpr->bEof = (pLeft->bEof || pRight->bEof);
+
        }
+
        break;
+
      }
+
  
+
      case FTSQUERY_OR: {
+
        Fts3Expr *pLeft = pExpr->pLeft;
+
        Fts3Expr *pRight = pExpr->pRight;
+
        sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+

+
        assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
+
        assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
+

+
        if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
+
          fts3EvalNext(pCsr, pLeft, pRc);
+
        }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
+
          fts3EvalNext(pCsr, pRight, pRc);
+
        }else{
+
          fts3EvalNext(pCsr, pLeft, pRc);
+
          fts3EvalNext(pCsr, pRight, pRc);
+
        }
+

+
        pExpr->bEof = (pLeft->bEof && pRight->bEof);
+
        iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+
        if( pRight->bEof || (pLeft->bEof==0 &&  iCmp<0) ){
+
          pExpr->iDocid = pLeft->iDocid;
+
        }else{
+
          pExpr->iDocid = pRight->iDocid;
+
        }
+

+
        break;
+
      }
+

+
      case FTSQUERY_NOT: {
+
        Fts3Expr *pLeft = pExpr->pLeft;
+
        Fts3Expr *pRight = pExpr->pRight;
+

+
        if( pRight->bStart==0 ){
+
          fts3EvalNext(pCsr, pRight, pRc);
+
          assert( *pRc!=SQLITE_OK || pRight->bStart );
+
        }
+

+
        fts3EvalNext(pCsr, pLeft, pRc);
+
        if( pLeft->bEof==0 ){
+
          while( !*pRc 
+
              && !pRight->bEof 
+
              && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 
+
          ){
+
            fts3EvalNext(pCsr, pRight, pRc);
+
          }
+
        }
+
        pExpr->iDocid = pLeft->iDocid;
+
        pExpr->bEof = pLeft->bEof;
+
        break;
+
      }
+

+
      default: {
+
        Fts3Phrase *pPhrase = pExpr->pPhrase;
+
        fts3EvalZeroPoslist(pPhrase);
+
        *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
+
        pExpr->iDocid = pPhrase->doclist.iDocid;
+
        break;
+
      }
+
    }
+
  }
+
}
+

+
static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
+
  int bHit = 1;
+
  if( *pRc==SQLITE_OK ){
+
    switch( pExpr->eType ){
+
      case FTSQUERY_NEAR:
+
      case FTSQUERY_AND:
+
        bHit = (
+
            fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
+
         && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
+
         && fts3EvalNearTest(pExpr, pRc)
+
        );
+

+
        /* If the NEAR expression does not match any rows, zero the doclist for 
+
        ** all phrases involved in the NEAR. This is because the snippet(),
+
        ** offsets() and matchinfo() functions are not supposed to recognize 
+
        ** any instances of phrases that are part of unmatched NEAR queries. 
+
        ** For example if this expression:
+
        **
+
        **    ... MATCH 'a OR (b NEAR c)'
+
        **
+
        ** is matched against a row containing:
+
        **
+
        **        'a b d e'
+
        **
+
        ** then any snippet() should ony highlight the "a" term, not the "b"
+
        ** (as "b" is part of a non-matching NEAR clause).
+
        */
+
        if( bHit==0 
+
         && pExpr->eType==FTSQUERY_NEAR 
+
         && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
+
        ){
+
          Fts3Expr *p;
+
          for(p=pExpr; p->pPhrase==0; p=p->pLeft){
+
            if( p->pRight->iDocid==pCsr->iPrevId ){
+
              fts3EvalZeroPoslist(p->pRight->pPhrase);
+
            }
+
          }
+
          if( p->iDocid==pCsr->iPrevId ){
+
            fts3EvalZeroPoslist(p->pPhrase);
+
          }
+
        }
+

+
        break;
+

+
      case FTSQUERY_OR: {
+
        int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
+
        int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
+
        bHit = bHit1 || bHit2;
+
        break;
+
      }
+

+
      case FTSQUERY_NOT:
+
        bHit = (
+
            fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
+
         && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
+
        );
+
        break;
+

+
      default: {
+
        if( pCsr->pDeferred 
+
         && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
+
        ){
+
          Fts3Phrase *pPhrase = pExpr->pPhrase;
+
          assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
+
          if( pExpr->bDeferred ){
+
            fts3EvalZeroPoslist(pPhrase);
+
          }
+
          *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
+
          bHit = (pPhrase->doclist.pList!=0);
+
          pExpr->iDocid = pCsr->iPrevId;
+
        }else{
+
          bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
+
        }
+
        break;
+
      }
+
    }
+
  }
+
  return bHit;
+
}
+

+
/*
+
** Return 1 if both of the following are true:
+
**
+
**   1. *pRc is SQLITE_OK when this function returns, and
+
**
+
**   2. After scanning the current FTS table row for the deferred tokens,
+
**      it is determined that the row does not match the query.
+
**
+
** Or, if no error occurs and it seems the current row does match the FTS
+
** query, return 0.
+
*/
+
static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
+
  int rc = *pRc;
+
  int bMiss = 0;
+
  if( rc==SQLITE_OK ){
+
    if( pCsr->pDeferred ){
+
      rc = fts3CursorSeek(0, pCsr);
+
      if( rc==SQLITE_OK ){
+
        rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
+
      }
+
    }
+
    bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
+
    sqlite3Fts3FreeDeferredDoclists(pCsr);
+
    *pRc = rc;
+
  }
+
  return (rc==SQLITE_OK && bMiss);
+
}
+

+
/*
+
** Advance to the next document that matches the FTS expression in
+
** Fts3Cursor.pExpr.
+
*/
+
SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
+
  int rc = SQLITE_OK;             /* Return Code */
+
  Fts3Expr *pExpr = pCsr->pExpr;
+
  assert( pCsr->isEof==0 );
+
  if( pExpr==0 ){
+
    pCsr->isEof = 1;
+
  }else{
+
    do {
+
      if( pCsr->isRequireSeek==0 ){
+
        sqlite3_reset(pCsr->pStmt);
+
      }
+
      assert( sqlite3_data_count(pCsr->pStmt)==0 );
+
      fts3EvalNext(pCsr, pExpr, &rc);
+
      pCsr->isEof = pExpr->bEof;
+
      pCsr->isRequireSeek = 1;
+
      pCsr->isMatchinfoNeeded = 1;
+
      pCsr->iPrevId = pExpr->iDocid;
+
    }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
+
  }
+
  return rc;
+
}
+

+
/*
+
** Restart interation for expression pExpr so that the next call to
+
** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental 
+
** loading or merging of phrase doclists for this iteration.
+
**
+
** If *pRc is other than SQLITE_OK when this function is called, it is
+
** a no-op. If an error occurs within this function, *pRc is set to an
+
** SQLite error code before returning.
+
*/
+
static void fts3EvalRestart(
+
  Fts3Cursor *pCsr,
+
  Fts3Expr *pExpr,
+
  int *pRc
+
){
+
  if( pExpr && *pRc==SQLITE_OK ){
+
    Fts3Phrase *pPhrase = pExpr->pPhrase;
+

+
    if( pPhrase ){
+
      fts3EvalZeroPoslist(pPhrase);
+
      if( pPhrase->bIncr ){
+
        assert( pPhrase->nToken==1 );
+
        assert( pPhrase->aToken[0].pSegcsr );
+
        sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
+
        *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
+
      }
+

+
      pPhrase->doclist.pNextDocid = 0;
+
      pPhrase->doclist.iDocid = 0;
+
    }
+

+
    pExpr->iDocid = 0;
+
    pExpr->bEof = 0;
+
    pExpr->bStart = 0;
+

+
    fts3EvalRestart(pCsr, pExpr->pLeft, pRc);
+
    fts3EvalRestart(pCsr, pExpr->pRight, pRc);
+
  }
+
}
+

+
/*
+
** After allocating the Fts3Expr.aMI[] array for each phrase in the 
+
** expression rooted at pExpr, the cursor iterates through all rows matched
+
** by pExpr, calling this function for each row. This function increments
+
** the values in Fts3Expr.aMI[] according to the position-list currently
+
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase 
+
** expression nodes.
+
*/
+
static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
+
  if( pExpr ){
+
    Fts3Phrase *pPhrase = pExpr->pPhrase;
+
    if( pPhrase && pPhrase->doclist.pList ){
+
      int iCol = 0;
+
      char *p = pPhrase->doclist.pList;
+

+
      assert( *p );
+
      while( 1 ){
+
        u8 c = 0;
+
        int iCnt = 0;
+
        while( 0xFE & (*p | c) ){
+
          if( (c&0x80)==0 ) iCnt++;
+
          c = *p++ & 0x80;
+
        }
+

+
        /* aMI[iCol*3 + 1] = Number of occurrences
+
        ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
+
        */
+
        pExpr->aMI[iCol*3 + 1] += iCnt;
+
        pExpr->aMI[iCol*3 + 2] += (iCnt>0);
+
        if( *p==0x00 ) break;
+
        p++;
+
        p += sqlite3Fts3GetVarint32(p, &iCol);
+
      }
+
    }
+

+
    fts3EvalUpdateCounts(pExpr->pLeft);
+
    fts3EvalUpdateCounts(pExpr->pRight);
+
  }
+
}
+

+
/*
+
** Expression pExpr must be of type FTSQUERY_PHRASE.
+
**
+
** If it is not already allocated and populated, this function allocates and
+
** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
+
** of a NEAR expression, then it also allocates and populates the same array
+
** for all other phrases that are part of the NEAR expression.
+
**
+
** SQLITE_OK is returned if the aMI[] array is successfully allocated and
+
** populated. Otherwise, if an error occurs, an SQLite error code is returned.
+
*/
+
static int fts3EvalGatherStats(
+
  Fts3Cursor *pCsr,               /* Cursor object */
+
  Fts3Expr *pExpr                 /* FTSQUERY_PHRASE expression */
+
){
+
  int rc = SQLITE_OK;             /* Return code */
+

+
  assert( pExpr->eType==FTSQUERY_PHRASE );
+
  if( pExpr->aMI==0 ){
+
    Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
    Fts3Expr *pRoot;                /* Root of NEAR expression */
+
    Fts3Expr *p;                    /* Iterator used for several purposes */
+

+
    sqlite3_int64 iPrevId = pCsr->iPrevId;
+
    sqlite3_int64 iDocid;
+
    u8 bEof;
+

+
    /* Find the root of the NEAR expression */
+
    pRoot = pExpr;
+
    while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){
+
      pRoot = pRoot->pParent;
+
    }
+
    iDocid = pRoot->iDocid;
+
    bEof = pRoot->bEof;
+
    assert( pRoot->bStart );
+

+
    /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */
+
    for(p=pRoot; p; p=p->pLeft){
+
      Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
+
      assert( pE->aMI==0 );
+
      pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
+
      if( !pE->aMI ) return SQLITE_NOMEM;
+
      memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
+
    }
+

+
    fts3EvalRestart(pCsr, pRoot, &rc);
+

+
    while( pCsr->isEof==0 && rc==SQLITE_OK ){
+

+
      do {
+
        /* Ensure the %_content statement is reset. */
+
        if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
+
        assert( sqlite3_data_count(pCsr->pStmt)==0 );
+

+
        /* Advance to the next document */
+
        fts3EvalNext(pCsr, pRoot, &rc);
+
        pCsr->isEof = pRoot->bEof;
+
        pCsr->isRequireSeek = 1;
+
        pCsr->isMatchinfoNeeded = 1;
+
        pCsr->iPrevId = pRoot->iDocid;
+
      }while( pCsr->isEof==0 
+
           && pRoot->eType==FTSQUERY_NEAR 
+
           && fts3EvalLoadDeferred(pCsr, &rc) 
+
      );
+

+
      if( rc==SQLITE_OK && pCsr->isEof==0 ){
+
        fts3EvalUpdateCounts(pRoot);
+
      }
+
    }
+

+
    pCsr->isEof = 0;
+
    pCsr->iPrevId = iPrevId;
+

+
    if( bEof ){
+
      pRoot->bEof = bEof;
+
    }else{
+
      /* Caution: pRoot may iterate through docids in ascending or descending
+
      ** order. For this reason, even though it seems more defensive, the 
+
      ** do loop can not be written:
+
      **
+
      **   do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
+
      */
+
      fts3EvalRestart(pCsr, pRoot, &rc);
+
      do {
+
        fts3EvalNext(pCsr, pRoot, &rc);
+
        assert( pRoot->bEof==0 );
+
      }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
+
      fts3EvalLoadDeferred(pCsr, &rc);
+
    }
+
  }
+
  return rc;
+
}
+

+
/*
+
** This function is used by the matchinfo() module to query a phrase 
+
** expression node for the following information:
+
**
+
**   1. The total number of occurrences of the phrase in each column of 
+
**      the FTS table (considering all rows), and
+
**
+
**   2. For each column, the number of rows in the table for which the
+
**      column contains at least one instance of the phrase.
+
**
+
** If no error occurs, SQLITE_OK is returned and the values for each column
+
** written into the array aiOut as follows:
+
**
+
**   aiOut[iCol*3 + 1] = Number of occurrences
+
**   aiOut[iCol*3 + 2] = Number of rows containing at least one instance
+
**
+
** Caveats:
+
**
+
**   * If a phrase consists entirely of deferred tokens, then all output 
+
**     values are set to the number of documents in the table. In other
+
**     words we assume that very common tokens occur exactly once in each 
+
**     column of each row of the table.
+
**
+
**   * If a phrase contains some deferred tokens (and some non-deferred 
+
**     tokens), count the potential occurrence identified by considering
+
**     the non-deferred tokens instead of actual phrase occurrences.
+
**
+
**   * If the phrase is part of a NEAR expression, then only phrase instances
+
**     that meet the NEAR constraint are included in the counts.
+
*/
+
SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
+
  Fts3Cursor *pCsr,               /* FTS cursor handle */
+
  Fts3Expr *pExpr,                /* Phrase expression */
+
  u32 *aiOut                      /* Array to write results into (see above) */
+
){
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
  int rc = SQLITE_OK;
+
  int iCol;
+

+
  if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
+
    assert( pCsr->nDoc>0 );
+
    for(iCol=0; iCol<pTab->nColumn; iCol++){
+
      aiOut[iCol*3 + 1] = (u32)pCsr->nDoc;
+
      aiOut[iCol*3 + 2] = (u32)pCsr->nDoc;
+
    }
+
  }else{
+
    rc = fts3EvalGatherStats(pCsr, pExpr);
+
    if( rc==SQLITE_OK ){
+
      assert( pExpr->aMI );
+
      for(iCol=0; iCol<pTab->nColumn; iCol++){
+
        aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1];
+
        aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2];
+
      }
+
    }
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** The expression pExpr passed as the second argument to this function
+
** must be of type FTSQUERY_PHRASE. 
+
**
+
** The returned value is either NULL or a pointer to a buffer containing
+
** a position-list indicating the occurrences of the phrase in column iCol
+
** of the current row. 
+
**
+
** More specifically, the returned buffer contains 1 varint for each 
+
** occurence of the phrase in the column, stored using the normal (delta+2) 
+
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
+
** if the requested column contains "a b X c d X X" and the position-list
+
** for 'X' is requested, the buffer returned may contain:
+
**
+
**     0x04 0x05 0x03 0x01   or   0x04 0x05 0x03 0x00
+
**
+
** This function works regardless of whether or not the phrase is deferred,
+
** incremental, or neither.
+
*/
+
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(
+
  Fts3Cursor *pCsr,               /* FTS3 cursor object */
+
  Fts3Expr *pExpr,                /* Phrase to return doclist for */
+
  int iCol                        /* Column to return position list for */
+
){
+
  Fts3Phrase *pPhrase = pExpr->pPhrase;
+
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
  char *pIter = pPhrase->doclist.pList;
+
  int iThis;
+

+
  assert( iCol>=0 && iCol<pTab->nColumn );
+
  if( !pIter 
+
   || pExpr->bEof 
+
   || pExpr->iDocid!=pCsr->iPrevId
+
   || (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) 
+
  ){
+
    return 0;
+
  }
+

+
  assert( pPhrase->doclist.nList>0 );
+
  if( *pIter==0x01 ){
+
    pIter++;
+
    pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+
  }else{
+
    iThis = 0;
+
  }
+
  while( iThis<iCol ){
+
    fts3ColumnlistCopy(0, &pIter);
+
    if( *pIter==0x00 ) return 0;
+
    pIter++;
+
    pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+
  }
+

+
  return ((iCol==iThis)?pIter:0);
+
}
+

+
/*
+
** Free all components of the Fts3Phrase structure that were allocated by
+
** the eval module. Specifically, this means to free:
+
**
+
**   * the contents of pPhrase->doclist, and
+
**   * any Fts3MultiSegReader objects held by phrase tokens.
+
*/
+
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
+
  if( pPhrase ){
+
    int i;
+
    sqlite3_free(pPhrase->doclist.aAll);
+
    fts3EvalZeroPoslist(pPhrase);
+
    memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
+
    for(i=0; i<pPhrase->nToken; i++){
+
      fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
+
      pPhrase->aToken[i].pSegcsr = 0;
+
    }
+
  }
+
}
+

#endif

/************** End of fts3.c ************************************************/
@@ -114471,7 +116446,6 @@ SQLITE_API int sqlite3_extension_init(
******************************************************************************
**
*/
-

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)


@@ -114485,7 +116459,7 @@ struct Fts3auxTable {

struct Fts3auxCursor {
  sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
-
  Fts3SegReaderCursor csr;        /* Must be right after "base" */
+
  Fts3MultiSegReader csr;        /* Must be right after "base" */
  Fts3SegFilter filter;
  char *zStop;
  int nStop;                      /* Byte-length of string zStop */
@@ -114553,6 +116527,7 @@ static int fts3auxConnectMethod(
  p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
  p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
  p->pFts3Tab->db = db;
+
  p->pFts3Tab->nIndex = 1;

  memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
  memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
@@ -114799,6 +116774,7 @@ static int fts3auxFilterMethod(
  int isScan;

  UNUSED_PARAMETER(nVal);
+
  UNUSED_PARAMETER(idxStr);

  assert( idxStr==0 );
  assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
@@ -114832,7 +116808,7 @@ static int fts3auxFilterMethod(
    if( pCsr->zStop==0 ) return SQLITE_NOMEM;
  }

-
  rc = sqlite3Fts3SegReaderCursor(pFts3, FTS3_SEGCURSOR_ALL,
+
  rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL,
      pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
  );
  if( rc==SQLITE_OK ){
@@ -114916,7 +116892,10 @@ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){
     0,                           /* xCommit       */
     0,                           /* xRollback     */
     0,                           /* xFindFunction */
-
     0                            /* xRename       */
+
     0,                           /* xRename       */
+
     0,                           /* xSavepoint    */
+
     0,                           /* xRelease      */
+
     0                            /* xRollbackTo   */
  };
  int rc;                         /* Return code */

@@ -115008,12 +116987,21 @@ SQLITE_API int sqlite3_fts3_enable_parentheses = 0;
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10


+
/*
+
** isNot:
+
**   This variable is used by function getNextNode(). When getNextNode() is
+
**   called, it sets ParseContext.isNot to true if the 'next node' is a 
+
**   FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
+
**   FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
+
**   zero.
+
*/
typedef struct ParseContext ParseContext;
struct ParseContext {
  sqlite3_tokenizer *pTokenizer;      /* Tokenizer module */
  const char **azCol;                 /* Array of column names for fts3 table */
  int nCol;                           /* Number of entries in azCol[] */
  int iDefaultCol;                    /* Default column to query */
+
  int isNot;                          /* True if getNextNode() sees a unary - */
  sqlite3_context *pCtx;              /* Write error message here */
  int nNest;                          /* Number of nested brackets */
};
@@ -115099,7 +117087,7 @@ static int getNextToken(
          iEnd++;
        }
        if( !sqlite3_fts3_enable_parentheses && iStart>0 && z[iStart-1]=='-' ){
-
          pRet->pPhrase->isNot = 1;
+
          pParse->isNot = 1;
        }
      }
      nConsumed = iEnd;
@@ -115151,36 +117139,55 @@ static int getNextString(
  char *zTemp = 0;
  int nTemp = 0;

+
  const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
+
  int nToken = 0;
+

+
  /* The final Fts3Expr data structure, including the Fts3Phrase,
+
  ** Fts3PhraseToken structures token buffers are all stored as a single 
+
  ** allocation so that the expression can be freed with a single call to
+
  ** sqlite3_free(). Setting this up requires a two pass approach.
+
  **
+
  ** The first pass, in the block below, uses a tokenizer cursor to iterate
+
  ** through the tokens in the expression. This pass uses fts3ReallocOrFree()
+
  ** to assemble data in two dynamic buffers:
+
  **
+
  **   Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
+
  **             structure, followed by the array of Fts3PhraseToken 
+
  **             structures. This pass only populates the Fts3PhraseToken array.
+
  **
+
  **   Buffer zTemp: Contains copies of all tokens.
+
  **
+
  ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
+
  ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
+
  ** structures.
+
  */
  rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor);
  if( rc==SQLITE_OK ){
    int ii;
    pCursor->pTokenizer = pTokenizer;
    for(ii=0; rc==SQLITE_OK; ii++){
-
      const char *zToken;
-
      int nToken, iBegin, iEnd, iPos;
-
      rc = pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
+
      const char *zByte;
+
      int nByte, iBegin, iEnd, iPos;
+
      rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
      if( rc==SQLITE_OK ){
-
        int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
-
        p = fts3ReallocOrFree(p, nByte+ii*sizeof(Fts3PhraseToken));
-
        zTemp = fts3ReallocOrFree(zTemp, nTemp + nToken);
-
        if( !p || !zTemp ){
-
          goto no_mem;
-
        }
-
        if( ii==0 ){
-
          memset(p, 0, nByte);
-
          p->pPhrase = (Fts3Phrase *)&p[1];
-
        }
-
        p->pPhrase = (Fts3Phrase *)&p[1];
-
        memset(&p->pPhrase->aToken[ii], 0, sizeof(Fts3PhraseToken));
-
        p->pPhrase->nToken = ii+1;
-
        p->pPhrase->aToken[ii].n = nToken;
-
        memcpy(&zTemp[nTemp], zToken, nToken);
-
        nTemp += nToken;
-
        if( iEnd<nInput && zInput[iEnd]=='*' ){
-
          p->pPhrase->aToken[ii].isPrefix = 1;
-
        }else{
-
          p->pPhrase->aToken[ii].isPrefix = 0;
-
        }
+
        Fts3PhraseToken *pToken;
+

+
        p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
+
        if( !p ) goto no_mem;
+

+
        zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
+
        if( !zTemp ) goto no_mem;
+

+
        assert( nToken==ii );
+
        pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
+
        memset(pToken, 0, sizeof(Fts3PhraseToken));
+

+
        memcpy(&zTemp[nTemp], zByte, nByte);
+
        nTemp += nByte;
+

+
        pToken->n = nByte;
+
        pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
+
        nToken = ii+1;
      }
    }

@@ -115190,28 +117197,24 @@ static int getNextString(

  if( rc==SQLITE_DONE ){
    int jj;
-
    char *zNew = NULL;
-
    int nNew = 0;
-
    int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
-
    nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(Fts3PhraseToken);
-
    p = fts3ReallocOrFree(p, nByte + nTemp);
-
    if( !p ){
-
      goto no_mem;
-
    }
-
    if( zTemp ){
-
      zNew = &(((char *)p)[nByte]);
-
      memcpy(zNew, zTemp, nTemp);
-
    }else{
-
      memset(p, 0, nByte+nTemp);
-
    }
+
    char *zBuf = 0;
+

+
    p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
+
    if( !p ) goto no_mem;
+
    memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
+
    p->eType = FTSQUERY_PHRASE;
    p->pPhrase = (Fts3Phrase *)&p[1];
+
    p->pPhrase->iColumn = pParse->iDefaultCol;
+
    p->pPhrase->nToken = nToken;
+

+
    zBuf = (char *)&p->pPhrase->aToken[nToken];
+
    memcpy(zBuf, zTemp, nTemp);
+
    sqlite3_free(zTemp);
+

    for(jj=0; jj<p->pPhrase->nToken; jj++){
-
      p->pPhrase->aToken[jj].z = &zNew[nNew];
-
      nNew += p->pPhrase->aToken[jj].n;
+
      p->pPhrase->aToken[jj].z = zBuf;
+
      zBuf += p->pPhrase->aToken[jj].n;
    }
-
    sqlite3_free(zTemp);
-
    p->eType = FTSQUERY_PHRASE;
-
    p->pPhrase->iColumn = pParse->iDefaultCol;
    rc = SQLITE_OK;
  }

@@ -115268,6 +117271,8 @@ static int getNextNode(
  const char *zInput = z;
  int nInput = n;

+
  pParse->isNot = 0;
+

  /* Skip over any whitespace before checking for a keyword, an open or
  ** close bracket, or a quoted string. 
  */
@@ -115486,7 +117491,7 @@ static int fts3ExprParse(
      int isPhrase;

      if( !sqlite3_fts3_enable_parentheses 
-
       && p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot 
+
       && p->eType==FTSQUERY_PHRASE && pParse->isNot 
      ){
        /* Create an implicit NOT operator. */
        Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
@@ -115504,7 +117509,6 @@ static int fts3ExprParse(
        p = pPrev;
      }else{
        int eType = p->eType;
-
        assert( eType!=FTSQUERY_PHRASE || !p->pPhrase->isNot );
        isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);

        /* The isRequirePhrase variable is set to true if a phrase or
@@ -115667,9 +117671,11 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
*/
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
  if( p ){
+
    assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
    sqlite3Fts3ExprFree(p->pLeft);
    sqlite3Fts3ExprFree(p->pRight);
-
    sqlite3_free(p->aDoclist);
+
    sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
+
    sqlite3_free(p->aMI);
    sqlite3_free(p);
  }
}
@@ -115726,7 +117732,7 @@ static char *exprToString(Fts3Expr *pExpr, char *zBuf){
      Fts3Phrase *pPhrase = pExpr->pPhrase;
      int i;
      zBuf = sqlite3_mprintf(
-
          "%zPHRASE %d %d", zBuf, pPhrase->iColumn, pPhrase->isNot);
+
          "%zPHRASE %d 0", zBuf, pPhrase->iColumn);
      for(i=0; zBuf && i<pPhrase->nToken; i++){
        zBuf = sqlite3_mprintf("%z %.*s%s", zBuf, 
            pPhrase->aToken[i].n, pPhrase->aToken[i].z,
@@ -116273,7 +118279,6 @@ SQLITE_PRIVATE void *sqlite3Fts3HashInsert(



-

/*
** Class derived from sqlite3_tokenizer
*/
@@ -116913,12 +118918,12 @@ SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
-
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-

#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
#endif

+
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+


/*
** Implementation of the SQL scalar function for accessing the underlying 
@@ -117042,7 +119047,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
){
  int rc;
  char *z = (char *)zArg;
-
  int n;
+
  int n = 0;
  char *zCopy;
  char *zEnd;                     /* Pointer to nul-term of zCopy */
  sqlite3_tokenizer_module *m;
@@ -117407,7 +119412,6 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable(



-

typedef struct simple_tokenizer {
  sqlite3_tokenizer base;
  char delim[128];             /* flag ASCII delimiters */
@@ -117644,14 +119648,40 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(
*/
#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)

+
/*
+
** Under certain circumstances, b-tree nodes (doclists) can be loaded into
+
** memory incrementally instead of all at once. This can be a big performance
+
** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext()
+
** method before retrieving all query results (as may happen, for example,
+
** if a query has a LIMIT clause).
+
**
+
** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD 
+
** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
+
** The code is written so that the hard lower-limit for each of these values 
+
** is 1. Clearly such small values would be inefficient, but can be useful 
+
** for testing purposes.
+
**
+
** If this module is built with SQLITE_TEST defined, these constants may
+
** be overridden at runtime for testing purposes. File fts3_test.c contains
+
** a Tcl interface to read and write the values.
+
*/
+
#ifdef SQLITE_TEST
+
int test_fts3_node_chunksize = (4*1024);
+
int test_fts3_node_chunk_threshold = (4*1024)*4;
+
# define FTS3_NODE_CHUNKSIZE       test_fts3_node_chunksize
+
# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
+
#else
+
# define FTS3_NODE_CHUNKSIZE (4*1024) 
+
# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
+
#endif
+

typedef struct PendingList PendingList;
typedef struct SegmentNode SegmentNode;
typedef struct SegmentWriter SegmentWriter;

/*
-
** Data structure used while accumulating terms in the pending-terms hash
-
** table. The hash table entry maps from term (a string) to a malloc'd
-
** instance of this structure.
+
** An instance of the following data structure is used to build doclists
+
** incrementally. See function fts3PendingListAppend() for details.
*/
struct PendingList {
  int nData;
@@ -117682,7 +119712,6 @@ struct Fts3DeferredToken {
**
**   sqlite3Fts3SegReaderNew()
**   sqlite3Fts3SegReaderFree()
-
**   sqlite3Fts3SegReaderCost()
**   sqlite3Fts3SegReaderIterate()
**
** Methods used to manipulate Fts3SegReader structures:
@@ -117701,6 +119730,9 @@ struct Fts3SegReader {

  char *aNode;                    /* Pointer to node data (or NULL) */
  int nNode;                      /* Size of buffer at aNode (or 0) */
+
  int nPopulate;                  /* If >0, bytes of buffer aNode[] loaded */
+
  sqlite3_blob *pBlob;            /* If not NULL, blob handle to read node */
+

  Fts3HashElem **ppNextElem;

  /* Variables set by fts3SegReaderNext(). These may be read directly
@@ -117714,8 +119746,11 @@ struct Fts3SegReader {
  char *aDoclist;                 /* Pointer to doclist of current entry */
  int nDoclist;                   /* Size of doclist in current entry */

-
  /* The following variables are used to iterate through the current doclist */
+
  /* The following variables are used by fts3SegReaderNextDocid() to iterate 
+
  ** through the current doclist (aDoclist/nDoclist).
+
  */
  char *pOffsetList;
+
  int nOffsetList;                /* For descending pending seg-readers only */
  sqlite3_int64 iDocid;
};

@@ -117753,6 +119788,14 @@ struct SegmentWriter {
**   fts3NodeAddTerm()
**   fts3NodeWrite()
**   fts3NodeFree()
+
**
+
** When a b+tree is written to the database (either as a result of a merge
+
** or the pending-terms table being flushed), leaves are written into the 
+
** database file as soon as they are completely populated. The interior of
+
** the tree is assembled in memory and written out only once all leaves have
+
** been populated and stored. This is Ok, as the b+-tree fanout is usually
+
** very large, meaning that the interior of the tree consumes relatively 
+
** little memory.
*/
struct SegmentNode {
  SegmentNode *pParent;           /* Parent node (or NULL for root node) */
@@ -117783,10 +119826,10 @@ struct SegmentNode {
#define SQL_NEXT_SEGMENTS_ID          10
#define SQL_INSERT_SEGDIR             11
#define SQL_SELECT_LEVEL              12
-
#define SQL_SELECT_ALL_LEVEL          13
+
#define SQL_SELECT_LEVEL_RANGE        13
#define SQL_SELECT_LEVEL_COUNT        14
-
#define SQL_SELECT_SEGDIR_COUNT_MAX   15
-
#define SQL_DELETE_SEGDIR_BY_LEVEL    16
+
#define SQL_SELECT_SEGDIR_MAX_LEVEL   15
+
#define SQL_DELETE_SEGDIR_LEVEL       16
#define SQL_DELETE_SEGMENTS_RANGE     17
#define SQL_CONTENT_INSERT            18
#define SQL_DELETE_DOCSIZE            19
@@ -117795,6 +119838,11 @@ struct SegmentNode {
#define SQL_SELECT_DOCTOTAL           22
#define SQL_REPLACE_DOCTOTAL          23

+
#define SQL_SELECT_ALL_PREFIX_LEVEL   24
+
#define SQL_DELETE_ALL_TERMS_SEGDIR   25
+

+
#define SQL_DELETE_SEGDIR_RANGE       26
+

/*
** This function is used to obtain an SQLite prepared statement handle
** for the statement identified by the second argument. If successful,
@@ -117830,10 +119878,11 @@ static int fts3SqlStmt(
/* 12 */  "SELECT idx, start_block, leaves_end_block, end_block, root "
            "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
/* 13 */  "SELECT idx, start_block, leaves_end_block, end_block, root "
-
            "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC",
+
            "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?"
+
            "ORDER BY level DESC, idx ASC",

/* 14 */  "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
-
/* 15 */  "SELECT count(*), max(level) FROM %Q.'%q_segdir'",
+
/* 15 */  "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",

/* 16 */  "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
/* 17 */  "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
@@ -117843,6 +119892,11 @@ static int fts3SqlStmt(
/* 21 */  "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
/* 22 */  "SELECT value FROM %Q.'%q_stat' WHERE id=0",
/* 23 */  "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
+
/* 24 */  "",
+
/* 25 */  "",
+

+
/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
+

  };
  int rc = SQLITE_OK;
  sqlite3_stmt *pStmt;
@@ -117899,7 +119953,7 @@ static int fts3SelectDocsize(
    rc = sqlite3_step(pStmt);
    if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
      rc = sqlite3_reset(pStmt);
-
      if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT;
+
      if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
      pStmt = 0;
    }else{
      rc = SQLITE_OK;
@@ -117998,14 +120052,32 @@ SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){
**   3: end_block
**   4: root
*/
-
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table *p, int iLevel, sqlite3_stmt **ppStmt){
+
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
+
  Fts3Table *p,                   /* FTS3 table */
+
  int iIndex,                     /* Index for p->aIndex[] */
+
  int iLevel,                     /* Level to select */
+
  sqlite3_stmt **ppStmt           /* OUT: Compiled statement */
+
){
  int rc;
  sqlite3_stmt *pStmt = 0;
+

+
  assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 );
+
  assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
+
  assert( iIndex>=0 && iIndex<p->nIndex );
+

  if( iLevel<0 ){
-
    rc = fts3SqlStmt(p, SQL_SELECT_ALL_LEVEL, &pStmt, 0);
+
    /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
+
    rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
+
    if( rc==SQLITE_OK ){ 
+
      sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
+
      sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1);
+
    }
  }else{
+
    /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
    rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
-
    if( rc==SQLITE_OK ) sqlite3_bind_int(pStmt, 1, iLevel);
+
    if( rc==SQLITE_OK ){ 
+
      sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL);
+
    }
  }
  *ppStmt = pStmt;
  return rc;
@@ -118121,6 +120193,47 @@ static int fts3PendingListAppend(
}

/*
+
** Free a PendingList object allocated by fts3PendingListAppend().
+
*/
+
static void fts3PendingListDelete(PendingList *pList){
+
  sqlite3_free(pList);
+
}
+

+
/*
+
** Add an entry to one of the pending-terms hash tables.
+
*/
+
static int fts3PendingTermsAddOne(
+
  Fts3Table *p,
+
  int iCol,
+
  int iPos,
+
  Fts3Hash *pHash,                /* Pending terms hash table to add entry to */
+
  const char *zToken,
+
  int nToken
+
){
+
  PendingList *pList;
+
  int rc = SQLITE_OK;
+

+
  pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
+
  if( pList ){
+
    p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
+
  }
+
  if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
+
    if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
+
      /* Malloc failed while inserting the new entry. This can only 
+
      ** happen if there was no previous entry for this token.
+
      */
+
      assert( 0==fts3HashFind(pHash, zToken, nToken) );
+
      sqlite3_free(pList);
+
      rc = SQLITE_NOMEM;
+
    }
+
  }
+
  if( rc==SQLITE_OK ){
+
    p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
+
  }
+
  return rc;
+
}
+

+
/*
** Tokenize the nul-terminated string zText and add all tokens to the
** pending-terms hash-table. The docid used is that currently stored in
** p->iPrevDocid, and the column is specified by argument iCol.
@@ -118150,6 +120263,14 @@ static int fts3PendingTermsAdd(

  assert( pTokenizer && pModule );

+
  /* If the user has inserted a NULL value, this function may be called with
+
  ** zText==0. In this case, add zero token entries to the hash table and 
+
  ** return early. */
+
  if( zText==0 ){
+
    *pnWord = 0;
+
    return SQLITE_OK;
+
  }
+

  rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
  if( rc!=SQLITE_OK ){
    return rc;
@@ -118160,8 +120281,7 @@ static int fts3PendingTermsAdd(
  while( SQLITE_OK==rc
      && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
  ){
-
    PendingList *pList;
-
 
+
    int i;
    if( iPos>=nWord ) nWord = iPos+1;

    /* Positions cannot be negative; we use -1 as a terminator internally.
@@ -118172,22 +120292,19 @@ static int fts3PendingTermsAdd(
      break;
    }

-
    pList = (PendingList *)fts3HashFind(&p->pendingTerms, zToken, nToken);
-
    if( pList ){
-
      p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
-
    }
-
    if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
-
      if( pList==fts3HashInsert(&p->pendingTerms, zToken, nToken, pList) ){
-
        /* Malloc failed while inserting the new entry. This can only 
-
        ** happen if there was no previous entry for this token.
-
        */
-
        assert( 0==fts3HashFind(&p->pendingTerms, zToken, nToken) );
-
        sqlite3_free(pList);
-
        rc = SQLITE_NOMEM;
-
      }
-
    }
-
    if( rc==SQLITE_OK ){
-
      p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
+
    /* Add the term to the terms index */
+
    rc = fts3PendingTermsAddOne(
+
        p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
+
    );
+
    
+
    /* Add the term to each of the prefix indexes that it is not too 
+
    ** short for. */
+
    for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
+
      struct Fts3Index *pIndex = &p->aIndex[i];
+
      if( nToken<pIndex->nPrefix ) continue;
+
      rc = fts3PendingTermsAddOne(
+
          p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
+
      );
    }
  }

@@ -118217,14 +120334,19 @@ static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){
}

/*
-
** Discard the contents of the pending-terms hash table. 
+
** Discard the contents of the pending-terms hash tables. 
*/
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
-
  Fts3HashElem *pElem;
-
  for(pElem=fts3HashFirst(&p->pendingTerms); pElem; pElem=fts3HashNext(pElem)){
-
    sqlite3_free(fts3HashData(pElem));
+
  int i;
+
  for(i=0; i<p->nIndex; i++){
+
    Fts3HashElem *pElem;
+
    Fts3Hash *pHash = &p->aIndex[i].hPending;
+
    for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){
+
      PendingList *pList = (PendingList *)fts3HashData(pElem);
+
      fts3PendingListDelete(pList);
+
    }
+
    fts3HashClear(pHash);
  }
-
  fts3HashClear(&p->pendingTerms);
  p->nPendingData = 0;
}

@@ -118240,11 +120362,9 @@ static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
  int i;                          /* Iterator variable */
  for(i=2; i<p->nColumn+2; i++){
    const char *zText = (const char *)sqlite3_value_text(apVal[i]);
-
    if( zText ){
-
      int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
-
      if( rc!=SQLITE_OK ){
-
        return rc;
-
      }
+
    int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
+
    if( rc!=SQLITE_OK ){
+
      return rc;
    }
    aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
  }
@@ -118349,14 +120469,14 @@ static int fts3DeleteAll(Fts3Table *p){
static void fts3DeleteTerms( 
  int *pRC,               /* Result code */
  Fts3Table *p,           /* The FTS table to delete from */
-
  sqlite3_value **apVal,  /* apVal[] contains the docid to be deleted */
+
  sqlite3_value *pRowid,  /* The docid to be deleted */
  u32 *aSz                /* Sizes of deleted document written here */
){
  int rc;
  sqlite3_stmt *pSelect;

  if( *pRC ) return;
-
  rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal);
+
  rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
  if( rc==SQLITE_OK ){
    if( SQLITE_ROW==sqlite3_step(pSelect) ){
      int i;
@@ -118382,7 +120502,7 @@ static void fts3DeleteTerms(
** Forward declaration to account for the circular dependency between
** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
*/
-
static int fts3SegmentMerge(Fts3Table *, int);
+
static int fts3SegmentMerge(Fts3Table *, int, int);

/* 
** This function allocates a new level iLevel index in the segdir table.
@@ -118399,7 +120519,12 @@ static int fts3SegmentMerge(Fts3Table *, int);
** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
** returned. Otherwise, an SQLite error code is returned.
*/
-
static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){
+
static int fts3AllocateSegdirIdx(
+
  Fts3Table *p, 
+
  int iIndex,                     /* Index for p->aIndex */
+
  int iLevel, 
+
  int *piIdx
+
){
  int rc;                         /* Return Code */
  sqlite3_stmt *pNextIdx;         /* Query for next idx at level iLevel */
  int iNext = 0;                  /* Result of query pNextIdx */
@@ -118407,7 +120532,7 @@ static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){
  /* Set variable iNext to the next available segdir index at level iLevel. */
  rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
  if( rc==SQLITE_OK ){
-
    sqlite3_bind_int(pNextIdx, 1, iLevel);
+
    sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
    if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
      iNext = sqlite3_column_int(pNextIdx, 0);
    }
@@ -118421,7 +120546,7 @@ static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){
    ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
    */
    if( iNext>=FTS3_MERGE_COUNT ){
-
      rc = fts3SegmentMerge(p, iLevel);
+
      rc = fts3SegmentMerge(p, iIndex, iLevel);
      *piIdx = 0;
    }else{
      *piIdx = iNext;
@@ -118462,7 +120587,8 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
  Fts3Table *p,                   /* FTS3 table handle */
  sqlite3_int64 iBlockid,         /* Access the row with blockid=$iBlockid */
  char **paBlob,                  /* OUT: Blob data in malloc'd buffer */
-
  int *pnBlob                     /* OUT: Size of blob data */
+
  int *pnBlob,                    /* OUT: Size of blob data */
+
  int *pnLoad                     /* OUT: Bytes actually loaded */
){
  int rc;                         /* Return code */

@@ -118483,11 +120609,16 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(

  if( rc==SQLITE_OK ){
    int nByte = sqlite3_blob_bytes(p->pSegments);
+
    *pnBlob = nByte;
    if( paBlob ){
      char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
      if( !aByte ){
        rc = SQLITE_NOMEM;
      }else{
+
        if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
+
          nByte = FTS3_NODE_CHUNKSIZE;
+
          *pnLoad = nByte;
+
        }
        rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
        memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
        if( rc!=SQLITE_OK ){
@@ -118497,7 +120628,6 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
      }
      *paBlob = aByte;
    }
-
    *pnBlob = nByte;
  }

  return rc;
@@ -118511,13 +120641,55 @@ SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
  sqlite3_blob_close(p->pSegments);
  p->pSegments = 0;
}
+
    
+
static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
+
  int nRead;                      /* Number of bytes to read */
+
  int rc;                         /* Return code */
+

+
  nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
+
  rc = sqlite3_blob_read(
+
      pReader->pBlob, 
+
      &pReader->aNode[pReader->nPopulate],
+
      nRead,
+
      pReader->nPopulate
+
  );
+

+
  if( rc==SQLITE_OK ){
+
    pReader->nPopulate += nRead;
+
    memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
+
    if( pReader->nPopulate==pReader->nNode ){
+
      sqlite3_blob_close(pReader->pBlob);
+
      pReader->pBlob = 0;
+
      pReader->nPopulate = 0;
+
    }
+
  }
+
  return rc;
+
}
+

+
static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
+
  int rc = SQLITE_OK;
+
  assert( !pReader->pBlob 
+
       || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
+
  );
+
  while( pReader->pBlob && rc==SQLITE_OK 
+
     &&  (pFrom - pReader->aNode + nByte)>pReader->nPopulate
+
  ){
+
    rc = fts3SegReaderIncrRead(pReader);
+
  }
+
  return rc;
+
}

/*
** Move the iterator passed as the first argument to the next term in the
** segment. If successful, SQLITE_OK is returned. If there is no next term,
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
-
static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
+
static int fts3SegReaderNext(
+
  Fts3Table *p, 
+
  Fts3SegReader *pReader,
+
  int bIncr
+
){
+
  int rc;                         /* Return code of various sub-routines */
  char *pNext;                    /* Cursor variable */
  int nPrefix;                    /* Number of bytes in term prefix */
  int nSuffix;                    /* Number of bytes in term suffix */
@@ -118529,7 +120701,6 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
  }

  if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
-
    int rc;                       /* Return code from Fts3ReadBlock() */

    if( fts3SegReaderIsPending(pReader) ){
      Fts3HashElem *pElem = *(pReader->ppNextElem);
@@ -118549,6 +120720,8 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){

    if( !fts3SegReaderIsRootOnly(pReader) ){
      sqlite3_free(pReader->aNode);
+
      sqlite3_blob_close(pReader->pBlob);
+
      pReader->pBlob = 0;
    }
    pReader->aNode = 0;

@@ -118560,21 +120733,31 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
    }

    rc = sqlite3Fts3ReadBlock(
-
        p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode
+
        p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, 
+
        (bIncr ? &pReader->nPopulate : 0)
    );
    if( rc!=SQLITE_OK ) return rc;
+
    assert( pReader->pBlob==0 );
+
    if( bIncr && pReader->nPopulate<pReader->nNode ){
+
      pReader->pBlob = p->pSegments;
+
      p->pSegments = 0;
+
    }
    pNext = pReader->aNode;
  }
+

+
  assert( !fts3SegReaderIsPending(pReader) );
+

+
  rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
+
  if( rc!=SQLITE_OK ) return rc;
  
  /* Because of the FTS3_NODE_PADDING bytes of padding, the following is 
-
  ** safe (no risk of overread) even if the node data is corrupted.  
-
  */
+
  ** safe (no risk of overread) even if the node data is corrupted. */
  pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
  pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
  if( nPrefix<0 || nSuffix<=0 
   || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] 
  ){
-
    return SQLITE_CORRUPT;
+
    return SQLITE_CORRUPT_VTAB;
  }

  if( nPrefix+nSuffix>pReader->nTermAlloc ){
@@ -118586,6 +120769,10 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
    pReader->zTerm = zNew;
    pReader->nTermAlloc = nNew;
  }
+

+
  rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX);
+
  if( rc!=SQLITE_OK ) return rc;
+

  memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
  pReader->nTerm = nPrefix+nSuffix;
  pNext += nSuffix;
@@ -118598,9 +120785,9 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
  ** of these statements is untrue, then the data structure is corrupt.
  */
  if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] 
-
   || pReader->aDoclist[pReader->nDoclist-1]
+
   || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
  ){
-
    return SQLITE_CORRUPT;
+
    return SQLITE_CORRUPT_VTAB;
  }
  return SQLITE_OK;
}
@@ -118609,12 +120796,26 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
** Set the SegReader to point to the first docid in the doclist associated
** with the current term.
*/
-
static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
-
  int n;
+
static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
+
  int rc = SQLITE_OK;
  assert( pReader->aDoclist );
  assert( !pReader->pOffsetList );
-
  n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
-
  pReader->pOffsetList = &pReader->aDoclist[n];
+
  if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
+
    u8 bEof = 0;
+
    pReader->iDocid = 0;
+
    pReader->nOffsetList = 0;
+
    sqlite3Fts3DoclistPrev(0,
+
        pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList, 
+
        &pReader->iDocid, &pReader->nOffsetList, &bEof
+
    );
+
  }else{
+
    rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX);
+
    if( rc==SQLITE_OK ){
+
      int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
+
      pReader->pOffsetList = &pReader->aDoclist[n];
+
    }
+
  }
+
  return rc;
}

/*
@@ -118627,128 +120828,125 @@ static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
** *pnOffsetList is set to the length of the set of column-offset
** lists, not including the nul-terminator byte. For example:
*/
-
static void fts3SegReaderNextDocid(
-
  Fts3SegReader *pReader,
-
  char **ppOffsetList,
-
  int *pnOffsetList
+
static int fts3SegReaderNextDocid(
+
  Fts3Table *pTab,
+
  Fts3SegReader *pReader,         /* Reader to advance to next docid */
+
  char **ppOffsetList,            /* OUT: Pointer to current position-list */
+
  int *pnOffsetList               /* OUT: Length of *ppOffsetList in bytes */
){
+
  int rc = SQLITE_OK;
  char *p = pReader->pOffsetList;
  char c = 0;

-
  /* Pointer p currently points at the first byte of an offset list. The
-
  ** following two lines advance it to point one byte past the end of
-
  ** the same offset list.
-
  */
-
  while( *p | c ) c = *p++ & 0x80;
-
  p++;
-

-
  /* If required, populate the output variables with a pointer to and the
-
  ** size of the previous offset-list.
-
  */
-
  if( ppOffsetList ){
-
    *ppOffsetList = pReader->pOffsetList;
-
    *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
-
  }
+
  assert( p );

-
  /* If there are no more entries in the doclist, set pOffsetList to
-
  ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
-
  ** Fts3SegReader.pOffsetList to point to the next offset list before
-
  ** returning.
-
  */
-
  if( p>=&pReader->aDoclist[pReader->nDoclist] ){
-
    pReader->pOffsetList = 0;
+
  if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
+
    /* A pending-terms seg-reader for an FTS4 table that uses order=desc.
+
    ** Pending-terms doclists are always built up in ascending order, so
+
    ** we have to iterate through them backwards here. */
+
    u8 bEof = 0;
+
    if( ppOffsetList ){
+
      *ppOffsetList = pReader->pOffsetList;
+
      *pnOffsetList = pReader->nOffsetList - 1;
+
    }
+
    sqlite3Fts3DoclistPrev(0,
+
        pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid,
+
        &pReader->nOffsetList, &bEof
+
    );
+
    if( bEof ){
+
      pReader->pOffsetList = 0;
+
    }else{
+
      pReader->pOffsetList = p;
+
    }
  }else{
-
    sqlite3_int64 iDelta;
-
    pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
-
    pReader->iDocid += iDelta;
-
  }
-
}
+
    char *pEnd = &pReader->aDoclist[pReader->nDoclist];

-
/*
-
** This function is called to estimate the amount of data that will be 
-
** loaded from the disk If SegReaderIterate() is called on this seg-reader,
-
** in units of average document size.
-
** 
-
** This can be used as follows: If the caller has a small doclist that 
-
** contains references to N documents, and is considering merging it with
-
** a large doclist (size X "average documents"), it may opt not to load
-
** the large doclist if X>N.
-
*/
-
SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(
-
  Fts3Cursor *pCsr,               /* FTS3 cursor handle */
-
  Fts3SegReader *pReader,         /* Segment-reader handle */
-
  int *pnCost                     /* IN/OUT: Number of bytes read */
-
){
-
  Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
-
  int rc = SQLITE_OK;             /* Return code */
-
  int nCost = 0;                  /* Cost in bytes to return */
-
  int pgsz = p->nPgsz;            /* Database page size */
-

-
  /* If this seg-reader is reading the pending-terms table, or if all data
-
  ** for the segment is stored on the root page of the b-tree, then the cost
-
  ** is zero. In this case all required data is already in main memory.
-
  */
-
  if( p->bHasStat 
-
   && !fts3SegReaderIsPending(pReader) 
-
   && !fts3SegReaderIsRootOnly(pReader) 
-
  ){
-
    int nBlob = 0;
-
    sqlite3_int64 iBlock;
-

-
    if( pCsr->nRowAvg==0 ){
-
      /* The average document size, which is required to calculate the cost
-
      ** of each doclist, has not yet been determined. Read the required 
-
      ** data from the %_stat table to calculate it.
-
      **
-
      ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 
-
      ** varints, where nCol is the number of columns in the FTS3 table.
-
      ** The first varint is the number of documents currently stored in
-
      ** the table. The following nCol varints contain the total amount of
-
      ** data stored in all rows of each column of the table, from left
-
      ** to right.
+
    /* Pointer p currently points at the first byte of an offset list. The
+
    ** following block advances it to point one byte past the end of
+
    ** the same offset list. */
+
    while( 1 ){
+
  
+
      /* The following line of code (and the "p++" below the while() loop) is
+
      ** normally all that is required to move pointer p to the desired 
+
      ** position. The exception is if this node is being loaded from disk
+
      ** incrementally and pointer "p" now points to the first byte passed
+
      ** the populated part of pReader->aNode[].
      */
-
      sqlite3_stmt *pStmt;
-
      sqlite3_int64 nDoc = 0;
-
      sqlite3_int64 nByte = 0;
-
      const char *pEnd;
-
      const char *a;
-

-
      rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
-
      if( rc!=SQLITE_OK ) return rc;
-
      a = sqlite3_column_blob(pStmt, 0);
-
      assert( a );
-

-
      pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
-
      a += sqlite3Fts3GetVarint(a, &nDoc);
-
      while( a<pEnd ){
-
        a += sqlite3Fts3GetVarint(a, &nByte);
-
      }
-
      if( nDoc==0 || nByte==0 ){
-
        sqlite3_reset(pStmt);
-
        return SQLITE_CORRUPT;
-
      }
-

-
      pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
-
      assert( pCsr->nRowAvg>0 ); 
-
      rc = sqlite3_reset(pStmt);
+
      while( *p | c ) c = *p++ & 0x80;
+
      assert( *p==0 );
+
  
+
      if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
+
      rc = fts3SegReaderIncrRead(pReader);
      if( rc!=SQLITE_OK ) return rc;
    }
+
    p++;
+
  
+
    /* If required, populate the output variables with a pointer to and the
+
    ** size of the previous offset-list.
+
    */
+
    if( ppOffsetList ){
+
      *ppOffsetList = pReader->pOffsetList;
+
      *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
+
    }

-
    /* Assume that a blob flows over onto overflow pages if it is larger
-
    ** than (pgsz-35) bytes in size (the file-format documentation
-
    ** confirms this).
+
    while( p<pEnd && *p==0 ) p++;
+
  
+
    /* If there are no more entries in the doclist, set pOffsetList to
+
    ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
+
    ** Fts3SegReader.pOffsetList to point to the next offset list before
+
    ** returning.
    */
-
    for(iBlock=pReader->iStartBlock; iBlock<=pReader->iLeafEndBlock; iBlock++){
-
      rc = sqlite3Fts3ReadBlock(p, iBlock, 0, &nBlob);
-
      if( rc!=SQLITE_OK ) break;
-
      if( (nBlob+35)>pgsz ){
-
        int nOvfl = (nBlob + 34)/pgsz;
-
        nCost += ((nOvfl + pCsr->nRowAvg - 1)/pCsr->nRowAvg);
+
    if( p>=pEnd ){
+
      pReader->pOffsetList = 0;
+
    }else{
+
      rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
+
      if( rc==SQLITE_OK ){
+
        sqlite3_int64 iDelta;
+
        pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
+
        if( pTab->bDescIdx ){
+
          pReader->iDocid -= iDelta;
+
        }else{
+
          pReader->iDocid += iDelta;
+
        }
      }
    }
  }

-
  *pnCost += nCost;
+
  return SQLITE_OK;
+
}
+

+

+
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(
+
  Fts3Cursor *pCsr, 
+
  Fts3MultiSegReader *pMsr,
+
  int *pnOvfl
+
){
+
  Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
+
  int nOvfl = 0;
+
  int ii;
+
  int rc = SQLITE_OK;
+
  int pgsz = p->nPgsz;
+

+
  assert( p->bHasStat );
+
  assert( pgsz>0 );
+

+
  for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
+
    Fts3SegReader *pReader = pMsr->apSegment[ii];
+
    if( !fts3SegReaderIsPending(pReader) 
+
     && !fts3SegReaderIsRootOnly(pReader) 
+
    ){
+
      sqlite3_int64 jj;
+
      for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
+
        int nBlob;
+
        rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
+
        if( rc!=SQLITE_OK ) break;
+
        if( (nBlob+35)>pgsz ){
+
          nOvfl += (nBlob + 34)/pgsz;
+
        }
+
      }
+
    }
+
  }
+
  *pnOvfl = nOvfl;
  return rc;
}

@@ -118761,6 +120959,7 @@ SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
    sqlite3_free(pReader->zTerm);
    if( !fts3SegReaderIsRootOnly(pReader) ){
      sqlite3_free(pReader->aNode);
+
      sqlite3_blob_close(pReader->pBlob);
    }
  }
  sqlite3_free(pReader);
@@ -118837,24 +121036,42 @@ static int fts3CompareElemByTerm(const void *lhs, const void *rhs){
/*
** This function is used to allocate an Fts3SegReader that iterates through
** a subset of the terms stored in the Fts3Table.pendingTerms array.
+
**
+
** If the isPrefixIter parameter is zero, then the returned SegReader iterates
+
** through each term in the pending-terms table. Or, if isPrefixIter is
+
** non-zero, it iterates through each term and its prefixes. For example, if
+
** the pending terms hash table contains the terms "sqlite", "mysql" and
+
** "firebird", then the iterator visits the following 'terms' (in the order
+
** shown):
+
**
+
**   f fi fir fire fireb firebi firebir firebird
+
**   m my mys mysq mysql
+
**   s sq sql sqli sqlit sqlite
+
**
+
** Whereas if isPrefixIter is zero, the terms visited are:
+
**
+
**   firebird mysql sqlite
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
  Fts3Table *p,                   /* Virtual table handle */
+
  int iIndex,                     /* Index for p->aIndex */
  const char *zTerm,              /* Term to search for */
  int nTerm,                      /* Size of buffer zTerm */
-
  int isPrefix,                   /* True for a term-prefix query */
+
  int bPrefix,                    /* True for a prefix iterator */
  Fts3SegReader **ppReader        /* OUT: SegReader for pending-terms */
){
  Fts3SegReader *pReader = 0;     /* Fts3SegReader object to return */
  Fts3HashElem **aElem = 0;       /* Array of term hash entries to scan */
  int nElem = 0;                  /* Size of array at aElem */
  int rc = SQLITE_OK;             /* Return Code */
+
  Fts3Hash *pHash;

-
  if( isPrefix ){
+
  pHash = &p->aIndex[iIndex].hPending;
+
  if( bPrefix ){
    int nAlloc = 0;               /* Size of allocated array at aElem */
    Fts3HashElem *pE = 0;         /* Iterator variable */

-
    for(pE=fts3HashFirst(&p->pendingTerms); pE; pE=fts3HashNext(pE)){
+
    for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
      char *zKey = (char *)fts3HashKey(pE);
      int nKey = fts3HashKeysize(pE);
      if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
@@ -118871,6 +121088,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
          }
          aElem = aElem2;
        }
+

        aElem[nElem++] = pE;
      }
    }
@@ -118884,7 +121102,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
    }

  }else{
-
    Fts3HashElem *pE = fts3HashFindElem(&p->pendingTerms, zTerm, nTerm);
+
    /* The query is a simple term lookup that matches at most one term in
+
    ** the index. All that is required is a straight hash-lookup. */
+
    Fts3HashElem *pE = fts3HashFindElem(pHash, zTerm, nTerm);
    if( pE ){
      aElem = &pE;
      nElem = 1;
@@ -118904,7 +121124,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
    }
  }

-
  if( isPrefix ){
+
  if( bPrefix ){
    sqlite3_free(aElem);
  }
  *ppReader = pReader;
@@ -118968,6 +121188,18 @@ static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
  assert( pLhs->aNode && pRhs->aNode );
  return rc;
}
+
static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
+
  int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
+
  if( rc==0 ){
+
    if( pLhs->iDocid==pRhs->iDocid ){
+
      rc = pRhs->iIdx - pLhs->iIdx;
+
    }else{
+
      rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1;
+
    }
+
  }
+
  assert( pLhs->aNode && pRhs->aNode );
+
  return rc;
+
}

/*
** Compare the term that the Fts3SegReader object passed as the first argument
@@ -119496,16 +121728,16 @@ static void fts3SegWriterFree(SegmentWriter *pWriter){
** The first value in the apVal[] array is assumed to contain an integer.
** This function tests if there exist any documents with docid values that
** are different from that integer. i.e. if deleting the document with docid
-
** apVal[0] would mean the FTS3 table were empty.
+
** pRowid would mean the FTS3 table were empty.
**
** If successful, *pisEmpty is set to true if the table is empty except for
-
** document apVal[0], or false otherwise, and SQLITE_OK is returned. If an
+
** document pRowid, or false otherwise, and SQLITE_OK is returned. If an
** error occurs, an SQLite error code is returned.
*/
-
static int fts3IsEmpty(Fts3Table *p, sqlite3_value **apVal, int *pisEmpty){
+
static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
  sqlite3_stmt *pStmt;
  int rc;
-
  rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, apVal);
+
  rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
  if( rc==SQLITE_OK ){
    if( SQLITE_ROW==sqlite3_step(pStmt) ){
      *pisEmpty = sqlite3_column_int(pStmt, 0);
@@ -119516,21 +121748,30 @@ static int fts3IsEmpty(Fts3Table *p, sqlite3_value **apVal, int *pisEmpty){
}

/*
-
** Set *pnSegment to the total number of segments in the database. Set
-
** *pnMax to the largest segment level in the database (segment levels
-
** are stored in the 'level' column of the %_segdir table).
+
** Set *pnMax to the largest segment level in the database for the index
+
** iIndex.
+
**
+
** Segment levels are stored in the 'level' column of the %_segdir table.
**
** Return SQLITE_OK if successful, or an SQLite error code if not.
*/
-
static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
+
static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){
  sqlite3_stmt *pStmt;
  int rc;
+
  assert( iIndex>=0 && iIndex<p->nIndex );

-
  rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_COUNT_MAX, &pStmt, 0);
+
  /* Set pStmt to the compiled version of:
+
  **
+
  **   SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
+
  **
+
  ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
+
  */
+
  rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
  if( rc!=SQLITE_OK ) return rc;
+
  sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
+
  sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1);
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
-
    *pnSegment = sqlite3_column_int(pStmt, 0);
-
    *pnMax = sqlite3_column_int(pStmt, 1);
+
    *pnMax = sqlite3_column_int(pStmt, 0);
  }
  return sqlite3_reset(pStmt);
}
@@ -119551,6 +121792,7 @@ static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
*/
static int fts3DeleteSegdir(
  Fts3Table *p,                   /* Virtual table handle */
+
  int iIndex,                     /* Index for p->aIndex */
  int iLevel,                     /* Level of %_segdir entries to delete */
  Fts3SegReader **apSegment,      /* Array of SegReader objects */
  int nReader                     /* Size of array apSegment */
@@ -119573,20 +121815,25 @@ static int fts3DeleteSegdir(
    return rc;
  }

+
  assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
  if( iLevel==FTS3_SEGCURSOR_ALL ){
-
    fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
-
  }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
-
    sqlite3Fts3PendingTermsClear(p);
+
    rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
+
    if( rc==SQLITE_OK ){
+
      sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
+
      sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1);
+
    }
  }else{
-
    assert( iLevel>=0 );
-
    rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_BY_LEVEL, &pDelete, 0);
+
    rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
    if( rc==SQLITE_OK ){
-
      sqlite3_bind_int(pDelete, 1, iLevel);
-
      sqlite3_step(pDelete);
-
      rc = sqlite3_reset(pDelete);
+
      sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
    }
  }

+
  if( rc==SQLITE_OK ){
+
    sqlite3_step(pDelete);
+
    rc = sqlite3_reset(pDelete);
+
  }
+

  return rc;
}

@@ -119633,15 +121880,106 @@ static void fts3ColumnFilter(
  *pnList = nList;
}

-
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
+
/*
+
** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
+
** existing data). Grow the buffer if required.
+
**
+
** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
+
** trying to resize the buffer, return SQLITE_NOMEM.
+
*/
+
static int fts3MsrBufferData(
+
  Fts3MultiSegReader *pMsr,       /* Multi-segment-reader handle */
+
  char *pList,
+
  int nList
+
){
+
  if( nList>pMsr->nBuffer ){
+
    char *pNew;
+
    pMsr->nBuffer = nList*2;
+
    pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
+
    if( !pNew ) return SQLITE_NOMEM;
+
    pMsr->aBuffer = pNew;
+
  }
+

+
  memcpy(pMsr->aBuffer, pList, nList);
+
  return SQLITE_OK;
+
}
+

+
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
  Fts3Table *p,                   /* Virtual table handle */
-
  Fts3SegReaderCursor *pCsr,      /* Cursor object */
-
  Fts3SegFilter *pFilter          /* Restrictions on range of iteration */
+
  Fts3MultiSegReader *pMsr,       /* Multi-segment-reader handle */
+
  sqlite3_int64 *piDocid,         /* OUT: Docid value */
+
  char **paPoslist,               /* OUT: Pointer to position list */
+
  int *pnPoslist                  /* OUT: Size of position list in bytes */
+
){
+
  int nMerge = pMsr->nAdvance;
+
  Fts3SegReader **apSegment = pMsr->apSegment;
+
  int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
+
    p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
+
  );
+

+
  if( nMerge==0 ){
+
    *paPoslist = 0;
+
    return SQLITE_OK;
+
  }
+

+
  while( 1 ){
+
    Fts3SegReader *pSeg;
+
    pSeg = pMsr->apSegment[0];
+

+
    if( pSeg->pOffsetList==0 ){
+
      *paPoslist = 0;
+
      break;
+
    }else{
+
      int rc;
+
      char *pList;
+
      int nList;
+
      int j;
+
      sqlite3_int64 iDocid = apSegment[0]->iDocid;
+

+
      rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
+
      j = 1;
+
      while( rc==SQLITE_OK 
+
        && j<nMerge
+
        && apSegment[j]->pOffsetList
+
        && apSegment[j]->iDocid==iDocid
+
      ){
+
        rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
+
        j++;
+
      }
+
      if( rc!=SQLITE_OK ) return rc;
+
      fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
+

+
      if( pMsr->iColFilter>=0 ){
+
        fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
+
      }
+

+
      if( nList>0 ){
+
        if( fts3SegReaderIsPending(apSegment[0]) ){
+
          rc = fts3MsrBufferData(pMsr, pList, nList+1);
+
          if( rc!=SQLITE_OK ) return rc;
+
          *paPoslist = pMsr->aBuffer;
+
          assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
+
        }else{
+
          *paPoslist = pList;
+
        }
+
        *piDocid = iDocid;
+
        *pnPoslist = nList;
+
        break;
+
      }
+
    }
+
  }
+

+
  return SQLITE_OK;
+
}
+

+
static int fts3SegReaderStart(
+
  Fts3Table *p,                   /* Virtual table handle */
+
  Fts3MultiSegReader *pCsr,       /* Cursor object */
+
  const char *zTerm,              /* Term searched for (or NULL) */
+
  int nTerm                       /* Length of zTerm in bytes */
){
  int i;
-

-
  /* Initialize the cursor object */
-
  pCsr->pFilter = pFilter;
+
  int nSeg = pCsr->nSegment;

  /* If the Fts3SegFilter defines a specific term (or term prefix) to search 
  ** for, then advance each segment iterator until it points to a term of
@@ -119649,24 +121987,105 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
  ** unnecessary merge/sort operations for the case where single segment
  ** b-tree leaf nodes contain more than one term.
  */
-
  for(i=0; i<pCsr->nSegment; i++){
-
    int nTerm = pFilter->nTerm;
-
    const char *zTerm = pFilter->zTerm;
+
  for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
    Fts3SegReader *pSeg = pCsr->apSegment[i];
    do {
-
      int rc = fts3SegReaderNext(p, pSeg);
+
      int rc = fts3SegReaderNext(p, pSeg, 0);
      if( rc!=SQLITE_OK ) return rc;
    }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
  }
-
  fts3SegReaderSort(
-
      pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp);
+
  fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);

  return SQLITE_OK;
}

+
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
+
  Fts3Table *p,                   /* Virtual table handle */
+
  Fts3MultiSegReader *pCsr,       /* Cursor object */
+
  Fts3SegFilter *pFilter          /* Restrictions on range of iteration */
+
){
+
  pCsr->pFilter = pFilter;
+
  return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm);
+
}
+

+
SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
+
  Fts3Table *p,                   /* Virtual table handle */
+
  Fts3MultiSegReader *pCsr,       /* Cursor object */
+
  int iCol,                       /* Column to match on. */
+
  const char *zTerm,              /* Term to iterate through a doclist for */
+
  int nTerm                       /* Number of bytes in zTerm */
+
){
+
  int i;
+
  int rc;
+
  int nSegment = pCsr->nSegment;
+
  int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
+
    p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
+
  );
+

+
  assert( pCsr->pFilter==0 );
+
  assert( zTerm && nTerm>0 );
+

+
  /* Advance each segment iterator until it points to the term zTerm/nTerm. */
+
  rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm);
+
  if( rc!=SQLITE_OK ) return rc;
+

+
  /* Determine how many of the segments actually point to zTerm/nTerm. */
+
  for(i=0; i<nSegment; i++){
+
    Fts3SegReader *pSeg = pCsr->apSegment[i];
+
    if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
+
      break;
+
    }
+
  }
+
  pCsr->nAdvance = i;
+

+
  /* Advance each of the segments to point to the first docid. */
+
  for(i=0; i<pCsr->nAdvance; i++){
+
    rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
+
    if( rc!=SQLITE_OK ) return rc;
+
  }
+
  fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
+

+
  assert( iCol<0 || iCol<p->nColumn );
+
  pCsr->iColFilter = iCol;
+

+
  return SQLITE_OK;
+
}
+

+
/*
+
** This function is called on a MultiSegReader that has been started using
+
** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also
+
** have been made. Calling this function puts the MultiSegReader in such
+
** a state that if the next two calls are:
+
**
+
**   sqlite3Fts3SegReaderStart()
+
**   sqlite3Fts3SegReaderStep()
+
**
+
** then the entire doclist for the term is available in 
+
** MultiSegReader.aDoclist/nDoclist.
+
*/
+
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
+
  int i;                          /* Used to iterate through segment-readers */
+

+
  assert( pCsr->zTerm==0 );
+
  assert( pCsr->nTerm==0 );
+
  assert( pCsr->aDoclist==0 );
+
  assert( pCsr->nDoclist==0 );
+

+
  pCsr->nAdvance = 0;
+
  pCsr->bRestart = 1;
+
  for(i=0; i<pCsr->nSegment; i++){
+
    pCsr->apSegment[i]->pOffsetList = 0;
+
    pCsr->apSegment[i]->nOffsetList = 0;
+
    pCsr->apSegment[i]->iDocid = 0;
+
  }
+

+
  return SQLITE_OK;
+
}
+

+

SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
  Fts3Table *p,                   /* Virtual table handle */
-
  Fts3SegReaderCursor *pCsr       /* Cursor object */
+
  Fts3MultiSegReader *pCsr        /* Cursor object */
){
  int rc = SQLITE_OK;

@@ -119679,6 +122098,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
  Fts3SegReader **apSegment = pCsr->apSegment;
  int nSegment = pCsr->nSegment;
  Fts3SegFilter *pFilter = pCsr->pFilter;
+
  int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
+
    p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
+
  );

  if( pCsr->nSegment==0 ) return SQLITE_OK;

@@ -119690,7 +122112,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
    ** forward. Then sort the list in order of current term again.  
    */
    for(i=0; i<pCsr->nAdvance; i++){
-
      rc = fts3SegReaderNext(p, apSegment[i]);
+
      rc = fts3SegReaderNext(p, apSegment[i], 0);
      if( rc!=SQLITE_OK ) return rc;
    }
    fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
@@ -119729,10 +122151,18 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
    }

    assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
-
    if( nMerge==1 && !isIgnoreEmpty ){
-
      pCsr->aDoclist = apSegment[0]->aDoclist;
+
    if( nMerge==1 
+
     && !isIgnoreEmpty 
+
     && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
+
    ){
      pCsr->nDoclist = apSegment[0]->nDoclist;
-
      rc = SQLITE_ROW;
+
      if( fts3SegReaderIsPending(apSegment[0]) ){
+
        rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
+
        pCsr->aDoclist = pCsr->aBuffer;
+
      }else{
+
        pCsr->aDoclist = apSegment[0]->aDoclist;
+
      }
+
      if( rc==SQLITE_OK ) rc = SQLITE_ROW;
    }else{
      int nDoclist = 0;           /* Size of doclist */
      sqlite3_int64 iPrev = 0;    /* Previous docid stored in doclist */
@@ -119742,22 +122172,22 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
      ** and a single term returned with the merged doclist.
      */
      for(i=0; i<nMerge; i++){
-
        fts3SegReaderFirstDocid(apSegment[i]);
+
        fts3SegReaderFirstDocid(p, apSegment[i]);
      }
-
      fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderDoclistCmp);
+
      fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
      while( apSegment[0]->pOffsetList ){
        int j;                    /* Number of segments that share a docid */
        char *pList;
        int nList;
        int nByte;
        sqlite3_int64 iDocid = apSegment[0]->iDocid;
-
        fts3SegReaderNextDocid(apSegment[0], &pList, &nList);
+
        fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
        j = 1;
        while( j<nMerge
            && apSegment[j]->pOffsetList
            && apSegment[j]->iDocid==iDocid
        ){
-
          fts3SegReaderNextDocid(apSegment[j], 0, 0);
+
          fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
          j++;
        }

@@ -119766,7 +122196,19 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
        }

        if( !isIgnoreEmpty || nList>0 ){
-
          nByte = sqlite3Fts3VarintLen(iDocid-iPrev) + (isRequirePos?nList+1:0);
+

+
          /* Calculate the 'docid' delta value to write into the merged 
+
          ** doclist. */
+
          sqlite3_int64 iDelta;
+
          if( p->bDescIdx && nDoclist>0 ){
+
            iDelta = iPrev - iDocid;
+
          }else{
+
            iDelta = iDocid - iPrev;
+
          }
+
          assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
+
          assert( nDoclist>0 || iDelta==iDocid );
+

+
          nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
          if( nDoclist+nByte>pCsr->nBuffer ){
            char *aNew;
            pCsr->nBuffer = (nDoclist+nByte)*2;
@@ -119776,9 +122218,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
            }
            pCsr->aBuffer = aNew;
          }
-
          nDoclist += sqlite3Fts3PutVarint(
-
              &pCsr->aBuffer[nDoclist], iDocid-iPrev
-
          );
+
          nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
          iPrev = iDocid;
          if( isRequirePos ){
            memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
@@ -119787,7 +122227,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
          }
        }

-
        fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderDoclistCmp);
+
        fts3SegReaderSort(apSegment, nMerge, j, xCmp);
      }
      if( nDoclist>0 ){
        pCsr->aDoclist = pCsr->aBuffer;
@@ -119801,8 +122241,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
  return rc;
}

+

SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
-
  Fts3SegReaderCursor *pCsr       /* Cursor object */
+
  Fts3MultiSegReader *pCsr       /* Cursor object */
){
  if( pCsr ){
    int i;
@@ -119829,43 +122270,56 @@ SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, 
** an SQLite error code is returned.
*/
-
static int fts3SegmentMerge(Fts3Table *p, int iLevel){
+
static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){
  int rc;                         /* Return code */
  int iIdx = 0;                   /* Index of new segment */
-
  int iNewLevel = 0;              /* Level to create new segment at */
+
  int iNewLevel = 0;              /* Level/index to create new segment at */
  SegmentWriter *pWriter = 0;     /* Used to write the new, merged, segment */
  Fts3SegFilter filter;           /* Segment term filter condition */
-
  Fts3SegReaderCursor csr;        /* Cursor to iterate through level(s) */
+
  Fts3MultiSegReader csr;        /* Cursor to iterate through level(s) */
+
  int bIgnoreEmpty = 0;           /* True to ignore empty segments */

-
  rc = sqlite3Fts3SegReaderCursor(p, iLevel, 0, 0, 1, 0, &csr);
+
  assert( iLevel==FTS3_SEGCURSOR_ALL
+
       || iLevel==FTS3_SEGCURSOR_PENDING
+
       || iLevel>=0
+
  );
+
  assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
+
  assert( iIndex>=0 && iIndex<p->nIndex );
+

+
  rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr);
  if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;

  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 
-
    ** greatest segment level currently present in the database. The index
-
    ** of the new segment is always 0.  */
-
    int nDummy; /* TODO: Remove this */
+
    ** greatest segment level currently present in the database for this
+
    ** index. The idx of the new segment is always 0.  */
    if( csr.nSegment==1 ){
      rc = SQLITE_DONE;
      goto finished;
    }
-
    rc = fts3SegmentCountMax(p, &nDummy, &iNewLevel);
+
    rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel);
+
    bIgnoreEmpty = 1;
+

+
  }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
+
    iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL; 
+
    rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx);
  }else{
-
    /* This call is to merge all segments at level iLevel. Find the next
+
    /* This call is to merge all segments at level iLevel. find the next
    ** available segment index at level iLevel+1. The call to
    ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to 
    ** a single iLevel+2 segment if necessary.  */
-
    iNewLevel = iLevel+1;
-
    rc = fts3AllocateSegdirIdx(p, iNewLevel, &iIdx);
+
    rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx);
+
    iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1;
  }
  if( rc!=SQLITE_OK ) goto finished;
  assert( csr.nSegment>0 );
-
  assert( iNewLevel>=0 );
+
  assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) );
+
  assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) );

  memset(&filter, 0, sizeof(Fts3SegFilter));
  filter.flags = FTS3_SEGMENT_REQUIRE_POS;
-
  filter.flags |= (iLevel==FTS3_SEGCURSOR_ALL ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
+
  filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);

  rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
  while( SQLITE_OK==rc ){
@@ -119877,8 +122331,10 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
  if( rc!=SQLITE_OK ) goto finished;
  assert( pWriter );

-
  rc = fts3DeleteSegdir(p, iLevel, csr.apSegment, csr.nSegment);
-
  if( rc!=SQLITE_OK ) goto finished;
+
  if( iLevel!=FTS3_SEGCURSOR_PENDING ){
+
    rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment);
+
    if( rc!=SQLITE_OK ) goto finished;
+
  }
  rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);

 finished:
@@ -119889,10 +122345,17 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){


/* 
-
** Flush the contents of pendingTerms to a level 0 segment.
+
** Flush the contents of pendingTerms to level 0 segments.
*/
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
-
  return fts3SegmentMerge(p, FTS3_SEGCURSOR_PENDING);
+
  int rc = SQLITE_OK;
+
  int i;
+
  for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
+
    rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING);
+
    if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+
  }
+
  sqlite3Fts3PendingTermsClear(p);
+
  return rc;
}

/*
@@ -120043,6 +122506,23 @@ static void fts3UpdateDocTotals(
  sqlite3_free(a);
}

+
static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
+
  int i;
+
  int bSeenDone = 0;
+
  int rc = SQLITE_OK;
+
  for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
+
    rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL);
+
    if( rc==SQLITE_DONE ){
+
      bSeenDone = 1;
+
      rc = SQLITE_OK;
+
    }
+
  }
+
  sqlite3Fts3SegmentsClose(p);
+
  sqlite3Fts3PendingTermsClear(p);
+

+
  return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
+
}
+

/*
** Handle a 'special' INSERT of the form:
**
@@ -120059,12 +122539,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
  if( !zVal ){
    return SQLITE_NOMEM;
  }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
-
    rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL);
-
    if( rc==SQLITE_DONE ){
-
      rc = SQLITE_OK;
-
    }else{
-
      sqlite3Fts3PendingTermsClear(p);
-
    }
+
    rc = fts3DoOptimize(p, 0);
#ifdef SQLITE_TEST
  }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
    p->nNodeSize = atoi(&zVal[9]);
@@ -120077,57 +122552,19 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
    rc = SQLITE_ERROR;
  }

-
  sqlite3Fts3SegmentsClose(p);
  return rc;
}

/*
-
** Return the deferred doclist associated with deferred token pDeferred.
-
** This function assumes that sqlite3Fts3CacheDeferredDoclists() has already
-
** been called to allocate and populate the doclist.
-
*/
-
SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *pDeferred, int *pnByte){
-
  if( pDeferred->pList ){
-
    *pnByte = pDeferred->pList->nData;
-
    return pDeferred->pList->aData;
-
  }
-
  *pnByte = 0;
-
  return 0;
-
}
-

-
/*
-
** Helper fucntion for FreeDeferredDoclists(). This function removes all
-
** references to deferred doclists from within the tree of Fts3Expr 
-
** structures headed by 
-
*/
-
static void fts3DeferredDoclistClear(Fts3Expr *pExpr){
-
  if( pExpr ){
-
    fts3DeferredDoclistClear(pExpr->pLeft);
-
    fts3DeferredDoclistClear(pExpr->pRight);
-
    if( pExpr->isLoaded ){
-
      sqlite3_free(pExpr->aDoclist);
-
      pExpr->isLoaded = 0;
-
      pExpr->aDoclist = 0;
-
      pExpr->nDoclist = 0;
-
      pExpr->pCurrent = 0;
-
      pExpr->iCurrent = 0;
-
    }
-
  }
-
}
-

-
/*
** Delete all cached deferred doclists. Deferred doclists are cached
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
*/
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
  Fts3DeferredToken *pDef;
  for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
-
    sqlite3_free(pDef->pList);
+
    fts3PendingListDelete(pDef->pList);
    pDef->pList = 0;
  }
-
  if( pCsr->pDeferred ){
-
    fts3DeferredDoclistClear(pCsr->pExpr);
-
  }
}

/*
@@ -120139,7 +122576,7 @@ SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
  Fts3DeferredToken *pNext;
  for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
    pNext = pDef->pNext;
-
    sqlite3_free(pDef->pList);
+
    fts3PendingListDelete(pDef->pList);
    sqlite3_free(pDef);
  }
  pCsr->pDeferred = 0;
@@ -120204,6 +122641,33 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
  return rc;
}

+
SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
+
  Fts3DeferredToken *p, 
+
  char **ppData, 
+
  int *pnData
+
){
+
  char *pRet;
+
  int nSkip;
+
  sqlite3_int64 dummy;
+

+
  *ppData = 0;
+
  *pnData = 0;
+

+
  if( p->pList==0 ){
+
    return SQLITE_OK;
+
  }
+

+
  pRet = (char *)sqlite3_malloc(p->pList->nData);
+
  if( !pRet ) return SQLITE_NOMEM;
+

+
  nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
+
  *pnData = p->pList->nData - nSkip;
+
  *ppData = pRet;
+
  
+
  memcpy(pRet, &p->pList->aData[nSkip], *pnData);
+
  return SQLITE_OK;
+
}
+

/*
** Add an entry for token pToken to the pCsr->pDeferred list.
*/
@@ -120229,6 +122693,40 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
  return SQLITE_OK;
}

+
/*
+
** SQLite value pRowid contains the rowid of a row that may or may not be
+
** present in the FTS3 table. If it is, delete it and adjust the contents
+
** of subsiduary data structures accordingly.
+
*/
+
static int fts3DeleteByRowid(
+
  Fts3Table *p, 
+
  sqlite3_value *pRowid, 
+
  int *pnDoc,
+
  u32 *aSzDel
+
){
+
  int isEmpty = 0;
+
  int rc = fts3IsEmpty(p, pRowid, &isEmpty);
+
  if( rc==SQLITE_OK ){
+
    if( isEmpty ){
+
      /* Deleting this row means the whole table is empty. In this case
+
      ** delete the contents of all three tables and throw away any
+
      ** data in the pendingTerms hash table.  */
+
      rc = fts3DeleteAll(p);
+
      *pnDoc = *pnDoc - 1;
+
    }else{
+
      sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
+
      rc = fts3PendingTermsDocid(p, iRemove);
+
      fts3DeleteTerms(&rc, p, pRowid, aSzDel);
+
      fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
+
      if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
+
      if( p->bHasDocsize ){
+
        fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+
      }
+
    }
+
  }
+

+
  return rc;
+
}

/*
** This function does the work for the xUpdate method of FTS3 virtual
@@ -120244,49 +122742,97 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
  int rc = SQLITE_OK;             /* Return Code */
  int isRemove = 0;               /* True for an UPDATE or DELETE */
  sqlite3_int64 iRemove = 0;      /* Rowid removed by UPDATE or DELETE */
-
  u32 *aSzIns;                    /* Sizes of inserted documents */
+
  u32 *aSzIns = 0;                /* Sizes of inserted documents */
  u32 *aSzDel;                    /* Sizes of deleted documents */
  int nChng = 0;                  /* Net change in number of documents */
+
  int bInsertDone = 0;

  assert( p->pSegments==0 );

+
  /* Check for a "special" INSERT operation. One of the form:
+
  **
+
  **   INSERT INTO xyz(xyz) VALUES('command');
+
  */
+
  if( nArg>1 
+
   && sqlite3_value_type(apVal[0])==SQLITE_NULL 
+
   && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL 
+
  ){
+
    rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
+
    goto update_out;
+
  }
+

  /* Allocate space to hold the change in document sizes */
  aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
-
  if( aSzIns==0 ) return SQLITE_NOMEM;
+
  if( aSzIns==0 ){
+
    rc = SQLITE_NOMEM;
+
    goto update_out;
+
  }
  aSzDel = &aSzIns[p->nColumn+1];
  memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);

-
  /* If this is a DELETE or UPDATE operation, remove the old record. */
-
  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
-
    int isEmpty = 0;
-
    rc = fts3IsEmpty(p, apVal, &isEmpty);
-
    if( rc==SQLITE_OK ){
-
      if( isEmpty ){
-
        /* Deleting this row means the whole table is empty. In this case
-
        ** delete the contents of all three tables and throw away any
-
        ** data in the pendingTerms hash table.
-
        */
-
        rc = fts3DeleteAll(p);
+
  /* If this is an INSERT operation, or an UPDATE that modifies the rowid
+
  ** value, then this operation requires constraint handling.
+
  **
+
  ** If the on-conflict mode is REPLACE, this means that the existing row
+
  ** should be deleted from the database before inserting the new row. Or,
+
  ** if the on-conflict mode is other than REPLACE, then this method must
+
  ** detect the conflict and return SQLITE_CONSTRAINT before beginning to
+
  ** modify the database file.
+
  */
+
  if( nArg>1 ){
+
    /* Find the value object that holds the new rowid value. */
+
    sqlite3_value *pNewRowid = apVal[3+p->nColumn];
+
    if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
+
      pNewRowid = apVal[1];
+
    }
+

+
    if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && ( 
+
        sqlite3_value_type(apVal[0])==SQLITE_NULL
+
     || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
+
    )){
+
      /* The new rowid is not NULL (in this case the rowid will be
+
      ** automatically assigned and there is no chance of a conflict), and 
+
      ** the statement is either an INSERT or an UPDATE that modifies the
+
      ** rowid column. So if the conflict mode is REPLACE, then delete any
+
      ** existing row with rowid=pNewRowid. 
+
      **
+
      ** Or, if the conflict mode is not REPLACE, insert the new record into 
+
      ** the %_content table. If we hit the duplicate rowid constraint (or any
+
      ** other error) while doing so, return immediately.
+
      **
+
      ** This branch may also run if pNewRowid contains a value that cannot
+
      ** be losslessly converted to an integer. In this case, the eventual 
+
      ** call to fts3InsertData() (either just below or further on in this
+
      ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is 
+
      ** invoked, it will delete zero rows (since no row will have
+
      ** docid=$pNewRowid if $pNewRowid is not an integer value).
+
      */
+
      if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){
+
        rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel);
      }else{
-
        isRemove = 1;
-
        iRemove = sqlite3_value_int64(apVal[0]);
-
        rc = fts3PendingTermsDocid(p, iRemove);
-
        fts3DeleteTerms(&rc, p, apVal, aSzDel);
-
        fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal);
-
        if( p->bHasDocsize ){
-
          fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal);
-
        }
-
        nChng--;
+
        rc = fts3InsertData(p, apVal, pRowid);
+
        bInsertDone = 1;
      }
    }
-
  }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){
-
    sqlite3_free(aSzIns);
-
    return fts3SpecialInsert(p, apVal[p->nColumn+2]);
+
  }
+
  if( rc!=SQLITE_OK ){
+
    goto update_out;
+
  }
+

+
  /* If this is a DELETE or UPDATE operation, remove the old record. */
+
  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
+
    assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
+
    rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
+
    isRemove = 1;
+
    iRemove = sqlite3_value_int64(apVal[0]);
  }
  
  /* If this is an INSERT or UPDATE operation, insert the new record. */
  if( nArg>1 && rc==SQLITE_OK ){
-
    rc = fts3InsertData(p, apVal, pRowid);
+
    if( bInsertDone==0 ){
+
      rc = fts3InsertData(p, apVal, pRowid);
+
      if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
+
    }
    if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
      rc = fts3PendingTermsDocid(p, *pRowid);
    }
@@ -120303,6 +122849,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
    fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
  }

+
 update_out:
  sqlite3_free(aSzIns);
  sqlite3Fts3SegmentsClose(p);
  return rc;
@@ -120317,12 +122864,10 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
  int rc;
  rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
  if( rc==SQLITE_OK ){
-
    rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL);
-
    if( rc==SQLITE_OK ){
-
      rc = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
-
      if( rc==SQLITE_OK ){
-
        sqlite3Fts3PendingTermsClear(p);
-
      }
+
    rc = fts3DoOptimize(p, 1);
+
    if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+
      int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
+
      if( rc2!=SQLITE_OK ) rc = rc2;
    }else{
      sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
      sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
@@ -120512,71 +123057,19 @@ static int fts3ExprIterate(
}

/*
-
** The argument to this function is always a phrase node. Its doclist 
-
** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes
-
** to the left of this one in the query tree have already been loaded.
-
**
-
** If this phrase node is part of a series of phrase nodes joined by 
-
** NEAR operators (and is not the left-most of said series), then elements are
-
** removed from the phrases doclist consistent with the NEAR restriction. If
-
** required, elements may be removed from the doclists of phrases to the
-
** left of this one that are part of the same series of NEAR operator 
-
** connected phrases.
-
**
-
** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
-
*/
-
static int fts3ExprNearTrim(Fts3Expr *pExpr){
-
  int rc = SQLITE_OK;
-
  Fts3Expr *pParent = pExpr->pParent;
-

-
  assert( pExpr->eType==FTSQUERY_PHRASE );
-
  while( rc==SQLITE_OK
-
   && pParent 
-
   && pParent->eType==FTSQUERY_NEAR 
-
   && pParent->pRight==pExpr 
-
  ){
-
    /* This expression (pExpr) is the right-hand-side of a NEAR operator. 
-
    ** Find the expression to the left of the same operator.
-
    */
-
    int nNear = pParent->nNear;
-
    Fts3Expr *pLeft = pParent->pLeft;
-

-
    if( pLeft->eType!=FTSQUERY_PHRASE ){
-
      assert( pLeft->eType==FTSQUERY_NEAR );
-
      assert( pLeft->pRight->eType==FTSQUERY_PHRASE );
-
      pLeft = pLeft->pRight;
-
    }
-

-
    rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear);
-

-
    pExpr = pLeft;
-
    pParent = pExpr->pParent;
-
  }
-

-
  return rc;
-
}
-

-
/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
  int rc = SQLITE_OK;
+
  Fts3Phrase *pPhrase = pExpr->pPhrase;
  LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;

  UNUSED_PARAMETER(iPhrase);

  p->nPhrase++;
-
  p->nToken += pExpr->pPhrase->nToken;
-

-
  if( pExpr->isLoaded==0 ){
-
    rc = sqlite3Fts3ExprLoadDoclist(p->pCsr, pExpr);
-
    pExpr->isLoaded = 1;
-
    if( rc==SQLITE_OK ){
-
      rc = fts3ExprNearTrim(pExpr);
-
    }
-
  }
+
  p->nToken += pPhrase->nToken;

  return rc;
}
@@ -120750,7 +123243,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){

  pPhrase->nToken = pExpr->pPhrase->nToken;

-
  pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol);
+
  pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
  if( pCsr ){
    int iFirst = 0;
    pPhrase->pList = pCsr;
@@ -121107,26 +123600,6 @@ static int fts3ColumnlistCount(char **ppCollist){
  return nEntry;
}

-
static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){
-
  char *pCsr = *pp;
-
  while( *pCsr ){
-
    int nHit;
-
    sqlite3_int64 iCol = 0;
-
    if( *pCsr==0x01 ){
-
      pCsr++;
-
      pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
-
    }
-
    nHit = fts3ColumnlistCount(&pCsr);
-
    assert( nHit>0 );
-
    if( isGlobal ){
-
      aOut[iCol*3+1]++;
-
    }
-
    aOut[iCol*3] += nHit;
-
  }
-
  pCsr++;
-
  *pp = pCsr;
-
}
-

/*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
** for a single query. 
@@ -121160,48 +123633,9 @@ static int fts3ExprGlobalHitsCb(
  void *pCtx                      /* Pointer to MatchInfo structure */
){
  MatchInfo *p = (MatchInfo *)pCtx;
-
  Fts3Cursor *pCsr = p->pCursor;
-
  char *pIter;
-
  char *pEnd;
-
  char *pFree = 0;
-
  u32 *aOut = &p->aMatchinfo[3*iPhrase*p->nCol];
-

-
  assert( pExpr->isLoaded );
-
  assert( pExpr->eType==FTSQUERY_PHRASE );
-

-
  if( pCsr->pDeferred ){
-
    Fts3Phrase *pPhrase = pExpr->pPhrase;
-
    int ii;
-
    for(ii=0; ii<pPhrase->nToken; ii++){
-
      if( pPhrase->aToken[ii].bFulltext ) break;
-
    }
-
    if( ii<pPhrase->nToken ){
-
      int nFree = 0;
-
      int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree);
-
      if( rc!=SQLITE_OK ) return rc;
-
      pIter = pFree;
-
      pEnd = &pFree[nFree];
-
    }else{
-
      int iCol;                   /* Column index */
-
      for(iCol=0; iCol<p->nCol; iCol++){
-
        aOut[iCol*3 + 1] = (u32)p->nDoc;
-
        aOut[iCol*3 + 2] = (u32)p->nDoc;
-
      }
-
      return SQLITE_OK;
-
    }
-
  }else{
-
    pIter = pExpr->aDoclist;
-
    pEnd = &pExpr->aDoclist[pExpr->nDoclist];
-
  }
-

-
  /* Fill in the global hit count matrix row for this phrase. */
-
  while( pIter<pEnd ){
-
    while( *pIter++ & 0x80 );      /* Skip past docid. */
-
    fts3LoadColumnlistCounts(&pIter, &aOut[1], 1);
-
  }
-

-
  sqlite3_free(pFree);
-
  return SQLITE_OK;
+
  return sqlite3Fts3EvalPhraseStats(
+
      p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol]
+
  );
}

/*
@@ -121218,14 +123652,13 @@ static int fts3ExprLocalHitsCb(
  int iStart = iPhrase * p->nCol * 3;
  int i;

-
  for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
-

-
  if( pExpr->aDoclist ){
+
  for(i=0; i<p->nCol; i++){
    char *pCsr;
-

-
    pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1);
+
    pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i);
    if( pCsr ){
-
      fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
+
      p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr);
+
    }else{
+
      p->aMatchinfo[iStart+i*3] = 0;
    }
  }

@@ -121295,7 +123728,7 @@ static int fts3MatchinfoSelectDoctotal(

  a = sqlite3_column_blob(pStmt, 0);
  a += sqlite3Fts3GetVarint(a, &nDoc);
-
  if( nDoc==0 ) return SQLITE_CORRUPT;
+
  if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
  *pnDoc = (u32)nDoc;

  if( paLen ) *paLen = a;
@@ -121311,9 +123744,8 @@ static int fts3MatchinfoSelectDoctotal(
typedef struct LcsIterator LcsIterator;
struct LcsIterator {
  Fts3Expr *pExpr;                /* Pointer to phrase expression */
-
  char *pRead;                    /* Cursor used to iterate through aDoclist */
  int iPosOffset;                 /* Tokens count up to end of this phrase */
-
  int iCol;                       /* Current column number */
+
  char *pRead;                    /* Cursor used to iterate through aDoclist */
  int iPos;                       /* Current position */
};

@@ -121344,17 +123776,10 @@ static int fts3LcsIteratorAdvance(LcsIterator *pIter){
  int rc = 0;

  pRead += sqlite3Fts3GetVarint(pRead, &iRead);
-
  if( iRead==0 ){
-
    pIter->iCol = LCS_ITERATOR_FINISHED;
+
  if( iRead==0 || iRead==1 ){
+
    pRead = 0;
    rc = 1;
  }else{
-
    if( iRead==1 ){
-
      pRead += sqlite3Fts3GetVarint(pRead, &iRead);
-
      pIter->iCol = (int)iRead;
-
      pIter->iPos = pIter->iPosOffset;
-
      pRead += sqlite3Fts3GetVarint(pRead, &iRead);
-
      rc = 1;
-
    }
    pIter->iPos += (int)(iRead-2);
  }

@@ -121386,42 +123811,34 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
  if( !aIter ) return SQLITE_NOMEM;
  memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
  (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
+

  for(i=0; i<pInfo->nPhrase; i++){
    LcsIterator *pIter = &aIter[i];
    nToken -= pIter->pExpr->pPhrase->nToken;
    pIter->iPosOffset = nToken;
-
    pIter->pRead = sqlite3Fts3FindPositions(pIter->pExpr, pCsr->iPrevId, -1);
-
    if( pIter->pRead ){
-
      pIter->iPos = pIter->iPosOffset;
-
      fts3LcsIteratorAdvance(&aIter[i]);
-
    }else{
-
      pIter->iCol = LCS_ITERATOR_FINISHED;
-
    }
  }

  for(iCol=0; iCol<pInfo->nCol; iCol++){
    int nLcs = 0;                 /* LCS value for this column */
    int nLive = 0;                /* Number of iterators in aIter not at EOF */

-
    /* Loop through the iterators in aIter[]. Set nLive to the number of
-
    ** iterators that point to a position-list corresponding to column iCol.
-
    */
    for(i=0; i<pInfo->nPhrase; i++){
-
      assert( aIter[i].iCol>=iCol );
-
      if( aIter[i].iCol==iCol ) nLive++;
+
      LcsIterator *pIt = &aIter[i];
+
      pIt->pRead = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol);
+
      if( pIt->pRead ){
+
        pIt->iPos = pIt->iPosOffset;
+
        fts3LcsIteratorAdvance(&aIter[i]);
+
        nLive++;
+
      }
    }

-
    /* The following loop runs until all iterators in aIter[] have finished
-
    ** iterating through positions in column iCol. Exactly one of the 
-
    ** iterators is advanced each time the body of the loop is run.
-
    */
    while( nLive>0 ){
      LcsIterator *pAdv = 0;      /* The iterator to advance by one position */
      int nThisLcs = 0;           /* LCS for the current iterator positions */

      for(i=0; i<pInfo->nPhrase; i++){
        LcsIterator *pIter = &aIter[i];
-
        if( iCol!=pIter->iCol ){  
+
        if( pIter->pRead==0 ){
          /* This iterator is already at EOF for this column. */
          nThisLcs = 0;
        }else{
@@ -121487,7 +123904,7 @@ static int fts3MatchinfoValues(
        
      case FTS3_MATCHINFO_NDOC:
        if( bGlobal ){
-
          sqlite3_int64 nDoc;
+
          sqlite3_int64 nDoc = 0;
          rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
          pInfo->aMatchinfo[0] = (u32)nDoc;
        }
@@ -121743,6 +124160,7 @@ struct TermOffset {
};

struct TermOffsetCtx {
+
  Fts3Cursor *pCsr;
  int iCol;                       /* Column of table to populate aTerm for */
  int iTerm;
  sqlite3_int64 iDocid;
@@ -121760,7 +124178,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
  int iPos = 0;                   /* First position in position-list */

  UNUSED_PARAMETER(iPhrase);
-
  pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol);
+
  pList = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
  nTerm = pExpr->pPhrase->nToken;
  if( pList ){
    fts3GetDeltaPosition(&pList, &iPos);
@@ -121813,6 +124231,7 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
    goto offsets_out;
  }
  sCtx.iDocid = pCsr->iPrevId;
+
  sCtx.pCsr = pCsr;

  /* Loop through the table columns, appending offset information to 
  ** string-buffer res for each column.
@@ -121888,7 +124307,7 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
          );
          rc = fts3StringAppend(&res, aBuffer, -1);
        }else if( rc==SQLITE_DONE ){
-
          rc = SQLITE_CORRUPT;
+
          rc = SQLITE_CORRUPT_VTAB;
        }
      }
    }
@@ -122476,17 +124895,17 @@ nodeAcquire(
  if( pNode && iNode==1 ){
    pRtree->iDepth = readInt16(pNode->zData);
    if( pRtree->iDepth>RTREE_MAX_DEPTH ){
-
      rc = SQLITE_CORRUPT;
+
      rc = SQLITE_CORRUPT_VTAB;
    }
  }

  /* If no error has occurred so far, check if the "number of entries"
  ** field on the node is too large. If so, set the return code to 
-
  ** SQLITE_CORRUPT.
+
  ** SQLITE_CORRUPT_VTAB.
  */
  if( pNode && rc==SQLITE_OK ){
    if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
-
      rc = SQLITE_CORRUPT;
+
      rc = SQLITE_CORRUPT_VTAB;
    }
  }

@@ -122494,7 +124913,7 @@ nodeAcquire(
    if( pNode!=0 ){
      nodeHashInsert(pRtree, pNode);
    }else{
-
      rc = SQLITE_CORRUPT;
+
      rc = SQLITE_CORRUPT_VTAB;
    }
    *ppNode = pNode;
  }else{
@@ -123021,7 +125440,7 @@ static int nodeRowidIndex(
      return SQLITE_OK;
    }
  }
-
  return SQLITE_CORRUPT;
+
  return SQLITE_CORRUPT_VTAB;
}

/*
@@ -123380,7 +125799,7 @@ static float cellArea(Rtree *pRtree, RtreeCell *p){
  float area = 1.0;
  int ii;
  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-
    area = area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
+
    area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
  }
  return area;
}
@@ -123393,7 +125812,7 @@ static float cellMargin(Rtree *pRtree, RtreeCell *p){
  float margin = 0.0;
  int ii;
  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-
    margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
+
    margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
  }
  return margin;
}
@@ -123478,7 +125897,7 @@ static float cellOverlap(
          o = 0.0;
          break;
        }else{
-
          o = o * (x2-x1);
+
          o = o * (float)(x2-x1);
        }
      }
      overlap += o;
@@ -123497,12 +125916,12 @@ static float cellOverlapEnlargement(
  int nCell, 
  int iExclude
){
-
  float before;
-
  float after;
+
  double before;
+
  double after;
  before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
  cellUnion(pRtree, p, pInsert);
  after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
-
  return after-before;
+
  return (float)(after-before);
}
#endif

@@ -123524,11 +125943,11 @@ static int ChooseLeaf(

  for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
    int iCell;
-
    sqlite3_int64 iBest;
+
    sqlite3_int64 iBest = 0;

-
    float fMinGrowth;
-
    float fMinArea;
-
    float fMinOverlap;
+
    float fMinGrowth = 0.0;
+
    float fMinArea = 0.0;
+
    float fMinOverlap = 0.0;

    int nCell = NCELL(pNode);
    RtreeCell cell;
@@ -123616,7 +126035,7 @@ static int AdjustTree(
    int iCell;

    if( nodeParentIndex(pRtree, p, &iCell) ){
-
      return SQLITE_CORRUPT;
+
      return SQLITE_CORRUPT_VTAB;
    }

    nodeGetCell(pRtree, pParent, iCell, &cell);
@@ -123958,9 +126377,9 @@ static int splitNodeStartree(
  int *aSpare;
  int ii;

-
  int iBestDim;
-
  int iBestSplit;
-
  float fBestMargin;
+
  int iBestDim = 0;
+
  int iBestSplit = 0;
+
  float fBestMargin = 0.0;

  int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));

@@ -123982,9 +126401,9 @@ static int splitNodeStartree(

  for(ii=0; ii<pRtree->nDim; ii++){
    float margin = 0.0;
-
    float fBestOverlap;
-
    float fBestArea;
-
    int iBestLeft;
+
    float fBestOverlap = 0.0;
+
    float fBestArea = 0.0;
+
    int iBestLeft = 0;
    int nLeft;

    for(
@@ -124288,7 +126707,7 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
    }
    rc = sqlite3_reset(pRtree->pReadParent);
    if( rc==SQLITE_OK ) rc = rc2;
-
    if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT;
+
    if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
    pChild = pChild->pParent;
  }
  return rc;
@@ -124299,7 +126718,7 @@ static int deleteCell(Rtree *, RtreeNode *, int, int);
static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
  int rc;
  int rc2;
-
  RtreeNode *pParent;
+
  RtreeNode *pParent = 0;
  int iCell;

  assert( pNode->nRef==1 );
@@ -124447,19 +126866,19 @@ static int Reinsert(
    }
    aOrder[ii] = ii;
    for(iDim=0; iDim<pRtree->nDim; iDim++){
-
      aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
-
      aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
+
      aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]);
+
      aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]);
    }
  }
  for(iDim=0; iDim<pRtree->nDim; iDim++){
-
    aCenterCoord[iDim] = aCenterCoord[iDim]/((float)nCell*2.0);
+
    aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0));
  }

  for(ii=0; ii<nCell; ii++){
    aDistance[ii] = 0.0;
    for(iDim=0; iDim<pRtree->nDim; iDim++){
-
      float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) - 
-
          DCOORD(aCell[ii].aCoord[iDim*2]);
+
      float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) - 
+
          DCOORD(aCell[ii].aCoord[iDim*2]));
      aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
    }
  }
@@ -124558,10 +126977,10 @@ static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){
    /* Find a node to store this cell in. pNode->iNode currently contains
    ** the height of the sub-tree headed by the cell.
    */
-
    rc = ChooseLeaf(pRtree, &cell, pNode->iNode, &pInsert);
+
    rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert);
    if( rc==SQLITE_OK ){
      int rc2;
-
      rc = rtreeInsertCell(pRtree, pInsert, &cell, pNode->iNode);
+
      rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode);
      rc2 = nodeRelease(pRtree, pInsert);
      if( rc==SQLITE_OK ){
        rc = rc2;
@@ -124585,113 +127004,119 @@ static int newRowid(Rtree *pRtree, i64 *piRowid){
}

/*
-
** The xUpdate method for rtree module virtual tables.
+
** Remove the entry with rowid=iDelete from the r-tree structure.
*/
-
static int rtreeUpdate(
-
  sqlite3_vtab *pVtab, 
-
  int nData, 
-
  sqlite3_value **azData, 
-
  sqlite_int64 *pRowid
-
){
-
  Rtree *pRtree = (Rtree *)pVtab;
-
  int rc = SQLITE_OK;
+
static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
+
  int rc;                         /* Return code */
+
  RtreeNode *pLeaf;               /* Leaf node containing record iDelete */
+
  int iCell;                      /* Index of iDelete cell in pLeaf */
+
  RtreeNode *pRoot;               /* Root node of rtree structure */

-
  rtreeReference(pRtree);

-
  assert(nData>=1);
+
  /* Obtain a reference to the root node to initialise Rtree.iDepth */
+
  rc = nodeAcquire(pRtree, 1, 0, &pRoot);

-
  /* If azData[0] is not an SQL NULL value, it is the rowid of a
-
  ** record to delete from the r-tree table. The following block does
-
  ** just that.
+
  /* Obtain a reference to the leaf node that contains the entry 
+
  ** about to be deleted. 
  */
-
  if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
-
    i64 iDelete;                /* The rowid to delete */
-
    RtreeNode *pLeaf;           /* Leaf node containing record iDelete */
-
    int iCell;                  /* Index of iDelete cell in pLeaf */
-
    RtreeNode *pRoot;
-

-
    /* Obtain a reference to the root node to initialise Rtree.iDepth */
-
    rc = nodeAcquire(pRtree, 1, 0, &pRoot);
+
  if( rc==SQLITE_OK ){
+
    rc = findLeafNode(pRtree, iDelete, &pLeaf);
+
  }

-
    /* Obtain a reference to the leaf node that contains the entry 
-
    ** about to be deleted. 
-
    */
+
  /* Delete the cell in question from the leaf node. */
+
  if( rc==SQLITE_OK ){
+
    int rc2;
+
    rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
    if( rc==SQLITE_OK ){
-
      iDelete = sqlite3_value_int64(azData[0]);
-
      rc = findLeafNode(pRtree, iDelete, &pLeaf);
+
      rc = deleteCell(pRtree, pLeaf, iCell, 0);
    }
-

-
    /* Delete the cell in question from the leaf node. */
+
    rc2 = nodeRelease(pRtree, pLeaf);
    if( rc==SQLITE_OK ){
-
      int rc2;
-
      rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
-
      if( rc==SQLITE_OK ){
-
        rc = deleteCell(pRtree, pLeaf, iCell, 0);
-
      }
-
      rc2 = nodeRelease(pRtree, pLeaf);
-
      if( rc==SQLITE_OK ){
-
        rc = rc2;
-
      }
+
      rc = rc2;
    }
+
  }

-
    /* Delete the corresponding entry in the <rtree>_rowid table. */
-
    if( rc==SQLITE_OK ){
-
      sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
-
      sqlite3_step(pRtree->pDeleteRowid);
-
      rc = sqlite3_reset(pRtree->pDeleteRowid);
-
    }
+
  /* Delete the corresponding entry in the <rtree>_rowid table. */
+
  if( rc==SQLITE_OK ){
+
    sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
+
    sqlite3_step(pRtree->pDeleteRowid);
+
    rc = sqlite3_reset(pRtree->pDeleteRowid);
+
  }

-
    /* Check if the root node now has exactly one child. If so, remove
-
    ** it, schedule the contents of the child for reinsertion and 
-
    ** reduce the tree height by one.
-
    **
-
    ** This is equivalent to copying the contents of the child into
-
    ** the root node (the operation that Gutman's paper says to perform 
-
    ** in this scenario).
-
    */
-
    if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
-
      int rc2;
-
      RtreeNode *pChild;
-
      i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
-
      rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
-
      if( rc==SQLITE_OK ){
-
        rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
-
      }
-
      rc2 = nodeRelease(pRtree, pChild);
-
      if( rc==SQLITE_OK ) rc = rc2;
-
      if( rc==SQLITE_OK ){
-
        pRtree->iDepth--;
-
        writeInt16(pRoot->zData, pRtree->iDepth);
-
        pRoot->isDirty = 1;
-
      }
+
  /* Check if the root node now has exactly one child. If so, remove
+
  ** it, schedule the contents of the child for reinsertion and 
+
  ** reduce the tree height by one.
+
  **
+
  ** This is equivalent to copying the contents of the child into
+
  ** the root node (the operation that Gutman's paper says to perform 
+
  ** in this scenario).
+
  */
+
  if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
+
    int rc2;
+
    RtreeNode *pChild;
+
    i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
+
    rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
+
    if( rc==SQLITE_OK ){
+
      rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
    }
-

-
    /* Re-insert the contents of any underfull nodes removed from the tree. */
-
    for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
-
      if( rc==SQLITE_OK ){
-
        rc = reinsertNodeContent(pRtree, pLeaf);
-
      }
-
      pRtree->pDeleted = pLeaf->pNext;
-
      sqlite3_free(pLeaf);
+
    rc2 = nodeRelease(pRtree, pChild);
+
    if( rc==SQLITE_OK ) rc = rc2;
+
    if( rc==SQLITE_OK ){
+
      pRtree->iDepth--;
+
      writeInt16(pRoot->zData, pRtree->iDepth);
+
      pRoot->isDirty = 1;
    }
+
  }

-
    /* Release the reference to the root node. */
+
  /* Re-insert the contents of any underfull nodes removed from the tree. */
+
  for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
    if( rc==SQLITE_OK ){
-
      rc = nodeRelease(pRtree, pRoot);
-
    }else{
-
      nodeRelease(pRtree, pRoot);
+
      rc = reinsertNodeContent(pRtree, pLeaf);
    }
+
    pRtree->pDeleted = pLeaf->pNext;
+
    sqlite3_free(pLeaf);
  }

-
  /* If the azData[] array contains more than one element, elements
-
  ** (azData[2]..azData[argc-1]) contain a new record to insert into
-
  ** the r-tree structure.
+
  /* Release the reference to the root node. */
+
  if( rc==SQLITE_OK ){
+
    rc = nodeRelease(pRtree, pRoot);
+
  }else{
+
    nodeRelease(pRtree, pRoot);
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** The xUpdate method for rtree module virtual tables.
+
*/
+
static int rtreeUpdate(
+
  sqlite3_vtab *pVtab, 
+
  int nData, 
+
  sqlite3_value **azData, 
+
  sqlite_int64 *pRowid
+
){
+
  Rtree *pRtree = (Rtree *)pVtab;
+
  int rc = SQLITE_OK;
+
  RtreeCell cell;                 /* New cell to insert if nData>1 */
+
  int bHaveRowid = 0;             /* Set to 1 after new rowid is determined */
+

+
  rtreeReference(pRtree);
+
  assert(nData>=1);
+

+
  /* Constraint handling. A write operation on an r-tree table may return
+
  ** SQLITE_CONSTRAINT for two reasons:
+
  **
+
  **   1. A duplicate rowid value, or
+
  **   2. The supplied data violates the "x2>=x1" constraint.
+
  **
+
  ** In the first case, if the conflict-handling mode is REPLACE, then
+
  ** the conflicting row can be removed before proceeding. In the second
+
  ** case, SQLITE_CONSTRAINT must be returned regardless of the
+
  ** conflict-handling mode specified by the user.
  */
-
  if( rc==SQLITE_OK && nData>1 ){
-
    /* Insert a new record into the r-tree */
-
    RtreeCell cell;
+
  if( nData>1 ){
    int ii;
-
    RtreeNode *pLeaf;

    /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
    assert( nData==(pRtree->nDim*2 + 3) );
@@ -124715,18 +127140,49 @@ static int rtreeUpdate(
      }
    }

-
    /* Figure out the rowid of the new row. */
-
    if( sqlite3_value_type(azData[2])==SQLITE_NULL ){
-
      rc = newRowid(pRtree, &cell.iRowid);
-
    }else{
+
    /* If a rowid value was supplied, check if it is already present in 
+
    ** the table. If so, the constraint has failed. */
+
    if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
      cell.iRowid = sqlite3_value_int64(azData[2]);
-
      sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
-
      if( SQLITE_ROW==sqlite3_step(pRtree->pReadRowid) ){
-
        sqlite3_reset(pRtree->pReadRowid);
-
        rc = SQLITE_CONSTRAINT;
-
        goto constraint;
+
      if( sqlite3_value_type(azData[0])==SQLITE_NULL
+
       || sqlite3_value_int64(azData[0])!=cell.iRowid
+
      ){
+
        int steprc;
+
        sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
+
        steprc = sqlite3_step(pRtree->pReadRowid);
+
        rc = sqlite3_reset(pRtree->pReadRowid);
+
        if( SQLITE_ROW==steprc ){
+
          if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
+
            rc = rtreeDeleteRowid(pRtree, cell.iRowid);
+
          }else{
+
            rc = SQLITE_CONSTRAINT;
+
            goto constraint;
+
          }
+
        }
      }
-
      rc = sqlite3_reset(pRtree->pReadRowid);
+
      bHaveRowid = 1;
+
    }
+
  }
+

+
  /* If azData[0] is not an SQL NULL value, it is the rowid of a
+
  ** record to delete from the r-tree table. The following block does
+
  ** just that.
+
  */
+
  if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
+
    rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
+
  }
+

+
  /* If the azData[] array contains more than one element, elements
+
  ** (azData[2]..azData[argc-1]) contain a new record to insert into
+
  ** the r-tree structure.
+
  */
+
  if( rc==SQLITE_OK && nData>1 ){
+
    /* Insert the new record into the r-tree */
+
    RtreeNode *pLeaf;
+

+
    /* Figure out the rowid of the new row. */
+
    if( bHaveRowid==0 ){
+
      rc = newRowid(pRtree, &cell.iRowid);
    }
    *pRowid = cell.iRowid;

@@ -124771,7 +127227,7 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
}

static sqlite3_module rtreeModule = {
-
  0,                         /* iVersion */
+
  0,                          /* iVersion */
  rtreeCreate,                /* xCreate - create a table */
  rtreeConnect,               /* xConnect - connect to an existing table */
  rtreeBestIndex,             /* xBestIndex - Determine search strategy */
@@ -124790,7 +127246,10 @@ static sqlite3_module rtreeModule = {
  0,                          /* xCommit - commit transaction */
  0,                          /* xRollback - rollback transaction */
  0,                          /* xFindFunction - function overloading */
-
  rtreeRename                 /* xRename - rename the table */
+
  rtreeRename,                /* xRename - rename the table */
+
  0,                          /* xSavepoint */
+
  0,                          /* xRelease */
+
  0                           /* xRollbackTo */
};

static int rtreeSqlInit(
@@ -124910,7 +127369,7 @@ static int getNodeSize(
  int rc;
  char *zSql;
  if( isCreate ){
-
    int iPageSize;
+
    int iPageSize = 0;
    zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
    rc = getIntFromStmt(db, zSql, &iPageSize);
    if( rc==SQLITE_OK ){
@@ -124967,6 +127426,8 @@ static int rtreeInit(
    return SQLITE_ERROR;
  }

+
  sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
+

  /* Allocate the sqlite3_vtab structure */
  nDb = strlen(argv[1]);
  nName = strlen(argv[2]);
@@ -125711,10 +128172,7 @@ SQLITE_API int sqlite3_extension_init(
**
*************************************************************************
** This file implements a tokenizer for fts3 based on the ICU library.
-
** 
-
** $Id: fts3_icu.c,v 1.3 2008/09/01 18:34:20 danielk1977 Exp $
*/
-

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#ifdef SQLITE_ENABLE_ICU

modified external/sqlite/sqlite3.h
@@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.7.6.2"
-
#define SQLITE_VERSION_NUMBER 3007006
-
#define SQLITE_SOURCE_ID      "2011-04-17 17:25:17 154ddbc17120be2915eb03edc52af1225eb7cb5e"
+
#define SQLITE_VERSION        "3.7.7.1"
+
#define SQLITE_VERSION_NUMBER 3007007
+
#define SQLITE_SOURCE_ID      "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -310,7 +310,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** argument.  ^If the callback function of the 3rd argument to
** sqlite3_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements.  ^The 4th argument to
-
** to sqlite3_exec() is relayed through to the 1st argument of each
+
** sqlite3_exec() is relayed through to the 1st argument of each
** callback invocation.  ^If the callback pointer to sqlite3_exec()
** is NULL, then no callback is ever invoked and result rows are
** ignored.
@@ -375,7 +375,8 @@ SQLITE_API int sqlite3_exec(
**
** New error codes may be added in future versions of SQLite.
**
-
** See also: [SQLITE_IOERR_READ | extended result codes]
+
** See also: [SQLITE_IOERR_READ | extended result codes],
+
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
*/
#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
@@ -452,17 +453,21 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SHMOPEN           (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
+
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
+
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
+
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
+
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
+
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
-
** in the 4th parameter to the xOpen method of the
-
** [sqlite3_vfs] object.
+
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
*/
#define SQLITE_OPEN_READONLY         0x00000001  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE        0x00000002  /* Ok for sqlite3_open_v2() */
@@ -470,6 +475,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_DELETEONCLOSE    0x00000008  /* VFS only */
#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_MAIN_DB          0x00000100  /* VFS only */
#define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
@@ -580,17 +586,18 @@ struct sqlite3_file {
/*
** CAPI3REF: OS Interface File Virtual Methods Object
**
-
** Every file opened by the [sqlite3_vfs] xOpen method populates an
+
** Every file opened by the [sqlite3_vfs.xOpen] method populates an
** [sqlite3_file] object (or, more commonly, a subclass of the
** [sqlite3_file] object) with a pointer to an instance of this object.
** This object defines the methods used to perform various operations
** against the open file represented by the [sqlite3_file] object.
**
-
** If the xOpen method sets the sqlite3_file.pMethods element 
+
** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element 
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
-
** may be invoked even if the xOpen reported that it failed.  The
-
** only way to prevent a call to xClose following a failed xOpen
-
** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
+
** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed.  The
+
** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
+
** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
+
** to NULL.
**
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
** [SQLITE_SYNC_FULL].  The first choice is the normal fsync().
@@ -762,7 +769,8 @@ typedef struct sqlite3_mutex sqlite3_mutex;
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
-
** in the name of the object stands for "virtual file system".
+
** in the name of the object stands for "virtual file system".  See
+
** the [VFS | VFS documentation] for further information.
**
** The value of the iVersion field is initially 1 but may be larger in
** future versions of SQLite.  Additional fields may be appended to this
@@ -791,6 +799,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** The zName field holds the name of the VFS module.  The name must
** be unique across all VFS modules.
**
+
** [[sqlite3_vfs.xOpen]]
** ^SQLite guarantees that the zFilename parameter to xOpen
** is either a NULL pointer or string obtained
** from xFullPathname() with an optional suffix added.
@@ -868,6 +877,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** element will be valid after xOpen returns regardless of the success
** or failure of the xOpen call.
**
+
** [[sqlite3_vfs.xAccess]]
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
@@ -892,7 +902,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** method returns a Julian Day Number for the current date and time as
** a floating point value.
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
-
** Day Number multipled by 86400000 (the number of milliseconds in 
+
** Day Number multiplied by 86400000 (the number of milliseconds in 
** a 24-hour day).  
** ^SQLite will use the xCurrentTimeInt64() method to get the current
** date and time if that method is available (if iVersion is 2 or 
@@ -1114,9 +1124,9 @@ SQLITE_API int sqlite3_os_end(void);
** implementation of an application-defined [sqlite3_os_init()].
**
** The first argument to sqlite3_config() is an integer
-
** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
+
** [configuration option] that determines
** what property of SQLite is to be configured.  Subsequent arguments
-
** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
+
** vary depending on the [configuration option]
** in the first argument.
**
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
@@ -1226,6 +1236,7 @@ struct sqlite3_mem_methods {

/*
** CAPI3REF: Configuration Options
+
** KEYWORDS: {configuration option}
**
** These constants are the available integer configuration options that
** can be passed as the first argument to the [sqlite3_config()] interface.
@@ -1238,7 +1249,7 @@ struct sqlite3_mem_methods {
** is invoked.
**
** <dl>
-
** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
+
** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
** <dd>There are no arguments to this option.  ^This option sets the
** [threading mode] to Single-thread.  In other words, it disables
** all mutexing and puts SQLite into a mode where it can only be used
@@ -1249,7 +1260,7 @@ struct sqlite3_mem_methods {
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
** configuration option.</dd>
**
-
** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
+
** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
** <dd>There are no arguments to this option.  ^This option sets the
** [threading mode] to Multi-thread.  In other words, it disables
** mutexing on [database connection] and [prepared statement] objects.
@@ -1263,7 +1274,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
**
-
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
+
** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option.  ^This option sets the
** [threading mode] to Serialized. In other words, this option enables
** all mutexes including the recursive
@@ -1279,7 +1290,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
**
-
** <dt>SQLITE_CONFIG_MALLOC</dt>
+
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mem_methods] structure.  The argument specifies
** alternative low-level memory allocation routines to be used in place of
@@ -1287,7 +1298,7 @@ struct sqlite3_mem_methods {
** its own private copy of the content of the [sqlite3_mem_methods] structure
** before the [sqlite3_config()] call returns.</dd>
**
-
** <dt>SQLITE_CONFIG_GETMALLOC</dt>
+
** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mem_methods] structure.  The [sqlite3_mem_methods]
** structure is filled with the currently defined memory allocation routines.)^
@@ -1295,7 +1306,7 @@ struct sqlite3_mem_methods {
** routines with a wrapper that simulations memory allocation failure or
** tracks memory usage, for example. </dd>
**
-
** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
+
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^This option takes single argument of type int, interpreted as a 
** boolean, which enables or disables the collection of memory allocation 
** statistics. ^(When memory allocation statistics are disabled, the 
@@ -1311,7 +1322,7 @@ struct sqlite3_mem_methods {
** allocation statistics are disabled by default.
** </dd>
**
-
** <dt>SQLITE_CONFIG_SCRATCH</dt>
+
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
** scratch memory.  There are three arguments:  A pointer an 8-byte
** aligned memory buffer from which the scratch allocations will be
@@ -1327,9 +1338,9 @@ struct sqlite3_mem_methods {
** scratch memory beyond what is provided by this configuration option, then 
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
**
-
** <dt>SQLITE_CONFIG_PAGECACHE</dt>
+
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
-
** the database page cache with the default page cache implemenation.  
+
** the database page cache with the default page cache implementation.  
** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1348,7 +1359,7 @@ struct sqlite3_mem_methods {
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
** will be undefined.</dd>
**
-
** <dt>SQLITE_CONFIG_HEAP</dt>
+
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
** <dd> ^This option specifies a static memory buffer that SQLite will use
** for all of its dynamic memory allocation needs beyond those provided
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
@@ -1365,7 +1376,7 @@ struct sqlite3_mem_methods {
** The minimum allocation size is capped at 2^12. Reasonable values
** for the minimum allocation size are 2^5 through 2^8.</dd>
**
-
** <dt>SQLITE_CONFIG_MUTEX</dt>
+
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure.  The argument specifies
** alternative low-level mutex routines to be used in place
@@ -1377,7 +1388,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
** return [SQLITE_ERROR].</dd>
**
-
** <dt>SQLITE_CONFIG_GETMUTEX</dt>
+
** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure.  The
** [sqlite3_mutex_methods]
@@ -1390,7 +1401,7 @@ struct sqlite3_mem_methods {
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
** return [SQLITE_ERROR].</dd>
**
-
** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
** <dd> ^(This option takes two arguments that determine the default
** memory allocation for the lookaside memory allocator on each
** [database connection].  The first argument is the
@@ -1400,18 +1411,18 @@ struct sqlite3_mem_methods {
** verb to [sqlite3_db_config()] can be used to change the lookaside
** configuration on individual connections.)^ </dd>
**
-
** <dt>SQLITE_CONFIG_PCACHE</dt>
+
** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
** <dd> ^(This option takes a single argument which is a pointer to
** an [sqlite3_pcache_methods] object.  This object specifies the interface
** to a custom page cache implementation.)^  ^SQLite makes a copy of the
** object and uses it for page cache memory allocations.</dd>
**
-
** <dt>SQLITE_CONFIG_GETPCACHE</dt>
+
** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
** <dd> ^(This option takes a single argument which is a pointer to an
** [sqlite3_pcache_methods] object.  SQLite copies of the current
** page cache implementation into that object.)^ </dd>
**
-
** <dt>SQLITE_CONFIG_LOG</dt>
+
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
** function with a call signature of void(*)(void*,int,const char*), 
** and a pointer to void. ^If the function pointer is not NULL, it is
@@ -1429,6 +1440,18 @@ struct sqlite3_mem_methods {
** In a multi-threaded application, the application-defined logger
** function must be threadsafe. </dd>
**
+
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
+
** <dd> This option takes a single argument of type int. If non-zero, then
+
** URI handling is globally enabled. If the parameter is zero, then URI handling
+
** is globally disabled. If URI handling is globally enabled, all filenames
+
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
+
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
+
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
+
** connection is opened. If it is globally disabled, filenames are
+
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
+
** database connection is opened. By default, URI handling is globally
+
** disabled. The default value may be changed by compiling with the
+
** [SQLITE_USE_URI] symbol defined.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -1447,6 +1470,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
+
#define SQLITE_CONFIG_URI          17  /* int */

/*
** CAPI3REF: Database Connection Configuration Options
@@ -1532,13 +1556,17 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
**
** ^This routine returns the [rowid] of the most recent
** successful [INSERT] into the database from the [database connection]
-
** in the first argument.  ^If no successful [INSERT]s
+
** in the first argument.  ^As of SQLite version 3.7.7, this routines
+
** records the last insert rowid of both ordinary tables and [virtual tables].
+
** ^If no successful [INSERT]s
** have ever occurred on that database connection, zero is returned.
**
-
** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
-
** row is returned by this routine as long as the trigger is running.
-
** But once the trigger terminates, the value returned by this routine
-
** reverts to the last value inserted before the trigger fired.)^
+
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
+
** method, then this routine will return the [rowid] of the inserted
+
** row as long as the trigger or virtual table method is running.
+
** But once the trigger or virtual table method ends, the value returned 
+
** by this routine reverts to what it was before the trigger or virtual
+
** table method began.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
@@ -2201,6 +2229,9 @@ SQLITE_API int sqlite3_set_authorizer(
** to signal SQLite whether or not the action is permitted.  See the
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
+
**
+
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
+
** from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */
@@ -2323,7 +2354,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
** CAPI3REF: Opening A New Database Connection
**
-
** ^These routines open an SQLite database file whose name is given by the
+
** ^These routines open an SQLite database file as specified by the 
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
@@ -2350,7 +2381,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** sqlite3_open_v2() can take one of
** the following three values, optionally combined with the 
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
-
** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
+
** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
**
** <dl>
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
@@ -2369,9 +2400,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** </dl>
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
-
** combinations shown above or one of the combinations shown above combined
-
** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
-
** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
+
** combinations shown above optionally combined with other
+
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined.
**
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
@@ -2386,6 +2416,11 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**
+
** ^The fourth parameter to sqlite3_open_v2() is the name of the
+
** [sqlite3_vfs] object that defines the operating system interface that
+
** the new database connection should use.  ^If the fourth parameter is
+
** a NULL pointer then the default [sqlite3_vfs] object is used.
+
**
** ^If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection.  ^This in-memory database will vanish when
** the database connection is closed.  Future versions of SQLite might
@@ -2398,10 +2433,111 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** on-disk database will be created.  ^This private database will be
** automatically deleted as soon as the database connection is closed.
**
-
** ^The fourth parameter to sqlite3_open_v2() is the name of the
-
** [sqlite3_vfs] object that defines the operating system interface that
-
** the new database connection should use.  ^If the fourth parameter is
-
** a NULL pointer then the default [sqlite3_vfs] object is used.
+
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
+
**
+
** ^If [URI filename] interpretation is enabled, and the filename argument
+
** begins with "file:", then the filename is interpreted as a URI. ^URI
+
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
+
** set in the fourth argument to sqlite3_open_v2(), or if it has
+
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
+
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
+
** As of SQLite version 3.7.7, URI filename interpretation is turned off
+
** by default, but future releases of SQLite might enable URI filename
+
** interpretation by default.  See "[URI filenames]" for additional
+
** information.
+
**
+
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
+
** authority, then it must be either an empty string or the string 
+
** "localhost". ^If the authority is not an empty string or "localhost", an 
+
** error is returned to the caller. ^The fragment component of a URI, if 
+
** present, is ignored.
+
**
+
** ^SQLite uses the path component of the URI as the name of the disk file
+
** which contains the database. ^If the path begins with a '/' character, 
+
** then it is interpreted as an absolute path. ^If the path does not begin 
+
** with a '/' (meaning that the authority section is omitted from the URI)
+
** then the path is interpreted as a relative path. 
+
** ^On windows, the first component of an absolute path 
+
** is a drive specification (e.g. "C:").
+
**
+
** [[core URI query parameters]]
+
** The query component of a URI may contain parameters that are interpreted
+
** either by SQLite itself, or by a [VFS | custom VFS implementation].
+
** SQLite interprets the following three query parameters:
+
**
+
** <ul>
+
**   <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
+
**     a VFS object that provides the operating system interface that should
+
**     be used to access the database file on disk. ^If this option is set to
+
**     an empty string the default VFS object is used. ^Specifying an unknown
+
**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
+
**     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)^. 
+
**     ^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.
+
**
+
**   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
+
**     "private". ^Setting it to "shared" is equivalent to setting the
+
**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
+
**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
+
**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
+
**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
+
**     a URI filename, its value overrides any behaviour requested by setting
+
**     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+
** </ul>
+
**
+
** ^Specifying an unknown parameter in the query component of a URI is not an
+
** error.  Future versions of SQLite might understand additional query
+
** parameters.  See "[query parameters with special meaning to SQLite]" for
+
** additional information.
+
**
+
** [[URI filename examples]] <h3>URI filename examples</h3>
+
**
+
** <table border="1" align=center cellpadding=5>
+
** <tr><th> URI filenames <th> Results
+
** <tr><td> file:data.db <td> 
+
**          Open the file "data.db" in the current directory.
+
** <tr><td> file:/home/fred/data.db<br>
+
**          file:///home/fred/data.db <br> 
+
**          file://localhost/home/fred/data.db <br> <td> 
+
**          Open the database file "/home/fred/data.db".
+
** <tr><td> file://darkstar/home/fred/data.db <td> 
+
**          An error. "darkstar" is not a recognized authority.
+
** <tr><td style="white-space:nowrap"> 
+
**          file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
+
**     <td> Windows only: Open the file "data.db" on fred's desktop on drive
+
**          C:. Note that the %20 escaping in this example is not strictly 
+
**          necessary - space characters can be used literally
+
**          in URI filenames.
+
** <tr><td> file:data.db?mode=ro&cache=private <td> 
+
**          Open file "data.db" in the current directory for read-only access.
+
**          Regardless of whether or not shared-cache mode is enabled by
+
**          default, use a private cache.
+
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
+
**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+
** <tr><td> file:data.db?mode=readonly <td> 
+
**          An error. "readonly" is not a valid option for the "mode" parameter.
+
** </table>
+
**
+
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
+
** query components of a URI. A hexadecimal escape sequence consists of a
+
** percent sign - "%" - followed by exactly two hexadecimal digits 
+
** specifying an octet value. ^Before the path or query components of a
+
** URI filename are interpreted, they are encoded using UTF-8 and all 
+
** hexadecimal escape sequences replaced by a single byte containing the
+
** corresponding octet. If this process generates an invalid UTF-8 encoding,
+
** the results are undefined.
**
** <b>Note to Windows users:</b>  The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
@@ -2425,6 +2561,26 @@ SQLITE_API int sqlite3_open_v2(
);

/*
+
** CAPI3REF: Obtain Values For URI Parameters
+
**
+
** This is a utility routine, useful to VFS implementations, that checks
+
** to see if a database file was a URI that contained a specific query 
+
** parameter, and if so obtains the value of the query parameter.
+
**
+
** The zFilename argument is the filename pointer passed into the xOpen()
+
** method of a VFS implementation.  The zParam argument is the name of the
+
** query parameter we seek.  This routine returns the value of the zParam
+
** parameter if it exists.  If the parameter does not exist, this routine
+
** returns a NULL pointer.
+
**
+
** If the zFilename argument to this function is not a pointer that SQLite
+
** passed into the xOpen VFS method, then the behavior of this routine
+
** is undefined and probably undesirable.
+
*/
+
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+

+

+
/*
** CAPI3REF: Error Codes And Messages
**
** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -2539,43 +2695,45 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** Additional information is available at [limits | Limits in SQLite].
**
** <dl>
-
** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
+
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
+
** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
+
** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
** <dd>The maximum number of columns in a table definition or in the
** result set of a [SELECT] or the maximum number of columns in an index
** or in an ORDER BY or GROUP BY clause.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
+
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
+
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
+
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
** <dd>The maximum number of instructions in a virtual machine program
** used to implement an SQL statement.  This limit is not currently
** enforced, though that might be added in some future release of
** SQLite.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
+
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
** <dd>The maximum number of arguments on a function.</dd>)^
**
-
** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
+
** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
**
+
** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
** <dd>The maximum length of the pattern argument to the [LIKE] or
** [GLOB] operators.</dd>)^
**
+
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
-
** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
+
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^
** </dl>
*/
@@ -3104,7 +3262,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
** database locks it needs to do its job.  ^If the statement is a [COMMIT]
** or occurs outside of an explicit transaction, then you can retry the
-
** statement.  If the statement is not a [COMMIT] and occurs within a
+
** statement.  If the statement is not a [COMMIT] and occurs within an
** explicit transaction then you should rollback the transaction before
** continuing.
**
@@ -3383,7 +3541,7 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
** CAPI3REF: Destroy A Prepared Statement Object
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
-
** ^If the most recent evaluation of the statement encountered no errors or
+
** ^If the most recent evaluation of the statement encountered no errors
** or if the statement is never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK.  ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
@@ -4610,6 +4768,11 @@ struct sqlite3_module {
                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
                       void **ppArg);
  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+
  /* The methods above are in version 1 of the sqlite_module object. Those 
+
  ** below are for version 2 and greater. */
+
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+
  int (*xRelease)(sqlite3_vtab *pVTab, int);
+
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};

/*
@@ -5292,7 +5455,7 @@ struct sqlite3_mutex_methods {
**
** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
** the routine should return 1.   This seems counter-intuitive since
-
** clearly the mutex cannot be held if it does not exist.  But the
+
** clearly the mutex cannot be held if it does not exist.  But
** the reason the mutex does not exist is because the build is not
** using mutexes.  And we do not want the assert() containing the
** call to sqlite3_mutex_held() to fail, so a non-zero return is
@@ -5415,7 +5578,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_PGHDRSZ                 17
#define SQLITE_TESTCTRL_SCRATCHMALLOC           18
-
#define SQLITE_TESTCTRL_LAST                    18
+
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         19
+
#define SQLITE_TESTCTRL_LAST                    19

/*
** CAPI3REF: SQLite Runtime Status
@@ -5424,7 +5588,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for
** the specific parameter to measure.  ^(Recognized integer codes
-
** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
+
** are of the form [status parameters | SQLITE_STATUS_...].)^
** ^The current value of the parameter is returned into *pCurrent.
** ^The highest recorded value is returned in *pHighwater.  ^If the
** resetFlag is true, then the highest record value is reset after
@@ -5451,12 +5615,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF

/*
** CAPI3REF: Status Parameters
+
** KEYWORDS: {status parameters}
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite3_status()].
**
** <dl>
-
** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
+
** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
** <dd>This parameter is the current amount of memory checked out
** using [sqlite3_malloc()], either directly or indirectly.  The
** figure includes calls made to [sqlite3_malloc()] by the application
@@ -5466,23 +5631,24 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** this parameter.  The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+
** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
** internal equivalents).  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
+
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
** <dd>This parameter records the number of separate memory allocations
** currently checked out.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
+
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
** [pagecache memory allocator] that was configured using 
** [SQLITE_CONFIG_PAGECACHE].  The
** value returned is in pages, not in bytes.</dd>)^
**
+
** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] 
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of page cache
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
@@ -5492,13 +5658,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
+
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [pagecache memory allocator].  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
+
** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
** <dd>This parameter returns the number of allocations used out of the
** [scratch memory allocator] configured using
** [SQLITE_CONFIG_SCRATCH].  The value returned is in allocations, not
@@ -5506,7 +5672,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** outstanding at time, this parameter also reports the number of threads
** using scratch memory at the same time.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
+
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of scratch memory
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
** buffer and where forced to overflow to [sqlite3_malloc()].  The values
@@ -5516,13 +5682,13 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** slots were available.
** </dd>)^
**
-
** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
+
** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [scratch memory allocator].  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-
** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
+
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
** <dd>This parameter records the deepest parser stack.  It is only
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
** </dl>
@@ -5547,9 +5713,9 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** about a single [database connection].  ^The first argument is the
** database connection object to be interrogated.  ^The second argument
** is an integer constant, taken from the set of
-
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
+
** [SQLITE_DBSTATUS options], that
** determines the parameter to interrogate.  The set of 
-
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
+
** [SQLITE_DBSTATUS options] is likely
** to grow in future releases of SQLite.
**
** ^The current value of the requested parameter is written into *pCur
@@ -5566,6 +5732,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r

/*
** CAPI3REF: Status Parameters for database connections
+
** KEYWORDS: {SQLITE_DBSTATUS options}
**
** These constants are the available integer "verbs" that can be passed as
** the second argument to the [sqlite3_db_status()] interface.
@@ -5577,15 +5744,16 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** if a discontinued or unsupported verb is invoked.
**
** <dl>
-
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
-
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
+
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were 
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
+
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
@@ -5593,6 +5761,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
+
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
@@ -5600,12 +5769,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
-
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
+
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
-
** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
+
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^ 
@@ -5614,7 +5783,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
-
** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
+
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
@@ -5636,7 +5805,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** CAPI3REF: Prepared Statement Status
**
** ^(Each prepared statement maintains various
-
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
+
** [SQLITE_STMTSTATUS counters] that measure the number
** of times it has performed specific operations.)^  These counters can
** be used to monitor the performance characteristics of the prepared
** statements.  For example, if the number of table steps greatly exceeds
@@ -5647,7 +5816,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** ^(This interface is used to retrieve and reset counter values from
** a [prepared statement].  The first argument is the prepared statement
** object to be interrogated.  The second argument
-
** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
+
** is an integer code for a specific [SQLITE_STMTSTATUS counter]
** to be interrogated.)^
** ^The current value of the requested counter is returned.
** ^If the resetFlg is true, then the counter is reset to zero after this
@@ -5659,24 +5828,25 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);

/*
** CAPI3REF: Status Parameters for prepared statements
+
** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite3_stmt_status()] interface.
** The meanings of the various counters are as follows:
**
** <dl>
-
** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
+
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan.  Large numbers for this counter
** may indicate opportunities for performance improvement through 
** careful use of indices.</dd>
**
-
** <dt>SQLITE_STMTSTATUS_SORT</dt>
+
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
** improvement performance through careful use of indices.</dd>
**
-
** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
+
** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
** <dd>^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
@@ -5727,6 +5897,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** the application may discard the parameter after the call to
** [sqlite3_config()] returns.)^
**
+
** [[the xInit() page cache method]]
** ^(The xInit() method is called once for each effective 
** call to [sqlite3_initialize()])^
** (usually only once during the lifetime of the process). ^(The xInit()
@@ -5737,6 +5908,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** built-in default page cache is used instead of the application defined
** page cache.)^
**
+
** [[the xShutdown() page cache method]]
** ^The xShutdown() method is called by [sqlite3_shutdown()].
** It can be used to clean up 
** any outstanding resources before process shutdown, if required.
@@ -5751,6 +5923,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^SQLite will never invoke xInit() more than once without an intervening
** call to xShutdown().
**
+
** [[the xCreate() page cache methods]]
** ^SQLite invokes the xCreate() method to construct a new cache instance.
** SQLite will typically create one cache instance for each open database file,
** though this is not guaranteed. ^The
@@ -5775,6 +5948,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** ^Hence, a cache created with bPurgeable false will
** never contain any unpinned pages.
**
+
** [[the xCachesize() page cache method]]
** ^(The xCachesize() method may be called at any time by SQLite to set the
** suggested maximum cache-size (number of pages stored by) the cache
** instance passed as the first argument. This is the value configured using
@@ -5782,14 +5956,16 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** parameter, the implementation is not required to do anything with this
** value; it is advisory only.
**
+
** [[the xPagecount() page cache methods]]
** The xPagecount() method must return the number of pages currently
** stored in the cache, both pinned and unpinned.
** 
+
** [[the xFetch() page cache methods]]
** The xFetch() method locates a page in the cache and returns a pointer to 
** the page, or a NULL pointer.
** A "page", in this context, means a buffer of szPage bytes aligned at an
** 8-byte boundary. The page to be fetched is determined by the key. ^The
-
** mimimum key value is 1.  After it has been retrieved using xFetch, the page 
+
** minimum key value is 1.  After it has been retrieved using xFetch, the page 
** is considered to be "pinned".
**
** If the requested page is already in the page cache, then the page cache
@@ -5813,6 +5989,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
+
** [[the xUnpin() page cache method]]
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument.  If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
@@ -5825,6 +6002,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** call to xUnpin() unpins the page regardless of the number of prior calls 
** to xFetch().
**
+
** [[the xRekey() page cache methods]]
** The xRekey() method is used to change the key value associated with the
** page passed as the second argument. If the cache
** previously contains an entry associated with newKey, it must be
@@ -5837,6 +6015,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** of these pages are pinned, they are implicitly unpinned, meaning that
** they can be safely discarded.
**
+
** [[the xDestroy() page cache method]]
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
** All resources associated with the specified cache should be freed. ^After
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
@@ -5899,7 +6078,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** There should be exactly one call to sqlite3_backup_finish() for each
** successful call to sqlite3_backup_init().
**
-
** <b>sqlite3_backup_init()</b>
+
** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
**
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the 
** [database connection] associated with the destination database 
@@ -5926,7 +6105,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** sqlite3_backup_finish() functions to perform the specified backup 
** operation.
**
-
** <b>sqlite3_backup_step()</b>
+
** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
**
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between 
** the source and destination databases specified by [sqlite3_backup] object B.
@@ -5983,7 +6162,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
-
** <b>sqlite3_backup_finish()</b>
+
** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
**
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the 
** application wishes to abandon the backup operation, the application
@@ -6006,7 +6185,8 @@ typedef struct sqlite3_backup sqlite3_backup;
** is not a permanent error and does not affect the return value of
** sqlite3_backup_finish().
**
-
** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
+
** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
+
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
**
** ^Each call to sqlite3_backup_step() sets two values inside
** the [sqlite3_backup] object: the number of pages still to be backed
@@ -6392,6 +6572,93 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
#define SQLITE_CHECKPOINT_FULL    1
#define SQLITE_CHECKPOINT_RESTART 2

+
/*
+
** CAPI3REF: Virtual Table Interface Configuration
+
**
+
** This function may be called by either the [xConnect] or [xCreate] method
+
** of a [virtual table] implementation to configure
+
** various facets of the virtual table interface.
+
**
+
** If this interface is invoked outside the context of an xConnect or
+
** xCreate virtual table method then the behavior is undefined.
+
**
+
** At present, there is only one option that may be configured using
+
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].)  Further options
+
** may be added in the future.
+
*/
+
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+

+
/*
+
** CAPI3REF: Virtual Table Configuration Options
+
**
+
** These macros define the various options to the
+
** [sqlite3_vtab_config()] interface that [virtual table] implementations
+
** can use to customize and optimize their behavior.
+
**
+
** <dl>
+
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
+
** <dd>Calls of the form
+
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
+
** where X is an integer.  If X is zero, then the [virtual table] whose
+
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
+
** support constraints.  In this configuration (which is the default) if
+
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
+
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
+
** specified as part of the users SQL statement, regardless of the actual
+
** ON CONFLICT mode specified.
+
**
+
** If X is non-zero, then the virtual table implementation guarantees
+
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
+
** any modifications to internal or persistent data structures have been made.
+
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite 
+
** is able to roll back a statement or database transaction, and abandon
+
** or continue processing the current SQL statement as appropriate. 
+
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
+
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
+
** had been ABORT.
+
**
+
** Virtual table implementations that are required to handle OR REPLACE
+
** must do so within the [xUpdate] method. If a call to the 
+
** [sqlite3_vtab_on_conflict()] function indicates that the current ON 
+
** CONFLICT policy is REPLACE, the virtual table implementation should 
+
** silently replace the appropriate rows within the xUpdate callback and
+
** return SQLITE_OK. Or, if this is not possible, it may return
+
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
+
** constraint handling.
+
** </dl>
+
*/
+
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+

+
/*
+
** CAPI3REF: Determine The Virtual Table Conflict Policy
+
**
+
** This function may only be called from within a call to the [xUpdate] method
+
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
+
** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
+
** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
+
** of the SQL statement that triggered the call to the [xUpdate] method of the
+
** [virtual table].
+
*/
+
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+

+
/*
+
** CAPI3REF: Conflict resolution modes
+
**
+
** These constants are returned by [sqlite3_vtab_on_conflict()] to
+
** inform a [virtual table] implementation what the [ON CONFLICT] mode
+
** is for the SQL statement being evaluated.
+
**
+
** Note that the [SQLITE_IGNORE] constant is also used as a potential
+
** return value from the [sqlite3_set_authorizer()] callback and that
+
** [SQLITE_ABORT] is also a [result code].
+
*/
+
#define SQLITE_ROLLBACK 1
+
/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
+
#define SQLITE_FAIL     3
+
/* #define SQLITE_ABORT 4  // Also an error code */
+
#define SQLITE_REPLACE  5
+

+


/*
** Undo the hack that converts floating point types to integer for