Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Update sqlite to 3.7.7.1 while here remove compat
Baptiste Daroussin committed 14 years ago
commit 7454ae132d5959e8841380949fedec1b4d07624a
parent 146165ab77db20298aa9d4717c02c7348571c8b2
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