Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update sqlite to 3.7.8
Baptiste Daroussin committed 14 years ago
commit c3d6c47014d5e752d8fa19e9a62b25b3133bbdbf
parent ca0b8b4
2 files changed +4632 -1954
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.7.1.  By combining all the individual C code files into this 
+
** version 3.7.8.  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
@@ -387,19 +387,25 @@
** specify which memory allocation subsystem to use.
**
**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
+
**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
**
+
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
+
** assert() macro is enabled, each call into the Win32 native heap subsystem
+
** will cause HeapValidate to be called.  If heap validation should fail, an
+
** assertion will be triggered.
+
**
** (Historical note:  There used to be several other options, but we've
** pared it down to just these two.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
-
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
+
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
-
 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
+
 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
#endif
-
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
+
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif

@@ -650,9 +656,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.7.7.1"
-
#define SQLITE_VERSION_NUMBER 3007007
-
#define SQLITE_SOURCE_ID      "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"
+
#define SQLITE_VERSION        "3.7.8"
+
#define SQLITE_VERSION_NUMBER 3007008
+
#define SQLITE_SOURCE_ID      "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1284,6 +1290,37 @@ struct sqlite3_io_methods {
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
+
**
+
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
+
** retry counts and intervals for certain disk I/O operations for the
+
** windows [VFS] in order to work to provide robustness against
+
** anti-virus programs.  By default, the windows VFS will retry file read,
+
** file write, and file delete opertions up to 10 times, with a delay
+
** of 25 milliseconds before the first retry and with the delay increasing
+
** by an additional 25 milliseconds with each subsequent retry.  This
+
** opcode allows those to values (10 retries and 25 milliseconds of delay)
+
** to be adjusted.  The values are changed for all database connections
+
** within the same process.  The argument is a pointer to an array of two
+
** integers where the first integer i the new retry count and the second
+
** integer is the delay.  If either integer is negative, then the setting
+
** is not changed but instead the prior value of that setting is written
+
** into the array entry, allowing the current retry settings to be
+
** interrogated.  The zDbName parameter is ignored.
+
**
+
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
+
** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
+
** write ahead log and shared memory files used for transaction control
+
** are automatically deleted when the latest connection to the database
+
** closes.  Setting persistent WAL mode causes those files to persist after
+
** close.  Persisting the files is useful when other processes that do not
+
** have write permission on the directory containing the database file want
+
** to read the database file, as the WAL and shared memory files must exist
+
** in order for the database to be readable.  The fourth parameter to
+
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
+
** WAL mode.  If the integer is -1, then it is overwritten with the current
+
** WAL persistence setting.
+
** 
*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
@@ -1293,7 +1330,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8
-

+
#define SQLITE_FCNTL_WIN32_AV_RETRY   9
+
#define SQLITE_FCNTL_PERSIST_WAL     10

/*
** CAPI3REF: Mutex Handle
@@ -1721,16 +1759,10 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** order to verify that SQLite recovers gracefully from such
** conditions.
**
-
** The xMalloc and xFree methods must work like the
-
** malloc() and free() functions from the standard C library.
-
** The xRealloc method must work like realloc() from the standard C library
-
** with the exception that if the second argument to xRealloc is zero,
-
** xRealloc must be a no-op - it must not perform any allocation or
-
** deallocation.  ^SQLite guarantees that the second argument to
+
** The xMalloc, xRealloc, and xFree methods must work like the
+
** malloc(), realloc() and free() functions from the standard C library.
+
** ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.
-
** And so in cases where xRoundup always returns a positive number,
-
** xRealloc can perform exactly as the standard library realloc() and
-
** still be in compliance with this specification.
**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc.  The allocated size
@@ -8146,6 +8178,7 @@ SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
+
/* #include <stdio.h> */

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
@@ -8189,6 +8222,7 @@ struct VdbeOp {
    KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    int *ai;               /* Used when p4type is P4_INTARRAY */
    SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
+
    int (*xAdvance)(BtCursor *, int *);
  } p4;
#ifdef SQLITE_DEBUG
  char *zComment;          /* Comment to improve readability */
@@ -8244,6 +8278,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */
+
#define P4_ADVANCE  (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */

/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
** is made.  That copy is freed when the Vdbe is finalized.  But if the
@@ -8341,102 +8376,105 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Or                                  68   /* same as TK_OR       */
#define OP_Not                                 19   /* same as TK_NOT      */
#define OP_BitNot                              93   /* same as TK_BITNOT   */
-
#define OP_If                                  26
-
#define OP_IfNot                               27
+
#define OP_Once                                26
+
#define OP_If                                  27
+
#define OP_IfNot                               28
#define OP_IsNull                              73   /* same as TK_ISNULL   */
#define OP_NotNull                             74   /* same as TK_NOTNULL  */
-
#define OP_Column                              28
-
#define OP_Affinity                            29
-
#define OP_MakeRecord                          30
-
#define OP_Count                               31
-
#define OP_Savepoint                           32
-
#define OP_AutoCommit                          33
-
#define OP_Transaction                         34
-
#define OP_ReadCookie                          35
-
#define OP_SetCookie                           36
-
#define OP_VerifyCookie                        37
-
#define OP_OpenRead                            38
-
#define OP_OpenWrite                           39
-
#define OP_OpenAutoindex                       40
-
#define OP_OpenEphemeral                       41
-
#define OP_OpenPseudo                          42
-
#define OP_Close                               43
-
#define OP_SeekLt                              44
-
#define OP_SeekLe                              45
-
#define OP_SeekGe                              46
-
#define OP_SeekGt                              47
-
#define OP_Seek                                48
-
#define OP_NotFound                            49
-
#define OP_Found                               50
-
#define OP_IsUnique                            51
-
#define OP_NotExists                           52
-
#define OP_Sequence                            53
-
#define OP_NewRowid                            54
-
#define OP_Insert                              55
-
#define OP_InsertInt                           56
-
#define OP_Delete                              57
-
#define OP_ResetCount                          58
-
#define OP_RowKey                              59
-
#define OP_RowData                             60
-
#define OP_Rowid                               61
-
#define OP_NullRow                             62
-
#define OP_Last                                63
-
#define OP_Sort                                64
-
#define OP_Rewind                              65
-
#define OP_Prev                                66
-
#define OP_Next                                67
-
#define OP_IdxInsert                           70
-
#define OP_IdxDelete                           71
-
#define OP_IdxRowid                            72
-
#define OP_IdxLT                               81
-
#define OP_IdxGE                               92
-
#define OP_Destroy                             95
-
#define OP_Clear                               96
-
#define OP_CreateIndex                         97
-
#define OP_CreateTable                         98
-
#define OP_ParseSchema                         99
-
#define OP_LoadAnalysis                       100
-
#define OP_DropTable                          101
-
#define OP_DropIndex                          102
-
#define OP_DropTrigger                        103
-
#define OP_IntegrityCk                        104
-
#define OP_RowSetAdd                          105
-
#define OP_RowSetRead                         106
-
#define OP_RowSetTest                         107
-
#define OP_Program                            108
-
#define OP_Param                              109
-
#define OP_FkCounter                          110
-
#define OP_FkIfZero                           111
-
#define OP_MemMax                             112
-
#define OP_IfPos                              113
-
#define OP_IfNeg                              114
-
#define OP_IfZero                             115
-
#define OP_AggStep                            116
-
#define OP_AggFinal                           117
-
#define OP_Checkpoint                         118
-
#define OP_JournalMode                        119
-
#define OP_Vacuum                             120
-
#define OP_IncrVacuum                         121
-
#define OP_Expire                             122
-
#define OP_TableLock                          123
-
#define OP_VBegin                             124
-
#define OP_VCreate                            125
-
#define OP_VDestroy                           126
-
#define OP_VOpen                              127
-
#define OP_VFilter                            128
-
#define OP_VColumn                            129
-
#define OP_VNext                              131
-
#define OP_VRename                            132
-
#define OP_VUpdate                            133
-
#define OP_Pagecount                          134
-
#define OP_MaxPgcnt                           135
-
#define OP_Trace                              136
-
#define OP_Noop                               137
-
#define OP_Explain                            138
-

-
/* The following opcode values are never used */
-
#define OP_NotUsed_139                        139
-
#define OP_NotUsed_140                        140
+
#define OP_Column                              29
+
#define OP_Affinity                            30
+
#define OP_MakeRecord                          31
+
#define OP_Count                               32
+
#define OP_Savepoint                           33
+
#define OP_AutoCommit                          34
+
#define OP_Transaction                         35
+
#define OP_ReadCookie                          36
+
#define OP_SetCookie                           37
+
#define OP_VerifyCookie                        38
+
#define OP_OpenRead                            39
+
#define OP_OpenWrite                           40
+
#define OP_OpenAutoindex                       41
+
#define OP_OpenEphemeral                       42
+
#define OP_SorterOpen                          43
+
#define OP_OpenPseudo                          44
+
#define OP_Close                               45
+
#define OP_SeekLt                              46
+
#define OP_SeekLe                              47
+
#define OP_SeekGe                              48
+
#define OP_SeekGt                              49
+
#define OP_Seek                                50
+
#define OP_NotFound                            51
+
#define OP_Found                               52
+
#define OP_IsUnique                            53
+
#define OP_NotExists                           54
+
#define OP_Sequence                            55
+
#define OP_NewRowid                            56
+
#define OP_Insert                              57
+
#define OP_InsertInt                           58
+
#define OP_Delete                              59
+
#define OP_ResetCount                          60
+
#define OP_SorterCompare                       61
+
#define OP_SorterData                          62
+
#define OP_RowKey                              63
+
#define OP_RowData                             64
+
#define OP_Rowid                               65
+
#define OP_NullRow                             66
+
#define OP_Last                                67
+
#define OP_SorterSort                          70
+
#define OP_Sort                                71
+
#define OP_Rewind                              72
+
#define OP_SorterNext                          81
+
#define OP_Prev                                92
+
#define OP_Next                                95
+
#define OP_SorterInsert                        96
+
#define OP_IdxInsert                           97
+
#define OP_IdxDelete                           98
+
#define OP_IdxRowid                            99
+
#define OP_IdxLT                              100
+
#define OP_IdxGE                              101
+
#define OP_Destroy                            102
+
#define OP_Clear                              103
+
#define OP_CreateIndex                        104
+
#define OP_CreateTable                        105
+
#define OP_ParseSchema                        106
+
#define OP_LoadAnalysis                       107
+
#define OP_DropTable                          108
+
#define OP_DropIndex                          109
+
#define OP_DropTrigger                        110
+
#define OP_IntegrityCk                        111
+
#define OP_RowSetAdd                          112
+
#define OP_RowSetRead                         113
+
#define OP_RowSetTest                         114
+
#define OP_Program                            115
+
#define OP_Param                              116
+
#define OP_FkCounter                          117
+
#define OP_FkIfZero                           118
+
#define OP_MemMax                             119
+
#define OP_IfPos                              120
+
#define OP_IfNeg                              121
+
#define OP_IfZero                             122
+
#define OP_AggStep                            123
+
#define OP_AggFinal                           124
+
#define OP_Checkpoint                         125
+
#define OP_JournalMode                        126
+
#define OP_Vacuum                             127
+
#define OP_IncrVacuum                         128
+
#define OP_Expire                             129
+
#define OP_TableLock                          131
+
#define OP_VBegin                             132
+
#define OP_VCreate                            133
+
#define OP_VDestroy                           134
+
#define OP_VOpen                              135
+
#define OP_VFilter                            136
+
#define OP_VColumn                            137
+
#define OP_VNext                              138
+
#define OP_VRename                            139
+
#define OP_VUpdate                            140
+
#define OP_Pagecount                          146
+
#define OP_MaxPgcnt                           147
+
#define OP_Trace                              148
+
#define OP_Noop                               149
+
#define OP_Explain                            150


/* Properties such as "out2" or "jump" that are specified in
@@ -8454,22 +8492,22 @@ typedef struct VdbeOpList VdbeOpList;
/*   0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
/*  16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
-
/*  24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
-
/*  32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
-
/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
-
/*  48 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00,\
-
/*  56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
-
/*  64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x08, 0x00,\
-
/*  72 */ 0x02, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
+
/*  24 */ 0x00, 0x01, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
+
/*  32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
+
/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
+
/*  48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
+
/*  56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+
/*  64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
+
/*  72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
/*  80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
-
/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\
-
/*  96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
-
/* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\
-
/* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
-
/* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-
/* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,\
-
/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
-
/* 144 */ 0x04, 0x04,}
+
/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
+
/*  96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
+
/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+
/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
+
/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
+
/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
+
/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
+
/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}

/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -8487,12 +8525,12 @@ 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);
+
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
+
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
+
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
-
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
+
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
@@ -8524,9 +8562,9 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
SQLITE_PRIVATE   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif

-
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
-
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
+
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
@@ -9560,6 +9598,7 @@ struct sqlite3 {
#define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
#define SQLITE_IdxRealAsInt   0x80        /* Store REAL as INT in indices */
+
#define SQLITE_DistinctOpt    0x80        /* DISTINCT using indexes */
#define SQLITE_OptMask        0xff        /* Mask of all disablable opts */

/*
@@ -10139,6 +10178,7 @@ struct AggInfo {
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  int sortingIdx;         /* Cursor number of the sorting index */
+
  int sortingIdxPTab;     /* Cursor number of pseudo-table */
  ExprList *pGroupBy;     /* The group by clause */
  int nSortingColumn;     /* Number of columns in the sorting index */
  struct AggInfo_col {    /* For each column used in source tables */
@@ -10448,9 +10488,11 @@ struct SrcList {
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
-
    u8 isPopulated;   /* Temporary table associated with SELECT is populated */
+
    int addrFillSub;  /* Address of subroutine to manifest a subquery */
+
    int regReturn;    /* Register holding return address of addrFillSub */
    u8 jointype;      /* Type of join between this able and the previous */
    u8 notIndexed;    /* True if there is a NOT INDEXED clause */
+
    u8 isCorrelated;  /* True if sub-query is correlated */
#ifndef SQLITE_OMIT_EXPLAIN
    u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
#endif
@@ -10570,6 +10612,7 @@ struct WhereInfo {
  u16 wctrlFlags;      /* Flags originally passed to sqlite3WhereBegin() */
  u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
  u8 untestedTerms;    /* Not all WHERE terms resolved by outer loop */
+
  u8 eDistinct;
  SrcList *pTabList;             /* List of tables in the join */
  int iTop;                      /* The very beginning of the WHERE loop */
  int iContinue;                 /* Jump here to continue with next record */
@@ -10581,6 +10624,9 @@ struct WhereInfo {
  WhereLevel a[1];               /* Information about each nest loop in WHERE */
};

+
#define WHERE_DISTINCT_UNIQUE 1
+
#define WHERE_DISTINCT_ORDERED 2
+

/*
** A NameContext defines a context in which to resolve table and column
** names.  The context consists of a list of tables (the pSrcList) field and
@@ -10666,6 +10712,7 @@ struct Select {
#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
+
#define SF_UseSorter       0x0040  /* Sort using a sorter */


/*
@@ -11342,7 +11389,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, E
#endif
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
+
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
@@ -11992,7 +12039,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_THREADSAFE==1,      /* bFullMutex */
   SQLITE_USE_URI,            /* bOpenUri */
   0x7ffffffe,                /* mxStrlen */
-
   100,                       /* szLookaside */
+
   128,                       /* szLookaside */
   500,                       /* nLookaside */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
@@ -12215,6 +12262,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_LOCK_TRACE
  "LOCK_TRACE",
#endif
+
#ifdef SQLITE_MAX_SCHEMA_RETRY
+
  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+
#endif
#ifdef SQLITE_MEMDEBUG
  "MEMDEBUG",
#endif
@@ -12328,6 +12378,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_MEMORYDB
  "OMIT_MEMORYDB",
#endif
+
#ifdef SQLITE_OMIT_MERGE_SORT
+
  "OMIT_MERGE_SORT",
+
#endif
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
  "OMIT_OR_OPTIMIZATION",
#endif
@@ -12394,6 +12447,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif
+
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
+
  "PAGECACHE_BLOCKALLOC",
+
#endif
#ifdef SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
@@ -12514,6 +12570,9 @@ typedef struct VdbeOp Op;
*/
typedef unsigned char Bool;

+
/* Opaque type used by code in vdbesort.c */
+
typedef struct VdbeSorter VdbeSorter;
+

/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
@@ -12540,11 +12599,13 @@ struct VdbeCursor {
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
+
  Bool isSorter;        /* True if a new-style sorter */
  sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */
+
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */

  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
  ** OP_IsUnique opcode on this cursor. */
@@ -12864,6 +12925,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
+
#define MemReleaseExt(X)  \
+
  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
+
    sqlite3VdbeMemReleaseExternal(X);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
@@ -12872,6 +12936,24 @@ SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);

+
#ifdef SQLITE_OMIT_MERGE_SORT
+
# define sqlite3VdbeSorterInit(Y,Z)      SQLITE_OK
+
# define sqlite3VdbeSorterWrite(X,Y,Z)   SQLITE_OK
+
# define sqlite3VdbeSorterClose(Y,Z)
+
# define sqlite3VdbeSorterRowkey(Y,Z)    SQLITE_OK
+
# define sqlite3VdbeSorterRewind(X,Y,Z)  SQLITE_OK
+
# define sqlite3VdbeSorterNext(X,Y,Z)    SQLITE_OK
+
# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
+
#else
+
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
+
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
+
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
+
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
+
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
+
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
+
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
+
#endif
+

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
SQLITE_PRIVATE   void sqlite3VdbeLeave(Vdbe*);
@@ -13165,6 +13247,8 @@ SQLITE_API int sqlite3_db_status(
**      Willmann-Bell, Inc
**      Richmond, Virginia (USA)
*/
+
/* #include <stdlib.h> */
+
/* #include <assert.h> */
#include <time.h>

#ifndef SQLITE_OMIT_DATETIME_FUNCS
@@ -13546,7 +13630,9 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
  struct tm *pX;
+
#if SQLITE_THREADSAFE>0
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+
#endif
  sqlite3_mutex_enter(mutex);
  pX = localtime(t);
#ifndef SQLITE_OMIT_BUILTIN_TEST
@@ -14380,7 +14466,7 @@ SQLITE_PRIVATE int sqlite3OsOpen(
  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  ** reaching the VFS. */
-
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut);
+
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
@@ -14452,7 +14538,7 @@ SQLITE_PRIVATE int sqlite3OsOpenMalloc(
){
  int rc = SQLITE_NOMEM;
  sqlite3_file *pFile;
-
  pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile);
+
  pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
  if( pFile ){
    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
    if( rc!=SQLITE_OK ){
@@ -14916,6 +15002,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
# define backtrace(A,B) 1
# define backtrace_symbols_fd(A,B,C)
#endif
+
/* #include <stdio.h> */

/*
** Each memory allocation looks like this:
@@ -15841,7 +15928,7 @@ static void *memsys3MallocUnsafe(int nByte){
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
-
void memsys3FreeUnsafe(void *pOld){
+
static void memsys3FreeUnsafe(void *pOld){
  Mem3Block *p = (Mem3Block*)pOld;
  int i;
  u32 size, x;
@@ -15916,7 +16003,7 @@ static void *memsys3Malloc(int nBytes){
/*
** Free memory.
*/
-
void memsys3Free(void *pPrior){
+
static void memsys3Free(void *pPrior){
  assert( pPrior );
  memsys3Enter();
  memsys3FreeUnsafe(pPrior);
@@ -15926,7 +16013,7 @@ void memsys3Free(void *pPrior){
/*
** Change the size of an existing memory allocation
*/
-
void *memsys3Realloc(void *pPrior, int nBytes){
+
static void *memsys3Realloc(void *pPrior, int nBytes){
  int nOld;
  void *p;
  if( pPrior==0 ){
@@ -18019,6 +18106,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
**
** Memory allocation functions used throughout sqlite.
*/
+
/* #include <stdarg.h> */

/*
** Attempt to release up to n bytes of non-essential memory currently
@@ -19996,6 +20084,7 @@ SQLITE_PRIVATE void sqlite3PrngResetState(void){
**     0xfe 0xff   big-endian utf-16 follows
**
*/
+
/* #include <assert.h> */

#ifndef SQLITE_AMALGAMATION
/*
@@ -20538,6 +20627,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
** strings, and stuff like that.
**
*/
+
/* #include <stdarg.h> */
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif
@@ -21670,12 +21760,15 @@ SQLITE_PRIVATE int sqlite3AbsInt32(int x){

#ifdef SQLITE_ENABLE_8_3_NAMES
/*
-
** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
+
** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
** three characters, then shorten the suffix on z[] to be the last three
** characters of the original suffix.
**
+
** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
+
** do the suffix shortening regardless of URI parameter.
+
**
** Examples:
**
**     test.db-journal    =>   test.nal
@@ -21683,9 +21776,12 @@ SQLITE_PRIVATE int sqlite3AbsInt32(int x){
**     test.db-shm        =>   test.shm
*/
SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
+
#if SQLITE_ENABLE_8_3_NAMES<2
  const char *zOk;
  zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
-
  if( zOk && sqlite3GetBoolean(zOk) ){
+
  if( zOk && sqlite3GetBoolean(zOk) )
+
#endif
+
  {
    int i, sz;
    sz = sqlite3Strlen30(z);
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
@@ -21710,6 +21806,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
** This is the implementation of generic hash-tables
** used in SQLite.
*/
+
/* #include <assert.h> */

/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
@@ -22004,53 +22101,53 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
     /*  23 */ "Permutation",
     /*  24 */ "Compare",
     /*  25 */ "Jump",
-
     /*  26 */ "If",
-
     /*  27 */ "IfNot",
-
     /*  28 */ "Column",
-
     /*  29 */ "Affinity",
-
     /*  30 */ "MakeRecord",
-
     /*  31 */ "Count",
-
     /*  32 */ "Savepoint",
-
     /*  33 */ "AutoCommit",
-
     /*  34 */ "Transaction",
-
     /*  35 */ "ReadCookie",
-
     /*  36 */ "SetCookie",
-
     /*  37 */ "VerifyCookie",
-
     /*  38 */ "OpenRead",
-
     /*  39 */ "OpenWrite",
-
     /*  40 */ "OpenAutoindex",
-
     /*  41 */ "OpenEphemeral",
-
     /*  42 */ "OpenPseudo",
-
     /*  43 */ "Close",
-
     /*  44 */ "SeekLt",
-
     /*  45 */ "SeekLe",
-
     /*  46 */ "SeekGe",
-
     /*  47 */ "SeekGt",
-
     /*  48 */ "Seek",
-
     /*  49 */ "NotFound",
-
     /*  50 */ "Found",
-
     /*  51 */ "IsUnique",
-
     /*  52 */ "NotExists",
-
     /*  53 */ "Sequence",
-
     /*  54 */ "NewRowid",
-
     /*  55 */ "Insert",
-
     /*  56 */ "InsertInt",
-
     /*  57 */ "Delete",
-
     /*  58 */ "ResetCount",
-
     /*  59 */ "RowKey",
-
     /*  60 */ "RowData",
-
     /*  61 */ "Rowid",
-
     /*  62 */ "NullRow",
-
     /*  63 */ "Last",
-
     /*  64 */ "Sort",
-
     /*  65 */ "Rewind",
-
     /*  66 */ "Prev",
-
     /*  67 */ "Next",
+
     /*  26 */ "Once",
+
     /*  27 */ "If",
+
     /*  28 */ "IfNot",
+
     /*  29 */ "Column",
+
     /*  30 */ "Affinity",
+
     /*  31 */ "MakeRecord",
+
     /*  32 */ "Count",
+
     /*  33 */ "Savepoint",
+
     /*  34 */ "AutoCommit",
+
     /*  35 */ "Transaction",
+
     /*  36 */ "ReadCookie",
+
     /*  37 */ "SetCookie",
+
     /*  38 */ "VerifyCookie",
+
     /*  39 */ "OpenRead",
+
     /*  40 */ "OpenWrite",
+
     /*  41 */ "OpenAutoindex",
+
     /*  42 */ "OpenEphemeral",
+
     /*  43 */ "SorterOpen",
+
     /*  44 */ "OpenPseudo",
+
     /*  45 */ "Close",
+
     /*  46 */ "SeekLt",
+
     /*  47 */ "SeekLe",
+
     /*  48 */ "SeekGe",
+
     /*  49 */ "SeekGt",
+
     /*  50 */ "Seek",
+
     /*  51 */ "NotFound",
+
     /*  52 */ "Found",
+
     /*  53 */ "IsUnique",
+
     /*  54 */ "NotExists",
+
     /*  55 */ "Sequence",
+
     /*  56 */ "NewRowid",
+
     /*  57 */ "Insert",
+
     /*  58 */ "InsertInt",
+
     /*  59 */ "Delete",
+
     /*  60 */ "ResetCount",
+
     /*  61 */ "SorterCompare",
+
     /*  62 */ "SorterData",
+
     /*  63 */ "RowKey",
+
     /*  64 */ "RowData",
+
     /*  65 */ "Rowid",
+
     /*  66 */ "NullRow",
+
     /*  67 */ "Last",
     /*  68 */ "Or",
     /*  69 */ "And",
-
     /*  70 */ "IdxInsert",
-
     /*  71 */ "IdxDelete",
-
     /*  72 */ "IdxRowid",
+
     /*  70 */ "SorterSort",
+
     /*  71 */ "Sort",
+
     /*  72 */ "Rewind",
     /*  73 */ "IsNull",
     /*  74 */ "NotNull",
     /*  75 */ "Ne",
@@ -22059,7 +22156,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
     /*  78 */ "Le",
     /*  79 */ "Lt",
     /*  80 */ "Ge",
-
     /*  81 */ "IdxLT",
+
     /*  81 */ "SorterNext",
     /*  82 */ "BitAnd",
     /*  83 */ "BitOr",
     /*  84 */ "ShiftLeft",
@@ -22070,60 +22167,65 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
     /*  89 */ "Divide",
     /*  90 */ "Remainder",
     /*  91 */ "Concat",
-
     /*  92 */ "IdxGE",
+
     /*  92 */ "Prev",
     /*  93 */ "BitNot",
     /*  94 */ "String8",
-
     /*  95 */ "Destroy",
-
     /*  96 */ "Clear",
-
     /*  97 */ "CreateIndex",
-
     /*  98 */ "CreateTable",
-
     /*  99 */ "ParseSchema",
-
     /* 100 */ "LoadAnalysis",
-
     /* 101 */ "DropTable",
-
     /* 102 */ "DropIndex",
-
     /* 103 */ "DropTrigger",
-
     /* 104 */ "IntegrityCk",
-
     /* 105 */ "RowSetAdd",
-
     /* 106 */ "RowSetRead",
-
     /* 107 */ "RowSetTest",
-
     /* 108 */ "Program",
-
     /* 109 */ "Param",
-
     /* 110 */ "FkCounter",
-
     /* 111 */ "FkIfZero",
-
     /* 112 */ "MemMax",
-
     /* 113 */ "IfPos",
-
     /* 114 */ "IfNeg",
-
     /* 115 */ "IfZero",
-
     /* 116 */ "AggStep",
-
     /* 117 */ "AggFinal",
-
     /* 118 */ "Checkpoint",
-
     /* 119 */ "JournalMode",
-
     /* 120 */ "Vacuum",
-
     /* 121 */ "IncrVacuum",
-
     /* 122 */ "Expire",
-
     /* 123 */ "TableLock",
-
     /* 124 */ "VBegin",
-
     /* 125 */ "VCreate",
-
     /* 126 */ "VDestroy",
-
     /* 127 */ "VOpen",
-
     /* 128 */ "VFilter",
-
     /* 129 */ "VColumn",
+
     /*  95 */ "Next",
+
     /*  96 */ "SorterInsert",
+
     /*  97 */ "IdxInsert",
+
     /*  98 */ "IdxDelete",
+
     /*  99 */ "IdxRowid",
+
     /* 100 */ "IdxLT",
+
     /* 101 */ "IdxGE",
+
     /* 102 */ "Destroy",
+
     /* 103 */ "Clear",
+
     /* 104 */ "CreateIndex",
+
     /* 105 */ "CreateTable",
+
     /* 106 */ "ParseSchema",
+
     /* 107 */ "LoadAnalysis",
+
     /* 108 */ "DropTable",
+
     /* 109 */ "DropIndex",
+
     /* 110 */ "DropTrigger",
+
     /* 111 */ "IntegrityCk",
+
     /* 112 */ "RowSetAdd",
+
     /* 113 */ "RowSetRead",
+
     /* 114 */ "RowSetTest",
+
     /* 115 */ "Program",
+
     /* 116 */ "Param",
+
     /* 117 */ "FkCounter",
+
     /* 118 */ "FkIfZero",
+
     /* 119 */ "MemMax",
+
     /* 120 */ "IfPos",
+
     /* 121 */ "IfNeg",
+
     /* 122 */ "IfZero",
+
     /* 123 */ "AggStep",
+
     /* 124 */ "AggFinal",
+
     /* 125 */ "Checkpoint",
+
     /* 126 */ "JournalMode",
+
     /* 127 */ "Vacuum",
+
     /* 128 */ "IncrVacuum",
+
     /* 129 */ "Expire",
     /* 130 */ "Real",
-
     /* 131 */ "VNext",
-
     /* 132 */ "VRename",
-
     /* 133 */ "VUpdate",
-
     /* 134 */ "Pagecount",
-
     /* 135 */ "MaxPgcnt",
-
     /* 136 */ "Trace",
-
     /* 137 */ "Noop",
-
     /* 138 */ "Explain",
-
     /* 139 */ "NotUsed_139",
-
     /* 140 */ "NotUsed_140",
+
     /* 131 */ "TableLock",
+
     /* 132 */ "VBegin",
+
     /* 133 */ "VCreate",
+
     /* 134 */ "VDestroy",
+
     /* 135 */ "VOpen",
+
     /* 136 */ "VFilter",
+
     /* 137 */ "VColumn",
+
     /* 138 */ "VNext",
+
     /* 139 */ "VRename",
+
     /* 140 */ "VUpdate",
     /* 141 */ "ToText",
     /* 142 */ "ToBlob",
     /* 143 */ "ToNumeric",
     /* 144 */ "ToInt",
     /* 145 */ "ToReal",
+
     /* 146 */ "Pagecount",
+
     /* 147 */ "MaxPgcnt",
+
     /* 148 */ "Trace",
+
     /* 149 */ "Noop",
+
     /* 150 */ "Explain",
  };
  return azName[i];
}
@@ -22218,11 +22320,14 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

-
#ifdef SQLITE_DEBUG
-
SQLITE_PRIVATE int sqlite3OSTrace = 0;
-
#define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
+
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+
# ifndef SQLITE_DEBUG_OS_TRACE
+
#   define SQLITE_DEBUG_OS_TRACE 0
+
# endif
+
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
-
#define OSTRACE(X)
+
# define OSTRACE(X)
#endif

/*
@@ -24379,6 +24484,7 @@ SQLITE_API int sqlite3_os_end(void){
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+
/* #include <time.h> */
#include <sys/time.h>
#include <errno.h>
#ifndef SQLITE_OMIT_WAL
@@ -24414,6 +24520,7 @@ SQLITE_API int sqlite3_os_end(void){
** the SQLITE_UNIX_THREADS macro.
*/
#if SQLITE_THREADSAFE
+
/* # include <pthread.h> */
# define SQLITE_UNIX_THREADS 1
#endif

@@ -24469,7 +24576,6 @@ struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */
  unixInodeInfo *pInode;              /* Info about locks on this inode */
  int h;                              /* The file descriptor */
-
  int dirfd;                          /* File descriptor for the directory */
  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
@@ -24511,8 +24617,14 @@ struct unixFile {
/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
-
#define UNIXFILE_EXCL   0x01     /* Connections from one process only */
-
#define UNIXFILE_RDONLY 0x02     /* Connection is read only */
+
#define UNIXFILE_EXCL        0x01     /* Connections from one process only */
+
#define UNIXFILE_RDONLY      0x02     /* Connection is read only */
+
#define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
+
#ifndef SQLITE_DISABLE_DIRSYNC
+
# define UNIXFILE_DIRSYNC    0x08     /* Directory sync needed */
+
#else
+
# define UNIXFILE_DIRSYNC    0x00
+
#endif

/*
** Include code that is common to all os_*.c files
@@ -24550,11 +24662,14 @@ struct unixFile {
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

-
#ifdef SQLITE_DEBUG
-
SQLITE_PRIVATE int sqlite3OSTrace = 0;
-
#define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
+
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+
# ifndef SQLITE_DEBUG_OS_TRACE
+
#   define SQLITE_DEBUG_OS_TRACE 0
+
# endif
+
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
-
#define OSTRACE(X)
+
# define OSTRACE(X)
#endif

/*
@@ -24763,6 +24878,9 @@ static int posixOpen(const char *zFile, int flags, int mode){
  return open(zFile, flags, mode);
}

+
/* Forward reference */
+
static int openDirectory(const char*, int*);
+

/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
@@ -24859,6 +24977,12 @@ static struct unix_syscall {
#endif
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)

+
  { "unlink",       (sqlite3_syscall_ptr)unlink,           0 },
+
#define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)
+

+
  { "openDirectory",    (sqlite3_syscall_ptr)openDirectory,      0 },
+
#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
+

}; /* End of the overrideable system calls */

/*
@@ -25143,7 +25267,9 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
  case ENODEV:
  case ENXIO:
  case ENOENT:
+
#ifdef ESTALE                     /* ESTALE is not defined on Interix systems */
  case ESTALE:
+
#endif
  case ENOSYS:
    /* these should force the client to close the file and reconnect */
    
@@ -26213,10 +26339,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){
*/
static int closeUnixFile(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;
-
  if( pFile->dirfd>=0 ){
-
    robust_close(pFile, pFile->dirfd, __LINE__);
-
    pFile->dirfd=-1;
-
  }
  if( pFile->h>=0 ){
    robust_close(pFile, pFile->h, __LINE__);
    pFile->h = -1;
@@ -26224,7 +26346,7 @@ static int closeUnixFile(sqlite3_file *id){
#if OS_VXWORKS
  if( pFile->pId ){
    if( pFile->isDelete ){
-
      unlink(pFile->pId->zCanonicalName);
+
      osUnlink(pFile->pId->zCanonicalName);
    }
    vxworksReleaseFileId(pFile->pId);
    pFile->pId = 0;
@@ -26473,7 +26595,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
  
  /* To fully unlock the database, delete the lock file */
  assert( eFileLock==NO_LOCK );
-
  if( unlink(zLockFile) ){
+
  if( osUnlink(zLockFile) ){
    int rc = 0;
    int tErrno = errno;
    if( ENOENT != tErrno ){
@@ -26979,11 +27101,12 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;
+
  afpLockingContext *context;
  
  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  
  assert( pFile );
-
  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+
  context = (afpLockingContext *) pFile->lockingContext;
  if( context->reserved ){
    *pResOut = 1;
    return SQLITE_OK;
@@ -27123,7 +27246,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
  ** operating system calls for the specified lock.
  */
  if( eFileLock==SHARED_LOCK ){
-
    int lrc1, lrc2, lrc1Errno;
+
    int lrc1, lrc2, lrc1Errno = 0;
    long lk, mask;
    
    assert( pInode->nShared==0 );
@@ -27497,17 +27620,19 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
#elif defined(USE_PREAD64)
  do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
#else
-
  newOffset = lseek(id->h, offset, SEEK_SET);
-
  SimulateIOError( newOffset-- );
-
  if( newOffset!=offset ){
-
    if( newOffset == -1 ){
-
      ((unixFile*)id)->lastErrno = errno;
-
    }else{
-
      ((unixFile*)id)->lastErrno = 0;			
+
  do{
+
    newOffset = lseek(id->h, offset, SEEK_SET);
+
    SimulateIOError( newOffset-- );
+
    if( newOffset!=offset ){
+
      if( newOffset == -1 ){
+
        ((unixFile*)id)->lastErrno = errno;
+
      }else{
+
        ((unixFile*)id)->lastErrno = 0;			
+
      }
+
      return -1;
    }
-
    return -1;
-
  }
-
  do{ got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
+
    got = osWrite(id->h, pBuf, cnt);
+
  }while( got<0 && errno==EINTR );
#endif
  TIMER_END;
  if( got<0 ){
@@ -27597,11 +27722,11 @@ SQLITE_API int sqlite3_fullsync_count = 0;

/*
** We do not trust systems to provide a working fdatasync().  Some do.
-
** Others do no.  To be safe, we will stick with the (slower) fsync().
-
** If you know that your system does support fdatasync() correctly,
+
** Others do no.  To be safe, we will stick with the (slightly slower)
+
** fsync(). If you know that your system does support fdatasync() correctly,
** then simply compile with -Dfdatasync=fdatasync
*/
-
#if !defined(fdatasync) && !defined(__linux__)
+
#if !defined(fdatasync)
# define fdatasync fsync
#endif

@@ -27710,6 +27835,50 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
}

/*
+
** Open a file descriptor to the directory containing file zFilename.
+
** If successful, *pFd is set to the opened file descriptor and
+
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
+
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
+
** value.
+
**
+
** The directory file descriptor is used for only one thing - to
+
** fsync() a directory to make sure file creation and deletion events
+
** are flushed to disk.  Such fsyncs are not needed on newer
+
** journaling filesystems, but are required on older filesystems.
+
**
+
** This routine can be overridden using the xSetSysCall interface.
+
** The ability to override this routine was added in support of the
+
** chromium sandbox.  Opening a directory is a security risk (we are
+
** told) so making it overrideable allows the chromium sandbox to
+
** replace this routine with a harmless no-op.  To make this routine
+
** a no-op, replace it with a stub that returns SQLITE_OK but leaves
+
** *pFd set to a negative number.
+
**
+
** If SQLITE_OK is returned, the caller is responsible for closing
+
** the file descriptor *pFd using close().
+
*/
+
static int openDirectory(const char *zFilename, int *pFd){
+
  int ii;
+
  int fd = -1;
+
  char zDirname[MAX_PATHNAME+1];
+

+
  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
+
  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
+
  if( ii>0 ){
+
    zDirname[ii] = '\0';
+
    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
+
    if( fd>=0 ){
+
#ifdef FD_CLOEXEC
+
      osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+
#endif
+
      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
+
    }
+
  }
+
  *pFd = fd;
+
  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
+
}
+

+
/*
** Make sure all writes to a particular file are committed to disk.
**
** If dataOnly==0 then both the file itself and its metadata (file
@@ -27749,28 +27918,23 @@ static int unixSync(sqlite3_file *id, int flags){
    pFile->lastErrno = errno;
    return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
  }
-
  if( pFile->dirfd>=0 ){
-
    OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
+

+
  /* Also fsync the directory containing the file if the DIRSYNC flag
+
  ** is set.  This is a one-time occurrance.  Many systems (examples: AIX)
+
  ** are unable to fsync a directory, so ignore errors on the fsync.
+
  */
+
  if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
+
    int dirfd;
+
    OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
            HAVE_FULLFSYNC, isFullsync));
-
#ifndef SQLITE_DISABLE_DIRSYNC
-
    /* The directory sync is only attempted if full_fsync is
-
    ** turned off or unavailable.  If a full_fsync occurred above,
-
    ** then the directory sync is superfluous.
-
    */
-
    if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
-
       /*
-
       ** We have received multiple reports of fsync() returning
-
       ** errors when applied to directories on certain file systems.
-
       ** A failed directory sync is not a big deal.  So it seems
-
       ** better to ignore the error.  Ticket #1657
-
       */
-
       /* pFile->lastErrno = errno; */
-
       /* return SQLITE_IOERR; */
+
    rc = osOpenDirectory(pFile->zPath, &dirfd);
+
    if( rc==SQLITE_OK && dirfd>=0 ){
+
      full_fsync(dirfd, 0, 0);
+
      robust_close(pFile, dirfd, __LINE__);
+
    }else if( rc==SQLITE_CANTOPEN ){
+
      rc = SQLITE_OK;
    }
-
#endif
-
    /* Only need to sync once, so close the  directory when we are done */
-
    robust_close(pFile, pFile->dirfd, __LINE__);
-
    pFile->dirfd = -1;
+
    pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
  }
  return rc;
}
@@ -27852,14 +28016,12 @@ static int proxyFileControl(sqlite3_file*,int,void*);

/* 
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT 
-
** file-control operation.
-
**
-
** If the user has configured a chunk-size for this file, it could be
-
** that the file needs to be extended at this point. Otherwise, the
-
** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
+
** file-control operation.  Enlarge the database to nBytes in size
+
** (rounded up to the next chunk-size).  If the database is already
+
** nBytes or larger, this routine is a no-op.
*/
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
-
  if( pFile->szChunk ){
+
  if( pFile->szChunk>0 ){
    i64 nSize;                    /* Required file size */
    struct stat buf;              /* Used to hold return values of fstat() */
   
@@ -27908,21 +28070,37 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
+
  unixFile *pFile = (unixFile*)id;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
-
      *(int*)pArg = ((unixFile*)id)->eFileLock;
+
      *(int*)pArg = pFile->eFileLock;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
-
      *(int*)pArg = ((unixFile*)id)->lastErrno;
+
      *(int*)pArg = pFile->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
-
      ((unixFile*)id)->szChunk = *(int *)pArg;
+
      pFile->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
-
      return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
+
      int rc;
+
      SimulateIOErrorBenign(1);
+
      rc = fcntlSizeHint(pFile, *(i64 *)pArg);
+
      SimulateIOErrorBenign(0);
+
      return rc;
+
    }
+
    case SQLITE_FCNTL_PERSIST_WAL: {
+
      int bPersist = *(int*)pArg;
+
      if( bPersist<0 ){
+
        *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
+
      }else if( bPersist==0 ){
+
        pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
+
      }else{
+
        pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
+
      }
+
      return SQLITE_OK;
    }
#ifndef NDEBUG
    /* The pager calls this method to signal that it has done
@@ -28038,11 +28216,9 @@ struct unixShm {
  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
  u8 hasMutex;               /* True if holding the unixShmNode mutex */
+
  u8 id;                     /* Id of this connection within its unixShmNode */
  u16 sharedMask;            /* Mask of shared locks held */
  u16 exclMask;              /* Mask of exclusive locks held */
-
#ifdef SQLITE_DEBUG
-
  u8 id;                     /* Id of this connection within its unixShmNode */
-
#endif
};

/*
@@ -28138,7 +28314,7 @@ static void unixShmPurge(unixFile *pFd){
  if( p && p->nRef==0 ){
    int i;
    assert( p->pInode==pFd->pInode );
-
    if( p->mutex ) sqlite3_mutex_free(p->mutex);
+
    sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i++){
      if( p->h>=0 ){
        munmap(p->apRegion[i], p->szRegion);
@@ -28607,7 +28783,7 @@ static int unixShmUnmap(
  assert( pShmNode->nRef>0 );
  pShmNode->nRef--;
  if( pShmNode->nRef==0 ){
-
    if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename);
+
    if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
    unixShmPurge(pDbFd);
  }
  unixLeaveMutex();
@@ -28920,7 +29096,7 @@ typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
static int fillInUnixFile(
  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
  int h,                  /* Open file descriptor of file being opened */
-
  int dirfd,              /* Directory file descriptor */
+
  int syncDir,            /* True to sync directory on first sync */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename,  /* Name of the file being opened */
  int noLock,             /* Omit locking if true */
@@ -28951,7 +29127,6 @@ static int fillInUnixFile(

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
-
  pNew->dirfd = dirfd;
  pNew->zPath = zFilename;
  if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
    pNew->ctrlFlags = UNIXFILE_EXCL;
@@ -28961,6 +29136,9 @@ static int fillInUnixFile(
  if( isReadOnly ){
    pNew->ctrlFlags |= UNIXFILE_RDONLY;
  }
+
  if( syncDir ){
+
    pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
+
  }

#if OS_VXWORKS
  pNew->pId = vxworksFindFileId(zFilename);
@@ -29087,13 +29265,12 @@ static int fillInUnixFile(
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
    h = -1;
-
    unlink(zFilename);
+
    osUnlink(zFilename);
    isDelete = 0;
  }
  pNew->isDelete = isDelete;
#endif
  if( rc!=SQLITE_OK ){
-
    if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__);
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
@@ -29103,37 +29280,6 @@ static int fillInUnixFile(
}

/*
-
** Open a file descriptor to the directory containing file zFilename.
-
** If successful, *pFd is set to the opened file descriptor and
-
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
-
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
-
** value.
-
**
-
** If SQLITE_OK is returned, the caller is responsible for closing
-
** the file descriptor *pFd using close().
-
*/
-
static int openDirectory(const char *zFilename, int *pFd){
-
  int ii;
-
  int fd = -1;
-
  char zDirname[MAX_PATHNAME+1];
-

-
  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
-
  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
-
  if( ii>0 ){
-
    zDirname[ii] = '\0';
-
    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
-
    if( fd>=0 ){
-
#ifdef FD_CLOEXEC
-
      osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
-
#endif
-
      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
-
    }
-
  }
-
  *pFd = fd;
-
  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
-
}
-

-
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
@@ -29247,7 +29393,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
  **
  ** Even if a subsequent open() call does succeed, the consequences of
  ** not searching for a resusable file descriptor are not dire.  */
-
  if( 0==stat(zPath, &sStat) ){
+
  if( 0==osStat(zPath, &sStat) ){
    unixInodeInfo *pInode;

    unixEnterMutex();
@@ -29323,7 +29469,7 @@ static int findCreateFileMode(
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

-
    if( 0==stat(zDb, &sStat) ){
+
    if( 0==osStat(zDb, &sStat) ){
      *pMode = sStat.st_mode & 0777;
    }else{
      rc = SQLITE_IOERR_FSTAT;
@@ -29365,7 +29511,6 @@ static int unixOpen(
){
  unixFile *p = (unixFile *)pFile;
  int fd = -1;                   /* File descriptor returned by open() */
-
  int dirfd = -1;                /* Directory file descriptor */
  int openFlags = 0;             /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */
@@ -29379,12 +29524,15 @@ static int unixOpen(
#if SQLITE_ENABLE_LOCKING_STYLE
  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
#endif
+
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
+
  struct statfs fsInfo;
+
#endif

  /* If creating a master or main-file journal, this function will open
  ** a file-descriptor on the directory too. The first time unixSync()
  ** is called the directory file descriptor will be fsync()ed and close()d.
  */
-
  int isOpenDirectory = (isCreate && (
+
  int syncDir = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
@@ -29438,7 +29586,7 @@ static int unixOpen(
    p->pUnused = pUnused;
  }else if( !zName ){
    /* If zName is NULL, the upper layer is requesting a temp file. */
-
    assert(isDelete && !isOpenDirectory);
+
    assert(isDelete && !syncDir);
    rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
@@ -29494,7 +29642,7 @@ static int unixOpen(
#if OS_VXWORKS
    zPath = zName;
#else
-
    unlink(zName);
+
    osUnlink(zName);
#endif
  }
#if SQLITE_ENABLE_LOCKING_STYLE
@@ -29503,19 +29651,6 @@ static int unixOpen(
  }
#endif

-
  if( isOpenDirectory ){
-
    rc = openDirectory(zPath, &dirfd);
-
    if( rc!=SQLITE_OK ){
-
      /* It is safe to close fd at this point, because it is guaranteed not
-
      ** to be open on a database file. If it were open on a database file,
-
      ** it would not be safe to close as this would release any locks held
-
      ** on the file by this process.  */
-
      assert( eType!=SQLITE_OPEN_MAIN_DB );
-
      robust_close(p, fd, __LINE__);
-
      goto open_finished;
-
    }
-
  }
-

#ifdef FD_CLOEXEC
  osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
@@ -29524,10 +29659,8 @@ static int unixOpen(

  
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-
  struct statfs fsInfo;
  if( fstatfs(fd, &fsInfo) == -1 ){
    ((unixFile*)pFile)->lastErrno = errno;
-
    if( dirfd>=0 ) robust_close(p, dirfd, __LINE__);
    robust_close(p, fd, __LINE__);
    return SQLITE_IOERR_ACCESS;
  }
@@ -29549,7 +29682,6 @@ static int unixOpen(
    if( envforce!=NULL ){
      useProxy = atoi(envforce)>0;
    }else{
-
      struct statfs fsInfo;
      if( statfs(zPath, &fsInfo) == -1 ){
        /* In theory, the close(fd) call is sub-optimal. If the file opened
        ** with fd is a database file, and there are other connections open
@@ -29559,9 +29691,6 @@ static int unixOpen(
        ** not while other file descriptors opened by the same process on
        ** the same file are working.  */
        p->lastErrno = errno;
-
        if( dirfd>=0 ){
-
          robust_close(p, dirfd, __LINE__);
-
        }
        robust_close(p, fd, __LINE__);
        rc = SQLITE_IOERR_ACCESS;
        goto open_finished;
@@ -29569,7 +29698,7 @@ static int unixOpen(
      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
    }
    if( useProxy ){
-
      rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
+
      rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
                          isDelete, isReadonly);
      if( rc==SQLITE_OK ){
        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
@@ -29587,7 +29716,7 @@ static int unixOpen(
  }
#endif
  
-
  rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
+
  rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
                      isDelete, isReadonly);
open_finished:
  if( rc!=SQLITE_OK ){
@@ -29609,13 +29738,13 @@ static int unixDelete(
  int rc = SQLITE_OK;
  UNUSED_PARAMETER(NotUsed);
  SimulateIOError(return SQLITE_IOERR_DELETE);
-
  if( unlink(zPath)==(-1) && errno!=ENOENT ){
+
  if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
  }
#ifndef SQLITE_DISABLE_DIRSYNC
  if( dirSync ){
    int fd;
-
    rc = openDirectory(zPath, &fd);
+
    rc = osOpenDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if OS_VXWORKS
      if( fsync(fd)==-1 )
@@ -29626,6 +29755,8 @@ static int unixDelete(
        rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
      }
      robust_close(0, fd, __LINE__);
+
    }else if( rc==SQLITE_CANTOPEN ){
+
      rc = SQLITE_OK;
    }
  }
#endif
@@ -29668,7 +29799,7 @@ static int unixAccess(
  *pResOut = (osAccess(zPath, amode)==0);
  if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
    struct stat buf;
-
    if( 0==stat(zPath, &buf) && buf.st_size==0 ){
+
    if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
      *pResOut = 0;
    }
  }
@@ -30187,7 +30318,6 @@ static int proxyCreateUnixFile(
    int islockfile           /* if non zero missing dirs will be created */
) {
  int fd = -1;
-
  int dirfd = -1;
  unixFile *pNew;
  int rc = SQLITE_OK;
  int openFlags = O_RDWR | O_CREAT;
@@ -30252,7 +30382,7 @@ static int proxyCreateUnixFile(
  pUnused->flags = openFlags;
  pNew->pUnused = pUnused;
  
-
  rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0);
+
  rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
  if( rc==SQLITE_OK ){
    *ppFile = pNew;
    return SQLITE_OK;
@@ -30292,6 +30422,8 @@ static int proxyGetHostID(unsigned char *pHostID, int *pError){
      return SQLITE_IOERR;
    }
  }
+
#else
+
  UNUSED_PARAMETER(pError);
#endif
#ifdef SQLITE_TEST
  /* simulate multiple hosts by creating unique hostid file paths */
@@ -30366,7 +30498,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
end_breaklock:
  if( rc ){
    if( fd>=0 ){
-
      unlink(tPath);
+
      osUnlink(tPath);
      robust_close(pFile, fd, __LINE__);
    }
    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
@@ -30384,6 +30516,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
  int nTries = 0;
  struct timespec conchModTime;
  
+
  memset(&conchModTime, 0, sizeof(conchModTime));
  do {
    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
    nTries ++;
@@ -30615,11 +30748,12 @@ static int proxyTakeConch(unixFile *pFile){
    end_takeconch:
      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
      if( rc==SQLITE_OK && pFile->openFlags ){
+
        int fd;
        if( pFile->h>=0 ){
          robust_close(pFile, pFile->h, __LINE__);
        }
        pFile->h = -1;
-
        int fd = robust_open(pCtx->dbPath, pFile->openFlags,
+
        fd = robust_open(pCtx->dbPath, pFile->openFlags,
                      SQLITE_DEFAULT_FILE_PERMISSIONS);
        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
        if( fd>=0 ){
@@ -31189,7 +31323,7 @@ SQLITE_API int sqlite3_os_init(void){

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
-
  assert( ArraySize(aSyscall)==16 );
+
  assert( ArraySize(aSyscall)==18 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
@@ -31305,11 +31439,14 @@ SQLITE_API int sqlite3_os_end(void){
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

-
#ifdef SQLITE_DEBUG
-
SQLITE_PRIVATE int sqlite3OSTrace = 0;
-
#define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
+
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+
# ifndef SQLITE_DEBUG_OS_TRACE
+
#   define SQLITE_DEBUG_OS_TRACE 0
+
# endif
+
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
-
#define OSTRACE(X)
+
# define OSTRACE(X)
#endif

/*
@@ -31521,8 +31658,9 @@ struct winFile {
  const sqlite3_io_methods *pMethod; /*** Must be first ***/
  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
  HANDLE h;               /* Handle for accessing the file */
-
  unsigned char locktype; /* Type of lock currently held on this file */
+
  u8 locktype;            /* Type of lock currently held on this file */
  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
+
  u8 bPersistWal;         /* True to persist WAL files */
  DWORD lastErrno;        /* The Windows errno from the last I/O error */
  DWORD sectorSize;       /* Sector size of the device file is on */
  winShm *pShm;           /* Instance of shared memory on this file */
@@ -31537,6 +31675,76 @@ struct winFile {
#endif
};

+
/*
+
 * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
+
 * various Win32 API heap functions instead of our own.
+
 */
+
#ifdef SQLITE_WIN32_MALLOC
+
/*
+
 * The initial size of the Win32-specific heap.  This value may be zero.
+
 */
+
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
+
#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
+
                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
+
#endif
+

+
/*
+
 * The maximum size of the Win32-specific heap.  This value may be zero.
+
 */
+
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
+
#  define SQLITE_WIN32_HEAP_MAX_SIZE  (0)
+
#endif
+

+
/*
+
 * The extra flags to use in calls to the Win32 heap APIs.  This value may be
+
 * zero for the default behavior.
+
 */
+
#ifndef SQLITE_WIN32_HEAP_FLAGS
+
#  define SQLITE_WIN32_HEAP_FLAGS     (0)
+
#endif
+

+
/*
+
** The winMemData structure stores information required by the Win32-specific
+
** sqlite3_mem_methods implementation.
+
*/
+
typedef struct winMemData winMemData;
+
struct winMemData {
+
#ifndef NDEBUG
+
  u32 magic;    /* Magic number to detect structure corruption. */
+
#endif
+
  HANDLE hHeap; /* The handle to our heap. */
+
  BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
+
};
+

+
#ifndef NDEBUG
+
#define WINMEM_MAGIC     0x42b2830b
+
#endif
+

+
static struct winMemData win_mem_data = {
+
#ifndef NDEBUG
+
  WINMEM_MAGIC,
+
#endif
+
  NULL, FALSE
+
};
+

+
#ifndef NDEBUG
+
#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+
#else
+
#define winMemAssertMagic()
+
#endif
+

+
#define winMemGetHeap() win_mem_data.hHeap
+

+
static void *winMemMalloc(int nBytes);
+
static void winMemFree(void *pPrior);
+
static void *winMemRealloc(void *pPrior, int nBytes);
+
static int winMemSize(void *p);
+
static int winMemRoundup(int n);
+
static int winMemInit(void *pAppData);
+
static void winMemShutdown(void *pAppData);
+

+
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
+
#endif /* SQLITE_WIN32_MALLOC */

/*
** Forward prototypes.
@@ -31589,6 +31797,188 @@ static int sqlite3_os_type = 0;
  }
#endif /* SQLITE_OS_WINCE */

+
#ifdef SQLITE_WIN32_MALLOC
+
/*
+
** Allocate nBytes of memory.
+
*/
+
static void *winMemMalloc(int nBytes){
+
  HANDLE hHeap;
+
  void *p;
+

+
  winMemAssertMagic();
+
  hHeap = winMemGetHeap();
+
  assert( hHeap!=0 );
+
  assert( hHeap!=INVALID_HANDLE_VALUE );
+
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+
#endif
+
  assert( nBytes>=0 );
+
  p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+
  if( !p ){
+
    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
+
        nBytes, GetLastError(), (void*)hHeap);
+
  }
+
  return p;
+
}
+

+
/*
+
** Free memory.
+
*/
+
static void winMemFree(void *pPrior){
+
  HANDLE hHeap;
+

+
  winMemAssertMagic();
+
  hHeap = winMemGetHeap();
+
  assert( hHeap!=0 );
+
  assert( hHeap!=INVALID_HANDLE_VALUE );
+
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+
#endif
+
  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
+
  if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
+
    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
+
        pPrior, GetLastError(), (void*)hHeap);
+
  }
+
}
+

+
/*
+
** Change the size of an existing memory allocation
+
*/
+
static void *winMemRealloc(void *pPrior, int nBytes){
+
  HANDLE hHeap;
+
  void *p;
+

+
  winMemAssertMagic();
+
  hHeap = winMemGetHeap();
+
  assert( hHeap!=0 );
+
  assert( hHeap!=INVALID_HANDLE_VALUE );
+
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+
#endif
+
  assert( nBytes>=0 );
+
  if( !pPrior ){
+
    p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+
  }else{
+
    p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
+
  }
+
  if( !p ){
+
    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
+
        pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(),
+
        (void*)hHeap);
+
  }
+
  return p;
+
}
+

+
/*
+
** Return the size of an outstanding allocation, in bytes.
+
*/
+
static int winMemSize(void *p){
+
  HANDLE hHeap;
+
  SIZE_T n;
+

+
  winMemAssertMagic();
+
  hHeap = winMemGetHeap();
+
  assert( hHeap!=0 );
+
  assert( hHeap!=INVALID_HANDLE_VALUE );
+
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+
#endif
+
  if( !p ) return 0;
+
  n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
+
  if( n==(SIZE_T)-1 ){
+
    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
+
        p, GetLastError(), (void*)hHeap);
+
    return 0;
+
  }
+
  return (int)n;
+
}
+

+
/*
+
** Round up a request size to the next valid allocation size.
+
*/
+
static int winMemRoundup(int n){
+
  return n;
+
}
+

+
/*
+
** Initialize this module.
+
*/
+
static int winMemInit(void *pAppData){
+
  winMemData *pWinMemData = (winMemData *)pAppData;
+

+
  if( !pWinMemData ) return SQLITE_ERROR;
+
  assert( pWinMemData->magic==WINMEM_MAGIC );
+
  if( !pWinMemData->hHeap ){
+
    pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS,
+
                                    SQLITE_WIN32_HEAP_INIT_SIZE,
+
                                    SQLITE_WIN32_HEAP_MAX_SIZE);
+
    if( !pWinMemData->hHeap ){
+
      sqlite3_log(SQLITE_NOMEM,
+
          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
+
          GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE,
+
          SQLITE_WIN32_HEAP_MAX_SIZE);
+
      return SQLITE_NOMEM;
+
    }
+
    pWinMemData->bOwned = TRUE;
+
  }
+
  assert( pWinMemData->hHeap!=0 );
+
  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+
  assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+
#endif
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Deinitialize this module.
+
*/
+
static void winMemShutdown(void *pAppData){
+
  winMemData *pWinMemData = (winMemData *)pAppData;
+

+
  if( !pWinMemData ) return;
+
  if( pWinMemData->hHeap ){
+
    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+
    assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+
#endif
+
    if( pWinMemData->bOwned ){
+
      if( !HeapDestroy(pWinMemData->hHeap) ){
+
        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
+
            GetLastError(), (void*)pWinMemData->hHeap);
+
      }
+
      pWinMemData->bOwned = FALSE;
+
    }
+
    pWinMemData->hHeap = NULL;
+
  }
+
}
+

+
/*
+
** Populate the low-level memory allocation function pointers in
+
** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+
** arguments specify the block of memory to manage.
+
**
+
** This routine is only called by sqlite3_config(), and therefore
+
** is not required to be threadsafe (it is not).
+
*/
+
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
+
  static const sqlite3_mem_methods winMemMethods = {
+
    winMemMalloc,
+
    winMemFree,
+
    winMemRealloc,
+
    winMemSize,
+
    winMemRoundup,
+
    winMemInit,
+
    winMemShutdown,
+
    &win_mem_data
+
  };
+
  return &winMemMethods;
+
}
+

+
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+
  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
+
}
+
#endif /* SQLITE_WIN32_MALLOC */
+

/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
**
@@ -31821,6 +32211,54 @@ static int winLogErrorAtLine(
  return errcode;
}

+
/*
+
** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
+
** will be retried following a locking error - probably caused by 
+
** antivirus software.  Also the initial delay before the first retry.
+
** The delay increases linearly with each retry.
+
*/
+
#ifndef SQLITE_WIN32_IOERR_RETRY
+
# define SQLITE_WIN32_IOERR_RETRY 10
+
#endif
+
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
+
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
+
#endif
+
static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
+
static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+

+
/*
+
** If a ReadFile() or WriteFile() error occurs, invoke this routine
+
** to see if it should be retried.  Return TRUE to retry.  Return FALSE
+
** to give up with an error.
+
*/
+
static int retryIoerr(int *pnRetry){
+
  DWORD e;
+
  if( *pnRetry>=win32IoerrRetry ){
+
    return 0;
+
  }
+
  e = GetLastError();
+
  if( e==ERROR_ACCESS_DENIED ||
+
      e==ERROR_LOCK_VIOLATION ||
+
      e==ERROR_SHARING_VIOLATION ){
+
    Sleep(win32IoerrRetryDelay*(1+*pnRetry));
+
    ++*pnRetry;
+
    return 1;
+
  }
+
  return 0;
+
}
+

+
/*
+
** Log a I/O error retry episode.
+
*/
+
static void logIoerr(int nRetry){
+
  if( nRetry ){
+
    sqlite3_log(SQLITE_IOERR, 
+
      "delayed %dms for lock/sharing conflict",
+
      win32IoerrRetryDelay*nRetry*(nRetry+1)/2
+
    );
+
  }
+
}
+

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
@@ -31829,6 +32267,7 @@ static int winLogErrorAtLine(
** WindowsCE does not have a localtime() function.  So create a
** substitute.
*/
+
/* #include <time.h> */
struct tm *__cdecl localtime(const time_t *t)
{
  static struct tm y;
@@ -32238,6 +32677,7 @@ static int winRead(
){
  winFile *pFile = (winFile*)id;  /* file handle */
  DWORD nRead;                    /* Number of bytes actually read from file */
+
  int nRetry = 0;                 /* Number of retrys */

  assert( id!=0 );
  SimulateIOError(return SQLITE_IOERR_READ);
@@ -32246,10 +32686,12 @@ static int winRead(
  if( seekWinFile(pFile, offset) ){
    return SQLITE_FULL;
  }
-
  if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
+
  while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
+
    if( retryIoerr(&nRetry) ) continue;
    pFile->lastErrno = GetLastError();
    return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
  }
+
  logIoerr(nRetry);
  if( nRead<(DWORD)amt ){
    /* Unread parts of the buffer must be zero-filled */
    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
@@ -32271,6 +32713,7 @@ static int winWrite(
){
  int rc;                         /* True if error has occured, else false */
  winFile *pFile = (winFile*)id;  /* File handle */
+
  int nRetry = 0;                 /* Number of retries */

  assert( amt>0 );
  assert( pFile );
@@ -32285,7 +32728,12 @@ static int winWrite(
    int nRem = amt;               /* Number of bytes yet to be written */
    DWORD nWrite;                 /* Bytes written by each WriteFile() call */

-
    while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
+
    while( nRem>0 ){
+
      if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
+
        if( retryIoerr(&nRetry) ) continue;
+
        break;
+
      }
+
      if( nWrite<=0 ) break;
      aRem += nWrite;
      nRem -= nWrite;
    }
@@ -32301,6 +32749,8 @@ static int winWrite(
      return SQLITE_FULL;
    }
    return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
+
  }else{
+
    logIoerr(nRetry);
  }
  return SQLITE_OK;
}
@@ -32322,7 +32772,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
  ** actual file size after the operation may be larger than the requested
  ** size).
  */
-
  if( pFile->szChunk ){
+
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

@@ -32351,9 +32801,19 @@ SQLITE_API int sqlite3_fullsync_count = 0;
** Make sure all writes to a particular file are committed to disk.
*/
static int winSync(sqlite3_file *id, int flags){
-
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
-
  winFile *pFile = (winFile*)id;
+
#ifndef SQLITE_NO_SYNC
+
  /*
+
  ** Used only when SQLITE_NO_SYNC is not defined.
+
   */
  BOOL rc;
+
#endif
+
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
+
    (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
+
  /*
+
  ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
+
  ** OSTRACE() macros.
+
   */
+
  winFile *pFile = (winFile*)id;
#else
  UNUSED_PARAMETER(id);
#endif
@@ -32694,29 +33154,62 @@ static int winUnlock(sqlite3_file *id, int locktype){
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){
+
  winFile *pFile = (winFile*)id;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
-
      *(int*)pArg = ((winFile*)id)->locktype;
+
      *(int*)pArg = pFile->locktype;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
-
      *(int*)pArg = (int)((winFile*)id)->lastErrno;
+
      *(int*)pArg = (int)pFile->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
-
      ((winFile*)id)->szChunk = *(int *)pArg;
+
      pFile->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
-
      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
-
      SimulateIOErrorBenign(1);
-
      winTruncate(id, sz);
-
      SimulateIOErrorBenign(0);
+
      if( pFile->szChunk>0 ){
+
        sqlite3_int64 oldSz;
+
        int rc = winFileSize(id, &oldSz);
+
        if( rc==SQLITE_OK ){
+
          sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
+
          if( newSz>oldSz ){
+
            SimulateIOErrorBenign(1);
+
            rc = winTruncate(id, newSz);
+
            SimulateIOErrorBenign(0);
+
          }
+
        }
+
        return rc;
+
      }
+
      return SQLITE_OK;
+
    }
+
    case SQLITE_FCNTL_PERSIST_WAL: {
+
      int bPersist = *(int*)pArg;
+
      if( bPersist<0 ){
+
        *(int*)pArg = pFile->bPersistWal;
+
      }else{
+
        pFile->bPersistWal = bPersist!=0;
+
      }
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SYNC_OMITTED: {
      return SQLITE_OK;
    }
+
    case SQLITE_FCNTL_WIN32_AV_RETRY: {
+
      int *a = (int*)pArg;
+
      if( a[0]>0 ){
+
        win32IoerrRetry = a[0];
+
      }else{
+
        a[0] = win32IoerrRetry;
+
      }
+
      if( a[1]>0 ){
+
        win32IoerrRetryDelay = a[1];
+
      }else{
+
        a[1] = win32IoerrRetryDelay;
+
      }
+
      return SQLITE_OK;
+
    }
  }
  return SQLITE_NOTFOUND;
}
@@ -33525,6 +34018,7 @@ static int winOpen(
  winFile *pFile = (winFile*)id;
  void *zConverted;              /* Filename in OS encoding */
  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
+
  int cnt = 0;

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
@@ -33644,31 +34138,31 @@ static int winOpen(
#endif

  if( isNT() ){
-
    h = CreateFileW((WCHAR*)zConverted,
-
       dwDesiredAccess,
-
       dwShareMode,
-
       NULL,
-
       dwCreationDisposition,
-
       dwFlagsAndAttributes,
-
       NULL
-
    );
+
    while( (h = CreateFileW((WCHAR*)zConverted,
+
                            dwDesiredAccess,
+
                            dwShareMode, NULL,
+
                            dwCreationDisposition,
+
                            dwFlagsAndAttributes,
+
                            NULL))==INVALID_HANDLE_VALUE &&
+
                            retryIoerr(&cnt) ){}
/* 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{
-
    h = CreateFileA((char*)zConverted,
-
       dwDesiredAccess,
-
       dwShareMode,
-
       NULL,
-
       dwCreationDisposition,
-
       dwFlagsAndAttributes,
-
       NULL
-
    );
+
    while( (h = CreateFileA((char*)zConverted,
+
                            dwDesiredAccess,
+
                            dwShareMode, NULL,
+
                            dwCreationDisposition,
+
                            dwFlagsAndAttributes,
+
                            NULL))==INVALID_HANDLE_VALUE &&
+
                            retryIoerr(&cnt) ){}
#endif
  }

+
  logIoerr(cnt);
+

  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
@@ -33734,15 +34228,13 @@ static int winOpen(
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
** up and returning an error.
*/
-
#define MX_DELETION_ATTEMPTS 5
static int winDelete(
  sqlite3_vfs *pVfs,          /* Not used on win32 */
  const char *zFilename,      /* Name of file to delete */
  int syncDir                 /* Not used on win32 */
){
  int cnt = 0;
-
  DWORD rc;
-
  DWORD error = 0;
+
  int rc;
  void *zConverted;
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(syncDir);
@@ -33753,34 +34245,30 @@ static int winDelete(
    return SQLITE_NOMEM;
  }
  if( isNT() ){
-
    do{
-
      DeleteFileW(zConverted);
-
    }while(   (   ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
-
               || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
-
           && (++cnt < MX_DELETION_ATTEMPTS)
-
           && (Sleep(100), 1) );
+
    rc = 1;
+
    while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
+
           (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
+
    rc = rc ? SQLITE_OK : SQLITE_ERROR;
/* 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{
-
    do{
-
      DeleteFileA(zConverted);
-
    }while(   (   ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
-
               || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
-
           && (++cnt < MX_DELETION_ATTEMPTS)
-
           && (Sleep(100), 1) );
+
    rc = 1;
+
    while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
+
           (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
+
    rc = rc ? SQLITE_OK : SQLITE_ERROR;
#endif
  }
+
  if( rc ){
+
    rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
+
  }else{
+
    logIoerr(cnt);
+
  }
  free(zConverted);
-
  OSTRACE(("DELETE \"%s\" %s\n", zFilename,
-
       ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
-
         "ok" : "failed" ));
-
 
-
  return (   (rc == INVALID_FILE_ATTRIBUTES) 
-
          && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
-
                 winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
+
  OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
+
  return rc;
}

/*
@@ -33803,11 +34291,13 @@ static int winAccess(
    return SQLITE_NOMEM;
  }
  if( isNT() ){
+
    int cnt = 0;
    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
    memset(&sAttrData, 0, sizeof(sAttrData));
-
    if( GetFileAttributesExW((WCHAR*)zConverted,
+
    while( !(rc = GetFileAttributesExW((WCHAR*)zConverted,
                             GetFileExInfoStandard, 
-
                             &sAttrData) ){
+
                             &sAttrData)) && retryIoerr(&cnt) ){}
+
    if( rc ){
      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
      ** as if it does not exist.
      */
@@ -33819,6 +34309,7 @@ static int winAccess(
        attr = sAttrData.dwFileAttributes;
      }
    }else{
+
      logIoerr(cnt);
      if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
        winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
        free(zConverted);
@@ -33843,7 +34334,8 @@ static int winAccess(
      rc = attr!=INVALID_FILE_ATTRIBUTES;
      break;
    case SQLITE_ACCESS_READWRITE:
-
      rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
+
      rc = attr!=INVALID_FILE_ATTRIBUTES &&
+
             (attr & FILE_ATTRIBUTE_READONLY)==0;
      break;
    default:
      assert(!"Invalid flags argument");
@@ -35299,6 +35791,9 @@ typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;

+
typedef struct PGroupBlock PGroupBlock;
+
typedef struct PGroupBlockList PGroupBlockList;
+

/* Each page cache (or PCache) belongs to a PGroup.  A PGroup is a set 
** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure.  A PGroup is an instance of
@@ -35328,8 +35823,66 @@ struct PGroup {
  int mxPinned;                  /* nMaxpage + 10 - nMinPage */
  int nCurrentPage;              /* Number of purgeable pages allocated */
  PgHdr1 *pLruHead, *pLruTail;   /* LRU list of unpinned pages */
+
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
+
  int isBusy;                    /* Do not run ReleaseMemory() if true */
+
  PGroupBlockList *pBlockList;   /* List of block-lists for this group */
+
#endif
+
};
+

+
/*
+
** If SQLITE_PAGECACHE_BLOCKALLOC is defined when the library is built,
+
** each PGroup structure has a linked list of the the following starting
+
** at PGroup.pBlockList. There is one entry for each distinct page-size 
+
** currently used by members of the PGroup (i.e. 1024 bytes, 4096 bytes
+
** etc.). Variable PGroupBlockList.nByte is set to the actual allocation
+
** size requested by each pcache, which is the database page-size plus
+
** the various header structures used by the pcache, pager and btree layers.
+
** Usually around (pgsz+200) bytes.
+
**
+
** This size (pgsz+200) bytes is not allocated efficiently by some
+
** implementations of malloc. In particular, some implementations are only
+
** able to allocate blocks of memory chunks of 2^N bytes, where N is some
+
** integer value. Since the page-size is a power of 2, this means we
+
** end up wasting (pgsz-200) bytes in each allocation.
+
**
+
** If SQLITE_PAGECACHE_BLOCKALLOC is defined, the (pgsz+200) byte blocks
+
** are not allocated directly. Instead, blocks of roughly M*(pgsz+200) bytes 
+
** are requested from malloc allocator. After a block is returned,
+
** sqlite3MallocSize() is used to determine how many (pgsz+200) byte
+
** allocations can fit in the space returned by malloc(). This value may
+
** be more than M.
+
**
+
** The blocks are stored in a doubly-linked list. Variable PGroupBlock.nEntry
+
** contains the number of allocations that will fit in the aData[] space.
+
** nEntry is limited to the number of bits in bitmask mUsed. If a slot
+
** within aData is in use, the corresponding bit in mUsed is set. Thus
+
** when (mUsed+1==(1 << nEntry)) the block is completely full.
+
**
+
** Each time a slot within a block is freed, the block is moved to the start
+
** of the linked-list. And if a block becomes completely full, then it is
+
** moved to the end of the list. As a result, when searching for a free
+
** slot, only the first block in the list need be examined. If it is full,
+
** then it is guaranteed that all blocks are full.
+
*/
+
struct PGroupBlockList {
+
  int nByte;                     /* Size of each allocation in bytes */
+
  PGroupBlock *pFirst;           /* First PGroupBlock in list */
+
  PGroupBlock *pLast;            /* Last PGroupBlock in list */
+
  PGroupBlockList *pNext;        /* Next block-list attached to group */
};

+
struct PGroupBlock {
+
  Bitmask mUsed;                 /* Mask of used slots */
+
  int nEntry;                    /* Maximum number of allocations in aData[] */
+
  u8 *aData;                     /* Pointer to data block */
+
  PGroupBlock *pNext;            /* Next PGroupBlock in list */
+
  PGroupBlock *pPrev;            /* Previous PGroupBlock in list */
+
  PGroupBlockList *pList;        /* Owner list */
+
};
+

+
/* Minimum value for PGroupBlock.nEntry */
+
#define PAGECACHE_BLOCKALLOC_MINENTRY 15
+

/* Each page cache is an instance of the following object.  Every
** open database file (including each in-memory database and each
** temporary or transient database) has a single page cache which
@@ -35434,6 +35987,17 @@ static SQLITE_WSD struct PCacheGlobal {
#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)

/*
+
** Blocks used by the SQLITE_PAGECACHE_BLOCKALLOC blocks to store/retrieve 
+
** a PGroupBlock pointer based on a pointer to a page buffer. 
+
*/
+
#define PAGE_SET_BLOCKPTR(pCache, pPg, pBlock) \
+
  ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) = pBlock )
+

+
#define PAGE_GET_BLOCKPTR(pCache, pPg) \
+
  ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) )
+

+

+
/*
** Macros to enter and leave the PCache LRU mutex.
*/
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
@@ -35558,13 +36122,146 @@ static int pcache1MemSize(void *p){
}
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */

+
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
+
/*
+
** The block pBlock belongs to list pList but is not currently linked in.
+
** Insert it into the start of the list.
+
*/
+
static void addBlockToList(PGroupBlockList *pList, PGroupBlock *pBlock){
+
  pBlock->pPrev = 0;
+
  pBlock->pNext = pList->pFirst;
+
  pList->pFirst = pBlock;
+
  if( pBlock->pNext ){
+
    pBlock->pNext->pPrev = pBlock;
+
  }else{
+
    assert( pList->pLast==0 );
+
    pList->pLast = pBlock;
+
  }
+
}
+

+
/*
+
** If there are no blocks in the list headed by pList, remove pList
+
** from the pGroup->pBlockList list and free it with sqlite3_free().
+
*/
+
static void freeListIfEmpty(PGroup *pGroup, PGroupBlockList *pList){
+
  assert( sqlite3_mutex_held(pGroup->mutex) );
+
  if( pList->pFirst==0 ){
+
    PGroupBlockList **pp;
+
    for(pp=&pGroup->pBlockList; *pp!=pList; pp=&(*pp)->pNext);
+
    *pp = (*pp)->pNext;
+
    sqlite3_free(pList);
+
  }
+
}
+
#endif /* SQLITE_PAGECACHE_BLOCKALLOC */
+

/*
** Allocate a new page object initially associated with cache pCache.
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
  int nByte = sizeof(PgHdr1) + pCache->szPage;
-
  void *pPg = pcache1Alloc(nByte);
+
  void *pPg = 0;
  PgHdr1 *p;
+

+
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
+
  PGroup *pGroup = pCache->pGroup;
+
  PGroupBlockList *pList;
+
  PGroupBlock *pBlock;
+
  int i;
+

+
  nByte += sizeof(PGroupBlockList *);
+
  nByte = ROUND8(nByte);
+

+
  for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
+
    if( pList->nByte==nByte ) break;
+
  }
+
  if( pList==0 ){
+
    PGroupBlockList *pNew;
+
    assert( pGroup->isBusy==0 );
+
    assert( sqlite3_mutex_held(pGroup->mutex) );
+
    pGroup->isBusy = 1;  /* Disable sqlite3PcacheReleaseMemory() */
+
    pNew = (PGroupBlockList *)sqlite3MallocZero(sizeof(PGroupBlockList));
+
    pGroup->isBusy = 0;  /* Reenable sqlite3PcacheReleaseMemory() */
+
    if( pNew==0 ){
+
      /* malloc() failure. Return early. */
+
      return 0;
+
    }
+
#ifdef SQLITE_DEBUG
+
    for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
+
      assert( pList->nByte!=nByte );
+
    }
+
#endif
+
    pNew->nByte = nByte;
+
    pNew->pNext = pGroup->pBlockList;
+
    pGroup->pBlockList = pNew;
+
    pList = pNew;
+
  }
+

+
  pBlock = pList->pFirst;
+
  if( pBlock==0 || pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) ){
+
    int sz;
+

+
    /* Allocate a new block. Try to allocate enough space for the PGroupBlock
+
    ** structure and MINENTRY allocations of nByte bytes each. If the 
+
    ** allocator returns more memory than requested, then more than MINENTRY 
+
    ** allocations may fit in it. */
+
    assert( sqlite3_mutex_held(pGroup->mutex) );
+
    pcache1LeaveMutex(pCache->pGroup);
+
    sz = sizeof(PGroupBlock) + PAGECACHE_BLOCKALLOC_MINENTRY * nByte;
+
    pBlock = (PGroupBlock *)sqlite3Malloc(sz);
+
    pcache1EnterMutex(pCache->pGroup);
+

+
    if( !pBlock ){
+
      freeListIfEmpty(pGroup, pList);
+
      return 0;
+
    }
+
    pBlock->nEntry = (sqlite3MallocSize(pBlock) - sizeof(PGroupBlock)) / nByte;
+
    if( pBlock->nEntry>=BMS ){
+
      pBlock->nEntry = BMS-1;
+
    }
+
    pBlock->pList = pList;
+
    pBlock->mUsed = 0;
+
    pBlock->aData = (u8 *)&pBlock[1];
+
    addBlockToList(pList, pBlock);
+

+
    sz = sqlite3MallocSize(pBlock);
+
    sqlite3_mutex_enter(pcache1.mutex);
+
    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
+
    sqlite3_mutex_leave(pcache1.mutex);
+
  }
+

+
  for(i=0; pPg==0 && ALWAYS(i<pBlock->nEntry); i++){
+
    if( 0==(pBlock->mUsed & ((Bitmask)1<<i)) ){
+
      pBlock->mUsed |= ((Bitmask)1<<i);
+
      pPg = (void *)&pBlock->aData[pList->nByte * i];
+
    }
+
  }
+
  assert( pPg );
+
  PAGE_SET_BLOCKPTR(pCache, pPg, pBlock);
+

+
  /* If the block is now full, shift it to the end of the list */
+
  if( pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) && pList->pLast!=pBlock ){
+
    assert( pList->pFirst==pBlock );
+
    assert( pBlock->pPrev==0 );
+
    assert( pList->pLast->pNext==0 );
+
    pList->pFirst = pBlock->pNext;
+
    pList->pFirst->pPrev = 0;
+
    pBlock->pPrev = pList->pLast;
+
    pBlock->pNext = 0;
+
    pList->pLast->pNext = pBlock;
+
    pList->pLast = pBlock;
+
  }
+
  p = PAGE_TO_PGHDR1(pCache, pPg);
+
  if( pCache->bPurgeable ){
+
    pCache->pGroup->nCurrentPage++;
+
  }
+
#else
+
  /* The group mutex must be released before pcache1Alloc() is called. This
+
  ** is because it may call sqlite3_release_memory(), which assumes that 
+
  ** this mutex is not held. */
+
  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+
  pcache1LeaveMutex(pCache->pGroup);
+
  pPg = pcache1Alloc(nByte);
+
  pcache1EnterMutex(pCache->pGroup);
  if( pPg ){
    p = PAGE_TO_PGHDR1(pCache, pPg);
    if( pCache->bPurgeable ){
@@ -35573,6 +36270,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
  }else{
    p = 0;
  }
+
#endif
  return p;
}

@@ -35586,10 +36284,52 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
static void pcache1FreePage(PgHdr1 *p){
  if( ALWAYS(p) ){
    PCache1 *pCache = p->pCache;
+
    void *pPg = PGHDR1_TO_PAGE(p);
+

+
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
+
    PGroupBlock *pBlock = PAGE_GET_BLOCKPTR(pCache, pPg);
+
    PGroupBlockList *pList = pBlock->pList;
+
    int i = ((u8 *)pPg - pBlock->aData) / pList->nByte;
+

+
    assert( pPg==(void *)&pBlock->aData[i*pList->nByte] );
+
    assert( pBlock->mUsed & ((Bitmask)1<<i) );
+
    pBlock->mUsed &= ~((Bitmask)1<<i);
+

+
    /* Remove the block from the list. If it is completely empty, free it.
+
    ** Or if it is not completely empty, re-insert it at the start of the
+
    ** list. */
+
    if( pList->pFirst==pBlock ){
+
      pList->pFirst = pBlock->pNext;
+
      if( pList->pFirst ) pList->pFirst->pPrev = 0;
+
    }else{
+
      pBlock->pPrev->pNext = pBlock->pNext;
+
    }
+
    if( pList->pLast==pBlock ){
+
      pList->pLast = pBlock->pPrev;
+
      if( pList->pLast ) pList->pLast->pNext = 0;
+
    }else{
+
      pBlock->pNext->pPrev = pBlock->pPrev;
+
    }
+

+
    if( pBlock->mUsed==0 ){
+
      PGroup *pGroup = p->pCache->pGroup;
+

+
      int sz = sqlite3MallocSize(pBlock);
+
      sqlite3_mutex_enter(pcache1.mutex);
+
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -sz);
+
      sqlite3_mutex_leave(pcache1.mutex);
+
      freeListIfEmpty(pGroup, pList);
+
      sqlite3_free(pBlock);
+
    }else{
+
      addBlockToList(pList, pBlock);
+
    }
+
#else
+
    assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
+
    pcache1Free(pPg);
+
#endif
    if( pCache->bPurgeable ){
      pCache->pGroup->nCurrentPage--;
    }
-
    pcache1Free(PGHDR1_TO_PAGE(p));
  }
}

@@ -36027,9 +36767,7 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
  */
  if( !pPage ){
    if( createFlag==1 ) sqlite3BeginBenignMalloc();
-
    pcache1LeaveMutex(pGroup);
    pPage = pcache1AllocPage(pCache);
-
    pcache1EnterMutex(pGroup);
    if( createFlag==1 ) sqlite3EndBenignMalloc();
  }

@@ -36199,6 +36937,9 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
  int nFree = 0;
+
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
+
  if( pcache1.grp.isBusy ) return 0;
+
#endif
  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
  assert( sqlite3_mutex_notheld(pcache1.mutex) );
  if( pcache1.pStart==0 ){
@@ -40530,6 +41271,7 @@ static int pagerSyncHotJournal(Pager *pPager){
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
  u8 *pTmp = (u8 *)pPager->pTmpSpace;

+
  assert( assert_pager_state(pPager) );
  disable_simulated_io_errors();
  sqlite3BeginBenignMalloc();
  /* pPager->errCode = 0; */
@@ -45427,13 +46169,15 @@ SQLITE_PRIVATE int sqlite3WalClose(
    */
    rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
    if( rc==SQLITE_OK ){
+
      int bPersistWal = -1;
      if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
      }
      rc = sqlite3WalCheckpoint(
          pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
      );
-
      if( rc==SQLITE_OK ){
+
      sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
+
      if( rc==SQLITE_OK && bPersistWal!=1 ){
        isDelete = 1;
      }
    }
@@ -48167,18 +48911,21 @@ static int btreeMoveto(
  int rc;                    /* Status code */
  UnpackedRecord *pIdxKey;   /* Unpacked index key */
  char aSpace[150];          /* Temp space for pIdxKey - to avoid a malloc */
+
  char *pFree = 0;

  if( pKey ){
    assert( nKey==(i64)(int)nKey );
-
    pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey,
-
                                      aSpace, sizeof(aSpace));
+
    pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+
        pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
+
    );
    if( pIdxKey==0 ) return SQLITE_NOMEM;
+
    sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
  }else{
    pIdxKey = 0;
  }
  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
-
  if( pKey ){
-
    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+
  if( pFree ){
+
    sqlite3DbFree(pCur->pKeyInfo->db, pFree);
  }
  return rc;
}
@@ -50254,11 +51001,12 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
      if( eType==PTRMAP_OVERFLOW1 ){
        CellInfo info;
        btreeParseCellPtr(pPage, pCell, &info);
-
        if( info.iOverflow ){
-
          if( iFrom==get4byte(&pCell[info.iOverflow]) ){
-
            put4byte(&pCell[info.iOverflow], iTo);
-
            break;
-
          }
+
        if( info.iOverflow
+
         && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
+
         && iFrom==get4byte(&pCell[info.iOverflow])
+
        ){
+
          put4byte(&pCell[info.iOverflow], iTo);
+
          break;
        }
      }else{
        if( get4byte(pCell)==iFrom ){
@@ -50979,7 +51727,8 @@ static int btreeCursor(
    return SQLITE_READONLY;
  }
  if( iTable==1 && btreePagecount(pBt)==0 ){
-
    return SQLITE_EMPTY;
+
    assert( wrFlag==0 );
+
    iTable = 0;
  }

  /* Now that no other errors can occur, finish filling in the BtCursor
@@ -51733,6 +52482,9 @@ static int moveToRoot(BtCursor *pCur){
      releasePage(pCur->apPage[i]);
    }
    pCur->iPage = 0;
+
  }else if( pCur->pgnoRoot==0 ){
+
    pCur->eState = CURSOR_INVALID;
+
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
    if( rc!=SQLITE_OK ){
@@ -51842,7 +52594,7 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
  rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    if( pCur->eState==CURSOR_INVALID ){
-
      assert( pCur->apPage[pCur->iPage]->nCell==0 );
+
      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->apPage[pCur->iPage]->nCell>0 );
@@ -51881,7 +52633,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
  rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    if( CURSOR_INVALID==pCur->eState ){
-
      assert( pCur->apPage[pCur->iPage]->nCell==0 );
+
      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->eState==CURSOR_VALID );
@@ -51954,12 +52706,12 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
  if( rc ){
    return rc;
  }
-
  assert( pCur->apPage[pCur->iPage] );
-
  assert( pCur->apPage[pCur->iPage]->isInit );
-
  assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
+
  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
+
  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
+
  assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
  if( pCur->eState==CURSOR_INVALID ){
    *pRes = -1;
-
    assert( pCur->apPage[pCur->iPage]->nCell==0 );
+
    assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
    return SQLITE_OK;
  }
  assert( pCur->apPage[0]->intKey || pIdxKey );
@@ -52686,6 +53438,9 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
  if( info.iOverflow==0 ){
    return SQLITE_OK;  /* No overflow pages. Return without doing anything */
  }
+
  if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
+
    return SQLITE_CORRUPT;  /* Cell extends past end of page */
+
  }
  ovflPgno = get4byte(&pCell[info.iOverflow]);
  assert( pBt->usableSize > 4 );
  ovflPageSize = pBt->usableSize - 4;
@@ -54869,6 +55624,11 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
  i64 nEntry = 0;                      /* Value to return in *pnEntry */
  int rc;                              /* Return code */
+

+
  if( pCur->pgnoRoot==0 ){
+
    *pnEntry = 0;
+
    return SQLITE_OK;
+
  }
  rc = moveToRoot(pCur);

  /* Unless an error occurs, the following loop runs one iteration for each
@@ -55653,7 +56413,6 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
  BtShared *pBt = pBtree->pBt;
  int rc;                         /* Return code */
 
-
  assert( pBtree->inTrans==TRANS_NONE );
  assert( iVersion==1 || iVersion==2 );

  /* If setting the version fields to 1, do not automatically open the
@@ -56092,102 +56851,106 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
    ** the case where the source and destination databases have the
    ** same schema version.
    */
-
    if( rc==SQLITE_DONE 
-
     && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
-
    ){
-
      int nDestTruncate;
-
  
-
      if( p->pDestDb ){
-
        sqlite3ResetInternalSchema(p->pDestDb, -1);
-
      }
-

-
      /* Set nDestTruncate to the final number of pages in the destination
-
      ** database. The complication here is that the destination page
-
      ** size may be different to the source page size. 
-
      **
-
      ** If the source page size is smaller than the destination page size, 
-
      ** round up. In this case the call to sqlite3OsTruncate() below will
-
      ** fix the size of the file. However it is important to call
-
      ** sqlite3PagerTruncateImage() here so that any pages in the 
-
      ** destination file that lie beyond the nDestTruncate page mark are
-
      ** journalled by PagerCommitPhaseOne() before they are destroyed
-
      ** by the file truncation.
-
      */
-
      assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
-
      assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
-
      if( pgszSrc<pgszDest ){
-
        int ratio = pgszDest/pgszSrc;
-
        nDestTruncate = (nSrcPage+ratio-1)/ratio;
-
        if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
-
          nDestTruncate--;
+
    if( rc==SQLITE_DONE ){
+
      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+
      if( rc==SQLITE_OK ){
+
        if( p->pDestDb ){
+
          sqlite3ResetInternalSchema(p->pDestDb, -1);
+
        }
+
        if( destMode==PAGER_JOURNALMODE_WAL ){
+
          rc = sqlite3BtreeSetVersion(p->pDest, 2);
        }
-
      }else{
-
        nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
      }
-
      sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
-

-
      if( pgszSrc<pgszDest ){
-
        /* If the source page-size is smaller than the destination page-size,
-
        ** two extra things may need to happen:
-
        **
-
        **   * The destination may need to be truncated, and
+
      if( rc==SQLITE_OK ){
+
        int nDestTruncate;
+
        /* Set nDestTruncate to the final number of pages in the destination
+
        ** database. The complication here is that the destination page
+
        ** size may be different to the source page size. 
        **
-
        **   * Data stored on the pages immediately following the 
-
        **     pending-byte page in the source database may need to be
-
        **     copied into the destination database.
+
        ** If the source page size is smaller than the destination page size, 
+
        ** round up. In this case the call to sqlite3OsTruncate() below will
+
        ** fix the size of the file. However it is important to call
+
        ** sqlite3PagerTruncateImage() here so that any pages in the 
+
        ** destination file that lie beyond the nDestTruncate page mark are
+
        ** journalled by PagerCommitPhaseOne() before they are destroyed
+
        ** by the file truncation.
        */
-
        const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
-
        sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
-
        i64 iOff;
-
        i64 iEnd;
-

-
        assert( pFile );
-
        assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
-
              nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
-
           && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
-
        ));
+
        assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
+
        assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
+
        if( pgszSrc<pgszDest ){
+
          int ratio = pgszDest/pgszSrc;
+
          nDestTruncate = (nSrcPage+ratio-1)/ratio;
+
          if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
+
            nDestTruncate--;
+
          }
+
        }else{
+
          nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
+
        }
+
        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);

-
        /* This call ensures that all data required to recreate the original
-
        ** database has been stored in the journal for pDestPager and the
-
        ** journal synced to disk. So at this point we may safely modify
-
        ** the database file in any way, knowing that if a power failure
-
        ** occurs, the original database will be reconstructed from the 
-
        ** journal file.  */
-
        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
-

-
        /* Write the extra pages and truncate the database file as required. */
-
        iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
-
        for(
-
          iOff=PENDING_BYTE+pgszSrc; 
-
          rc==SQLITE_OK && iOff<iEnd; 
-
          iOff+=pgszSrc
-
        ){
-
          PgHdr *pSrcPg = 0;
-
          const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
-
          rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
+
        if( pgszSrc<pgszDest ){
+
          /* If the source page-size is smaller than the destination page-size,
+
          ** two extra things may need to happen:
+
          **
+
          **   * The destination may need to be truncated, and
+
          **
+
          **   * Data stored on the pages immediately following the 
+
          **     pending-byte page in the source database may need to be
+
          **     copied into the destination database.
+
          */
+
          const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
+
          sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
+
          i64 iOff;
+
          i64 iEnd;
+

+
          assert( pFile );
+
          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
+
                nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
+
             && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
+
          ));
+

+
          /* This call ensures that all data required to recreate the original
+
          ** database has been stored in the journal for pDestPager and the
+
          ** journal synced to disk. So at this point we may safely modify
+
          ** the database file in any way, knowing that if a power failure
+
          ** occurs, the original database will be reconstructed from the 
+
          ** journal file.  */
+
          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+

+
          /* Write the extra pages and truncate the database file as required */
+
          iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
+
          for(
+
            iOff=PENDING_BYTE+pgszSrc; 
+
            rc==SQLITE_OK && iOff<iEnd; 
+
            iOff+=pgszSrc
+
          ){
+
            PgHdr *pSrcPg = 0;
+
            const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
+
            rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
+
            if( rc==SQLITE_OK ){
+
              u8 *zData = sqlite3PagerGetData(pSrcPg);
+
              rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
+
            }
+
            sqlite3PagerUnref(pSrcPg);
+
          }
          if( rc==SQLITE_OK ){
-
            u8 *zData = sqlite3PagerGetData(pSrcPg);
-
            rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
+
            rc = backupTruncateFile(pFile, iSize);
          }
-
          sqlite3PagerUnref(pSrcPg);
-
        }
-
        if( rc==SQLITE_OK ){
-
          rc = backupTruncateFile(pFile, iSize);
-
        }

-
        /* Sync the database file to disk. */
-
        if( rc==SQLITE_OK ){
-
          rc = sqlite3PagerSync(pDestPager);
+
          /* Sync the database file to disk. */
+
          if( rc==SQLITE_OK ){
+
            rc = sqlite3PagerSync(pDestPager);
+
          }
+
        }else{
+
          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
+
        }
+
    
+
        /* Finish committing the transaction to the destination database. */
+
        if( SQLITE_OK==rc
+
         && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
+
        ){
+
          rc = SQLITE_DONE;
        }
-
      }else{
-
        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
-
      }
-
  
-
      /* Finish committing the transaction to the destination database. */
-
      if( SQLITE_OK==rc
-
       && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
-
      ){
-
        rc = SQLITE_DONE;
      }
    }
  
@@ -56655,24 +57418,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
*/
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
  assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
-
  testcase( p->flags & MEM_Agg );
-
  testcase( p->flags & MEM_Dyn );
-
  testcase( p->flags & MEM_RowSet );
-
  testcase( p->flags & MEM_Frame );
-
  if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){
-
    if( p->flags&MEM_Agg ){
-
      sqlite3VdbeMemFinalize(p, p->u.pDef);
-
      assert( (p->flags & MEM_Agg)==0 );
-
      sqlite3VdbeMemRelease(p);
-
    }else if( p->flags&MEM_Dyn && p->xDel ){
-
      assert( (p->flags&MEM_RowSet)==0 );
-
      p->xDel((void *)p->z);
-
      p->xDel = 0;
-
    }else if( p->flags&MEM_RowSet ){
-
      sqlite3RowSetClear(p->u.pRowSet);
-
    }else if( p->flags&MEM_Frame ){
-
      sqlite3VdbeMemSetNull(p);
-
    }
+
  if( p->flags&MEM_Agg ){
+
    sqlite3VdbeMemFinalize(p, p->u.pDef);
+
    assert( (p->flags & MEM_Agg)==0 );
+
    sqlite3VdbeMemRelease(p);
+
  }else if( p->flags&MEM_Dyn && p->xDel ){
+
    assert( (p->flags&MEM_RowSet)==0 );
+
    p->xDel((void *)p->z);
+
    p->xDel = 0;
+
  }else if( p->flags&MEM_RowSet ){
+
    sqlite3RowSetClear(p->u.pRowSet);
+
  }else if( p->flags&MEM_Frame ){
+
    sqlite3VdbeMemSetNull(p);
  }
}

@@ -56682,7 +57439,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
** (Mem.type==SQLITE_TEXT).
*/
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
-
  sqlite3VdbeMemReleaseExternal(p);
+
  MemReleaseExt(p);
  sqlite3DbFree(p->db, p->zMalloc);
  p->z = 0;
  p->zMalloc = 0;
@@ -57004,7 +57761,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrepareToChange(Vdbe *pVdbe, Mem *pMem){
*/
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
  assert( (pFrom->flags & MEM_RowSet)==0 );
-
  sqlite3VdbeMemReleaseExternal(pTo);
+
  MemReleaseExt(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->xDel = 0;
  if( (pFrom->flags&MEM_Static)==0 ){
@@ -57022,7 +57779,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
  int rc = SQLITE_OK;

  assert( (pFrom->flags & MEM_RowSet)==0 );
-
  sqlite3VdbeMemReleaseExternal(pTo);
+
  MemReleaseExt(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->flags &= ~MEM_Dyn;

@@ -57977,6 +58734,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
      n = pOp[-1].p1;
      if( n>nMaxArgs ) nMaxArgs = n;
#endif
+
    }else if( opcode==OP_Next || opcode==OP_SorterNext ){
+
      pOp->p4.xAdvance = sqlite3BtreeNext;
+
      pOp->p4type = P4_ADVANCE;
+
    }else if( opcode==OP_Prev ){
+
      pOp->p4.xAdvance = sqlite3BtreePrevious;
+
      pOp->p4type = P4_ADVANCE;
    }

    if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
@@ -58068,10 +58831,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
** static array using sqlite3VdbeAddOpList but we want to make a
** few minor changes to the program.
*/
-
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
+
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
  assert( p!=0 );
-
  assert( addr>=0 );
-
  if( p->nOp>addr ){
+
  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p1 = val;
  }
}
@@ -58080,10 +58842,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
** Change the value of the P2 operand for a specific instruction.
** This routine is useful for setting a jump destination.
*/
-
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
+
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
  assert( p!=0 );
-
  assert( addr>=0 );
-
  if( p->nOp>addr ){
+
  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p2 = val;
  }
}
@@ -58091,10 +58852,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
/*
** Change the value of the P3 operand for a specific instruction.
*/
-
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
+
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
  assert( p!=0 );
-
  assert( addr>=0 );
-
  if( p->nOp>addr ){
+
  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p3 = val;
  }
}
@@ -58211,18 +58971,15 @@ SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
}

/*
-
** Change N opcodes starting at addr to No-ops.
+
** Change the opcode at addr into OP_Noop
*/
-
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
+
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
  if( p->aOp ){
    VdbeOp *pOp = &p->aOp[addr];
    sqlite3 *db = p->db;
-
    while( N-- ){
-
      freeP4(db, pOp->p4type, pOp->p4.p);
-
      memset(pOp, 0, sizeof(pOp[0]));
-
      pOp->opcode = OP_Noop;
-
      pOp++;
-
    }
+
    freeP4(db, pOp->p4type, pOp->p4.p);
+
    memset(pOp, 0, sizeof(pOp[0]));
+
    pOp->opcode = OP_Noop;
  }
}

@@ -58378,7 +59135,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  /* C89 specifies that the constant "dummy" will be initialized to all
  ** zeros, which is correct.  MSVC generates a warning, nevertheless. */
-
  static const VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
+
  static VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
  assert( p->magic==VDBE_MAGIC_INIT );
  if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
@@ -58486,6 +59243,10 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
      sqlite3_snprintf(nTemp, zTemp, "program");
      break;
    }
+
    case P4_ADVANCE: {
+
      zTemp[0] = 0;
+
      break;
+
    }
    default: {
      zP4 = pOp->p4.z;
      if( zP4==0 ){
@@ -59109,6 +59870,7 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
  if( pCx==0 ){
    return;
  }
+
  sqlite3VdbeSorterClose(p->db, pCx);
  if( pCx->pBt ){
    sqlite3BtreeClose(pCx->pBt);
    /* The pCx->pCursor will be close automatically, if it exists, by
@@ -60366,57 +61128,70 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
  return 0;
}

-

/*
-
** Given the nKey-byte encoding of a record in pKey[], parse the
-
** record into a UnpackedRecord structure.  Return a pointer to
-
** that structure.
+
** This routine is used to allocate sufficient space for an UnpackedRecord
+
** structure large enough to be used with sqlite3VdbeRecordUnpack() if
+
** the first argument is a pointer to KeyInfo structure pKeyInfo.
**
-
** The calling function might provide szSpace bytes of memory
-
** space at pSpace.  This space can be used to hold the returned
-
** VDbeParsedRecord structure if it is large enough.  If it is
-
** not big enough, space is obtained from sqlite3_malloc().
+
** The space is either allocated using sqlite3DbMallocRaw() or from within
+
** the unaligned buffer passed via the second and third arguments (presumably
+
** stack space). If the former, then *ppFree is set to a pointer that should
+
** be eventually freed by the caller using sqlite3DbFree(). Or, if the 
+
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
+
** before returning.
**
-
** The returned structure should be closed by a call to
-
** sqlite3VdbeDeleteUnpackedRecord().
-
*/ 
-
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
-
  KeyInfo *pKeyInfo,     /* Information about the record format */
-
  int nKey,              /* Size of the binary record */
-
  const void *pKey,      /* The binary record */
-
  char *pSpace,          /* Unaligned space available to hold the object */
-
  int szSpace            /* Size of pSpace[] in bytes */
+
** If an OOM error occurs, NULL is returned.
+
*/
+
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
+
  KeyInfo *pKeyInfo,              /* Description of the record */
+
  char *pSpace,                   /* Unaligned space available */
+
  int szSpace,                    /* Size of pSpace[] in bytes */
+
  char **ppFree                   /* OUT: Caller should free this pointer */
){
-
  const unsigned char *aKey = (const unsigned char *)pKey;
-
  UnpackedRecord *p;  /* The unpacked record that we will return */
-
  int nByte;          /* Memory space needed to hold p, in bytes */
-
  int d;
-
  u32 idx;
-
  u16 u;              /* Unsigned loop counter */
-
  u32 szHdr;
-
  Mem *pMem;
-
  int nOff;           /* Increase pSpace by this much to 8-byte align it */
-
  
-
  /*
-
  ** We want to shift the pointer pSpace up such that it is 8-byte aligned.
+
  UnpackedRecord *p;              /* Unpacked record to return */
+
  int nOff;                       /* Increment pSpace by nOff to align it */
+
  int nByte;                      /* Number of bytes required for *p */
+

+
  /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
  ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift 
  ** it by.  If pSpace is already 8-byte aligned, nOff should be zero.
  */
  nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
-
  pSpace += nOff;
-
  szSpace -= nOff;
  nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
-
  if( nByte>szSpace ){
-
    p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
-
    if( p==0 ) return 0;
-
    p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
+
  if( nByte>szSpace+nOff ){
+
    p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+
    *ppFree = (char *)p;
+
    if( !p ) return 0;
  }else{
-
    p = (UnpackedRecord*)pSpace;
-
    p->flags = UNPACKED_NEED_DESTROY;
+
    p = (UnpackedRecord*)&pSpace[nOff];
+
    *ppFree = 0;
  }
+

+
  p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
  p->pKeyInfo = pKeyInfo;
  p->nField = pKeyInfo->nField + 1;
-
  p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+
  return p;
+
}
+

+
/*
+
** Given the nKey-byte encoding of a record in pKey[], populate the 
+
** UnpackedRecord structure indicated by the fourth argument with the
+
** contents of the decoded record.
+
*/ 
+
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
+
  KeyInfo *pKeyInfo,     /* Information about the record format */
+
  int nKey,              /* Size of the binary record */
+
  const void *pKey,      /* The binary record */
+
  UnpackedRecord *p      /* Populate this structure before returning. */
+
){
+
  const unsigned char *aKey = (const unsigned char *)pKey;
+
  int d; 
+
  u32 idx;                        /* Offset in aKey[] to read from */
+
  u16 u;                          /* Unsigned loop counter */
+
  u32 szHdr;
+
  Mem *pMem = p->aMem;
+

+
  p->flags = 0;
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  idx = getVarint32(aKey, szHdr);
  d = szHdr;
@@ -60435,31 +61210,6 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
  }
  assert( u<=pKeyInfo->nField + 1 );
  p->nField = u;
-
  return (void*)p;
-
}
-

-
/*
-
** This routine destroys a UnpackedRecord object.
-
*/
-
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
-
#ifdef SQLITE_DEBUG
-
  int i;
-
  Mem *pMem;
-

-
  assert( p!=0 );
-
  assert( p->flags & UNPACKED_NEED_DESTROY );
-
  for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
-
    /* The unpacked record is always constructed by the
-
    ** sqlite3VdbeUnpackRecord() function above, which makes all
-
    ** strings and blobs static.  And none of the elements are
-
    ** ever transformed, so there is never anything to delete.
-
    */
-
    if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem);
-
  }
-
#endif
-
  if( p->flags & UNPACKED_NEED_FREE ){
-
    sqlite3DbFree(p->pKeyInfo->db, p);
-
  }
}

/*
@@ -61278,7 +62028,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
         && cnt++ < SQLITE_MAX_SCHEMA_RETRY
         && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
    sqlite3_reset(pStmt);
-
    v->expired = 0;
+
    assert( v->expired==0 );
  }
  if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
    /* This case occurs after failing to recompile an sql statement. 
@@ -62409,6 +63159,13 @@ SQLITE_API int sqlite3_found_count = 0;
*/
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)

+
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
+
#ifdef SQLITE_OMIT_MERGE_SORT
+
# define isSorter(x) 0
+
#else
+
# define isSorter(x) ((x)->pSorter!=0)
+
#endif
+

/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
@@ -63003,6 +63760,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      u32 szField;       /* Number of bytes in the content of a field */
      int szHdr;         /* Size of the header size field at start of record */
      int avail;         /* Number of bytes of available data */
+
      u32 t;             /* A type code from the record header */
      Mem *pReg;         /* PseudoTable input register */
    } am;
    struct OP_Affinity_stack_vars {
@@ -63074,9 +63832,12 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
    struct OP_OpenEphemeral_stack_vars {
      VdbeCursor *pCx;
    } ax;
-
    struct OP_OpenPseudo_stack_vars {
+
    struct OP_SorterOpen_stack_vars {
      VdbeCursor *pCx;
    } ay;
+
    struct OP_OpenPseudo_stack_vars {
+
      VdbeCursor *pCx;
+
    } az;
    struct OP_SeekGt_stack_vars {
      int res;
      int oc;
@@ -63084,18 +63845,19 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      UnpackedRecord r;
      int nField;
      i64 iKey;      /* The rowid we are to seek to */
-
    } az;
+
    } ba;
    struct OP_Seek_stack_vars {
      VdbeCursor *pC;
-
    } ba;
+
    } bb;
    struct OP_Found_stack_vars {
      int alreadyExists;
      VdbeCursor *pC;
      int res;
+
      char *pFree;
      UnpackedRecord *pIdxKey;
      UnpackedRecord r;
      char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-
    } bb;
+
    } bc;
    struct OP_IsUnique_stack_vars {
      u16 ii;
      VdbeCursor *pCx;
@@ -63104,13 +63866,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      Mem *aMx;
      UnpackedRecord r;                  /* B-Tree index search key */
      i64 R;                             /* Rowid stored in register P3 */
-
    } bc;
+
    } bd;
    struct OP_NotExists_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
      u64 iKey;
-
    } bd;
+
    } be;
    struct OP_NewRowid_stack_vars {
      i64 v;                 /* The new rowid */
      VdbeCursor *pC;        /* Cursor of table to get the new rowid */
@@ -63118,7 +63880,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      int cnt;               /* Counter to limit the number of searches */
      Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
      VdbeFrame *pFrame;     /* Root frame of VDBE */
-
    } be;
+
    } bf;
    struct OP_InsertInt_stack_vars {
      Mem *pData;       /* MEM cell holding data for the record to be inserted */
      Mem *pKey;        /* MEM cell holding key  for the record */
@@ -63129,83 +63891,89 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      const char *zDb;  /* database name - used by the update hook */
      const char *zTbl; /* Table name - used by the opdate hook */
      int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-
    } bf;
+
    } bg;
    struct OP_Delete_stack_vars {
      i64 iKey;
      VdbeCursor *pC;
-
    } bg;
+
    } bh;
+
    struct OP_SorterCompare_stack_vars {
+
      VdbeCursor *pC;
+
      int res;
+
    } bi;
+
    struct OP_SorterData_stack_vars {
+
      VdbeCursor *pC;
+
    } bj;
    struct OP_RowData_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      u32 n;
      i64 n64;
-
    } bh;
+
    } bk;
    struct OP_Rowid_stack_vars {
      VdbeCursor *pC;
      i64 v;
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
-
    } bi;
+
    } bl;
    struct OP_NullRow_stack_vars {
      VdbeCursor *pC;
-
    } bj;
+
    } bm;
    struct OP_Last_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
-
    } bk;
+
    } bn;
    struct OP_Rewind_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
-
    } bl;
+
    } bo;
    struct OP_Next_stack_vars {
      VdbeCursor *pC;
-
      BtCursor *pCrsr;
      int res;
-
    } bm;
+
    } bp;
    struct OP_IdxInsert_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int nKey;
      const char *zKey;
-
    } bn;
+
    } bq;
    struct OP_IdxDelete_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
      UnpackedRecord r;
-
    } bo;
+
    } br;
    struct OP_IdxRowid_stack_vars {
      BtCursor *pCrsr;
      VdbeCursor *pC;
      i64 rowid;
-
    } bp;
+
    } bs;
    struct OP_IdxGE_stack_vars {
      VdbeCursor *pC;
      int res;
      UnpackedRecord r;
-
    } bq;
+
    } bt;
    struct OP_Destroy_stack_vars {
      int iMoved;
      int iCnt;
      Vdbe *pVdbe;
      int iDb;
-
    } br;
+
    } bu;
    struct OP_Clear_stack_vars {
      int nChange;
-
    } bs;
+
    } bv;
    struct OP_CreateTable_stack_vars {
      int pgno;
      int flags;
      Db *pDb;
-
    } bt;
+
    } bw;
    struct OP_ParseSchema_stack_vars {
      int iDb;
      const char *zMaster;
      char *zSql;
      InitData initData;
-
    } bu;
+
    } bx;
    struct OP_IntegrityCk_stack_vars {
      int nRoot;      /* Number of tables to check.  (Number of root pages.) */
      int *aRoot;     /* Array of rootpage numbers for tables to be checked */
@@ -63213,14 +63981,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      int nErr;       /* Number of errors reported */
      char *z;        /* Text of the error report */
      Mem *pnErr;     /* Register keeping track of errors remaining */
-
    } bv;
+
    } by;
    struct OP_RowSetRead_stack_vars {
      i64 val;
-
    } bw;
+
    } bz;
    struct OP_RowSetTest_stack_vars {
      int iSet;
      int exists;
-
    } bx;
+
    } ca;
    struct OP_Program_stack_vars {
      int nMem;               /* Number of memory registers for sub-program */
      int nByte;              /* Bytes of runtime space required for sub-program */
@@ -63230,15 +63998,15 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      VdbeFrame *pFrame;      /* New vdbe frame to execute in */
      SubProgram *pProgram;   /* Sub-program to execute */
      void *t;                /* Token identifying trigger */
-
    } by;
+
    } cb;
    struct OP_Param_stack_vars {
      VdbeFrame *pFrame;
      Mem *pIn;
-
    } bz;
+
    } cc;
    struct OP_MemMax_stack_vars {
      Mem *pIn1;
      VdbeFrame *pFrame;
-
    } ca;
+
    } cd;
    struct OP_AggStep_stack_vars {
      int n;
      int i;
@@ -63246,34 +64014,34 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      Mem *pRec;
      sqlite3_context ctx;
      sqlite3_value **apVal;
-
    } cb;
+
    } ce;
    struct OP_AggFinal_stack_vars {
      Mem *pMem;
-
    } cc;
+
    } cf;
    struct OP_Checkpoint_stack_vars {
      int i;                          /* Loop counter */
      int aRes[3];                    /* Results */
      Mem *pMem;                      /* Write results here */
-
    } cd;
+
    } cg;
    struct OP_JournalMode_stack_vars {
      Btree *pBt;                     /* Btree to change journal mode of */
      Pager *pPager;                  /* Pager associated with pBt */
      int eNew;                       /* New journal mode */
      int eOld;                       /* The old journal mode */
      const char *zFilename;          /* Name of database file for pPager */
-
    } ce;
+
    } ch;
    struct OP_IncrVacuum_stack_vars {
      Btree *pBt;
-
    } cf;
+
    } ci;
    struct OP_VBegin_stack_vars {
      VTable *pVTab;
-
    } cg;
+
    } cj;
    struct OP_VOpen_stack_vars {
      VdbeCursor *pCur;
      sqlite3_vtab_cursor *pVtabCursor;
      sqlite3_vtab *pVtab;
      sqlite3_module *pModule;
-
    } ch;
+
    } ck;
    struct OP_VFilter_stack_vars {
      int nArg;
      int iQuery;
@@ -63286,23 +64054,23 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      int res;
      int i;
      Mem **apArg;
-
    } ci;
+
    } cl;
    struct OP_VColumn_stack_vars {
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
      Mem *pDest;
      sqlite3_context sContext;
-
    } cj;
+
    } cm;
    struct OP_VNext_stack_vars {
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
      int res;
      VdbeCursor *pCur;
-
    } ck;
+
    } cn;
    struct OP_VRename_stack_vars {
      sqlite3_vtab *pVtab;
      Mem *pName;
-
    } cl;
+
    } co;
    struct OP_VUpdate_stack_vars {
      sqlite3_vtab *pVtab;
      sqlite3_module *pModule;
@@ -63311,11 +64079,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      sqlite_int64 rowid;
      Mem **apArg;
      Mem *pX;
-
    } cm;
+
    } cp;
    struct OP_Trace_stack_vars {
      char *zTrace;
      char *z;
-
    } cn;
+
    } cq;
  } u;
  /* End automatically generated code
  ********************************************************************/
@@ -63415,7 +64183,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
      assert( pOp->p2<=p->nMem );
      pOut = &aMem[pOp->p2];
      memAboutToChange(p, pOut);
-
      sqlite3VdbeMemReleaseExternal(pOut);
+
      MemReleaseExt(pOut);
      pOut->flags = MEM_Int;
    }

@@ -63782,6 +64550,11 @@ case OP_Move: {
    u.ac.zMalloc = pOut->zMalloc;
    pOut->zMalloc = 0;
    sqlite3VdbeMemMove(pOut, pIn1);
+
#ifdef SQLITE_DEBUG
+
    if( pOut->pScopyFrom>=&aMem[u.ac.p1] && pOut->pScopyFrom<&aMem[u.ac.p1+pOp->p3] ){
+
      pOut->pScopyFrom += u.ac.p1 - pOp->p2;
+
    }
+
#endif
    pIn1->zMalloc = u.ac.zMalloc;
    REGISTER_TRACE(u.ac.p2++, pOut);
    pIn1++;
@@ -64780,6 +65553,16 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
  break;
}

+
/* Opcode: Once P1 P2 * * *
+
**
+
** Jump to P2 if the value in register P1 is a not null or zero.  If
+
** the value is NULL or zero, fall through and change the P1 register
+
** to an integer 1.
+
**
+
** When P1 is not used otherwise in a program, this opcode falls through
+
** once and jumps on all subsequent invocations.  It is the equivalent
+
** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
+
*/
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true.  The value
@@ -64792,6 +65575,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** 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.
*/
+
case OP_Once:               /* jump, in1 */
case OP_If:                 /* jump, in1 */
case OP_IfNot: {            /* jump, in1 */
#if 0  /* local variables moved into u.al */
@@ -64810,6 +65594,12 @@ case OP_IfNot: { /* jump, in1 */
  }
  if( u.al.c ){
    pc = pOp->p2-1;
+
  }else if( pOp->opcode==OP_Once ){
+
    assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
+
    memAboutToChange(p, pIn1);
+
    pIn1->flags = MEM_Int;
+
    pIn1->u.i = 1;
+
    REGISTER_TRACE(pOp->p1, pIn1);
  }
  break;
}
@@ -64880,6 +65670,7 @@ case OP_Column: {
  u32 szField;       /* Number of bytes in the content of a field */
  int szHdr;         /* Size of the header size field at start of record */
  int avail;         /* Number of bytes of available data */
+
  u32 t;             /* A type code from the record header */
  Mem *pReg;         /* PseudoTable input register */
#endif /* local variables moved into u.am */

@@ -64892,7 +65683,6 @@ case OP_Column: {
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.am.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.am.pDest);
-
  MemSetTypeFlag(u.am.pDest, MEM_Null);
  u.am.zRec = 0;

  /* This block sets the variable u.am.payloadSize to be the total number of
@@ -64936,7 +65726,7 @@ case OP_Column: {
      rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
      assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
    }
-
  }else if( u.am.pC->pseudoTableReg>0 ){
+
  }else if( ALWAYS(u.am.pC->pseudoTableReg>0) ){
    u.am.pReg = &aMem[u.am.pC->pseudoTableReg];
    assert( u.am.pReg->flags & MEM_Blob );
    assert( memIsValid(u.am.pReg) );
@@ -64949,9 +65739,10 @@ case OP_Column: {
    u.am.payloadSize = 0;
  }

-
  /* If u.am.payloadSize is 0, then just store a NULL */
+
  /* If u.am.payloadSize is 0, then just store a NULL.  This can happen because of
+
  ** nullRow or because of a corrupt database. */
  if( u.am.payloadSize==0 ){
-
    assert( u.am.pDest->flags&MEM_Null );
+
    MemSetTypeFlag(u.am.pDest, MEM_Null);
    goto op_column_out;
  }
  assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
@@ -65058,8 +65849,14 @@ case OP_Column: {
    for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
      if( u.am.zIdx<u.am.zEndHdr ){
        u.am.aOffset[u.am.i] = u.am.offset;
-
        u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]);
-
        u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]);
+
        if( u.am.zIdx[0]<0x80 ){
+
          u.am.t = u.am.zIdx[0];
+
          u.am.zIdx++;
+
        }else{
+
          u.am.zIdx += sqlite3GetVarint32(u.am.zIdx, &u.am.t);
+
        }
+
        u.am.aType[u.am.i] = u.am.t;
+
        u.am.szField = sqlite3VdbeSerialTypeLen(u.am.t);
        u.am.offset += u.am.szField;
        if( u.am.offset<u.am.szField ){  /* True if u.am.offset overflows */
          u.am.zIdx = &u.am.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
@@ -65100,7 +65897,7 @@ case OP_Column: {
  if( u.am.aOffset[u.am.p2] ){
    assert( rc==SQLITE_OK );
    if( u.am.zRec ){
-
      sqlite3VdbeMemReleaseExternal(u.am.pDest);
+
      MemReleaseExt(u.am.pDest);
      sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
    }else{
      u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
@@ -65117,7 +65914,7 @@ case OP_Column: {
    if( pOp->p4type==P4_MEM ){
      sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
    }else{
-
      assert( u.am.pDest->flags&MEM_Null );
+
      MemSetTypeFlag(u.am.pDest, MEM_Null);
    }
  }

@@ -65319,7 +66116,7 @@ case OP_Count: { /* out2-prerelease */
#endif /* local variables moved into u.ap */

  u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
-
  if( u.ap.pCrsr ){
+
  if( ALWAYS(u.ap.pCrsr) ){
    rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
  }else{
    u.ap.nEntry = 0;
@@ -65895,15 +66692,9 @@ case OP_OpenWrite: {
  rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor);
  u.aw.pCur->pKeyInfo = u.aw.pKeyInfo;

-
  /* Since it performs no memory allocation or IO, the only values that
-
  ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK.
-
  ** SQLITE_EMPTY is only returned when attempting to open the table
-
  ** rooted at page 1 of a zero-byte database.  */
-
  assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
-
  if( rc==SQLITE_EMPTY ){
-
    u.aw.pCur->pCursor = 0;
-
    rc = SQLITE_OK;
-
  }
+
  /* Since it performs no memory allocation or IO, the only value that
+
  ** sqlite3BtreeCursor() may return is SQLITE_OK. */
+
  assert( rc==SQLITE_OK );

  /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
  ** SQLite used to check if the root-page flags were sane at this point
@@ -65914,7 +66705,7 @@ case OP_OpenWrite: {
  break;
}

-
/* Opcode: OpenEphemeral P1 P2 * P4 *
+
/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
@@ -65931,6 +66722,11 @@ case OP_OpenWrite: {
** to a TEMP table at the SQL level, or to a table opened by
** this opcode.  Then this opcode was call OpenVirtual.  But
** that created confusion with the whole virtual-table idea.
+
**
+
** The P5 parameter can be a mask of the BTREE_* flags defined
+
** in btree.h.  These flags control aspects of the operation of
+
** the btree.  The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
+
** added automatically.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
**
@@ -65969,7 +66765,7 @@ case OP_OpenEphemeral: {
    if( pOp->p4.pKeyInfo ){
      int pgno;
      assert( pOp->p4type==P4_KEYINFO );
-
      rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY);
+
      rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
      if( rc==SQLITE_OK ){
        assert( pgno==MASTER_ROOT+1 );
        rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
@@ -65988,6 +66784,30 @@ case OP_OpenEphemeral: {
  break;
}

+
/* Opcode: OpenSorter P1 P2 * P4 *
+
**
+
** This opcode works like OP_OpenEphemeral except that it opens
+
** a transient index that is specifically designed to sort large
+
** tables using an external merge-sort algorithm.
+
*/
+
case OP_SorterOpen: {
+
#if 0  /* local variables moved into u.ay */
+
  VdbeCursor *pCx;
+
#endif /* local variables moved into u.ay */
+
#ifndef SQLITE_OMIT_MERGE_SORT
+
  u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+
  if( u.ay.pCx==0 ) goto no_mem;
+
  u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+
  u.ay.pCx->pKeyInfo->enc = ENC(p->db);
+
  u.ay.pCx->isSorter = 1;
+
  rc = sqlite3VdbeSorterInit(db, u.ay.pCx);
+
#else
+
  pOp->opcode = OP_OpenEphemeral;
+
  pc--;
+
#endif
+
  break;
+
}
+

/* Opcode: OpenPseudo P1 P2 P3 * *
**
** Open a new cursor that points to a fake table that contains a single
@@ -66004,17 +66824,17 @@ case OP_OpenEphemeral: {
** the pseudo-table.
*/
case OP_OpenPseudo: {
-
#if 0  /* local variables moved into u.ay */
+
#if 0  /* local variables moved into u.az */
  VdbeCursor *pCx;
-
#endif /* local variables moved into u.ay */
+
#endif /* local variables moved into u.az */

  assert( pOp->p1>=0 );
-
  u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
-
  if( u.ay.pCx==0 ) goto no_mem;
-
  u.ay.pCx->nullRow = 1;
-
  u.ay.pCx->pseudoTableReg = pOp->p2;
-
  u.ay.pCx->isTable = 1;
-
  u.ay.pCx->isIndex = 0;
+
  u.az.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+
  if( u.az.pCx==0 ) goto no_mem;
+
  u.az.pCx->nullRow = 1;
+
  u.az.pCx->pseudoTableReg = pOp->p2;
+
  u.az.pCx->isTable = 1;
+
  u.az.pCx->isIndex = 0;
  break;
}

@@ -66086,35 +66906,35 @@ case OP_SeekLt: /* jump, in3 */
case OP_SeekLe:         /* jump, in3 */
case OP_SeekGe:         /* jump, in3 */
case OP_SeekGt: {       /* jump, in3 */
-
#if 0  /* local variables moved into u.az */
+
#if 0  /* local variables moved into u.ba */
  int res;
  int oc;
  VdbeCursor *pC;
  UnpackedRecord r;
  int nField;
  i64 iKey;      /* The rowid we are to seek to */
-
#endif /* local variables moved into u.az */
+
#endif /* local variables moved into u.ba */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
-
  u.az.pC = p->apCsr[pOp->p1];
-
  assert( u.az.pC!=0 );
-
  assert( u.az.pC->pseudoTableReg==0 );
+
  u.ba.pC = p->apCsr[pOp->p1];
+
  assert( u.ba.pC!=0 );
+
  assert( u.ba.pC->pseudoTableReg==0 );
  assert( OP_SeekLe == OP_SeekLt+1 );
  assert( OP_SeekGe == OP_SeekLt+2 );
  assert( OP_SeekGt == OP_SeekLt+3 );
-
  assert( u.az.pC->isOrdered );
-
  if( u.az.pC->pCursor!=0 ){
-
    u.az.oc = pOp->opcode;
-
    u.az.pC->nullRow = 0;
-
    if( u.az.pC->isTable ){
+
  assert( u.ba.pC->isOrdered );
+
  if( ALWAYS(u.ba.pC->pCursor!=0) ){
+
    u.ba.oc = pOp->opcode;
+
    u.ba.pC->nullRow = 0;
+
    if( u.ba.pC->isTable ){
      /* The input value in P3 might be of any type: integer, real, string,
      ** blob, or NULL.  But it needs to be an integer before we can do
      ** the seek, so covert it. */
      pIn3 = &aMem[pOp->p3];
      applyNumericAffinity(pIn3);
-
      u.az.iKey = sqlite3VdbeIntValue(pIn3);
-
      u.az.pC->rowidIsValid = 0;
+
      u.ba.iKey = sqlite3VdbeIntValue(pIn3);
+
      u.ba.pC->rowidIsValid = 0;

      /* If the P3 value could not be converted into an integer without
      ** loss of information, then special processing is required... */
@@ -66129,101 +66949,101 @@ case OP_SeekGt: { /* jump, in3 */
        ** point number. */
        assert( (pIn3->flags & MEM_Real)!=0 );

-
        if( u.az.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.az.iKey || pIn3->r>0) ){
+
        if( u.ba.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.ba.iKey || pIn3->r>0) ){
          /* The P3 value is too large in magnitude to be expressed as an
          ** integer. */
-
          u.az.res = 1;
+
          u.ba.res = 1;
          if( pIn3->r<0 ){
-
            if( u.az.oc>=OP_SeekGe ){  assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
-
              rc = sqlite3BtreeFirst(u.az.pC->pCursor, &u.az.res);
+
            if( u.ba.oc>=OP_SeekGe ){  assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
+
              rc = sqlite3BtreeFirst(u.ba.pC->pCursor, &u.ba.res);
              if( rc!=SQLITE_OK ) goto abort_due_to_error;
            }
          }else{
-
            if( u.az.oc<=OP_SeekLe ){  assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
-
              rc = sqlite3BtreeLast(u.az.pC->pCursor, &u.az.res);
+
            if( u.ba.oc<=OP_SeekLe ){  assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
+
              rc = sqlite3BtreeLast(u.ba.pC->pCursor, &u.ba.res);
              if( rc!=SQLITE_OK ) goto abort_due_to_error;
            }
          }
-
          if( u.az.res ){
+
          if( u.ba.res ){
            pc = pOp->p2 - 1;
          }
          break;
-
        }else if( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekGe ){
+
        }else if( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekGe ){
          /* Use the ceiling() function to convert real->int */
-
          if( pIn3->r > (double)u.az.iKey ) u.az.iKey++;
+
          if( pIn3->r > (double)u.ba.iKey ) u.ba.iKey++;
        }else{
          /* Use the floor() function to convert real->int */
-
          assert( u.az.oc==OP_SeekLe || u.az.oc==OP_SeekGt );
-
          if( pIn3->r < (double)u.az.iKey ) u.az.iKey--;
+
          assert( u.ba.oc==OP_SeekLe || u.ba.oc==OP_SeekGt );
+
          if( pIn3->r < (double)u.ba.iKey ) u.ba.iKey--;
        }
      }
-
      rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, 0, (u64)u.az.iKey, 0, &u.az.res);
+
      rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, 0, (u64)u.ba.iKey, 0, &u.ba.res);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
-
      if( u.az.res==0 ){
-
        u.az.pC->rowidIsValid = 1;
-
        u.az.pC->lastRowid = u.az.iKey;
+
      if( u.ba.res==0 ){
+
        u.ba.pC->rowidIsValid = 1;
+
        u.ba.pC->lastRowid = u.ba.iKey;
      }
    }else{
-
      u.az.nField = pOp->p4.i;
+
      u.ba.nField = pOp->p4.i;
      assert( pOp->p4type==P4_INT32 );
-
      assert( u.az.nField>0 );
-
      u.az.r.pKeyInfo = u.az.pC->pKeyInfo;
-
      u.az.r.nField = (u16)u.az.nField;
+
      assert( u.ba.nField>0 );
+
      u.ba.r.pKeyInfo = u.ba.pC->pKeyInfo;
+
      u.ba.r.nField = (u16)u.ba.nField;

      /* The next line of code computes as follows, only faster:
-
      **   if( u.az.oc==OP_SeekGt || u.az.oc==OP_SeekLe ){
-
      **     u.az.r.flags = UNPACKED_INCRKEY;
+
      **   if( u.ba.oc==OP_SeekGt || u.ba.oc==OP_SeekLe ){
+
      **     u.ba.r.flags = UNPACKED_INCRKEY;
      **   }else{
-
      **     u.az.r.flags = 0;
+
      **     u.ba.r.flags = 0;
      **   }
      */
-
      u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt)));
-
      assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY );
-
      assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY );
-
      assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 );
-
      assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 );
+
      u.ba.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.ba.oc - OP_SeekLt)));
+
      assert( u.ba.oc!=OP_SeekGt || u.ba.r.flags==UNPACKED_INCRKEY );
+
      assert( u.ba.oc!=OP_SeekLe || u.ba.r.flags==UNPACKED_INCRKEY );
+
      assert( u.ba.oc!=OP_SeekGe || u.ba.r.flags==0 );
+
      assert( u.ba.oc!=OP_SeekLt || u.ba.r.flags==0 );

-
      u.az.r.aMem = &aMem[pOp->p3];
+
      u.ba.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
-
      { int i; for(i=0; i<u.az.r.nField; i++) assert( memIsValid(&u.az.r.aMem[i]) ); }
+
      { int i; for(i=0; i<u.ba.r.nField; i++) assert( memIsValid(&u.ba.r.aMem[i]) ); }
#endif
-
      ExpandBlob(u.az.r.aMem);
-
      rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, &u.az.r, 0, 0, &u.az.res);
+
      ExpandBlob(u.ba.r.aMem);
+
      rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, &u.ba.r, 0, 0, &u.ba.res);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
-
      u.az.pC->rowidIsValid = 0;
+
      u.ba.pC->rowidIsValid = 0;
    }
-
    u.az.pC->deferredMoveto = 0;
-
    u.az.pC->cacheStatus = CACHE_STALE;
+
    u.ba.pC->deferredMoveto = 0;
+
    u.ba.pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
-
    if( u.az.oc>=OP_SeekGe ){  assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
-
      if( u.az.res<0 || (u.az.res==0 && u.az.oc==OP_SeekGt) ){
-
        rc = sqlite3BtreeNext(u.az.pC->pCursor, &u.az.res);
+
    if( u.ba.oc>=OP_SeekGe ){  assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
+
      if( u.ba.res<0 || (u.ba.res==0 && u.ba.oc==OP_SeekGt) ){
+
        rc = sqlite3BtreeNext(u.ba.pC->pCursor, &u.ba.res);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
-
        u.az.pC->rowidIsValid = 0;
+
        u.ba.pC->rowidIsValid = 0;
      }else{
-
        u.az.res = 0;
+
        u.ba.res = 0;
      }
    }else{
-
      assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
-
      if( u.az.res>0 || (u.az.res==0 && u.az.oc==OP_SeekLt) ){
-
        rc = sqlite3BtreePrevious(u.az.pC->pCursor, &u.az.res);
+
      assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
+
      if( u.ba.res>0 || (u.ba.res==0 && u.ba.oc==OP_SeekLt) ){
+
        rc = sqlite3BtreePrevious(u.ba.pC->pCursor, &u.ba.res);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
-
        u.az.pC->rowidIsValid = 0;
+
        u.ba.pC->rowidIsValid = 0;
      }else{
-
        /* u.az.res might be negative because the table is empty.  Check to
+
        /* u.ba.res might be negative because the table is empty.  Check to
        ** see if this is the case.
        */
-
        u.az.res = sqlite3BtreeEof(u.az.pC->pCursor);
+
        u.ba.res = sqlite3BtreeEof(u.ba.pC->pCursor);
      }
    }
    assert( pOp->p2>0 );
-
    if( u.az.res ){
+
    if( u.ba.res ){
      pc = pOp->p2 - 1;
    }
  }else{
@@ -66246,20 +67066,20 @@ case OP_SeekGt: { /* jump, in3 */
** occur, no unnecessary I/O happens.
*/
case OP_Seek: {    /* in2 */
-
#if 0  /* local variables moved into u.ba */
+
#if 0  /* local variables moved into u.bb */
  VdbeCursor *pC;
-
#endif /* local variables moved into u.ba */
+
#endif /* local variables moved into u.bb */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.ba.pC = p->apCsr[pOp->p1];
-
  assert( u.ba.pC!=0 );
-
  if( ALWAYS(u.ba.pC->pCursor!=0) ){
-
    assert( u.ba.pC->isTable );
-
    u.ba.pC->nullRow = 0;
+
  u.bb.pC = p->apCsr[pOp->p1];
+
  assert( u.bb.pC!=0 );
+
  if( ALWAYS(u.bb.pC->pCursor!=0) ){
+
    assert( u.bb.pC->isTable );
+
    u.bb.pC->nullRow = 0;
    pIn2 = &aMem[pOp->p2];
-
    u.ba.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
-
    u.ba.pC->rowidIsValid = 0;
-
    u.ba.pC->deferredMoveto = 1;
+
    u.bb.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+
    u.bb.pC->rowidIsValid = 0;
+
    u.bb.pC->deferredMoveto = 1;
  }
  break;
}
@@ -66291,62 +67111,63 @@ case OP_Seek: { /* in2 */
*/
case OP_NotFound:       /* jump, in3 */
case OP_Found: {        /* jump, in3 */
-
#if 0  /* local variables moved into u.bb */
+
#if 0  /* local variables moved into u.bc */
  int alreadyExists;
  VdbeCursor *pC;
  int res;
+
  char *pFree;
  UnpackedRecord *pIdxKey;
  UnpackedRecord r;
  char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-
#endif /* local variables moved into u.bb */
+
#endif /* local variables moved into u.bc */

#ifdef SQLITE_TEST
  sqlite3_found_count++;
#endif

-
  u.bb.alreadyExists = 0;
+
  u.bc.alreadyExists = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
-
  u.bb.pC = p->apCsr[pOp->p1];
-
  assert( u.bb.pC!=0 );
+
  u.bc.pC = p->apCsr[pOp->p1];
+
  assert( u.bc.pC!=0 );
  pIn3 = &aMem[pOp->p3];
-
  if( ALWAYS(u.bb.pC->pCursor!=0) ){
+
  if( ALWAYS(u.bc.pC->pCursor!=0) ){

-
    assert( u.bb.pC->isTable==0 );
+
    assert( u.bc.pC->isTable==0 );
    if( pOp->p4.i>0 ){
-
      u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
-
      u.bb.r.nField = (u16)pOp->p4.i;
-
      u.bb.r.aMem = pIn3;
+
      u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
+
      u.bc.r.nField = (u16)pOp->p4.i;
+
      u.bc.r.aMem = pIn3;
#ifdef SQLITE_DEBUG
-
      { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); }
+
      { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
#endif
-
      u.bb.r.flags = UNPACKED_PREFIX_MATCH;
-
      u.bb.pIdxKey = &u.bb.r;
+
      u.bc.r.flags = UNPACKED_PREFIX_MATCH;
+
      u.bc.pIdxKey = &u.bc.r;
    }else{
+
      u.bc.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+
          u.bc.pC->pKeyInfo, u.bc.aTempRec, sizeof(u.bc.aTempRec), &u.bc.pFree
+
      );
+
      if( u.bc.pIdxKey==0 ) goto no_mem;
      assert( pIn3->flags & MEM_Blob );
      assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
-
      u.bb.pIdxKey = sqlite3VdbeRecordUnpack(u.bb.pC->pKeyInfo, pIn3->n, pIn3->z,
-
                                        u.bb.aTempRec, sizeof(u.bb.aTempRec));
-
      if( u.bb.pIdxKey==0 ){
-
        goto no_mem;
-
      }
-
      u.bb.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+
      sqlite3VdbeRecordUnpack(u.bc.pC->pKeyInfo, pIn3->n, pIn3->z, u.bc.pIdxKey);
+
      u.bc.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
    }
-
    rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, u.bb.pIdxKey, 0, 0, &u.bb.res);
+
    rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, u.bc.pIdxKey, 0, 0, &u.bc.res);
    if( pOp->p4.i==0 ){
-
      sqlite3VdbeDeleteUnpackedRecord(u.bb.pIdxKey);
+
      sqlite3DbFree(db, u.bc.pFree);
    }
    if( rc!=SQLITE_OK ){
      break;
    }
-
    u.bb.alreadyExists = (u.bb.res==0);
-
    u.bb.pC->deferredMoveto = 0;
-
    u.bb.pC->cacheStatus = CACHE_STALE;
+
    u.bc.alreadyExists = (u.bc.res==0);
+
    u.bc.pC->deferredMoveto = 0;
+
    u.bc.pC->cacheStatus = CACHE_STALE;
  }
  if( pOp->opcode==OP_Found ){
-
    if( u.bb.alreadyExists ) pc = pOp->p2 - 1;
+
    if( u.bc.alreadyExists ) pc = pOp->p2 - 1;
  }else{
-
    if( !u.bb.alreadyExists ) pc = pOp->p2 - 1;
+
    if( !u.bc.alreadyExists ) pc = pOp->p2 - 1;
  }
  break;
}
@@ -66378,7 +67199,7 @@ case OP_Found: { /* jump, in3 */
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: {        /* jump, in3 */
-
#if 0  /* local variables moved into u.bc */
+
#if 0  /* local variables moved into u.bd */
  u16 ii;
  VdbeCursor *pCx;
  BtCursor *pCrsr;
@@ -66386,55 +67207,55 @@ case OP_IsUnique: { /* jump, in3 */
  Mem *aMx;
  UnpackedRecord r;                  /* B-Tree index search key */
  i64 R;                             /* Rowid stored in register P3 */
-
#endif /* local variables moved into u.bc */
+
#endif /* local variables moved into u.bd */

  pIn3 = &aMem[pOp->p3];
-
  u.bc.aMx = &aMem[pOp->p4.i];
+
  u.bd.aMx = &aMem[pOp->p4.i];
  /* Assert that the values of parameters P1 and P4 are in range. */
  assert( pOp->p4type==P4_INT32 );
  assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );

  /* Find the index cursor. */
-
  u.bc.pCx = p->apCsr[pOp->p1];
-
  assert( u.bc.pCx->deferredMoveto==0 );
-
  u.bc.pCx->seekResult = 0;
-
  u.bc.pCx->cacheStatus = CACHE_STALE;
-
  u.bc.pCrsr = u.bc.pCx->pCursor;
+
  u.bd.pCx = p->apCsr[pOp->p1];
+
  assert( u.bd.pCx->deferredMoveto==0 );
+
  u.bd.pCx->seekResult = 0;
+
  u.bd.pCx->cacheStatus = CACHE_STALE;
+
  u.bd.pCrsr = u.bd.pCx->pCursor;

  /* If any of the values are NULL, take the jump. */
-
  u.bc.nField = u.bc.pCx->pKeyInfo->nField;
-
  for(u.bc.ii=0; u.bc.ii<u.bc.nField; u.bc.ii++){
-
    if( u.bc.aMx[u.bc.ii].flags & MEM_Null ){
+
  u.bd.nField = u.bd.pCx->pKeyInfo->nField;
+
  for(u.bd.ii=0; u.bd.ii<u.bd.nField; u.bd.ii++){
+
    if( u.bd.aMx[u.bd.ii].flags & MEM_Null ){
      pc = pOp->p2 - 1;
-
      u.bc.pCrsr = 0;
+
      u.bd.pCrsr = 0;
      break;
    }
  }
-
  assert( (u.bc.aMx[u.bc.nField].flags & MEM_Null)==0 );
+
  assert( (u.bd.aMx[u.bd.nField].flags & MEM_Null)==0 );

-
  if( u.bc.pCrsr!=0 ){
+
  if( u.bd.pCrsr!=0 ){
    /* Populate the index search key. */
-
    u.bc.r.pKeyInfo = u.bc.pCx->pKeyInfo;
-
    u.bc.r.nField = u.bc.nField + 1;
-
    u.bc.r.flags = UNPACKED_PREFIX_SEARCH;
-
    u.bc.r.aMem = u.bc.aMx;
+
    u.bd.r.pKeyInfo = u.bd.pCx->pKeyInfo;
+
    u.bd.r.nField = u.bd.nField + 1;
+
    u.bd.r.flags = UNPACKED_PREFIX_SEARCH;
+
    u.bd.r.aMem = u.bd.aMx;
#ifdef SQLITE_DEBUG
-
    { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
+
    { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
#endif

-
    /* Extract the value of u.bc.R from register P3. */
+
    /* Extract the value of u.bd.R from register P3. */
    sqlite3VdbeMemIntegerify(pIn3);
-
    u.bc.R = pIn3->u.i;
+
    u.bd.R = pIn3->u.i;

    /* Search the B-Tree index. If no conflicting record is found, jump
    ** to P2. Otherwise, copy the rowid of the conflicting record to
    ** register P3 and fall through to the next instruction.  */
-
    rc = sqlite3BtreeMovetoUnpacked(u.bc.pCrsr, &u.bc.r, 0, 0, &u.bc.pCx->seekResult);
-
    if( (u.bc.r.flags & UNPACKED_PREFIX_SEARCH) || u.bc.r.rowid==u.bc.R ){
+
    rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, &u.bd.r, 0, 0, &u.bd.pCx->seekResult);
+
    if( (u.bd.r.flags & UNPACKED_PREFIX_SEARCH) || u.bd.r.rowid==u.bd.R ){
      pc = pOp->p2 - 1;
    }else{
-
      pIn3->u.i = u.bc.r.rowid;
+
      pIn3->u.i = u.bd.r.rowid;
    }
  }
  break;
@@ -66455,42 +67276,42 @@ case OP_IsUnique: { /* jump, in3 */
** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: {        /* jump, in3 */
-
#if 0  /* local variables moved into u.bd */
+
#if 0  /* local variables moved into u.be */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  u64 iKey;
-
#endif /* local variables moved into u.bd */
+
#endif /* local variables moved into u.be */

  pIn3 = &aMem[pOp->p3];
  assert( pIn3->flags & MEM_Int );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bd.pC = p->apCsr[pOp->p1];
-
  assert( u.bd.pC!=0 );
-
  assert( u.bd.pC->isTable );
-
  assert( u.bd.pC->pseudoTableReg==0 );
-
  u.bd.pCrsr = u.bd.pC->pCursor;
-
  if( u.bd.pCrsr!=0 ){
-
    u.bd.res = 0;
-
    u.bd.iKey = pIn3->u.i;
-
    rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
-
    u.bd.pC->lastRowid = pIn3->u.i;
-
    u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
-
    u.bd.pC->nullRow = 0;
-
    u.bd.pC->cacheStatus = CACHE_STALE;
-
    u.bd.pC->deferredMoveto = 0;
-
    if( u.bd.res!=0 ){
+
  u.be.pC = p->apCsr[pOp->p1];
+
  assert( u.be.pC!=0 );
+
  assert( u.be.pC->isTable );
+
  assert( u.be.pC->pseudoTableReg==0 );
+
  u.be.pCrsr = u.be.pC->pCursor;
+
  if( ALWAYS(u.be.pCrsr!=0) ){
+
    u.be.res = 0;
+
    u.be.iKey = pIn3->u.i;
+
    rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, 0, u.be.iKey, 0, &u.be.res);
+
    u.be.pC->lastRowid = pIn3->u.i;
+
    u.be.pC->rowidIsValid = u.be.res==0 ?1:0;
+
    u.be.pC->nullRow = 0;
+
    u.be.pC->cacheStatus = CACHE_STALE;
+
    u.be.pC->deferredMoveto = 0;
+
    if( u.be.res!=0 ){
      pc = pOp->p2 - 1;
-
      assert( u.bd.pC->rowidIsValid==0 );
+
      assert( u.be.pC->rowidIsValid==0 );
    }
-
    u.bd.pC->seekResult = u.bd.res;
+
    u.be.pC->seekResult = u.be.res;
  }else{
    /* This happens when an attempt to open a read cursor on the
    ** sqlite_master table returns SQLITE_EMPTY.
    */
    pc = pOp->p2 - 1;
-
    assert( u.bd.pC->rowidIsValid==0 );
-
    u.bd.pC->seekResult = 0;
+
    assert( u.be.pC->rowidIsValid==0 );
+
    u.be.pC->seekResult = 0;
  }
  break;
}
@@ -66525,21 +67346,21 @@ case OP_Sequence: { /* out2-prerelease */
** AUTOINCREMENT feature.
*/
case OP_NewRowid: {           /* out2-prerelease */
-
#if 0  /* local variables moved into u.be */
+
#if 0  /* local variables moved into u.bf */
  i64 v;                 /* The new rowid */
  VdbeCursor *pC;        /* Cursor of table to get the new rowid */
  int res;               /* Result of an sqlite3BtreeLast() */
  int cnt;               /* Counter to limit the number of searches */
  Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
  VdbeFrame *pFrame;     /* Root frame of VDBE */
-
#endif /* local variables moved into u.be */
+
#endif /* local variables moved into u.bf */

-
  u.be.v = 0;
-
  u.be.res = 0;
+
  u.bf.v = 0;
+
  u.bf.res = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.be.pC = p->apCsr[pOp->p1];
-
  assert( u.be.pC!=0 );
-
  if( NEVER(u.be.pC->pCursor==0) ){
+
  u.bf.pC = p->apCsr[pOp->p1];
+
  assert( u.bf.pC!=0 );
+
  if( NEVER(u.bf.pC->pCursor==0) ){
    /* The zero initialization above is all that is needed */
  }else{
    /* The next rowid or record number (different terms for the same
@@ -66555,7 +67376,7 @@ case OP_NewRowid: { /* out2-prerelease */
    ** succeeded.  If the random rowid does exist, we select a new one
    ** and try again, up to 100 times.
    */
-
    assert( u.be.pC->isTable );
+
    assert( u.bf.pC->isTable );

#ifdef SQLITE_32BIT_ROWID
#   define MAX_ROWID 0x7fffffff
@@ -66567,23 +67388,23 @@ case OP_NewRowid: { /* out2-prerelease */
#   define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif

-
    if( !u.be.pC->useRandomRowid ){
-
      u.be.v = sqlite3BtreeGetCachedRowid(u.be.pC->pCursor);
-
      if( u.be.v==0 ){
-
        rc = sqlite3BtreeLast(u.be.pC->pCursor, &u.be.res);
+
    if( !u.bf.pC->useRandomRowid ){
+
      u.bf.v = sqlite3BtreeGetCachedRowid(u.bf.pC->pCursor);
+
      if( u.bf.v==0 ){
+
        rc = sqlite3BtreeLast(u.bf.pC->pCursor, &u.bf.res);
        if( rc!=SQLITE_OK ){
          goto abort_due_to_error;
        }
-
        if( u.be.res ){
-
          u.be.v = 1;   /* IMP: R-61914-48074 */
+
        if( u.bf.res ){
+
          u.bf.v = 1;   /* IMP: R-61914-48074 */
        }else{
-
          assert( sqlite3BtreeCursorIsValid(u.be.pC->pCursor) );
-
          rc = sqlite3BtreeKeySize(u.be.pC->pCursor, &u.be.v);
+
          assert( sqlite3BtreeCursorIsValid(u.bf.pC->pCursor) );
+
          rc = sqlite3BtreeKeySize(u.bf.pC->pCursor, &u.bf.v);
          assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
-
          if( u.be.v==MAX_ROWID ){
-
            u.be.pC->useRandomRowid = 1;
+
          if( u.bf.v==MAX_ROWID ){
+
            u.bf.pC->useRandomRowid = 1;
          }else{
-
            u.be.v++;   /* IMP: R-29538-34987 */
+
            u.bf.v++;   /* IMP: R-29538-34987 */
          }
        }
      }
@@ -66593,35 +67414,35 @@ case OP_NewRowid: { /* out2-prerelease */
        /* Assert that P3 is a valid memory cell. */
        assert( pOp->p3>0 );
        if( p->pFrame ){
-
          for(u.be.pFrame=p->pFrame; u.be.pFrame->pParent; u.be.pFrame=u.be.pFrame->pParent);
+
          for(u.bf.pFrame=p->pFrame; u.bf.pFrame->pParent; u.bf.pFrame=u.bf.pFrame->pParent);
          /* Assert that P3 is a valid memory cell. */
-
          assert( pOp->p3<=u.be.pFrame->nMem );
-
          u.be.pMem = &u.be.pFrame->aMem[pOp->p3];
+
          assert( pOp->p3<=u.bf.pFrame->nMem );
+
          u.bf.pMem = &u.bf.pFrame->aMem[pOp->p3];
        }else{
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=p->nMem );
-
          u.be.pMem = &aMem[pOp->p3];
-
          memAboutToChange(p, u.be.pMem);
+
          u.bf.pMem = &aMem[pOp->p3];
+
          memAboutToChange(p, u.bf.pMem);
        }
-
        assert( memIsValid(u.be.pMem) );
+
        assert( memIsValid(u.bf.pMem) );

-
        REGISTER_TRACE(pOp->p3, u.be.pMem);
-
        sqlite3VdbeMemIntegerify(u.be.pMem);
-
        assert( (u.be.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
-
        if( u.be.pMem->u.i==MAX_ROWID || u.be.pC->useRandomRowid ){
+
        REGISTER_TRACE(pOp->p3, u.bf.pMem);
+
        sqlite3VdbeMemIntegerify(u.bf.pMem);
+
        assert( (u.bf.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
+
        if( u.bf.pMem->u.i==MAX_ROWID || u.bf.pC->useRandomRowid ){
          rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
          goto abort_due_to_error;
        }
-
        if( u.be.v<u.be.pMem->u.i+1 ){
-
          u.be.v = u.be.pMem->u.i + 1;
+
        if( u.bf.v<u.bf.pMem->u.i+1 ){
+
          u.bf.v = u.bf.pMem->u.i + 1;
        }
-
        u.be.pMem->u.i = u.be.v;
+
        u.bf.pMem->u.i = u.bf.v;
      }
#endif

-
      sqlite3BtreeSetCachedRowid(u.be.pC->pCursor, u.be.v<MAX_ROWID ? u.be.v+1 : 0);
+
      sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, u.bf.v<MAX_ROWID ? u.bf.v+1 : 0);
    }
-
    if( u.be.pC->useRandomRowid ){
+
    if( u.bf.pC->useRandomRowid ){
      /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
      ** largest possible integer (9223372036854775807) then the database
      ** engine starts picking positive candidate ROWIDs at random until
@@ -66629,35 +67450,35 @@ case OP_NewRowid: { /* out2-prerelease */
      assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                             ** an AUTOINCREMENT table. */
      /* on the first attempt, simply do one more than previous */
-
      u.be.v = lastRowid;
-
      u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
-
      u.be.v++; /* ensure non-zero */
-
      u.be.cnt = 0;
-
      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
-
                                                 0, &u.be.res))==SQLITE_OK)
-
            && (u.be.res==0)
-
            && (++u.be.cnt<100)){
+
      u.bf.v = lastRowid;
+
      u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+
      u.bf.v++; /* ensure non-zero */
+
      u.bf.cnt = 0;
+
      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, 0, (u64)u.bf.v,
+
                                                 0, &u.bf.res))==SQLITE_OK)
+
            && (u.bf.res==0)
+
            && (++u.bf.cnt<100)){
        /* collision - try another random rowid */
-
        sqlite3_randomness(sizeof(u.be.v), &u.be.v);
-
        if( u.be.cnt<5 ){
+
        sqlite3_randomness(sizeof(u.bf.v), &u.bf.v);
+
        if( u.bf.cnt<5 ){
          /* try "small" random rowids for the initial attempts */
-
          u.be.v &= 0xffffff;
+
          u.bf.v &= 0xffffff;
        }else{
-
          u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+
          u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
        }
-
        u.be.v++; /* ensure non-zero */
+
        u.bf.v++; /* ensure non-zero */
      }
-
      if( rc==SQLITE_OK && u.be.res==0 ){
+
      if( rc==SQLITE_OK && u.bf.res==0 ){
        rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
        goto abort_due_to_error;
      }
-
      assert( u.be.v>0 );  /* EV: R-40812-03570 */
+
      assert( u.bf.v>0 );  /* EV: R-40812-03570 */
    }
-
    u.be.pC->rowidIsValid = 0;
-
    u.be.pC->deferredMoveto = 0;
-
    u.be.pC->cacheStatus = CACHE_STALE;
+
    u.bf.pC->rowidIsValid = 0;
+
    u.bf.pC->deferredMoveto = 0;
+
    u.bf.pC->cacheStatus = CACHE_STALE;
  }
-
  pOut->u.i = u.be.v;
+
  pOut->u.i = u.bf.v;
  break;
}

@@ -66707,7 +67528,7 @@ case OP_NewRowid: { /* out2-prerelease */
*/
case OP_Insert: 
case OP_InsertInt: {
-
#if 0  /* local variables moved into u.bf */
+
#if 0  /* local variables moved into u.bg */
  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  i64 iKey;         /* The integer ROWID or key for the record to be inserted */
@@ -66717,60 +67538,60 @@ case OP_InsertInt: {
  const char *zDb;  /* database name - used by the update hook */
  const char *zTbl; /* Table name - used by the opdate hook */
  int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-
#endif /* local variables moved into u.bf */
+
#endif /* local variables moved into u.bg */

-
  u.bf.pData = &aMem[pOp->p2];
+
  u.bg.pData = &aMem[pOp->p2];
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  assert( memIsValid(u.bf.pData) );
-
  u.bf.pC = p->apCsr[pOp->p1];
-
  assert( u.bf.pC!=0 );
-
  assert( u.bf.pC->pCursor!=0 );
-
  assert( u.bf.pC->pseudoTableReg==0 );
-
  assert( u.bf.pC->isTable );
-
  REGISTER_TRACE(pOp->p2, u.bf.pData);
+
  assert( memIsValid(u.bg.pData) );
+
  u.bg.pC = p->apCsr[pOp->p1];
+
  assert( u.bg.pC!=0 );
+
  assert( u.bg.pC->pCursor!=0 );
+
  assert( u.bg.pC->pseudoTableReg==0 );
+
  assert( u.bg.pC->isTable );
+
  REGISTER_TRACE(pOp->p2, u.bg.pData);

  if( pOp->opcode==OP_Insert ){
-
    u.bf.pKey = &aMem[pOp->p3];
-
    assert( u.bf.pKey->flags & MEM_Int );
-
    assert( memIsValid(u.bf.pKey) );
-
    REGISTER_TRACE(pOp->p3, u.bf.pKey);
-
    u.bf.iKey = u.bf.pKey->u.i;
+
    u.bg.pKey = &aMem[pOp->p3];
+
    assert( u.bg.pKey->flags & MEM_Int );
+
    assert( memIsValid(u.bg.pKey) );
+
    REGISTER_TRACE(pOp->p3, u.bg.pKey);
+
    u.bg.iKey = u.bg.pKey->u.i;
  }else{
    assert( pOp->opcode==OP_InsertInt );
-
    u.bf.iKey = pOp->p3;
+
    u.bg.iKey = pOp->p3;
  }

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
-
  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;
+
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bg.iKey;
+
  if( u.bg.pData->flags & MEM_Null ){
+
    u.bg.pData->z = 0;
+
    u.bg.pData->n = 0;
  }else{
-
    assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
+
    assert( u.bg.pData->flags & (MEM_Blob|MEM_Str) );
  }
-
  u.bf.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bf.pC->seekResult : 0);
-
  if( u.bf.pData->flags & MEM_Zero ){
-
    u.bf.nZero = u.bf.pData->u.nZero;
+
  u.bg.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bg.pC->seekResult : 0);
+
  if( u.bg.pData->flags & MEM_Zero ){
+
    u.bg.nZero = u.bg.pData->u.nZero;
  }else{
-
    u.bf.nZero = 0;
+
    u.bg.nZero = 0;
  }
-
  sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, 0);
-
  rc = sqlite3BtreeInsert(u.bf.pC->pCursor, 0, u.bf.iKey,
-
                          u.bf.pData->z, u.bf.pData->n, u.bf.nZero,
-
                          pOp->p5 & OPFLAG_APPEND, u.bf.seekResult
+
  sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
+
  rc = sqlite3BtreeInsert(u.bg.pC->pCursor, 0, u.bg.iKey,
+
                          u.bg.pData->z, u.bg.pData->n, u.bg.nZero,
+
                          pOp->p5 & OPFLAG_APPEND, u.bg.seekResult
  );
-
  u.bf.pC->rowidIsValid = 0;
-
  u.bf.pC->deferredMoveto = 0;
-
  u.bf.pC->cacheStatus = CACHE_STALE;
+
  u.bg.pC->rowidIsValid = 0;
+
  u.bg.pC->deferredMoveto = 0;
+
  u.bg.pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-
    u.bf.zDb = db->aDb[u.bf.pC->iDb].zName;
-
    u.bf.zTbl = pOp->p4.z;
-
    u.bf.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
-
    assert( u.bf.pC->isTable );
-
    db->xUpdateCallback(db->pUpdateArg, u.bf.op, u.bf.zDb, u.bf.zTbl, u.bf.iKey);
-
    assert( u.bf.pC->iDb>=0 );
+
    u.bg.zDb = db->aDb[u.bg.pC->iDb].zName;
+
    u.bg.zTbl = pOp->p4.z;
+
    u.bg.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+
    assert( u.bg.pC->isTable );
+
    db->xUpdateCallback(db->pUpdateArg, u.bg.op, u.bg.zDb, u.bg.zTbl, u.bg.iKey);
+
    assert( u.bg.pC->iDb>=0 );
  }
  break;
}
@@ -66796,47 +67617,47 @@ case OP_InsertInt: {
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
-
#if 0  /* local variables moved into u.bg */
+
#if 0  /* local variables moved into u.bh */
  i64 iKey;
  VdbeCursor *pC;
-
#endif /* local variables moved into u.bg */
+
#endif /* local variables moved into u.bh */

-
  u.bg.iKey = 0;
+
  u.bh.iKey = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bg.pC = p->apCsr[pOp->p1];
-
  assert( u.bg.pC!=0 );
-
  assert( u.bg.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
+
  u.bh.pC = p->apCsr[pOp->p1];
+
  assert( u.bh.pC!=0 );
+
  assert( u.bh.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */

-
  /* If the update-hook will be invoked, set u.bg.iKey to the rowid of the
+
  /* If the update-hook will be invoked, set u.bh.iKey to the rowid of the
  ** row being deleted.
  */
  if( db->xUpdateCallback && pOp->p4.z ){
-
    assert( u.bg.pC->isTable );
-
    assert( u.bg.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
-
    u.bg.iKey = u.bg.pC->lastRowid;
+
    assert( u.bh.pC->isTable );
+
    assert( u.bh.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
+
    u.bh.iKey = u.bh.pC->lastRowid;
  }

  /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
  ** OP_Column on the same table without any intervening operations that
-
  ** might move or invalidate the cursor.  Hence cursor u.bg.pC is always pointing
+
  ** might move or invalidate the cursor.  Hence cursor u.bh.pC is always pointing
  ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
  ** below is always a no-op and cannot fail.  We will run it anyhow, though,
  ** to guard against future changes to the code generator.
  **/
-
  assert( u.bg.pC->deferredMoveto==0 );
-
  rc = sqlite3VdbeCursorMoveto(u.bg.pC);
+
  assert( u.bh.pC->deferredMoveto==0 );
+
  rc = sqlite3VdbeCursorMoveto(u.bh.pC);
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;

-
  sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
-
  rc = sqlite3BtreeDelete(u.bg.pC->pCursor);
-
  u.bg.pC->cacheStatus = CACHE_STALE;
+
  sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
+
  rc = sqlite3BtreeDelete(u.bh.pC->pCursor);
+
  u.bh.pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-
    const char *zDb = db->aDb[u.bg.pC->iDb].zName;
+
    const char *zDb = db->aDb[u.bh.pC->iDb].zName;
    const char *zTbl = pOp->p4.z;
-
    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bg.iKey);
-
    assert( u.bg.pC->iDb>=0 );
+
    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bh.iKey);
+
    assert( u.bh.pC->iDb>=0 );
  }
  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  break;
@@ -66854,6 +67675,49 @@ case OP_ResetCount: {
  break;
}

+
/* Opcode: SorterCompare P1 P2 P3
+
**
+
** P1 is a sorter cursor. This instruction compares the record blob in 
+
** register P3 with the entry that the sorter cursor currently points to.
+
** If, excluding the rowid fields at the end, the two records are a match,
+
** fall through to the next instruction. Otherwise, jump to instruction P2.
+
*/
+
case OP_SorterCompare: {
+
#if 0  /* local variables moved into u.bi */
+
  VdbeCursor *pC;
+
  int res;
+
#endif /* local variables moved into u.bi */
+

+
  u.bi.pC = p->apCsr[pOp->p1];
+
  assert( isSorter(u.bi.pC) );
+
  pIn3 = &aMem[pOp->p3];
+
  rc = sqlite3VdbeSorterCompare(u.bi.pC, pIn3, &u.bi.res);
+
  if( u.bi.res ){
+
    pc = pOp->p2-1;
+
  }
+
  break;
+
};
+

+
/* Opcode: SorterData P1 P2 * * *
+
**
+
** Write into register P2 the current sorter data for sorter cursor P1.
+
*/
+
case OP_SorterData: {
+
#if 0  /* local variables moved into u.bj */
+
  VdbeCursor *pC;
+
#endif /* local variables moved into u.bj */
+
#ifndef SQLITE_OMIT_MERGE_SORT
+
  pOut = &aMem[pOp->p2];
+
  u.bj.pC = p->apCsr[pOp->p1];
+
  assert( u.bj.pC->isSorter );
+
  rc = sqlite3VdbeSorterRowkey(u.bj.pC, pOut);
+
#else
+
  pOp->opcode = OP_RowKey;
+
  pc--;
+
#endif
+
  break;
+
}
+

/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
@@ -66876,61 +67740,63 @@ case OP_ResetCount: {
*/
case OP_RowKey:
case OP_RowData: {
-
#if 0  /* local variables moved into u.bh */
+
#if 0  /* local variables moved into u.bk */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  u32 n;
  i64 n64;
-
#endif /* local variables moved into u.bh */
+
#endif /* local variables moved into u.bk */

  pOut = &aMem[pOp->p2];
  memAboutToChange(p, pOut);

  /* Note that RowKey and RowData are really exactly the same instruction */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bh.pC = p->apCsr[pOp->p1];
-
  assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
-
  assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
-
  assert( u.bh.pC!=0 );
-
  assert( u.bh.pC->nullRow==0 );
-
  assert( u.bh.pC->pseudoTableReg==0 );
-
  assert( u.bh.pC->pCursor!=0 );
-
  u.bh.pCrsr = u.bh.pC->pCursor;
-
  assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );
+
  u.bk.pC = p->apCsr[pOp->p1];
+
  assert( u.bk.pC->isSorter==0 );
+
  assert( u.bk.pC->isTable || pOp->opcode!=OP_RowData );
+
  assert( u.bk.pC->isIndex || pOp->opcode==OP_RowData );
+
  assert( u.bk.pC!=0 );
+
  assert( u.bk.pC->nullRow==0 );
+
  assert( u.bk.pC->pseudoTableReg==0 );
+
  assert( !u.bk.pC->isSorter );
+
  assert( u.bk.pC->pCursor!=0 );
+
  u.bk.pCrsr = u.bk.pC->pCursor;
+
  assert( sqlite3BtreeCursorIsValid(u.bk.pCrsr) );

  /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
  ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
  ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
  ** a no-op and can never fail.  But we leave it in place as a safety.
  */
-
  assert( u.bh.pC->deferredMoveto==0 );
-
  rc = sqlite3VdbeCursorMoveto(u.bh.pC);
+
  assert( u.bk.pC->deferredMoveto==0 );
+
  rc = sqlite3VdbeCursorMoveto(u.bk.pC);
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;

-
  if( u.bh.pC->isIndex ){
-
    assert( !u.bh.pC->isTable );
-
    rc = sqlite3BtreeKeySize(u.bh.pCrsr, &u.bh.n64);
+
  if( u.bk.pC->isIndex ){
+
    assert( !u.bk.pC->isTable );
+
    rc = sqlite3BtreeKeySize(u.bk.pCrsr, &u.bk.n64);
    assert( rc==SQLITE_OK );    /* True because of CursorMoveto() call above */
-
    if( u.bh.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+
    if( u.bk.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
-
    u.bh.n = (u32)u.bh.n64;
+
    u.bk.n = (u32)u.bk.n64;
  }else{
-
    rc = sqlite3BtreeDataSize(u.bh.pCrsr, &u.bh.n);
+
    rc = sqlite3BtreeDataSize(u.bk.pCrsr, &u.bk.n);
    assert( rc==SQLITE_OK );    /* DataSize() cannot fail */
-
    if( u.bh.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+
    if( u.bk.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
  }
-
  if( sqlite3VdbeMemGrow(pOut, u.bh.n, 0) ){
+
  if( sqlite3VdbeMemGrow(pOut, u.bk.n, 0) ){
    goto no_mem;
  }
-
  pOut->n = u.bh.n;
+
  pOut->n = u.bk.n;
  MemSetTypeFlag(pOut, MEM_Blob);
-
  if( u.bh.pC->isIndex ){
-
    rc = sqlite3BtreeKey(u.bh.pCrsr, 0, u.bh.n, pOut->z);
+
  if( u.bk.pC->isIndex ){
+
    rc = sqlite3BtreeKey(u.bk.pCrsr, 0, u.bk.n, pOut->z);
  }else{
-
    rc = sqlite3BtreeData(u.bh.pCrsr, 0, u.bh.n, pOut->z);
+
    rc = sqlite3BtreeData(u.bk.pCrsr, 0, u.bk.n, pOut->z);
  }
  pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);
@@ -66947,42 +67813,42 @@ case OP_RowData: {
** one opcode now works for both table types.
*/
case OP_Rowid: {                 /* out2-prerelease */
-
#if 0  /* local variables moved into u.bi */
+
#if 0  /* local variables moved into u.bl */
  VdbeCursor *pC;
  i64 v;
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
-
#endif /* local variables moved into u.bi */
+
#endif /* local variables moved into u.bl */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bi.pC = p->apCsr[pOp->p1];
-
  assert( u.bi.pC!=0 );
-
  assert( u.bi.pC->pseudoTableReg==0 );
-
  if( u.bi.pC->nullRow ){
+
  u.bl.pC = p->apCsr[pOp->p1];
+
  assert( u.bl.pC!=0 );
+
  assert( u.bl.pC->pseudoTableReg==0 );
+
  if( u.bl.pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
-
  }else if( u.bi.pC->deferredMoveto ){
-
    u.bi.v = u.bi.pC->movetoTarget;
+
  }else if( u.bl.pC->deferredMoveto ){
+
    u.bl.v = u.bl.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
  }else if( u.bi.pC->pVtabCursor ){
-
    u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab;
-
    u.bi.pModule = u.bi.pVtab->pModule;
-
    assert( u.bi.pModule->xRowid );
-
    rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v);
-
    importVtabErrMsg(p, u.bi.pVtab);
+
  }else if( u.bl.pC->pVtabCursor ){
+
    u.bl.pVtab = u.bl.pC->pVtabCursor->pVtab;
+
    u.bl.pModule = u.bl.pVtab->pModule;
+
    assert( u.bl.pModule->xRowid );
+
    rc = u.bl.pModule->xRowid(u.bl.pC->pVtabCursor, &u.bl.v);
+
    importVtabErrMsg(p, u.bl.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
  }else{
-
    assert( u.bi.pC->pCursor!=0 );
-
    rc = sqlite3VdbeCursorMoveto(u.bi.pC);
+
    assert( u.bl.pC->pCursor!=0 );
+
    rc = sqlite3VdbeCursorMoveto(u.bl.pC);
    if( rc ) goto abort_due_to_error;
-
    if( u.bi.pC->rowidIsValid ){
-
      u.bi.v = u.bi.pC->lastRowid;
+
    if( u.bl.pC->rowidIsValid ){
+
      u.bl.v = u.bl.pC->lastRowid;
    }else{
-
      rc = sqlite3BtreeKeySize(u.bi.pC->pCursor, &u.bi.v);
+
      rc = sqlite3BtreeKeySize(u.bl.pC->pCursor, &u.bl.v);
      assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
    }
  }
-
  pOut->u.i = u.bi.v;
+
  pOut->u.i = u.bl.v;
  break;
}

@@ -66993,17 +67859,18 @@ case OP_Rowid: { /* out2-prerelease */
** write a NULL.
*/
case OP_NullRow: {
-
#if 0  /* local variables moved into u.bj */
+
#if 0  /* local variables moved into u.bm */
  VdbeCursor *pC;
-
#endif /* local variables moved into u.bj */
+
#endif /* local variables moved into u.bm */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bj.pC = p->apCsr[pOp->p1];
-
  assert( u.bj.pC!=0 );
-
  u.bj.pC->nullRow = 1;
-
  u.bj.pC->rowidIsValid = 0;
-
  if( u.bj.pC->pCursor ){
-
    sqlite3BtreeClearCursor(u.bj.pC->pCursor);
+
  u.bm.pC = p->apCsr[pOp->p1];
+
  assert( u.bm.pC!=0 );
+
  u.bm.pC->nullRow = 1;
+
  u.bm.pC->rowidIsValid = 0;
+
  assert( u.bm.pC->pCursor || u.bm.pC->pVtabCursor );
+
  if( u.bm.pC->pCursor ){
+
    sqlite3BtreeClearCursor(u.bm.pC->pCursor);
  }
  break;
}
@@ -67017,26 +67884,26 @@ case OP_NullRow: {
** to the following instruction.
*/
case OP_Last: {        /* jump */
-
#if 0  /* local variables moved into u.bk */
+
#if 0  /* local variables moved into u.bn */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
-
#endif /* local variables moved into u.bk */
+
#endif /* local variables moved into u.bn */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bk.pC = p->apCsr[pOp->p1];
-
  assert( u.bk.pC!=0 );
-
  u.bk.pCrsr = u.bk.pC->pCursor;
-
  if( u.bk.pCrsr==0 ){
-
    u.bk.res = 1;
+
  u.bn.pC = p->apCsr[pOp->p1];
+
  assert( u.bn.pC!=0 );
+
  u.bn.pCrsr = u.bn.pC->pCursor;
+
  if( NEVER(u.bn.pCrsr==0) ){
+
    u.bn.res = 1;
  }else{
-
    rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
+
    rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
  }
-
  u.bk.pC->nullRow = (u8)u.bk.res;
-
  u.bk.pC->deferredMoveto = 0;
-
  u.bk.pC->rowidIsValid = 0;
-
  u.bk.pC->cacheStatus = CACHE_STALE;
-
  if( pOp->p2>0 && u.bk.res ){
+
  u.bn.pC->nullRow = (u8)u.bn.res;
+
  u.bn.pC->deferredMoveto = 0;
+
  u.bn.pC->rowidIsValid = 0;
+
  u.bn.pC->cacheStatus = CACHE_STALE;
+
  if( pOp->p2>0 && u.bn.res ){
    pc = pOp->p2 - 1;
  }
  break;
@@ -67055,6 +67922,10 @@ case OP_Last: { /* jump */
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/
+
case OP_SorterSort:    /* jump */
+
#ifdef SQLITE_OMIT_MERGE_SORT
+
  pOp->opcode = OP_Sort;
+
#endif
case OP_Sort: {        /* jump */
#ifdef SQLITE_TEST
  sqlite3_sort_count++;
@@ -67072,32 +67943,37 @@ case OP_Sort: { /* jump */
** to the following instruction.
*/
case OP_Rewind: {        /* jump */
-
#if 0  /* local variables moved into u.bl */
+
#if 0  /* local variables moved into u.bo */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
-
#endif /* local variables moved into u.bl */
+
#endif /* local variables moved into u.bo */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bl.pC = p->apCsr[pOp->p1];
-
  assert( u.bl.pC!=0 );
-
  u.bl.res = 1;
-
  if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){
-
    rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
-
    u.bl.pC->atFirst = u.bl.res==0 ?1:0;
-
    u.bl.pC->deferredMoveto = 0;
-
    u.bl.pC->cacheStatus = CACHE_STALE;
-
    u.bl.pC->rowidIsValid = 0;
-
  }
-
  u.bl.pC->nullRow = (u8)u.bl.res;
+
  u.bo.pC = p->apCsr[pOp->p1];
+
  assert( u.bo.pC!=0 );
+
  assert( u.bo.pC->isSorter==(pOp->opcode==OP_SorterSort) );
+
  u.bo.res = 1;
+
  if( isSorter(u.bo.pC) ){
+
    rc = sqlite3VdbeSorterRewind(db, u.bo.pC, &u.bo.res);
+
  }else{
+
    u.bo.pCrsr = u.bo.pC->pCursor;
+
    assert( u.bo.pCrsr );
+
    rc = sqlite3BtreeFirst(u.bo.pCrsr, &u.bo.res);
+
    u.bo.pC->atFirst = u.bo.res==0 ?1:0;
+
    u.bo.pC->deferredMoveto = 0;
+
    u.bo.pC->cacheStatus = CACHE_STALE;
+
    u.bo.pC->rowidIsValid = 0;
+
  }
+
  u.bo.pC->nullRow = (u8)u.bo.res;
  assert( pOp->p2>0 && pOp->p2<p->nOp );
-
  if( u.bl.res ){
+
  if( u.bo.res ){
    pc = pOp->p2 - 1;
  }
  break;
}

-
/* Opcode: Next P1 P2 * * P5
+
/* Opcode: Next P1 P2 * P4 P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index.  If there are no more key/value pairs then fall through
@@ -67106,6 +67982,9 @@ case OP_Rewind: { /* jump */
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
+
** P4 is always of type P4_ADVANCE. The function pointer points to
+
** sqlite3BtreeNext().
+
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
@@ -67120,43 +67999,52 @@ case OP_Rewind: { /* jump */
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
+
** P4 is always of type P4_ADVANCE. The function pointer points to
+
** sqlite3BtreePrevious().
+
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
+
case OP_SorterNext:    /* jump */
+
#ifdef SQLITE_OMIT_MERGE_SORT
+
  pOp->opcode = OP_Next;
+
#endif
case OP_Prev:          /* jump */
case OP_Next: {        /* jump */
-
#if 0  /* local variables moved into u.bm */
+
#if 0  /* local variables moved into u.bp */
  VdbeCursor *pC;
-
  BtCursor *pCrsr;
  int res;
-
#endif /* local variables moved into u.bm */
+
#endif /* local variables moved into u.bp */

  CHECK_FOR_INTERRUPT;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5<=ArraySize(p->aCounter) );
-
  u.bm.pC = p->apCsr[pOp->p1];
-
  if( u.bm.pC==0 ){
+
  u.bp.pC = p->apCsr[pOp->p1];
+
  if( u.bp.pC==0 ){
    break;  /* See ticket #2273 */
  }
-
  u.bm.pCrsr = u.bm.pC->pCursor;
-
  if( u.bm.pCrsr==0 ){
-
    u.bm.pC->nullRow = 1;
-
    break;
-
  }
-
  u.bm.res = 1;
-
  assert( u.bm.pC->deferredMoveto==0 );
-
  rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bm.pCrsr, &u.bm.res) :
-
                              sqlite3BtreePrevious(u.bm.pCrsr, &u.bm.res);
-
  u.bm.pC->nullRow = (u8)u.bm.res;
-
  u.bm.pC->cacheStatus = CACHE_STALE;
-
  if( u.bm.res==0 ){
+
  assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterNext) );
+
  if( isSorter(u.bp.pC) ){
+
    assert( pOp->opcode==OP_SorterNext );
+
    rc = sqlite3VdbeSorterNext(db, u.bp.pC, &u.bp.res);
+
  }else{
+
    u.bp.res = 1;
+
    assert( u.bp.pC->deferredMoveto==0 );
+
    assert( u.bp.pC->pCursor );
+
    assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
+
    assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
+
    rc = pOp->p4.xAdvance(u.bp.pC->pCursor, &u.bp.res);
+
  }
+
  u.bp.pC->nullRow = (u8)u.bp.res;
+
  u.bp.pC->cacheStatus = CACHE_STALE;
+
  if( u.bp.res==0 ){
    pc = pOp->p2 - 1;
    if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
  }
-
  u.bm.pC->rowidIsValid = 0;
+
  u.bp.pC->rowidIsValid = 0;
  break;
}

@@ -67172,31 +68060,40 @@ case OP_Next: { /* jump */
** This instruction only works for indices.  The equivalent instruction
** for tables is OP_Insert.
*/
+
case OP_SorterInsert:       /* in2 */
+
#ifdef SQLITE_OMIT_MERGE_SORT
+
  pOp->opcode = OP_IdxInsert;
+
#endif
case OP_IdxInsert: {        /* in2 */
-
#if 0  /* local variables moved into u.bn */
+
#if 0  /* local variables moved into u.bq */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int nKey;
  const char *zKey;
-
#endif /* local variables moved into u.bn */
+
#endif /* local variables moved into u.bq */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bn.pC = p->apCsr[pOp->p1];
-
  assert( u.bn.pC!=0 );
+
  u.bq.pC = p->apCsr[pOp->p1];
+
  assert( u.bq.pC!=0 );
+
  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
  pIn2 = &aMem[pOp->p2];
  assert( pIn2->flags & MEM_Blob );
-
  u.bn.pCrsr = u.bn.pC->pCursor;
-
  if( ALWAYS(u.bn.pCrsr!=0) ){
-
    assert( u.bn.pC->isTable==0 );
+
  u.bq.pCrsr = u.bq.pC->pCursor;
+
  if( ALWAYS(u.bq.pCrsr!=0) ){
+
    assert( u.bq.pC->isTable==0 );
    rc = ExpandBlob(pIn2);
    if( rc==SQLITE_OK ){
-
      u.bn.nKey = pIn2->n;
-
      u.bn.zKey = pIn2->z;
-
      rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
-
          ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
-
      );
-
      assert( u.bn.pC->deferredMoveto==0 );
-
      u.bn.pC->cacheStatus = CACHE_STALE;
+
      if( isSorter(u.bq.pC) ){
+
        rc = sqlite3VdbeSorterWrite(db, u.bq.pC, pIn2);
+
      }else{
+
        u.bq.nKey = pIn2->n;
+
        u.bq.zKey = pIn2->z;
+
        rc = sqlite3BtreeInsert(u.bq.pCrsr, u.bq.zKey, u.bq.nKey, "", 0, 0, pOp->p3,
+
            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bq.pC->seekResult : 0)
+
            );
+
        assert( u.bq.pC->deferredMoveto==0 );
+
        u.bq.pC->cacheStatus = CACHE_STALE;
+
      }
    }
  }
  break;
@@ -67209,33 +68106,33 @@ case OP_IdxInsert: { /* in2 */
** index opened by cursor P1.
*/
case OP_IdxDelete: {
-
#if 0  /* local variables moved into u.bo */
+
#if 0  /* local variables moved into u.br */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  UnpackedRecord r;
-
#endif /* local variables moved into u.bo */
+
#endif /* local variables moved into u.br */

  assert( pOp->p3>0 );
  assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bo.pC = p->apCsr[pOp->p1];
-
  assert( u.bo.pC!=0 );
-
  u.bo.pCrsr = u.bo.pC->pCursor;
-
  if( ALWAYS(u.bo.pCrsr!=0) ){
-
    u.bo.r.pKeyInfo = u.bo.pC->pKeyInfo;
-
    u.bo.r.nField = (u16)pOp->p3;
-
    u.bo.r.flags = 0;
-
    u.bo.r.aMem = &aMem[pOp->p2];
+
  u.br.pC = p->apCsr[pOp->p1];
+
  assert( u.br.pC!=0 );
+
  u.br.pCrsr = u.br.pC->pCursor;
+
  if( ALWAYS(u.br.pCrsr!=0) ){
+
    u.br.r.pKeyInfo = u.br.pC->pKeyInfo;
+
    u.br.r.nField = (u16)pOp->p3;
+
    u.br.r.flags = 0;
+
    u.br.r.aMem = &aMem[pOp->p2];
#ifdef SQLITE_DEBUG
-
    { int i; for(i=0; i<u.bo.r.nField; i++) assert( memIsValid(&u.bo.r.aMem[i]) ); }
+
    { int i; for(i=0; i<u.br.r.nField; i++) assert( memIsValid(&u.br.r.aMem[i]) ); }
#endif
-
    rc = sqlite3BtreeMovetoUnpacked(u.bo.pCrsr, &u.bo.r, 0, 0, &u.bo.res);
-
    if( rc==SQLITE_OK && u.bo.res==0 ){
-
      rc = sqlite3BtreeDelete(u.bo.pCrsr);
+
    rc = sqlite3BtreeMovetoUnpacked(u.br.pCrsr, &u.br.r, 0, 0, &u.br.res);
+
    if( rc==SQLITE_OK && u.br.res==0 ){
+
      rc = sqlite3BtreeDelete(u.br.pCrsr);
    }
-
    assert( u.bo.pC->deferredMoveto==0 );
-
    u.bo.pC->cacheStatus = CACHE_STALE;
+
    assert( u.br.pC->deferredMoveto==0 );
+
    u.br.pC->cacheStatus = CACHE_STALE;
  }
  break;
}
@@ -67249,28 +68146,28 @@ case OP_IdxDelete: {
** See also: Rowid, MakeRecord.
*/
case OP_IdxRowid: {              /* out2-prerelease */
-
#if 0  /* local variables moved into u.bp */
+
#if 0  /* local variables moved into u.bs */
  BtCursor *pCrsr;
  VdbeCursor *pC;
  i64 rowid;
-
#endif /* local variables moved into u.bp */
+
#endif /* local variables moved into u.bs */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bp.pC = p->apCsr[pOp->p1];
-
  assert( u.bp.pC!=0 );
-
  u.bp.pCrsr = u.bp.pC->pCursor;
+
  u.bs.pC = p->apCsr[pOp->p1];
+
  assert( u.bs.pC!=0 );
+
  u.bs.pCrsr = u.bs.pC->pCursor;
  pOut->flags = MEM_Null;
-
  if( ALWAYS(u.bp.pCrsr!=0) ){
-
    rc = sqlite3VdbeCursorMoveto(u.bp.pC);
+
  if( ALWAYS(u.bs.pCrsr!=0) ){
+
    rc = sqlite3VdbeCursorMoveto(u.bs.pC);
    if( NEVER(rc) ) goto abort_due_to_error;
-
    assert( u.bp.pC->deferredMoveto==0 );
-
    assert( u.bp.pC->isTable==0 );
-
    if( !u.bp.pC->nullRow ){
-
      rc = sqlite3VdbeIdxRowid(db, u.bp.pCrsr, &u.bp.rowid);
+
    assert( u.bs.pC->deferredMoveto==0 );
+
    assert( u.bs.pC->isTable==0 );
+
    if( !u.bs.pC->nullRow ){
+
      rc = sqlite3VdbeIdxRowid(db, u.bs.pCrsr, &u.bs.rowid);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
-
      pOut->u.i = u.bp.rowid;
+
      pOut->u.i = u.bs.rowid;
      pOut->flags = MEM_Int;
    }
  }
@@ -67305,39 +68202,39 @@ case OP_IdxRowid: { /* out2-prerelease */
*/
case OP_IdxLT:          /* jump */
case OP_IdxGE: {        /* jump */
-
#if 0  /* local variables moved into u.bq */
+
#if 0  /* local variables moved into u.bt */
  VdbeCursor *pC;
  int res;
  UnpackedRecord r;
-
#endif /* local variables moved into u.bq */
+
#endif /* local variables moved into u.bt */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  u.bq.pC = p->apCsr[pOp->p1];
-
  assert( u.bq.pC!=0 );
-
  assert( u.bq.pC->isOrdered );
-
  if( ALWAYS(u.bq.pC->pCursor!=0) ){
-
    assert( u.bq.pC->deferredMoveto==0 );
+
  u.bt.pC = p->apCsr[pOp->p1];
+
  assert( u.bt.pC!=0 );
+
  assert( u.bt.pC->isOrdered );
+
  if( ALWAYS(u.bt.pC->pCursor!=0) ){
+
    assert( u.bt.pC->deferredMoveto==0 );
    assert( pOp->p5==0 || pOp->p5==1 );
    assert( pOp->p4type==P4_INT32 );
-
    u.bq.r.pKeyInfo = u.bq.pC->pKeyInfo;
-
    u.bq.r.nField = (u16)pOp->p4.i;
+
    u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
+
    u.bt.r.nField = (u16)pOp->p4.i;
    if( pOp->p5 ){
-
      u.bq.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
+
      u.bt.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
    }else{
-
      u.bq.r.flags = UNPACKED_IGNORE_ROWID;
+
      u.bt.r.flags = UNPACKED_IGNORE_ROWID;
    }
-
    u.bq.r.aMem = &aMem[pOp->p3];
+
    u.bt.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
-
    { int i; for(i=0; i<u.bq.r.nField; i++) assert( memIsValid(&u.bq.r.aMem[i]) ); }
+
    { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
#endif
-
    rc = sqlite3VdbeIdxKeyCompare(u.bq.pC, &u.bq.r, &u.bq.res);
+
    rc = sqlite3VdbeIdxKeyCompare(u.bt.pC, &u.bt.r, &u.bt.res);
    if( pOp->opcode==OP_IdxLT ){
-
      u.bq.res = -u.bq.res;
+
      u.bt.res = -u.bt.res;
    }else{
      assert( pOp->opcode==OP_IdxGE );
-
      u.bq.res++;
+
      u.bt.res++;
    }
-
    if( u.bq.res>0 ){
+
    if( u.bt.res>0 ){
      pc = pOp->p2 - 1 ;
    }
  }
@@ -67365,39 +68262,39 @@ case OP_IdxGE: { /* jump */
** See also: Clear
*/
case OP_Destroy: {     /* out2-prerelease */
-
#if 0  /* local variables moved into u.br */
+
#if 0  /* local variables moved into u.bu */
  int iMoved;
  int iCnt;
  Vdbe *pVdbe;
  int iDb;
-
#endif /* local variables moved into u.br */
+
#endif /* local variables moved into u.bu */
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
  u.br.iCnt = 0;
-
  for(u.br.pVdbe=db->pVdbe; u.br.pVdbe; u.br.pVdbe = u.br.pVdbe->pNext){
-
    if( u.br.pVdbe->magic==VDBE_MAGIC_RUN && u.br.pVdbe->inVtabMethod<2 && u.br.pVdbe->pc>=0 ){
-
      u.br.iCnt++;
+
  u.bu.iCnt = 0;
+
  for(u.bu.pVdbe=db->pVdbe; u.bu.pVdbe; u.bu.pVdbe = u.bu.pVdbe->pNext){
+
    if( u.bu.pVdbe->magic==VDBE_MAGIC_RUN && u.bu.pVdbe->inVtabMethod<2 && u.bu.pVdbe->pc>=0 ){
+
      u.bu.iCnt++;
    }
  }
#else
-
  u.br.iCnt = db->activeVdbeCnt;
+
  u.bu.iCnt = db->activeVdbeCnt;
#endif
  pOut->flags = MEM_Null;
-
  if( u.br.iCnt>1 ){
+
  if( u.bu.iCnt>1 ){
    rc = SQLITE_LOCKED;
    p->errorAction = OE_Abort;
  }else{
-
    u.br.iDb = pOp->p3;
-
    assert( u.br.iCnt==1 );
-
    assert( (p->btreeMask & (((yDbMask)1)<<u.br.iDb))!=0 );
-
    rc = sqlite3BtreeDropTable(db->aDb[u.br.iDb].pBt, pOp->p1, &u.br.iMoved);
+
    u.bu.iDb = pOp->p3;
+
    assert( u.bu.iCnt==1 );
+
    assert( (p->btreeMask & (((yDbMask)1)<<u.bu.iDb))!=0 );
+
    rc = sqlite3BtreeDropTable(db->aDb[u.bu.iDb].pBt, pOp->p1, &u.bu.iMoved);
    pOut->flags = MEM_Int;
-
    pOut->u.i = u.br.iMoved;
+
    pOut->u.i = u.bu.iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
-
    if( rc==SQLITE_OK && u.br.iMoved!=0 ){
-
      sqlite3RootPageMoved(db, u.br.iDb, u.br.iMoved, pOp->p1);
+
    if( rc==SQLITE_OK && u.bu.iMoved!=0 ){
+
      sqlite3RootPageMoved(db, u.bu.iDb, u.bu.iMoved, pOp->p1);
      /* All OP_Destroy operations occur on the same btree */
-
      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.br.iDb+1 );
-
      resetSchemaOnFault = u.br.iDb+1;
+
      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bu.iDb+1 );
+
      resetSchemaOnFault = u.bu.iDb+1;
    }
#endif
  }
@@ -67423,21 +68320,21 @@ case OP_Destroy: { /* out2-prerelease */
** See also: Destroy
*/
case OP_Clear: {
-
#if 0  /* local variables moved into u.bs */
+
#if 0  /* local variables moved into u.bv */
  int nChange;
-
#endif /* local variables moved into u.bs */
+
#endif /* local variables moved into u.bv */

-
  u.bs.nChange = 0;
+
  u.bv.nChange = 0;
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
  rc = sqlite3BtreeClearTable(
-
      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bs.nChange : 0)
+
      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bv.nChange : 0)
  );
  if( pOp->p3 ){
-
    p->nChange += u.bs.nChange;
+
    p->nChange += u.bv.nChange;
    if( pOp->p3>0 ){
      assert( memIsValid(&aMem[pOp->p3]) );
      memAboutToChange(p, &aMem[pOp->p3]);
-
      aMem[pOp->p3].u.i += u.bs.nChange;
+
      aMem[pOp->p3].u.i += u.bv.nChange;
    }
  }
  break;
@@ -67467,25 +68364,25 @@ case OP_Clear: {
*/
case OP_CreateIndex:            /* out2-prerelease */
case OP_CreateTable: {          /* out2-prerelease */
-
#if 0  /* local variables moved into u.bt */
+
#if 0  /* local variables moved into u.bw */
  int pgno;
  int flags;
  Db *pDb;
-
#endif /* local variables moved into u.bt */
+
#endif /* local variables moved into u.bw */

-
  u.bt.pgno = 0;
+
  u.bw.pgno = 0;
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-
  u.bt.pDb = &db->aDb[pOp->p1];
-
  assert( u.bt.pDb->pBt!=0 );
+
  u.bw.pDb = &db->aDb[pOp->p1];
+
  assert( u.bw.pDb->pBt!=0 );
  if( pOp->opcode==OP_CreateTable ){
-
    /* u.bt.flags = BTREE_INTKEY; */
-
    u.bt.flags = BTREE_INTKEY;
+
    /* u.bw.flags = BTREE_INTKEY; */
+
    u.bw.flags = BTREE_INTKEY;
  }else{
-
    u.bt.flags = BTREE_BLOBKEY;
+
    u.bw.flags = BTREE_BLOBKEY;
  }
-
  rc = sqlite3BtreeCreateTable(u.bt.pDb->pBt, &u.bt.pgno, u.bt.flags);
-
  pOut->u.i = u.bt.pgno;
+
  rc = sqlite3BtreeCreateTable(u.bw.pDb->pBt, &u.bw.pgno, u.bw.flags);
+
  pOut->u.i = u.bw.pgno;
  break;
}

@@ -67498,44 +68395,44 @@ case OP_CreateTable: { /* out2-prerelease */
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
-
#if 0  /* local variables moved into u.bu */
+
#if 0  /* local variables moved into u.bx */
  int iDb;
  const char *zMaster;
  char *zSql;
  InitData initData;
-
#endif /* local variables moved into u.bu */
+
#endif /* local variables moved into u.bx */

  /* Any prepared statement that invokes this opcode will hold mutexes
  ** on every btree.  This is a prerequisite for invoking
  ** sqlite3InitCallback().
  */
#ifdef SQLITE_DEBUG
-
  for(u.bu.iDb=0; u.bu.iDb<db->nDb; u.bu.iDb++){
-
    assert( u.bu.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bu.iDb].pBt) );
+
  for(u.bx.iDb=0; u.bx.iDb<db->nDb; u.bx.iDb++){
+
    assert( u.bx.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bx.iDb].pBt) );
  }
#endif

-
  u.bu.iDb = pOp->p1;
-
  assert( u.bu.iDb>=0 && u.bu.iDb<db->nDb );
-
  assert( DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) );
+
  u.bx.iDb = pOp->p1;
+
  assert( u.bx.iDb>=0 && u.bx.iDb<db->nDb );
+
  assert( DbHasProperty(db, u.bx.iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
-
    u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb);
-
    u.bu.initData.db = db;
-
    u.bu.initData.iDb = pOp->p1;
-
    u.bu.initData.pzErrMsg = &p->zErrMsg;
-
    u.bu.zSql = sqlite3MPrintf(db,
+
    u.bx.zMaster = SCHEMA_TABLE(u.bx.iDb);
+
    u.bx.initData.db = db;
+
    u.bx.initData.iDb = pOp->p1;
+
    u.bx.initData.pzErrMsg = &p->zErrMsg;
+
    u.bx.zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
-
       db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z);
-
    if( u.bu.zSql==0 ){
+
       db->aDb[u.bx.iDb].zName, u.bx.zMaster, pOp->p4.z);
+
    if( u.bx.zSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
-
      u.bu.initData.rc = SQLITE_OK;
+
      u.bx.initData.rc = SQLITE_OK;
      assert( !db->mallocFailed );
-
      rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0);
-
      if( rc==SQLITE_OK ) rc = u.bu.initData.rc;
-
      sqlite3DbFree(db, u.bu.zSql);
+
      rc = sqlite3_exec(db, u.bx.zSql, sqlite3InitCallback, &u.bx.initData, 0);
+
      if( rc==SQLITE_OK ) rc = u.bx.initData.rc;
+
      sqlite3DbFree(db, u.bx.zSql);
      db->init.busy = 0;
    }
  }
@@ -67618,41 +68515,41 @@ case OP_DropTrigger: {
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
-
#if 0  /* local variables moved into u.bv */
+
#if 0  /* local variables moved into u.by */
  int nRoot;      /* Number of tables to check.  (Number of root pages.) */
  int *aRoot;     /* Array of rootpage numbers for tables to be checked */
  int j;          /* Loop counter */
  int nErr;       /* Number of errors reported */
  char *z;        /* Text of the error report */
  Mem *pnErr;     /* Register keeping track of errors remaining */
-
#endif /* local variables moved into u.bv */
+
#endif /* local variables moved into u.by */

-
  u.bv.nRoot = pOp->p2;
-
  assert( u.bv.nRoot>0 );
-
  u.bv.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bv.nRoot+1) );
-
  if( u.bv.aRoot==0 ) goto no_mem;
+
  u.by.nRoot = pOp->p2;
+
  assert( u.by.nRoot>0 );
+
  u.by.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.by.nRoot+1) );
+
  if( u.by.aRoot==0 ) goto no_mem;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-
  u.bv.pnErr = &aMem[pOp->p3];
-
  assert( (u.bv.pnErr->flags & MEM_Int)!=0 );
-
  assert( (u.bv.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+
  u.by.pnErr = &aMem[pOp->p3];
+
  assert( (u.by.pnErr->flags & MEM_Int)!=0 );
+
  assert( (u.by.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
  pIn1 = &aMem[pOp->p1];
-
  for(u.bv.j=0; u.bv.j<u.bv.nRoot; u.bv.j++){
-
    u.bv.aRoot[u.bv.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bv.j]);
+
  for(u.by.j=0; u.by.j<u.by.nRoot; u.by.j++){
+
    u.by.aRoot[u.by.j] = (int)sqlite3VdbeIntValue(&pIn1[u.by.j]);
  }
-
  u.bv.aRoot[u.bv.j] = 0;
+
  u.by.aRoot[u.by.j] = 0;
  assert( pOp->p5<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
-
  u.bv.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bv.aRoot, u.bv.nRoot,
-
                                 (int)u.bv.pnErr->u.i, &u.bv.nErr);
-
  sqlite3DbFree(db, u.bv.aRoot);
-
  u.bv.pnErr->u.i -= u.bv.nErr;
+
  u.by.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.by.aRoot, u.by.nRoot,
+
                                 (int)u.by.pnErr->u.i, &u.by.nErr);
+
  sqlite3DbFree(db, u.by.aRoot);
+
  u.by.pnErr->u.i -= u.by.nErr;
  sqlite3VdbeMemSetNull(pIn1);
-
  if( u.bv.nErr==0 ){
-
    assert( u.bv.z==0 );
-
  }else if( u.bv.z==0 ){
+
  if( u.by.nErr==0 ){
+
    assert( u.by.z==0 );
+
  }else if( u.by.z==0 ){
    goto no_mem;
  }else{
-
    sqlite3VdbeMemSetStr(pIn1, u.bv.z, -1, SQLITE_UTF8, sqlite3_free);
+
    sqlite3VdbeMemSetStr(pIn1, u.by.z, -1, SQLITE_UTF8, sqlite3_free);
  }
  UPDATE_MAX_BLOBSIZE(pIn1);
  sqlite3VdbeChangeEncoding(pIn1, encoding);
@@ -67686,20 +68583,20 @@ case OP_RowSetAdd: { /* in1, in2 */
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: {       /* jump, in1, out3 */
-
#if 0  /* local variables moved into u.bw */
+
#if 0  /* local variables moved into u.bz */
  i64 val;
-
#endif /* local variables moved into u.bw */
+
#endif /* local variables moved into u.bz */
  CHECK_FOR_INTERRUPT;
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_RowSet)==0
-
   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bw.val)==0
+
   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bz.val)==0
  ){
    /* The boolean index is empty */
    sqlite3VdbeMemSetNull(pIn1);
    pc = pOp->p2 - 1;
  }else{
    /* A value was pulled from the index */
-
    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bw.val);
+
    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bz.val);
  }
  break;
}
@@ -67728,14 +68625,14 @@ case OP_RowSetRead: { /* jump, in1, out3 */
** inserted as part of some other set).
*/
case OP_RowSetTest: {                     /* jump, in1, in3 */
-
#if 0  /* local variables moved into u.bx */
+
#if 0  /* local variables moved into u.ca */
  int iSet;
  int exists;
-
#endif /* local variables moved into u.bx */
+
#endif /* local variables moved into u.ca */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
-
  u.bx.iSet = pOp->p4.i;
+
  u.ca.iSet = pOp->p4.i;
  assert( pIn3->flags&MEM_Int );

  /* If there is anything other than a rowset object in memory cell P1,
@@ -67747,17 +68644,17 @@ case OP_RowSetTest: { /* jump, in1, in3 */
  }

  assert( pOp->p4type==P4_INT32 );
-
  assert( u.bx.iSet==-1 || u.bx.iSet>=0 );
-
  if( u.bx.iSet ){
-
    u.bx.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
-
                               (u8)(u.bx.iSet>=0 ? u.bx.iSet & 0xf : 0xff),
+
  assert( u.ca.iSet==-1 || u.ca.iSet>=0 );
+
  if( u.ca.iSet ){
+
    u.ca.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+
                               (u8)(u.ca.iSet>=0 ? u.ca.iSet & 0xf : 0xff),
                               pIn3->u.i);
-
    if( u.bx.exists ){
+
    if( u.ca.exists ){
      pc = pOp->p2 - 1;
      break;
    }
  }
-
  if( u.bx.iSet>=0 ){
+
  if( u.ca.iSet>=0 ){
    sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
  }
  break;
@@ -67780,7 +68677,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
** P4 is a pointer to the VM containing the trigger program.
*/
case OP_Program: {        /* jump */
-
#if 0  /* local variables moved into u.by */
+
#if 0  /* local variables moved into u.cb */
  int nMem;               /* Number of memory registers for sub-program */
  int nByte;              /* Bytes of runtime space required for sub-program */
  Mem *pRt;               /* Register to allocate runtime space */
@@ -67789,12 +68686,12 @@ case OP_Program: { /* jump */
  VdbeFrame *pFrame;      /* New vdbe frame to execute in */
  SubProgram *pProgram;   /* Sub-program to execute */
  void *t;                /* Token identifying trigger */
-
#endif /* local variables moved into u.by */
+
#endif /* local variables moved into u.cb */

-
  u.by.pProgram = pOp->p4.pProgram;
-
  u.by.pRt = &aMem[pOp->p3];
-
  assert( memIsValid(u.by.pRt) );
-
  assert( u.by.pProgram->nOp>0 );
+
  u.cb.pProgram = pOp->p4.pProgram;
+
  u.cb.pRt = &aMem[pOp->p3];
+
  assert( memIsValid(u.cb.pRt) );
+
  assert( u.cb.pProgram->nOp>0 );

  /* If the p5 flag is clear, then recursive invocation of triggers is
  ** disabled for backwards compatibility (p5 is set if this sub-program
@@ -67808,9 +68705,9 @@ case OP_Program: { /* jump */
  ** single trigger all have the same value for the SubProgram.token
  ** variable.  */
  if( pOp->p5 ){
-
    u.by.t = u.by.pProgram->token;
-
    for(u.by.pFrame=p->pFrame; u.by.pFrame && u.by.pFrame->token!=u.by.t; u.by.pFrame=u.by.pFrame->pParent);
-
    if( u.by.pFrame ) break;
+
    u.cb.t = u.cb.pProgram->token;
+
    for(u.cb.pFrame=p->pFrame; u.cb.pFrame && u.cb.pFrame->token!=u.cb.t; u.cb.pFrame=u.cb.pFrame->pParent);
+
    if( u.cb.pFrame ) break;
  }

  if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
@@ -67819,64 +68716,64 @@ case OP_Program: { /* jump */
    break;
  }

-
  /* Register u.by.pRt is used to store the memory required to save the state
+
  /* Register u.cb.pRt is used to store the memory required to save the state
  ** of the current program, and the memory required at runtime to execute
-
  ** the trigger program. If this trigger has been fired before, then u.by.pRt
+
  ** the trigger program. If this trigger has been fired before, then u.cb.pRt
  ** is already allocated. Otherwise, it must be initialized.  */
-
  if( (u.by.pRt->flags&MEM_Frame)==0 ){
+
  if( (u.cb.pRt->flags&MEM_Frame)==0 ){
    /* SubProgram.nMem is set to the number of memory cells used by the
    ** program stored in SubProgram.aOp. As well as these, one memory
    ** cell is required for each cursor used by the program. Set local
-
    ** variable u.by.nMem (and later, VdbeFrame.nChildMem) to this value.
+
    ** variable u.cb.nMem (and later, VdbeFrame.nChildMem) to this value.
    */
-
    u.by.nMem = u.by.pProgram->nMem + u.by.pProgram->nCsr;
-
    u.by.nByte = ROUND8(sizeof(VdbeFrame))
-
              + u.by.nMem * sizeof(Mem)
-
              + u.by.pProgram->nCsr * sizeof(VdbeCursor *);
-
    u.by.pFrame = sqlite3DbMallocZero(db, u.by.nByte);
-
    if( !u.by.pFrame ){
+
    u.cb.nMem = u.cb.pProgram->nMem + u.cb.pProgram->nCsr;
+
    u.cb.nByte = ROUND8(sizeof(VdbeFrame))
+
              + u.cb.nMem * sizeof(Mem)
+
              + u.cb.pProgram->nCsr * sizeof(VdbeCursor *);
+
    u.cb.pFrame = sqlite3DbMallocZero(db, u.cb.nByte);
+
    if( !u.cb.pFrame ){
      goto no_mem;
    }
-
    sqlite3VdbeMemRelease(u.by.pRt);
-
    u.by.pRt->flags = MEM_Frame;
-
    u.by.pRt->u.pFrame = u.by.pFrame;
-

-
    u.by.pFrame->v = p;
-
    u.by.pFrame->nChildMem = u.by.nMem;
-
    u.by.pFrame->nChildCsr = u.by.pProgram->nCsr;
-
    u.by.pFrame->pc = pc;
-
    u.by.pFrame->aMem = p->aMem;
-
    u.by.pFrame->nMem = p->nMem;
-
    u.by.pFrame->apCsr = p->apCsr;
-
    u.by.pFrame->nCursor = p->nCursor;
-
    u.by.pFrame->aOp = p->aOp;
-
    u.by.pFrame->nOp = p->nOp;
-
    u.by.pFrame->token = u.by.pProgram->token;
-

-
    u.by.pEnd = &VdbeFrameMem(u.by.pFrame)[u.by.pFrame->nChildMem];
-
    for(u.by.pMem=VdbeFrameMem(u.by.pFrame); u.by.pMem!=u.by.pEnd; u.by.pMem++){
-
      u.by.pMem->flags = MEM_Null;
-
      u.by.pMem->db = db;
+
    sqlite3VdbeMemRelease(u.cb.pRt);
+
    u.cb.pRt->flags = MEM_Frame;
+
    u.cb.pRt->u.pFrame = u.cb.pFrame;
+

+
    u.cb.pFrame->v = p;
+
    u.cb.pFrame->nChildMem = u.cb.nMem;
+
    u.cb.pFrame->nChildCsr = u.cb.pProgram->nCsr;
+
    u.cb.pFrame->pc = pc;
+
    u.cb.pFrame->aMem = p->aMem;
+
    u.cb.pFrame->nMem = p->nMem;
+
    u.cb.pFrame->apCsr = p->apCsr;
+
    u.cb.pFrame->nCursor = p->nCursor;
+
    u.cb.pFrame->aOp = p->aOp;
+
    u.cb.pFrame->nOp = p->nOp;
+
    u.cb.pFrame->token = u.cb.pProgram->token;
+

+
    u.cb.pEnd = &VdbeFrameMem(u.cb.pFrame)[u.cb.pFrame->nChildMem];
+
    for(u.cb.pMem=VdbeFrameMem(u.cb.pFrame); u.cb.pMem!=u.cb.pEnd; u.cb.pMem++){
+
      u.cb.pMem->flags = MEM_Null;
+
      u.cb.pMem->db = db;
    }
  }else{
-
    u.by.pFrame = u.by.pRt->u.pFrame;
-
    assert( u.by.pProgram->nMem+u.by.pProgram->nCsr==u.by.pFrame->nChildMem );
-
    assert( u.by.pProgram->nCsr==u.by.pFrame->nChildCsr );
-
    assert( pc==u.by.pFrame->pc );
+
    u.cb.pFrame = u.cb.pRt->u.pFrame;
+
    assert( u.cb.pProgram->nMem+u.cb.pProgram->nCsr==u.cb.pFrame->nChildMem );
+
    assert( u.cb.pProgram->nCsr==u.cb.pFrame->nChildCsr );
+
    assert( pc==u.cb.pFrame->pc );
  }

  p->nFrame++;
-
  u.by.pFrame->pParent = p->pFrame;
-
  u.by.pFrame->lastRowid = lastRowid;
-
  u.by.pFrame->nChange = p->nChange;
+
  u.cb.pFrame->pParent = p->pFrame;
+
  u.cb.pFrame->lastRowid = lastRowid;
+
  u.cb.pFrame->nChange = p->nChange;
  p->nChange = 0;
-
  p->pFrame = u.by.pFrame;
-
  p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
-
  p->nMem = u.by.pFrame->nChildMem;
-
  p->nCursor = (u16)u.by.pFrame->nChildCsr;
+
  p->pFrame = u.cb.pFrame;
+
  p->aMem = aMem = &VdbeFrameMem(u.cb.pFrame)[-1];
+
  p->nMem = u.cb.pFrame->nChildMem;
+
  p->nCursor = (u16)u.cb.pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
-
  p->aOp = aOp = u.by.pProgram->aOp;
-
  p->nOp = u.by.pProgram->nOp;
+
  p->aOp = aOp = u.cb.pProgram->aOp;
+
  p->nOp = u.cb.pProgram->nOp;
  pc = -1;

  break;
@@ -67895,13 +68792,13 @@ case OP_Program: { /* jump */
** calling OP_Program instruction.
*/
case OP_Param: {           /* out2-prerelease */
-
#if 0  /* local variables moved into u.bz */
+
#if 0  /* local variables moved into u.cc */
  VdbeFrame *pFrame;
  Mem *pIn;
-
#endif /* local variables moved into u.bz */
-
  u.bz.pFrame = p->pFrame;
-
  u.bz.pIn = &u.bz.pFrame->aMem[pOp->p1 + u.bz.pFrame->aOp[u.bz.pFrame->pc].p1];
-
  sqlite3VdbeMemShallowCopy(pOut, u.bz.pIn, MEM_Ephem);
+
#endif /* local variables moved into u.cc */
+
  u.cc.pFrame = p->pFrame;
+
  u.cc.pIn = &u.cc.pFrame->aMem[pOp->p1 + u.cc.pFrame->aOp[u.cc.pFrame->pc].p1];
+
  sqlite3VdbeMemShallowCopy(pOut, u.cc.pIn, MEM_Ephem);
  break;
}

@@ -67957,22 +68854,22 @@ case OP_FkIfZero: { /* jump */
** an integer.
*/
case OP_MemMax: {        /* in2 */
-
#if 0  /* local variables moved into u.ca */
+
#if 0  /* local variables moved into u.cd */
  Mem *pIn1;
  VdbeFrame *pFrame;
-
#endif /* local variables moved into u.ca */
+
#endif /* local variables moved into u.cd */
  if( p->pFrame ){
-
    for(u.ca.pFrame=p->pFrame; u.ca.pFrame->pParent; u.ca.pFrame=u.ca.pFrame->pParent);
-
    u.ca.pIn1 = &u.ca.pFrame->aMem[pOp->p1];
+
    for(u.cd.pFrame=p->pFrame; u.cd.pFrame->pParent; u.cd.pFrame=u.cd.pFrame->pParent);
+
    u.cd.pIn1 = &u.cd.pFrame->aMem[pOp->p1];
  }else{
-
    u.ca.pIn1 = &aMem[pOp->p1];
+
    u.cd.pIn1 = &aMem[pOp->p1];
  }
-
  assert( memIsValid(u.ca.pIn1) );
-
  sqlite3VdbeMemIntegerify(u.ca.pIn1);
+
  assert( memIsValid(u.cd.pIn1) );
+
  sqlite3VdbeMemIntegerify(u.cd.pIn1);
  pIn2 = &aMem[pOp->p2];
  sqlite3VdbeMemIntegerify(pIn2);
-
  if( u.ca.pIn1->u.i<pIn2->u.i){
-
    u.ca.pIn1->u.i = pIn2->u.i;
+
  if( u.cd.pIn1->u.i<pIn2->u.i){
+
    u.cd.pIn1->u.i = pIn2->u.i;
  }
  break;
}
@@ -68039,50 +68936,50 @@ case OP_IfZero: { /* jump, in1 */
** successors.
*/
case OP_AggStep: {
-
#if 0  /* local variables moved into u.cb */
+
#if 0  /* local variables moved into u.ce */
  int n;
  int i;
  Mem *pMem;
  Mem *pRec;
  sqlite3_context ctx;
  sqlite3_value **apVal;
-
#endif /* local variables moved into u.cb */
+
#endif /* local variables moved into u.ce */

-
  u.cb.n = pOp->p5;
-
  assert( u.cb.n>=0 );
-
  u.cb.pRec = &aMem[pOp->p2];
-
  u.cb.apVal = p->apArg;
-
  assert( u.cb.apVal || u.cb.n==0 );
-
  for(u.cb.i=0; u.cb.i<u.cb.n; u.cb.i++, u.cb.pRec++){
-
    assert( memIsValid(u.cb.pRec) );
-
    u.cb.apVal[u.cb.i] = u.cb.pRec;
-
    memAboutToChange(p, u.cb.pRec);
-
    sqlite3VdbeMemStoreType(u.cb.pRec);
-
  }
-
  u.cb.ctx.pFunc = pOp->p4.pFunc;
+
  u.ce.n = pOp->p5;
+
  assert( u.ce.n>=0 );
+
  u.ce.pRec = &aMem[pOp->p2];
+
  u.ce.apVal = p->apArg;
+
  assert( u.ce.apVal || u.ce.n==0 );
+
  for(u.ce.i=0; u.ce.i<u.ce.n; u.ce.i++, u.ce.pRec++){
+
    assert( memIsValid(u.ce.pRec) );
+
    u.ce.apVal[u.ce.i] = u.ce.pRec;
+
    memAboutToChange(p, u.ce.pRec);
+
    sqlite3VdbeMemStoreType(u.ce.pRec);
+
  }
+
  u.ce.ctx.pFunc = pOp->p4.pFunc;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-
  u.cb.ctx.pMem = u.cb.pMem = &aMem[pOp->p3];
-
  u.cb.pMem->n++;
-
  u.cb.ctx.s.flags = MEM_Null;
-
  u.cb.ctx.s.z = 0;
-
  u.cb.ctx.s.zMalloc = 0;
-
  u.cb.ctx.s.xDel = 0;
-
  u.cb.ctx.s.db = db;
-
  u.cb.ctx.isError = 0;
-
  u.cb.ctx.pColl = 0;
-
  if( u.cb.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+
  u.ce.ctx.pMem = u.ce.pMem = &aMem[pOp->p3];
+
  u.ce.pMem->n++;
+
  u.ce.ctx.s.flags = MEM_Null;
+
  u.ce.ctx.s.z = 0;
+
  u.ce.ctx.s.zMalloc = 0;
+
  u.ce.ctx.s.xDel = 0;
+
  u.ce.ctx.s.db = db;
+
  u.ce.ctx.isError = 0;
+
  u.ce.ctx.pColl = 0;
+
  if( u.ce.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
    assert( pOp>p->aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
-
    u.cb.ctx.pColl = pOp[-1].p4.pColl;
+
    u.ce.ctx.pColl = pOp[-1].p4.pColl;
  }
-
  (u.cb.ctx.pFunc->xStep)(&u.cb.ctx, u.cb.n, u.cb.apVal); /* IMP: R-24505-23230 */
-
  if( u.cb.ctx.isError ){
-
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cb.ctx.s));
-
    rc = u.cb.ctx.isError;
+
  (u.ce.ctx.pFunc->xStep)(&u.ce.ctx, u.ce.n, u.ce.apVal); /* IMP: R-24505-23230 */
+
  if( u.ce.ctx.isError ){
+
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ce.ctx.s));
+
    rc = u.ce.ctx.isError;
  }

-
  sqlite3VdbeMemRelease(&u.cb.ctx.s);
+
  sqlite3VdbeMemRelease(&u.ce.ctx.s);

  break;
}
@@ -68100,19 +68997,19 @@ case OP_AggStep: {
** the step function was not previously called.
*/
case OP_AggFinal: {
-
#if 0  /* local variables moved into u.cc */
+
#if 0  /* local variables moved into u.cf */
  Mem *pMem;
-
#endif /* local variables moved into u.cc */
+
#endif /* local variables moved into u.cf */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
-
  u.cc.pMem = &aMem[pOp->p1];
-
  assert( (u.cc.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
-
  rc = sqlite3VdbeMemFinalize(u.cc.pMem, pOp->p4.pFunc);
+
  u.cf.pMem = &aMem[pOp->p1];
+
  assert( (u.cf.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+
  rc = sqlite3VdbeMemFinalize(u.cf.pMem, pOp->p4.pFunc);
  if( rc ){
-
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cc.pMem));
+
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cf.pMem));
  }
-
  sqlite3VdbeChangeEncoding(u.cc.pMem, encoding);
-
  UPDATE_MAX_BLOBSIZE(u.cc.pMem);
-
  if( sqlite3VdbeMemTooBig(u.cc.pMem) ){
+
  sqlite3VdbeChangeEncoding(u.cf.pMem, encoding);
+
  UPDATE_MAX_BLOBSIZE(u.cf.pMem);
+
  if( sqlite3VdbeMemTooBig(u.cf.pMem) ){
    goto too_big;
  }
  break;
@@ -68131,25 +69028,25 @@ case OP_AggFinal: {
** mem[P3+2] are initialized to -1.
*/
case OP_Checkpoint: {
-
#if 0  /* local variables moved into u.cd */
+
#if 0  /* local variables moved into u.cg */
  int i;                          /* Loop counter */
  int aRes[3];                    /* Results */
  Mem *pMem;                      /* Write results here */
-
#endif /* local variables moved into u.cd */
+
#endif /* local variables moved into u.cg */

-
  u.cd.aRes[0] = 0;
-
  u.cd.aRes[1] = u.cd.aRes[2] = -1;
+
  u.cg.aRes[0] = 0;
+
  u.cg.aRes[1] = u.cg.aRes[2] = -1;
  assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
       || pOp->p2==SQLITE_CHECKPOINT_FULL
       || pOp->p2==SQLITE_CHECKPOINT_RESTART
  );
-
  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cd.aRes[1], &u.cd.aRes[2]);
+
  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cg.aRes[1], &u.cg.aRes[2]);
  if( rc==SQLITE_BUSY ){
    rc = SQLITE_OK;
-
    u.cd.aRes[0] = 1;
+
    u.cg.aRes[0] = 1;
  }
-
  for(u.cd.i=0, u.cd.pMem = &aMem[pOp->p3]; u.cd.i<3; u.cd.i++, u.cd.pMem++){
-
    sqlite3VdbeMemSetInt64(u.cd.pMem, (i64)u.cd.aRes[u.cd.i]);
+
  for(u.cg.i=0, u.cg.pMem = &aMem[pOp->p3]; u.cg.i<3; u.cg.i++, u.cg.pMem++){
+
    sqlite3VdbeMemSetInt64(u.cg.pMem, (i64)u.cg.aRes[u.cg.i]);
  }
  break;
};  
@@ -68168,91 +69065,91 @@ case OP_Checkpoint: {
** Write a string containing the final journal-mode to register P2.
*/
case OP_JournalMode: {    /* out2-prerelease */
-
#if 0  /* local variables moved into u.ce */
+
#if 0  /* local variables moved into u.ch */
  Btree *pBt;                     /* Btree to change journal mode of */
  Pager *pPager;                  /* Pager associated with pBt */
  int eNew;                       /* New journal mode */
  int eOld;                       /* The old journal mode */
  const char *zFilename;          /* Name of database file for pPager */
-
#endif /* local variables moved into u.ce */
+
#endif /* local variables moved into u.ch */

-
  u.ce.eNew = pOp->p3;
-
  assert( u.ce.eNew==PAGER_JOURNALMODE_DELETE
-
       || u.ce.eNew==PAGER_JOURNALMODE_TRUNCATE
-
       || u.ce.eNew==PAGER_JOURNALMODE_PERSIST
-
       || u.ce.eNew==PAGER_JOURNALMODE_OFF
-
       || u.ce.eNew==PAGER_JOURNALMODE_MEMORY
-
       || u.ce.eNew==PAGER_JOURNALMODE_WAL
-
       || u.ce.eNew==PAGER_JOURNALMODE_QUERY
+
  u.ch.eNew = pOp->p3;
+
  assert( u.ch.eNew==PAGER_JOURNALMODE_DELETE
+
       || u.ch.eNew==PAGER_JOURNALMODE_TRUNCATE
+
       || u.ch.eNew==PAGER_JOURNALMODE_PERSIST
+
       || u.ch.eNew==PAGER_JOURNALMODE_OFF
+
       || u.ch.eNew==PAGER_JOURNALMODE_MEMORY
+
       || u.ch.eNew==PAGER_JOURNALMODE_WAL
+
       || u.ch.eNew==PAGER_JOURNALMODE_QUERY
  );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );

-
  u.ce.pBt = db->aDb[pOp->p1].pBt;
-
  u.ce.pPager = sqlite3BtreePager(u.ce.pBt);
-
  u.ce.eOld = sqlite3PagerGetJournalMode(u.ce.pPager);
-
  if( u.ce.eNew==PAGER_JOURNALMODE_QUERY ) u.ce.eNew = u.ce.eOld;
-
  if( !sqlite3PagerOkToChangeJournalMode(u.ce.pPager) ) u.ce.eNew = u.ce.eOld;
+
  u.ch.pBt = db->aDb[pOp->p1].pBt;
+
  u.ch.pPager = sqlite3BtreePager(u.ch.pBt);
+
  u.ch.eOld = sqlite3PagerGetJournalMode(u.ch.pPager);
+
  if( u.ch.eNew==PAGER_JOURNALMODE_QUERY ) u.ch.eNew = u.ch.eOld;
+
  if( !sqlite3PagerOkToChangeJournalMode(u.ch.pPager) ) u.ch.eNew = u.ch.eOld;

#ifndef SQLITE_OMIT_WAL
-
  u.ce.zFilename = sqlite3PagerFilename(u.ce.pPager);
+
  u.ch.zFilename = sqlite3PagerFilename(u.ch.pPager);

  /* Do not allow a transition to journal_mode=WAL for a database
  ** in temporary storage or if the VFS does not support shared memory
  */
-
  if( u.ce.eNew==PAGER_JOURNALMODE_WAL
-
   && (u.ce.zFilename[0]==0                         /* Temp file */
-
       || !sqlite3PagerWalSupported(u.ce.pPager))   /* No shared-memory support */
+
  if( u.ch.eNew==PAGER_JOURNALMODE_WAL
+
   && (u.ch.zFilename[0]==0                         /* Temp file */
+
       || !sqlite3PagerWalSupported(u.ch.pPager))   /* No shared-memory support */
  ){
-
    u.ce.eNew = u.ce.eOld;
+
    u.ch.eNew = u.ch.eOld;
  }

-
  if( (u.ce.eNew!=u.ce.eOld)
-
   && (u.ce.eOld==PAGER_JOURNALMODE_WAL || u.ce.eNew==PAGER_JOURNALMODE_WAL)
+
  if( (u.ch.eNew!=u.ch.eOld)
+
   && (u.ch.eOld==PAGER_JOURNALMODE_WAL || u.ch.eNew==PAGER_JOURNALMODE_WAL)
  ){
    if( !db->autoCommit || db->activeVdbeCnt>1 ){
      rc = SQLITE_ERROR;
      sqlite3SetString(&p->zErrMsg, db,
          "cannot change %s wal mode from within a transaction",
-
          (u.ce.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+
          (u.ch.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
      );
      break;
    }else{

-
      if( u.ce.eOld==PAGER_JOURNALMODE_WAL ){
+
      if( u.ch.eOld==PAGER_JOURNALMODE_WAL ){
        /* If leaving WAL mode, close the log file. If successful, the call
        ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
        ** file. An EXCLUSIVE lock may still be held on the database file
        ** after a successful return.
        */
-
        rc = sqlite3PagerCloseWal(u.ce.pPager);
+
        rc = sqlite3PagerCloseWal(u.ch.pPager);
        if( rc==SQLITE_OK ){
-
          sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
+
          sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);
        }
-
      }else if( u.ce.eOld==PAGER_JOURNALMODE_MEMORY ){
+
      }else if( u.ch.eOld==PAGER_JOURNALMODE_MEMORY ){
        /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
        ** as an intermediate */
-
        sqlite3PagerSetJournalMode(u.ce.pPager, PAGER_JOURNALMODE_OFF);
+
        sqlite3PagerSetJournalMode(u.ch.pPager, PAGER_JOURNALMODE_OFF);
      }

      /* Open a transaction on the database file. Regardless of the journal
      ** mode, this transaction always uses a rollback journal.
      */
-
      assert( sqlite3BtreeIsInTrans(u.ce.pBt)==0 );
+
      assert( sqlite3BtreeIsInTrans(u.ch.pBt)==0 );
      if( rc==SQLITE_OK ){
-
        rc = sqlite3BtreeSetVersion(u.ce.pBt, (u.ce.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+
        rc = sqlite3BtreeSetVersion(u.ch.pBt, (u.ch.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
      }
    }
  }
#endif /* ifndef SQLITE_OMIT_WAL */

  if( rc ){
-
    u.ce.eNew = u.ce.eOld;
+
    u.ch.eNew = u.ch.eOld;
  }
-
  u.ce.eNew = sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
+
  u.ch.eNew = sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);

  pOut = &aMem[pOp->p2];
  pOut->flags = MEM_Str|MEM_Static|MEM_Term;
-
  pOut->z = (char *)sqlite3JournalModename(u.ce.eNew);
+
  pOut->z = (char *)sqlite3JournalModename(u.ch.eNew);
  pOut->n = sqlite3Strlen30(pOut->z);
  pOut->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pOut, encoding);
@@ -68281,14 +69178,14 @@ case OP_Vacuum: {
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: {        /* jump */
-
#if 0  /* local variables moved into u.cf */
+
#if 0  /* local variables moved into u.ci */
  Btree *pBt;
-
#endif /* local variables moved into u.cf */
+
#endif /* local variables moved into u.ci */

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-
  u.cf.pBt = db->aDb[pOp->p1].pBt;
-
  rc = sqlite3BtreeIncrVacuum(u.cf.pBt);
+
  u.ci.pBt = db->aDb[pOp->p1].pBt;
+
  rc = sqlite3BtreeIncrVacuum(u.ci.pBt);
  if( rc==SQLITE_DONE ){
    pc = pOp->p2 - 1;
    rc = SQLITE_OK;
@@ -68358,12 +69255,12 @@ case OP_TableLock: {
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
-
#if 0  /* local variables moved into u.cg */
+
#if 0  /* local variables moved into u.cj */
  VTable *pVTab;
-
#endif /* local variables moved into u.cg */
-
  u.cg.pVTab = pOp->p4.pVtab;
-
  rc = sqlite3VtabBegin(db, u.cg.pVTab);
-
  if( u.cg.pVTab ) importVtabErrMsg(p, u.cg.pVTab->pVtab);
+
#endif /* local variables moved into u.cj */
+
  u.cj.pVTab = pOp->p4.pVtab;
+
  rc = sqlite3VtabBegin(db, u.cj.pVTab);
+
  if( u.cj.pVTab ) importVtabErrMsg(p, u.cj.pVTab->pVtab);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -68402,32 +69299,32 @@ case OP_VDestroy: {
** table and stores that cursor in P1.
*/
case OP_VOpen: {
-
#if 0  /* local variables moved into u.ch */
+
#if 0  /* local variables moved into u.ck */
  VdbeCursor *pCur;
  sqlite3_vtab_cursor *pVtabCursor;
  sqlite3_vtab *pVtab;
  sqlite3_module *pModule;
-
#endif /* local variables moved into u.ch */
+
#endif /* local variables moved into u.ck */

-
  u.ch.pCur = 0;
-
  u.ch.pVtabCursor = 0;
-
  u.ch.pVtab = pOp->p4.pVtab->pVtab;
-
  u.ch.pModule = (sqlite3_module *)u.ch.pVtab->pModule;
-
  assert(u.ch.pVtab && u.ch.pModule);
-
  rc = u.ch.pModule->xOpen(u.ch.pVtab, &u.ch.pVtabCursor);
-
  importVtabErrMsg(p, u.ch.pVtab);
+
  u.ck.pCur = 0;
+
  u.ck.pVtabCursor = 0;
+
  u.ck.pVtab = pOp->p4.pVtab->pVtab;
+
  u.ck.pModule = (sqlite3_module *)u.ck.pVtab->pModule;
+
  assert(u.ck.pVtab && u.ck.pModule);
+
  rc = u.ck.pModule->xOpen(u.ck.pVtab, &u.ck.pVtabCursor);
+
  importVtabErrMsg(p, u.ck.pVtab);
  if( SQLITE_OK==rc ){
    /* Initialize sqlite3_vtab_cursor base class */
-
    u.ch.pVtabCursor->pVtab = u.ch.pVtab;
+
    u.ck.pVtabCursor->pVtab = u.ck.pVtab;

    /* Initialise vdbe cursor object */
-
    u.ch.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
-
    if( u.ch.pCur ){
-
      u.ch.pCur->pVtabCursor = u.ch.pVtabCursor;
-
      u.ch.pCur->pModule = u.ch.pVtabCursor->pVtab->pModule;
+
    u.ck.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+
    if( u.ck.pCur ){
+
      u.ck.pCur->pVtabCursor = u.ck.pVtabCursor;
+
      u.ck.pCur->pModule = u.ck.pVtabCursor->pVtab->pModule;
    }else{
      db->mallocFailed = 1;
-
      u.ch.pModule->xClose(u.ch.pVtabCursor);
+
      u.ck.pModule->xClose(u.ck.pVtabCursor);
    }
  }
  break;
@@ -68454,7 +69351,7 @@ case OP_VOpen: {
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: {   /* jump */
-
#if 0  /* local variables moved into u.ci */
+
#if 0  /* local variables moved into u.cl */
  int nArg;
  int iQuery;
  const sqlite3_module *pModule;
@@ -68466,45 +69363,45 @@ case OP_VFilter: { /* jump */
  int res;
  int i;
  Mem **apArg;
-
#endif /* local variables moved into u.ci */
+
#endif /* local variables moved into u.cl */

-
  u.ci.pQuery = &aMem[pOp->p3];
-
  u.ci.pArgc = &u.ci.pQuery[1];
-
  u.ci.pCur = p->apCsr[pOp->p1];
-
  assert( memIsValid(u.ci.pQuery) );
-
  REGISTER_TRACE(pOp->p3, u.ci.pQuery);
-
  assert( u.ci.pCur->pVtabCursor );
-
  u.ci.pVtabCursor = u.ci.pCur->pVtabCursor;
-
  u.ci.pVtab = u.ci.pVtabCursor->pVtab;
-
  u.ci.pModule = u.ci.pVtab->pModule;
+
  u.cl.pQuery = &aMem[pOp->p3];
+
  u.cl.pArgc = &u.cl.pQuery[1];
+
  u.cl.pCur = p->apCsr[pOp->p1];
+
  assert( memIsValid(u.cl.pQuery) );
+
  REGISTER_TRACE(pOp->p3, u.cl.pQuery);
+
  assert( u.cl.pCur->pVtabCursor );
+
  u.cl.pVtabCursor = u.cl.pCur->pVtabCursor;
+
  u.cl.pVtab = u.cl.pVtabCursor->pVtab;
+
  u.cl.pModule = u.cl.pVtab->pModule;

  /* Grab the index number and argc parameters */
-
  assert( (u.ci.pQuery->flags&MEM_Int)!=0 && u.ci.pArgc->flags==MEM_Int );
-
  u.ci.nArg = (int)u.ci.pArgc->u.i;
-
  u.ci.iQuery = (int)u.ci.pQuery->u.i;
+
  assert( (u.cl.pQuery->flags&MEM_Int)!=0 && u.cl.pArgc->flags==MEM_Int );
+
  u.cl.nArg = (int)u.cl.pArgc->u.i;
+
  u.cl.iQuery = (int)u.cl.pQuery->u.i;

  /* Invoke the xFilter method */
  {
-
    u.ci.res = 0;
-
    u.ci.apArg = p->apArg;
-
    for(u.ci.i = 0; u.ci.i<u.ci.nArg; u.ci.i++){
-
      u.ci.apArg[u.ci.i] = &u.ci.pArgc[u.ci.i+1];
-
      sqlite3VdbeMemStoreType(u.ci.apArg[u.ci.i]);
+
    u.cl.res = 0;
+
    u.cl.apArg = p->apArg;
+
    for(u.cl.i = 0; u.cl.i<u.cl.nArg; u.cl.i++){
+
      u.cl.apArg[u.cl.i] = &u.cl.pArgc[u.cl.i+1];
+
      sqlite3VdbeMemStoreType(u.cl.apArg[u.cl.i]);
    }

    p->inVtabMethod = 1;
-
    rc = u.ci.pModule->xFilter(u.ci.pVtabCursor, u.ci.iQuery, pOp->p4.z, u.ci.nArg, u.ci.apArg);
+
    rc = u.cl.pModule->xFilter(u.cl.pVtabCursor, u.cl.iQuery, pOp->p4.z, u.cl.nArg, u.cl.apArg);
    p->inVtabMethod = 0;
-
    importVtabErrMsg(p, u.ci.pVtab);
+
    importVtabErrMsg(p, u.cl.pVtab);
    if( rc==SQLITE_OK ){
-
      u.ci.res = u.ci.pModule->xEof(u.ci.pVtabCursor);
+
      u.cl.res = u.cl.pModule->xEof(u.cl.pVtabCursor);
    }

-
    if( u.ci.res ){
+
    if( u.cl.res ){
      pc = pOp->p2 - 1;
    }
  }
-
  u.ci.pCur->nullRow = 0;
+
  u.cl.pCur->nullRow = 0;

  break;
}
@@ -68518,51 +69415,51 @@ case OP_VFilter: { /* jump */
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
-
#if 0  /* local variables moved into u.cj */
+
#if 0  /* local variables moved into u.cm */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;
-
#endif /* local variables moved into u.cj */
+
#endif /* local variables moved into u.cm */

  VdbeCursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-
  u.cj.pDest = &aMem[pOp->p3];
-
  memAboutToChange(p, u.cj.pDest);
+
  u.cm.pDest = &aMem[pOp->p3];
+
  memAboutToChange(p, u.cm.pDest);
  if( pCur->nullRow ){
-
    sqlite3VdbeMemSetNull(u.cj.pDest);
+
    sqlite3VdbeMemSetNull(u.cm.pDest);
    break;
  }
-
  u.cj.pVtab = pCur->pVtabCursor->pVtab;
-
  u.cj.pModule = u.cj.pVtab->pModule;
-
  assert( u.cj.pModule->xColumn );
-
  memset(&u.cj.sContext, 0, sizeof(u.cj.sContext));
+
  u.cm.pVtab = pCur->pVtabCursor->pVtab;
+
  u.cm.pModule = u.cm.pVtab->pModule;
+
  assert( u.cm.pModule->xColumn );
+
  memset(&u.cm.sContext, 0, sizeof(u.cm.sContext));

  /* The output cell may already have a buffer allocated. Move
-
  ** the current contents to u.cj.sContext.s so in case the user-function
+
  ** the current contents to u.cm.sContext.s so in case the user-function
  ** can use the already allocated buffer instead of allocating a
  ** new one.
  */
-
  sqlite3VdbeMemMove(&u.cj.sContext.s, u.cj.pDest);
-
  MemSetTypeFlag(&u.cj.sContext.s, MEM_Null);
+
  sqlite3VdbeMemMove(&u.cm.sContext.s, u.cm.pDest);
+
  MemSetTypeFlag(&u.cm.sContext.s, MEM_Null);

-
  rc = u.cj.pModule->xColumn(pCur->pVtabCursor, &u.cj.sContext, pOp->p2);
-
  importVtabErrMsg(p, u.cj.pVtab);
-
  if( u.cj.sContext.isError ){
-
    rc = u.cj.sContext.isError;
+
  rc = u.cm.pModule->xColumn(pCur->pVtabCursor, &u.cm.sContext, pOp->p2);
+
  importVtabErrMsg(p, u.cm.pVtab);
+
  if( u.cm.sContext.isError ){
+
    rc = u.cm.sContext.isError;
  }

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occurred to ensure any
-
  ** dynamic allocation in u.cj.sContext.s (a Mem struct) is  released.
+
  ** dynamic allocation in u.cm.sContext.s (a Mem struct) is  released.
  */
-
  sqlite3VdbeChangeEncoding(&u.cj.sContext.s, encoding);
-
  sqlite3VdbeMemMove(u.cj.pDest, &u.cj.sContext.s);
-
  REGISTER_TRACE(pOp->p3, u.cj.pDest);
-
  UPDATE_MAX_BLOBSIZE(u.cj.pDest);
+
  sqlite3VdbeChangeEncoding(&u.cm.sContext.s, encoding);
+
  sqlite3VdbeMemMove(u.cm.pDest, &u.cm.sContext.s);
+
  REGISTER_TRACE(pOp->p3, u.cm.pDest);
+
  UPDATE_MAX_BLOBSIZE(u.cm.pDest);

-
  if( sqlite3VdbeMemTooBig(u.cj.pDest) ){
+
  if( sqlite3VdbeMemTooBig(u.cm.pDest) ){
    goto too_big;
  }
  break;
@@ -68577,22 +69474,22 @@ case OP_VColumn: {
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: {   /* jump */
-
#if 0  /* local variables moved into u.ck */
+
#if 0  /* local variables moved into u.cn */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  int res;
  VdbeCursor *pCur;
-
#endif /* local variables moved into u.ck */
+
#endif /* local variables moved into u.cn */

-
  u.ck.res = 0;
-
  u.ck.pCur = p->apCsr[pOp->p1];
-
  assert( u.ck.pCur->pVtabCursor );
-
  if( u.ck.pCur->nullRow ){
+
  u.cn.res = 0;
+
  u.cn.pCur = p->apCsr[pOp->p1];
+
  assert( u.cn.pCur->pVtabCursor );
+
  if( u.cn.pCur->nullRow ){
    break;
  }
-
  u.ck.pVtab = u.ck.pCur->pVtabCursor->pVtab;
-
  u.ck.pModule = u.ck.pVtab->pModule;
-
  assert( u.ck.pModule->xNext );
+
  u.cn.pVtab = u.cn.pCur->pVtabCursor->pVtab;
+
  u.cn.pModule = u.cn.pVtab->pModule;
+
  assert( u.cn.pModule->xNext );

  /* Invoke the xNext() method of the module. There is no way for the
  ** underlying implementation to return an error if one occurs during
@@ -68601,14 +69498,14 @@ case OP_VNext: { /* jump */
  ** some other method is next invoked on the save virtual table cursor.
  */
  p->inVtabMethod = 1;
-
  rc = u.ck.pModule->xNext(u.ck.pCur->pVtabCursor);
+
  rc = u.cn.pModule->xNext(u.cn.pCur->pVtabCursor);
  p->inVtabMethod = 0;
-
  importVtabErrMsg(p, u.ck.pVtab);
+
  importVtabErrMsg(p, u.cn.pVtab);
  if( rc==SQLITE_OK ){
-
    u.ck.res = u.ck.pModule->xEof(u.ck.pCur->pVtabCursor);
+
    u.cn.res = u.cn.pModule->xEof(u.cn.pCur->pVtabCursor);
  }

-
  if( !u.ck.res ){
+
  if( !u.cn.res ){
    /* If there is data, jump to P2 */
    pc = pOp->p2 - 1;
  }
@@ -68624,19 +69521,19 @@ case OP_VNext: { /* jump */
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
-
#if 0  /* local variables moved into u.cl */
+
#if 0  /* local variables moved into u.co */
  sqlite3_vtab *pVtab;
  Mem *pName;
-
#endif /* local variables moved into u.cl */
-

-
  u.cl.pVtab = pOp->p4.pVtab->pVtab;
-
  u.cl.pName = &aMem[pOp->p1];
-
  assert( u.cl.pVtab->pModule->xRename );
-
  assert( memIsValid(u.cl.pName) );
-
  REGISTER_TRACE(pOp->p1, u.cl.pName);
-
  assert( u.cl.pName->flags & MEM_Str );
-
  rc = u.cl.pVtab->pModule->xRename(u.cl.pVtab, u.cl.pName->z);
-
  importVtabErrMsg(p, u.cl.pVtab);
+
#endif /* local variables moved into u.co */
+

+
  u.co.pVtab = pOp->p4.pVtab->pVtab;
+
  u.co.pName = &aMem[pOp->p1];
+
  assert( u.co.pVtab->pModule->xRename );
+
  assert( memIsValid(u.co.pName) );
+
  REGISTER_TRACE(pOp->p1, u.co.pName);
+
  assert( u.co.pName->flags & MEM_Str );
+
  rc = u.co.pVtab->pModule->xRename(u.co.pVtab, u.co.pName->z);
+
  importVtabErrMsg(p, u.co.pVtab);
  p->expired = 0;

  break;
@@ -68668,7 +69565,7 @@ case OP_VRename: {
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
-
#if 0  /* local variables moved into u.cm */
+
#if 0  /* local variables moved into u.cp */
  sqlite3_vtab *pVtab;
  sqlite3_module *pModule;
  int nArg;
@@ -68676,33 +69573,33 @@ case OP_VUpdate: {
  sqlite_int64 rowid;
  Mem **apArg;
  Mem *pX;
-
#endif /* local variables moved into u.cm */
+
#endif /* local variables moved into u.cp */

  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;
+
  u.cp.pVtab = pOp->p4.pVtab->pVtab;
+
  u.cp.pModule = (sqlite3_module *)u.cp.pVtab->pModule;
+
  u.cp.nArg = pOp->p2;
  assert( pOp->p4type==P4_VTAB );
-
  if( ALWAYS(u.cm.pModule->xUpdate) ){
+
  if( ALWAYS(u.cp.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++){
-
      assert( memIsValid(u.cm.pX) );
-
      memAboutToChange(p, u.cm.pX);
-
      sqlite3VdbeMemStoreType(u.cm.pX);
-
      u.cm.apArg[u.cm.i] = u.cm.pX;
-
      u.cm.pX++;
+
    u.cp.apArg = p->apArg;
+
    u.cp.pX = &aMem[pOp->p3];
+
    for(u.cp.i=0; u.cp.i<u.cp.nArg; u.cp.i++){
+
      assert( memIsValid(u.cp.pX) );
+
      memAboutToChange(p, u.cp.pX);
+
      sqlite3VdbeMemStoreType(u.cp.pX);
+
      u.cp.apArg[u.cp.i] = u.cp.pX;
+
      u.cp.pX++;
    }
    db->vtabOnConflict = pOp->p5;
-
    rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
+
    rc = u.cp.pModule->xUpdate(u.cp.pVtab, u.cp.nArg, u.cp.apArg, &u.cp.rowid);
    db->vtabOnConflict = vtabOnConflict;
-
    importVtabErrMsg(p, u.cm.pVtab);
+
    importVtabErrMsg(p, u.cp.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 = lastRowid = u.cm.rowid;
+
      assert( u.cp.nArg>1 && u.cp.apArg[0] && (u.cp.apArg[0]->flags&MEM_Null) );
+
      db->lastRowid = lastRowid = u.cp.rowid;
    }
    if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
@@ -68762,21 +69659,21 @@ case OP_MaxPgcnt: { /* out2-prerelease */
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
-
#if 0  /* local variables moved into u.cn */
+
#if 0  /* local variables moved into u.cq */
  char *zTrace;
  char *z;
-
#endif /* local variables moved into u.cn */
+
#endif /* local variables moved into u.cq */

-
  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);
+
  if( db->xTrace && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
+
    u.cq.z = sqlite3VdbeExpandSql(p, u.cq.zTrace);
+
    db->xTrace(db->pTraceArg, u.cq.z);
+
    sqlite3DbFree(db, u.cq.z);
  }
#ifdef SQLITE_DEBUG
  if( (db->flags & SQLITE_SqlTrace)!=0
-
   && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+
   && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
-
    sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace);
+
    sqlite3DebugPrintf("SQL-trace: %s\n", u.cq.zTrace);
  }
#endif /* SQLITE_DEBUG */
  break;
@@ -69179,7 +70076,7 @@ SQLITE_API int sqlite3_blob_open(

      /* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
-
      sqlite3VdbeChangeToNoop(v, 2, 1);
+
      sqlite3VdbeChangeToNoop(v, 2);
#else
      sqlite3VdbeChangeP1(v, 2, iDb);
      sqlite3VdbeChangeP2(v, 2, pTab->tnum);
@@ -69189,7 +70086,7 @@ SQLITE_API int sqlite3_blob_open(

      /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
      ** parameter of the other to pTab->tnum.  */
-
      sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
+
      sqlite3VdbeChangeToNoop(v, 4 - flags);
      sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
      sqlite3VdbeChangeP3(v, 3 + flags, iDb);

@@ -69375,6 +70272,889 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
#endif /* #ifndef SQLITE_OMIT_INCRBLOB */

/************** End of vdbeblob.c ********************************************/
+
/************** Begin file vdbesort.c ****************************************/
+
/*
+
** 2011 July 9
+
**
+
** The author disclaims copyright to this source code.  In place of
+
** a legal notice, here is a blessing:
+
**
+
**    May you do good and not evil.
+
**    May you find forgiveness for yourself and forgive others.
+
**    May you share freely, never taking more than you give.
+
**
+
*************************************************************************
+
** This file contains code for the VdbeSorter object, used in concert with
+
** a VdbeCursor to sort large numbers of keys (as may be required, for
+
** example, by CREATE INDEX statements on tables too large to fit in main
+
** memory).
+
*/
+

+

+
#ifndef SQLITE_OMIT_MERGE_SORT
+

+
typedef struct VdbeSorterIter VdbeSorterIter;
+
typedef struct SorterRecord SorterRecord;
+

+
/*
+
** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
+
**
+
** As keys are added to the sorter, they are written to disk in a series
+
** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
+
** the same as the cache-size allowed for temporary databases. In order
+
** to allow the caller to extract keys from the sorter in sorted order,
+
** all PMAs currently stored on disk must be merged together. This comment
+
** describes the data structure used to do so. The structure supports 
+
** merging any number of arrays in a single pass with no redundant comparison 
+
** operations.
+
**
+
** The aIter[] array contains an iterator for each of the PMAs being merged.
+
** An aIter[] iterator either points to a valid key or else is at EOF. For 
+
** the purposes of the paragraphs below, we assume that the array is actually 
+
** N elements in size, where N is the smallest power of 2 greater to or equal 
+
** to the number of iterators being merged. The extra aIter[] elements are 
+
** treated as if they are empty (always at EOF).
+
**
+
** The aTree[] array is also N elements in size. The value of N is stored in
+
** the VdbeSorter.nTree variable.
+
**
+
** The final (N/2) elements of aTree[] contain the results of comparing
+
** pairs of iterator keys together. Element i contains the result of 
+
** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
+
** aTree element is set to the index of it. 
+
**
+
** For the purposes of this comparison, EOF is considered greater than any
+
** other key value. If the keys are equal (only possible with two EOF
+
** values), it doesn't matter which index is stored.
+
**
+
** The (N/4) elements of aTree[] that preceed the final (N/2) described 
+
** above contains the index of the smallest of each block of 4 iterators.
+
** And so on. So that aTree[1] contains the index of the iterator that 
+
** currently points to the smallest key value. aTree[0] is unused.
+
**
+
** Example:
+
**
+
**     aIter[0] -> Banana
+
**     aIter[1] -> Feijoa
+
**     aIter[2] -> Elderberry
+
**     aIter[3] -> Currant
+
**     aIter[4] -> Grapefruit
+
**     aIter[5] -> Apple
+
**     aIter[6] -> Durian
+
**     aIter[7] -> EOF
+
**
+
**     aTree[] = { X, 5   0, 5    0, 3, 5, 6 }
+
**
+
** The current element is "Apple" (the value of the key indicated by 
+
** iterator 5). When the Next() operation is invoked, iterator 5 will
+
** be advanced to the next key in its segment. Say the next key is
+
** "Eggplant":
+
**
+
**     aIter[5] -> Eggplant
+
**
+
** The contents of aTree[] are updated first by comparing the new iterator
+
** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator
+
** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
+
** The value of iterator 6 - "Durian" - is now smaller than that of iterator
+
** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
+
** so the value written into element 1 of the array is 0. As follows:
+
**
+
**     aTree[] = { X, 0   0, 6    0, 3, 5, 6 }
+
**
+
** In other words, each time we advance to the next sorter element, log2(N)
+
** key comparison operations are required, where N is the number of segments
+
** being merged (rounded up to the next power of 2).
+
*/
+
struct VdbeSorter {
+
  int nInMemory;                  /* Current size of pRecord list as PMA */
+
  int nTree;                      /* Used size of aTree/aIter (power of 2) */
+
  VdbeSorterIter *aIter;          /* Array of iterators to merge */
+
  int *aTree;                     /* Current state of incremental merge */
+
  i64 iWriteOff;                  /* Current write offset within file pTemp1 */
+
  i64 iReadOff;                   /* Current read offset within file pTemp1 */
+
  sqlite3_file *pTemp1;           /* PMA file 1 */
+
  int nPMA;                       /* Number of PMAs stored in pTemp1 */
+
  SorterRecord *pRecord;          /* Head of in-memory record list */
+
  int mnPmaSize;                  /* Minimum PMA size, in bytes */
+
  int mxPmaSize;                  /* Maximum PMA size, in bytes.  0==no limit */
+
  UnpackedRecord *pUnpacked;      /* Used to unpack keys */
+
};
+

+
/*
+
** The following type is an iterator for a PMA. It caches the current key in 
+
** variables nKey/aKey. If the iterator is at EOF, pFile==0.
+
*/
+
struct VdbeSorterIter {
+
  i64 iReadOff;                   /* Current read offset */
+
  i64 iEof;                       /* 1 byte past EOF for this iterator */
+
  sqlite3_file *pFile;            /* File iterator is reading from */
+
  int nAlloc;                     /* Bytes of space at aAlloc */
+
  u8 *aAlloc;                     /* Allocated space */
+
  int nKey;                       /* Number of bytes in key */
+
  u8 *aKey;                       /* Pointer to current key */
+
};
+

+
/*
+
** A structure to store a single record. All in-memory records are connected
+
** together into a linked list headed at VdbeSorter.pRecord using the 
+
** SorterRecord.pNext pointer.
+
*/
+
struct SorterRecord {
+
  void *pVal;
+
  int nVal;
+
  SorterRecord *pNext;
+
};
+

+
/* Minimum allowable value for the VdbeSorter.nWorking variable */
+
#define SORTER_MIN_WORKING 10
+

+
/* Maximum number of segments to merge in a single pass. */
+
#define SORTER_MAX_MERGE_COUNT 16
+

+
/*
+
** Free all memory belonging to the VdbeSorterIter object passed as the second
+
** argument. All structure fields are set to zero before returning.
+
*/
+
static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
+
  sqlite3DbFree(db, pIter->aAlloc);
+
  memset(pIter, 0, sizeof(VdbeSorterIter));
+
}
+

+
/*
+
** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
+
** no error occurs, or an SQLite error code if one does.
+
*/
+
static int vdbeSorterIterNext(
+
  sqlite3 *db,                    /* Database handle (for sqlite3DbMalloc() ) */
+
  VdbeSorterIter *pIter           /* Iterator to advance */
+
){
+
  int rc;                         /* Return Code */
+
  int nRead;                      /* Number of bytes read */
+
  int nRec = 0;                   /* Size of record in bytes */
+
  int iOff = 0;                   /* Size of serialized size varint in bytes */
+

+
  assert( pIter->iEof>=pIter->iReadOff );
+
  if( pIter->iEof-pIter->iReadOff>5 ){
+
    nRead = 5;
+
  }else{
+
    nRead = (int)(pIter->iEof - pIter->iReadOff);
+
  }
+
  if( nRead<=0 ){
+
    /* This is an EOF condition */
+
    vdbeSorterIterZero(db, pIter);
+
    return SQLITE_OK;
+
  }
+

+
  rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
+
  if( rc==SQLITE_OK ){
+
    iOff = getVarint32(pIter->aAlloc, nRec);
+
    if( (iOff+nRec)>nRead ){
+
      int nRead2;                   /* Number of extra bytes to read */
+
      if( (iOff+nRec)>pIter->nAlloc ){
+
        int nNew = pIter->nAlloc*2;
+
        while( (iOff+nRec)>nNew ) nNew = nNew*2;
+
        pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
+
        if( !pIter->aAlloc ) return SQLITE_NOMEM;
+
        pIter->nAlloc = nNew;
+
      }
+
  
+
      nRead2 = iOff + nRec - nRead;
+
      rc = sqlite3OsRead(
+
          pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
+
      );
+
    }
+
  }
+

+
  assert( rc!=SQLITE_OK || nRec>0 );
+
  pIter->iReadOff += iOff+nRec;
+
  pIter->nKey = nRec;
+
  pIter->aKey = &pIter->aAlloc[iOff];
+
  return rc;
+
}
+

+
/*
+
** Write a single varint, value iVal, to file-descriptor pFile. Return
+
** SQLITE_OK if successful, or an SQLite error code if some error occurs.
+
**
+
** The value of *piOffset when this function is called is used as the byte
+
** offset in file pFile to write to. Before returning, *piOffset is 
+
** incremented by the number of bytes written.
+
*/
+
static int vdbeSorterWriteVarint(
+
  sqlite3_file *pFile,            /* File to write to */
+
  i64 iVal,                       /* Value to write as a varint */
+
  i64 *piOffset                   /* IN/OUT: Write offset in file pFile */
+
){
+
  u8 aVarint[9];                  /* Buffer large enough for a varint */
+
  int nVarint;                    /* Number of used bytes in varint */
+
  int rc;                         /* Result of write() call */
+

+
  nVarint = sqlite3PutVarint(aVarint, iVal);
+
  rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
+
  *piOffset += nVarint;
+

+
  return rc;
+
}
+

+
/*
+
** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
+
** successful, or an SQLite error code if some error occurs.
+
**
+
** The value of *piOffset when this function is called is used as the
+
** byte offset in file pFile from whence to read the varint. If successful
+
** (i.e. if no IO error occurs), then *piOffset is set to the offset of
+
** the first byte past the end of the varint before returning. *piVal is
+
** set to the integer value read. If an error occurs, the final values of
+
** both *piOffset and *piVal are undefined.
+
*/
+
static int vdbeSorterReadVarint(
+
  sqlite3_file *pFile,            /* File to read from */
+
  i64 *piOffset,                  /* IN/OUT: Read offset in pFile */
+
  i64 *piVal                      /* OUT: Value read from file */
+
){
+
  u8 aVarint[9];                  /* Buffer large enough for a varint */
+
  i64 iOff = *piOffset;           /* Offset in file to read from */
+
  int rc;                         /* Return code */
+

+
  rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
+
  if( rc==SQLITE_OK ){
+
    *piOffset += getVarint(aVarint, (u64 *)piVal);
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** Initialize iterator pIter to scan through the PMA stored in file pFile
+
** starting at offset iStart and ending at offset iEof-1. This function 
+
** leaves the iterator pointing to the first key in the PMA (or EOF if the 
+
** PMA is empty).
+
*/
+
static int vdbeSorterIterInit(
+
  sqlite3 *db,                    /* Database handle */
+
  VdbeSorter *pSorter,            /* Sorter object */
+
  i64 iStart,                     /* Start offset in pFile */
+
  VdbeSorterIter *pIter,          /* Iterator to populate */
+
  i64 *pnByte                     /* IN/OUT: Increment this value by PMA size */
+
){
+
  int rc;
+

+
  assert( pSorter->iWriteOff>iStart );
+
  assert( pIter->aAlloc==0 );
+
  pIter->pFile = pSorter->pTemp1;
+
  pIter->iReadOff = iStart;
+
  pIter->nAlloc = 128;
+
  pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
+
  if( !pIter->aAlloc ){
+
    rc = SQLITE_NOMEM;
+
  }else{
+
    i64 nByte;                         /* Total size of PMA in bytes */
+
    rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
+
    *pnByte += nByte;
+
    pIter->iEof = pIter->iReadOff + nByte;
+
  }
+
  if( rc==SQLITE_OK ){
+
    rc = vdbeSorterIterNext(db, pIter);
+
  }
+
  return rc;
+
}
+

+

+
/*
+
** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, 
+
** size nKey2 bytes).  Argument pKeyInfo supplies the collation functions
+
** used by the comparison. If an error occurs, return an SQLite error code.
+
** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
+
** value, depending on whether key1 is smaller, equal to or larger than key2.
+
**
+
** If the bOmitRowid argument is non-zero, assume both keys end in a rowid
+
** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid
+
** is true and key1 contains even a single NULL value, it is considered to
+
** be less than key2. Even if key2 also contains NULL values.
+
**
+
** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
+
** has been allocated and contains an unpacked record that is used as key2.
+
*/
+
static void vdbeSorterCompare(
+
  VdbeCursor *pCsr,               /* Cursor object (for pKeyInfo) */
+
  int bOmitRowid,                 /* Ignore rowid field at end of keys */
+
  void *pKey1, int nKey1,         /* Left side of comparison */
+
  void *pKey2, int nKey2,         /* Right side of comparison */
+
  int *pRes                       /* OUT: Result of comparison */
+
){
+
  KeyInfo *pKeyInfo = pCsr->pKeyInfo;
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  UnpackedRecord *r2 = pSorter->pUnpacked;
+
  int i;
+

+
  if( pKey2 ){
+
    sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
+
  }
+

+
  if( bOmitRowid ){
+
    r2->nField = pKeyInfo->nField;
+
    assert( r2->nField>0 );
+
    for(i=0; i<r2->nField; i++){
+
      if( r2->aMem[i].flags & MEM_Null ){
+
        *pRes = -1;
+
        return;
+
      }
+
    }
+
    r2->flags |= UNPACKED_PREFIX_MATCH;
+
  }
+

+
  *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
+
}
+

+
/*
+
** This function is called to compare two iterator keys when merging 
+
** multiple b-tree segments. Parameter iOut is the index of the aTree[] 
+
** value to recalculate.
+
*/
+
static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  int i1;
+
  int i2;
+
  int iRes;
+
  VdbeSorterIter *p1;
+
  VdbeSorterIter *p2;
+

+
  assert( iOut<pSorter->nTree && iOut>0 );
+

+
  if( iOut>=(pSorter->nTree/2) ){
+
    i1 = (iOut - pSorter->nTree/2) * 2;
+
    i2 = i1 + 1;
+
  }else{
+
    i1 = pSorter->aTree[iOut*2];
+
    i2 = pSorter->aTree[iOut*2+1];
+
  }
+

+
  p1 = &pSorter->aIter[i1];
+
  p2 = &pSorter->aIter[i2];
+

+
  if( p1->pFile==0 ){
+
    iRes = i2;
+
  }else if( p2->pFile==0 ){
+
    iRes = i1;
+
  }else{
+
    int res;
+
    assert( pCsr->pSorter->pUnpacked!=0 );  /* allocated in vdbeSorterMerge() */
+
    vdbeSorterCompare(
+
        pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
+
    );
+
    if( res<=0 ){
+
      iRes = i1;
+
    }else{
+
      iRes = i2;
+
    }
+
  }
+

+
  pSorter->aTree[iOut] = iRes;
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Initialize the temporary index cursor just opened as a sorter cursor.
+
*/
+
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
+
  int pgsz;                       /* Page size of main database */
+
  int mxCache;                    /* Cache size */
+
  VdbeSorter *pSorter;            /* The new sorter */
+
  char *d;                        /* Dummy */
+

+
  assert( pCsr->pKeyInfo && pCsr->pBt==0 );
+
  pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
+
  if( pSorter==0 ){
+
    return SQLITE_NOMEM;
+
  }
+
  
+
  pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
+
  if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
+
  assert( pSorter->pUnpacked==(UnpackedRecord *)d );
+

+
  if( !sqlite3TempInMemory(db) ){
+
    pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+
    pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
+
    mxCache = db->aDb[0].pSchema->cache_size;
+
    if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
+
    pSorter->mxPmaSize = mxCache * pgsz;
+
  }
+

+
  return SQLITE_OK;
+
}
+

+
/*
+
** Free the list of sorted records starting at pRecord.
+
*/
+
static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
+
  SorterRecord *p;
+
  SorterRecord *pNext;
+
  for(p=pRecord; p; p=pNext){
+
    pNext = p->pNext;
+
    sqlite3DbFree(db, p);
+
  }
+
}
+

+
/*
+
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
+
*/
+
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  if( pSorter ){
+
    if( pSorter->aIter ){
+
      int i;
+
      for(i=0; i<pSorter->nTree; i++){
+
        vdbeSorterIterZero(db, &pSorter->aIter[i]);
+
      }
+
      sqlite3DbFree(db, pSorter->aIter);
+
    }
+
    if( pSorter->pTemp1 ){
+
      sqlite3OsCloseFree(pSorter->pTemp1);
+
    }
+
    vdbeSorterRecordFree(db, pSorter->pRecord);
+
    sqlite3DbFree(db, pSorter->pUnpacked);
+
    sqlite3DbFree(db, pSorter);
+
    pCsr->pSorter = 0;
+
  }
+
}
+

+
/*
+
** Allocate space for a file-handle and open a temporary file. If successful,
+
** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
+
** Otherwise, set *ppFile to 0 and return an SQLite error code.
+
*/
+
static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
+
  int dummy;
+
  return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
+
      SQLITE_OPEN_TEMP_JOURNAL |
+
      SQLITE_OPEN_READWRITE    | SQLITE_OPEN_CREATE |
+
      SQLITE_OPEN_EXCLUSIVE    | SQLITE_OPEN_DELETEONCLOSE, &dummy
+
  );
+
}
+

+
/*
+
** Merge the two sorted lists p1 and p2 into a single list.
+
** Set *ppOut to the head of the new list.
+
*/
+
static void vdbeSorterMerge(
+
  VdbeCursor *pCsr,               /* For pKeyInfo */
+
  SorterRecord *p1,               /* First list to merge */
+
  SorterRecord *p2,               /* Second list to merge */
+
  SorterRecord **ppOut            /* OUT: Head of merged list */
+
){
+
  SorterRecord *pFinal = 0;
+
  SorterRecord **pp = &pFinal;
+
  void *pVal2 = p2 ? p2->pVal : 0;
+

+
  while( p1 && p2 ){
+
    int res;
+
    vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
+
    if( res<=0 ){
+
      *pp = p1;
+
      pp = &p1->pNext;
+
      p1 = p1->pNext;
+
      pVal2 = 0;
+
    }else{
+
      *pp = p2;
+
       pp = &p2->pNext;
+
      p2 = p2->pNext;
+
      if( p2==0 ) break;
+
      pVal2 = p2->pVal;
+
    }
+
  }
+
  *pp = p1 ? p1 : p2;
+
  *ppOut = pFinal;
+
}
+

+
/*
+
** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK
+
** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
+
** occurs.
+
*/
+
static int vdbeSorterSort(VdbeCursor *pCsr){
+
  int i;
+
  SorterRecord **aSlot;
+
  SorterRecord *p;
+
  VdbeSorter *pSorter = pCsr->pSorter;
+

+
  aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
+
  if( !aSlot ){
+
    return SQLITE_NOMEM;
+
  }
+

+
  p = pSorter->pRecord;
+
  while( p ){
+
    SorterRecord *pNext = p->pNext;
+
    p->pNext = 0;
+
    for(i=0; aSlot[i]; i++){
+
      vdbeSorterMerge(pCsr, p, aSlot[i], &p);
+
      aSlot[i] = 0;
+
    }
+
    aSlot[i] = p;
+
    p = pNext;
+
  }
+

+
  p = 0;
+
  for(i=0; i<64; i++){
+
    vdbeSorterMerge(pCsr, p, aSlot[i], &p);
+
  }
+
  pSorter->pRecord = p;
+

+
  sqlite3_free(aSlot);
+
  return SQLITE_OK;
+
}
+

+

+
/*
+
** Write the current contents of the in-memory linked-list to a PMA. Return
+
** SQLITE_OK if successful, or an SQLite error code otherwise.
+
**
+
** The format of a PMA is:
+
**
+
**     * A varint. This varint contains the total number of bytes of content
+
**       in the PMA (not including the varint itself).
+
**
+
**     * One or more records packed end-to-end in order of ascending keys. 
+
**       Each record consists of a varint followed by a blob of data (the 
+
**       key). The varint is the number of bytes in the blob of data.
+
*/
+
static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
+
  int rc = SQLITE_OK;             /* Return code */
+
  VdbeSorter *pSorter = pCsr->pSorter;
+

+
  if( pSorter->nInMemory==0 ){
+
    assert( pSorter->pRecord==0 );
+
    return rc;
+
  }
+

+
  rc = vdbeSorterSort(pCsr);
+

+
  /* If the first temporary PMA file has not been opened, open it now. */
+
  if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
+
    rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
+
    assert( rc!=SQLITE_OK || pSorter->pTemp1 );
+
    assert( pSorter->iWriteOff==0 );
+
    assert( pSorter->nPMA==0 );
+
  }
+

+
  if( rc==SQLITE_OK ){
+
    i64 iOff = pSorter->iWriteOff;
+
    SorterRecord *p;
+
    SorterRecord *pNext = 0;
+
    static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+

+
    pSorter->nPMA++;
+
    rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
+
    for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
+
      pNext = p->pNext;
+
      rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);
+

+
      if( rc==SQLITE_OK ){
+
        rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
+
        iOff += p->nVal;
+
      }
+

+
      sqlite3DbFree(db, p);
+
    }
+

+
    /* This assert verifies that unless an error has occurred, the size of 
+
    ** the PMA on disk is the same as the expected size stored in
+
    ** pSorter->nInMemory. */ 
+
    assert( rc!=SQLITE_OK || pSorter->nInMemory==(
+
          iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
+
    ));
+

+
    pSorter->iWriteOff = iOff;
+
    if( rc==SQLITE_OK ){
+
      /* Terminate each file with 8 extra bytes so that from any offset
+
      ** in the file we can always read 9 bytes without a SHORT_READ error */
+
      rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
+
    }
+
    pSorter->pRecord = p;
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** Add a record to the sorter.
+
*/
+
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
+
  sqlite3 *db,                    /* Database handle */
+
  VdbeCursor *pCsr,               /* Sorter cursor */
+
  Mem *pVal                       /* Memory cell containing record */
+
){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  int rc = SQLITE_OK;             /* Return Code */
+
  SorterRecord *pNew;             /* New list element */
+

+
  assert( pSorter );
+
  pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;
+

+
  pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
+
  if( pNew==0 ){
+
    rc = SQLITE_NOMEM;
+
  }else{
+
    pNew->pVal = (void *)&pNew[1];
+
    memcpy(pNew->pVal, pVal->z, pVal->n);
+
    pNew->nVal = pVal->n;
+
    pNew->pNext = pSorter->pRecord;
+
    pSorter->pRecord = pNew;
+
  }
+

+
  /* See if the contents of the sorter should now be written out. They
+
  ** are written out when either of the following are true:
+
  **
+
  **   * The total memory allocated for the in-memory list is greater 
+
  **     than (page-size * cache-size), or
+
  **
+
  **   * The total memory allocated for the in-memory list is greater 
+
  **     than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
+
  */
+
  if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
+
        (pSorter->nInMemory>pSorter->mxPmaSize)
+
     || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
+
  )){
+
    rc = vdbeSorterListToPMA(db, pCsr);
+
    pSorter->nInMemory = 0;
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** Helper function for sqlite3VdbeSorterRewind(). 
+
*/
+
static int vdbeSorterInitMerge(
+
  sqlite3 *db,                    /* Database handle */
+
  VdbeCursor *pCsr,               /* Cursor handle for this sorter */
+
  i64 *pnByte                     /* Sum of bytes in all opened PMAs */
+
){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  int rc = SQLITE_OK;             /* Return code */
+
  int i;                          /* Used to iterator through aIter[] */
+
  i64 nByte = 0;                  /* Total bytes in all opened PMAs */
+

+
  /* Initialize the iterators. */
+
  for(i=0; i<SORTER_MAX_MERGE_COUNT; i++){
+
    VdbeSorterIter *pIter = &pSorter->aIter[i];
+
    rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
+
    pSorter->iReadOff = pIter->iEof;
+
    assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff );
+
    if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break;
+
  }
+

+
  /* Initialize the aTree[] array. */
+
  for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
+
    rc = vdbeSorterDoCompare(pCsr, i);
+
  }
+

+
  *pnByte = nByte;
+
  return rc;
+
}
+

+
/*
+
** Once the sorter has been populated, this function is called to prepare
+
** for iterating through its contents in sorted order.
+
*/
+
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  int rc;                         /* Return code */
+
  sqlite3_file *pTemp2 = 0;       /* Second temp file to use */
+
  i64 iWrite2 = 0;                /* Write offset for pTemp2 */
+
  int nIter;                      /* Number of iterators used */
+
  int nByte;                      /* Bytes of space required for aIter/aTree */
+
  int N = 2;                      /* Power of 2 >= nIter */
+

+
  assert( pSorter );
+

+
  /* If no data has been written to disk, then do not do so now. Instead,
+
  ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
+
  ** from the in-memory list.  */
+
  if( pSorter->nPMA==0 ){
+
    *pbEof = !pSorter->pRecord;
+
    assert( pSorter->aTree==0 );
+
    return vdbeSorterSort(pCsr);
+
  }
+

+
  /* Write the current b-tree to a PMA. Close the b-tree cursor. */
+
  rc = vdbeSorterListToPMA(db, pCsr);
+
  if( rc!=SQLITE_OK ) return rc;
+

+
  /* Allocate space for aIter[] and aTree[]. */
+
  nIter = pSorter->nPMA;
+
  if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
+
  assert( nIter>0 );
+
  while( N<nIter ) N += N;
+
  nByte = N * (sizeof(int) + sizeof(VdbeSorterIter));
+
  pSorter->aIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte);
+
  if( !pSorter->aIter ) return SQLITE_NOMEM;
+
  pSorter->aTree = (int *)&pSorter->aIter[N];
+
  pSorter->nTree = N;
+

+
  do {
+
    int iNew;                     /* Index of new, merged, PMA */
+

+
    for(iNew=0; 
+
        rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA; 
+
        iNew++
+
    ){
+
      i64 nWrite;                 /* Number of bytes in new PMA */
+

+
      /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
+
      ** initialize an iterator for each of them and break out of the loop.
+
      ** These iterators will be incrementally merged as the VDBE layer calls
+
      ** sqlite3VdbeSorterNext().
+
      **
+
      ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs,
+
      ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs
+
      ** are merged into a single PMA that is written to file pTemp2.
+
      */
+
      rc = vdbeSorterInitMerge(db, pCsr, &nWrite);
+
      assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile );
+
      if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
+
        break;
+
      }
+

+
      /* Open the second temp file, if it is not already open. */
+
      if( pTemp2==0 ){
+
        assert( iWrite2==0 );
+
        rc = vdbeSorterOpenTempFile(db, &pTemp2);
+
      }
+

+
      if( rc==SQLITE_OK ){
+
        rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
+
      }
+

+
      if( rc==SQLITE_OK ){
+
        int bEof = 0;
+
        while( rc==SQLITE_OK && bEof==0 ){
+
          int nToWrite;
+
          VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+
          assert( pIter->pFile );
+
          nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
+
          rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
+
          iWrite2 += nToWrite;
+
          if( rc==SQLITE_OK ){
+
            rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
+
          }
+
        }
+
      }
+
    }
+

+
    if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
+
      break;
+
    }else{
+
      sqlite3_file *pTmp = pSorter->pTemp1;
+
      pSorter->nPMA = iNew;
+
      pSorter->pTemp1 = pTemp2;
+
      pTemp2 = pTmp;
+
      pSorter->iWriteOff = iWrite2;
+
      pSorter->iReadOff = 0;
+
      iWrite2 = 0;
+
    }
+
  }while( rc==SQLITE_OK );
+

+
  if( pTemp2 ){
+
    sqlite3OsCloseFree(pTemp2);
+
  }
+
  *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+
  return rc;
+
}
+

+
/*
+
** Advance to the next element in the sorter.
+
*/
+
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  int rc;                         /* Return code */
+

+
  if( pSorter->aTree ){
+
    int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
+
    int i;                        /* Index of aTree[] to recalculate */
+

+
    rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
+
    for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
+
      rc = vdbeSorterDoCompare(pCsr, i);
+
    }
+

+
    *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+
  }else{
+
    SorterRecord *pFree = pSorter->pRecord;
+
    pSorter->pRecord = pFree->pNext;
+
    pFree->pNext = 0;
+
    vdbeSorterRecordFree(db, pFree);
+
    *pbEof = !pSorter->pRecord;
+
    rc = SQLITE_OK;
+
  }
+
  return rc;
+
}
+

+
/*
+
** Return a pointer to a buffer owned by the sorter that contains the 
+
** current key.
+
*/
+
static void *vdbeSorterRowkey(
+
  VdbeSorter *pSorter,            /* Sorter object */
+
  int *pnKey                      /* OUT: Size of current key in bytes */
+
){
+
  void *pKey;
+
  if( pSorter->aTree ){
+
    VdbeSorterIter *pIter;
+
    pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+
    *pnKey = pIter->nKey;
+
    pKey = pIter->aKey;
+
  }else{
+
    *pnKey = pSorter->pRecord->nVal;
+
    pKey = pSorter->pRecord->pVal;
+
  }
+
  return pKey;
+
}
+

+
/*
+
** Copy the current sorter key into the memory cell pOut.
+
*/
+
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  void *pKey; int nKey;           /* Sorter key to copy into pOut */
+

+
  pKey = vdbeSorterRowkey(pSorter, &nKey);
+
  if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
+
    return SQLITE_NOMEM;
+
  }
+
  pOut->n = nKey;
+
  MemSetTypeFlag(pOut, MEM_Blob);
+
  memcpy(pOut->z, pKey, nKey);
+

+
  return SQLITE_OK;
+
}
+

+
/*
+
** Compare the key in memory cell pVal with the key that the sorter cursor
+
** passed as the first argument currently points to. For the purposes of
+
** the comparison, ignore the rowid field at the end of each record.
+
**
+
** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
+
** Otherwise, set *pRes to a negative, zero or positive value if the
+
** key in pVal is smaller than, equal to or larger than the current sorter
+
** key.
+
*/
+
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
+
  VdbeCursor *pCsr,               /* Sorter cursor */
+
  Mem *pVal,                      /* Value to compare to current sorter key */
+
  int *pRes                       /* OUT: Result of comparison */
+
){
+
  VdbeSorter *pSorter = pCsr->pSorter;
+
  void *pKey; int nKey;           /* Sorter key to compare pVal with */
+

+
  pKey = vdbeSorterRowkey(pSorter, &nKey);
+
  vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
+
  return SQLITE_OK;
+
}
+

+
#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
+

+
/************** End of vdbesort.c ********************************************/
/************** Begin file journal.c *****************************************/
/*
** 2007 August 22
@@ -69891,6 +71671,8 @@ SQLITE_PRIVATE int sqlite3MemJournalSize(void){
** This file contains routines used for walking the parser tree for
** an SQL statement.
*/
+
/* #include <stdlib.h> */
+
/* #include <string.h> */


/*
@@ -70029,6 +71811,8 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
** resolve all identifiers by associating them with a particular
** table and column.
*/
+
/* #include <stdlib.h> */
+
/* #include <string.h> */

/*
** Turn the pExpr expression into an alias for the iCol-th column of the
@@ -71008,11 +72792,25 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
    for(i=0; i<p->pSrc->nSrc; i++){
      struct SrcList_item *pItem = &p->pSrc->a[i];
      if( pItem->pSelect ){
+
        NameContext *pNC;         /* Used to iterate name contexts */
+
        int nRef = 0;             /* Refcount for pOuterNC and outer contexts */
        const char *zSavedContext = pParse->zAuthContext;
+

+
        /* Count the total number of references to pOuterNC and all of its
+
        ** parent contexts. After resolving references to expressions in
+
        ** pItem->pSelect, check if this value has changed. If so, then
+
        ** SELECT statement pItem->pSelect must be correlated. Set the
+
        ** pItem->isCorrelated flag if this is the case. */
+
        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
+

        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
        sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
        pParse->zAuthContext = zSavedContext;
        if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+

+
        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
+
        assert( pItem->isCorrelated==0 && nRef<=0 );
+
        pItem->isCorrelated = (nRef!=0);
      }
    }
  
@@ -72119,7 +73917,9 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
    pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
    pNewItem->jointype = pOldItem->jointype;
    pNewItem->iCursor = pOldItem->iCursor;
-
    pNewItem->isPopulated = pOldItem->isPopulated;
+
    pNewItem->addrFillSub = pOldItem->addrFillSub;
+
    pNewItem->regReturn = pOldItem->regReturn;
+
    pNewItem->isCorrelated = pOldItem->isCorrelated;
    pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
    pNewItem->notIndexed = pOldItem->notIndexed;
    pNewItem->pIndex = pOldItem->pIndex;
@@ -72678,8 +74478,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
      int iMem = ++pParse->nMem;
      int iAddr;

-
      iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
-
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+
      iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);

      sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
      eType = IN_INDEX_ROWID;
@@ -72710,8 +74509,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
          char *pKey;
  
          pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
-
          iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
-
          sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+
          iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
  
          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                               pKey,P4_KEYINFO_HANDOFF);
@@ -72792,7 +74590,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
  int rMayHaveNull,       /* Register that records whether NULLs exist in RHS */
  int isRowid             /* If true, LHS of IN operator is a rowid */
){
-
  int testAddr = 0;                       /* One-time test address */
+
  int testAddr = -1;                      /* One-time test address */
  int rReg = 0;                           /* Register storing resulting */
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( NEVER(v==0) ) return 0;
@@ -72810,15 +74608,13 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
  */
  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
    int mem = ++pParse->nMem;
-
    sqlite3VdbeAddOp1(v, OP_If, mem);
-
    testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
-
    assert( testAddr>0 || pParse->db->mallocFailed );
+
    testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
  }

#ifndef SQLITE_OMIT_EXPLAIN
  if( pParse->explain==2 ){
    char *zMsg = sqlite3MPrintf(
-
        pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ",
+
        pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
        pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
    );
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
@@ -72910,9 +74706,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
          ** this code only executes once.  Because for a non-constant
          ** expression we need to rerun this code each time.
          */
-
          if( testAddr && !sqlite3ExprIsConstant(pE2) ){
-
            sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
-
            testAddr = 0;
+
          if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
+
            sqlite3VdbeChangeToNoop(v, testAddr);
+
            testAddr = -1;
          }

          /* Evaluate the expression and insert it into the temp table */
@@ -72981,8 +74777,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
    }
  }

-
  if( testAddr ){
-
    sqlite3VdbeJumpHere(v, testAddr-1);
+
  if( testAddr>=0 ){
+
    sqlite3VdbeJumpHere(v, testAddr);
  }
  sqlite3ExprCachePop(pParse, 1);

@@ -73504,7 +75300,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
        inReg = pCol->iMem;
        break;
      }else if( pAggInfo->useSortingIdx ){
-
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
+
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
                              pCol->iSorterColumn, target);
        break;
      }
@@ -79010,7 +80806,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
  const char *z;
  Token sEnd;
  DbFixer sFix;
-
  Token *pName;
+
  Token *pName = 0;
  int iDb;
  sqlite3 *db = pParse->db;

@@ -79317,6 +81113,29 @@ static void destroyTable(Parse *pParse, Table *pTab){
}

/*
+
** Remove entries from the sqlite_stat1 and sqlite_stat2 tables
+
** after a DROP INDEX or DROP TABLE command.
+
*/
+
static void sqlite3ClearStatTables(
+
  Parse *pParse,         /* The parsing context */
+
  int iDb,               /* The database number */
+
  const char *zType,     /* "idx" or "tbl" */
+
  const char *zName      /* Name of index or table */
+
){
+
  static const char *azStatTab[] = { "sqlite_stat1", "sqlite_stat2" };
+
  int i;
+
  const char *zDbName = pParse->db->aDb[iDb].zName;
+
  for(i=0; i<ArraySize(azStatTab); i++){
+
    if( sqlite3FindTable(pParse->db, azStatTab[i], zDbName) ){
+
      sqlite3NestedParse(pParse,
+
        "DELETE FROM %Q.%s WHERE %s=%Q",
+
        zDbName, azStatTab[i], zType, zName
+
      );
+
    }
+
  }
+
}
+

+
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
@@ -79455,14 +81274,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
    sqlite3NestedParse(pParse, 
        "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
        pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
-

-
    /* Drop any statistics from the sqlite_stat1 table, if it exists */
-
    if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
-
      sqlite3NestedParse(pParse,
-
        "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName
-
      );
-
    }
-

+
    sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
    if( !isView && !IsVirtual(pTab) ){
      destroyTable(pParse, pTab);
    }
@@ -79644,7 +81456,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Btree cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Btree cursor used for pIndex */
+
  int iSorter = iTab;            /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
+
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
  Vdbe *v;                       /* Generate code into this virtual machine */
  KeyInfo *pKey;                 /* KeyInfo for index */
@@ -79677,10 +81491,41 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
  if( memRootPage>=0 ){
    sqlite3VdbeChangeP5(v, 1);
  }
+

+
#ifndef SQLITE_OMIT_MERGE_SORT
+
  /* Open the sorter cursor if we are to use one. */
+
  iSorter = pParse->nTab++;
+
  sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
+
#endif
+

+
  /* Open the table. Loop through all rows of the table, inserting index
+
  ** records into the sorter. */
  sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
+
  addr2 = addr1 + 1;
  regRecord = sqlite3GetTempReg(pParse);
  regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+

+
#ifndef SQLITE_OMIT_MERGE_SORT
+
  sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
+
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
+
  sqlite3VdbeJumpHere(v, addr1);
+
  addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
+
  if( pIndex->onError!=OE_None ){
+
    int j2 = sqlite3VdbeCurrentAddr(v) + 3;
+
    sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
+
    addr2 = sqlite3VdbeCurrentAddr(v);
+
    sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
+
    sqlite3HaltConstraint(
+
        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
+
    );
+
  }else{
+
    addr2 = sqlite3VdbeCurrentAddr(v);
+
  }
+
  sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
+
  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
+
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+
#else
  if( pIndex->onError!=OE_None ){
    const int regRowid = regIdxKey + pIndex->nColumn;
    const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
@@ -79699,13 +81544,16 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
    sqlite3HaltConstraint(
        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
  }
-
  sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
+
  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+
#endif
  sqlite3ReleaseTempReg(pParse, regRecord);
-
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
+
  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  sqlite3VdbeJumpHere(v, addr1);
+

  sqlite3VdbeAddOp1(v, OP_Close, iTab);
  sqlite3VdbeAddOp1(v, OP_Close, iIdx);
+
  sqlite3VdbeAddOp1(v, OP_Close, iSorter);
}

/*
@@ -80127,7 +81975,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
        onError==OE_None ? "" : " UNIQUE",
-
        pEnd->z - pName->z + 1,
+
        (int)(pEnd->z - pName->z) + 1,
        pName->z);
    }else{
      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
@@ -80285,15 +82133,9 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
-
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
-
       pIndex->zName
+
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
    );
-
    if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
-
      sqlite3NestedParse(pParse,
-
        "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
-
        db->aDb[iDb].zName, pIndex->zName
-
      );
-
    }
+
    sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
    sqlite3ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
@@ -80665,8 +82507,9 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI
** operator with A.  This routine shifts that operator over to B.
*/
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
-
  if( p && p->a ){
+
  if( p ){
    int i;
+
    assert( p->a || p->nSrc==0 );
    for(i=p->nSrc-1; i>0; i--){
      p->a[i].jointype = p->a[i-1].jointype;
    }
@@ -81922,7 +83765,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
    /* Collect rowids of every row to be deleted.
    */
    sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
-
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
+
    pWInfo = sqlite3WhereBegin(
+
        pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
+
    );
    if( pWInfo==0 ) goto delete_from_cleanup;
    regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
    sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
@@ -82220,6 +84065,8 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
*/
+
/* #include <stdlib.h> */
+
/* #include <assert.h> */

/*
** Return the collating function associated with a function.
@@ -84369,7 +86216,7 @@ static void fkScanChildren(
  ** clause. If the constraint is not deferred, throw an exception for
  ** each row found. Otherwise, for deferred constraints, increment the
  ** deferred constraint counter by nIncr for each row selected.  */
-
  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
+
  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite3ParseToplevel(pParse)->mayAbort = 1;
  }
@@ -84543,7 +86390,24 @@ SQLITE_PRIVATE void sqlite3FkCheck(
      pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
    }
    if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+
      assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
      if( !isIgnoreErrors || db->mallocFailed ) return;
+
      if( pTo==0 ){
+
        /* If isIgnoreErrors is true, then a table is being dropped. In this
+
        ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
+
        ** before actually dropping it in order to check FK constraints.
+
        ** If the parent table of an FK constraint on the current table is
+
        ** missing, behave as if it is empty. i.e. decrement the relevant
+
        ** FK counter for each row of the current table with non-NULL keys.
+
        */
+
        Vdbe *v = sqlite3GetVdbe(pParse);
+
        int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
+
        for(i=0; i<pFKey->nCol; i++){
+
          int iReg = pFKey->aCol[i].iFrom + regOld + 1;
+
          sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
+
        }
+
        sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
+
      }
      continue;
    }
    assert( pFKey->nCol==1 || (aiFree && pIdx) );
@@ -87236,6 +89100,9 @@ struct sqlite3_api_routines {
  int (*wal_autocheckpoint)(sqlite3*,int);
  int (*wal_checkpoint)(sqlite3*,const char*);
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
+
  int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
+
  int (*vtab_config)(sqlite3*,int op,...);
+
  int (*vtab_on_conflict)(sqlite3*);
};

/*
@@ -87436,6 +89303,9 @@ struct sqlite3_api_routines {
#define sqlite3_wal_autocheckpoint     sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint         sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook               sqlite3_api->wal_hook
+
#define sqlite3_blob_reopen            sqlite3_api->blob_reopen
+
#define sqlite3_vtab_config            sqlite3_api->vtab_config
+
#define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
#endif /* SQLITE_CORE */

#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
@@ -87445,6 +89315,7 @@ struct sqlite3_api_routines {

/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/
+
/* #include <string.h> */

#ifndef SQLITE_OMIT_LOAD_EXTENSION

@@ -87510,6 +89381,8 @@ struct sqlite3_api_routines {
# define sqlite3_create_module 0
# define sqlite3_create_module_v2 0
# define sqlite3_declare_vtab 0
+
# define sqlite3_vtab_config 0
+
# define sqlite3_vtab_on_conflict 0
#endif

#ifdef SQLITE_OMIT_SHARED_CACHE
@@ -87533,6 +89406,7 @@ struct sqlite3_api_routines {
#define sqlite3_blob_open      0
#define sqlite3_blob_read      0
#define sqlite3_blob_write     0
+
#define sqlite3_blob_reopen    0
#endif

/*
@@ -87798,6 +89672,9 @@ static const sqlite3_api_routines sqlite3Apis = {
  0,
  0,
#endif
+
  sqlite3_blob_reopen,
+
  sqlite3_vtab_config,
+
  sqlite3_vtab_on_conflict,
};

/*
@@ -90555,6 +92432,8 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
    clearSelect(db, pNew);
    if( pNew!=&standin ) sqlite3DbFree(db, pNew);
    pNew = 0;
+
  }else{
+
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
  return pNew;
}
@@ -90885,12 +92764,18 @@ static void pushOntoSorter(
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
  int regRecord = sqlite3GetTempReg(pParse);
+
  int op;
  sqlite3ExprCacheClear(pParse);
  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
  sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
-
  sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
+
  if( pSelect->selFlags & SF_UseSorter ){
+
    op = OP_SorterInsert;
+
  }else{
+
    op = OP_IdxInsert;
+
  }
+
  sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
  if( pSelect->iLimit ){
@@ -91359,9 +93244,20 @@ static void generateSortTail(
  }else{
    regRowid = sqlite3GetTempReg(pParse);
  }
-
  addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
-
  codeOffset(v, p, addrContinue);
-
  sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
+
  if( p->selFlags & SF_UseSorter ){
+
    int regSortOut = ++pParse->nMem;
+
    int ptab2 = pParse->nTab++;
+
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
+
    addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
+
    codeOffset(v, p, addrContinue);
+
    sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
+
    sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
+
    sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
+
  }else{
+
    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
+
    codeOffset(v, p, addrContinue);
+
    sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
+
  }
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
@@ -91414,7 +93310,11 @@ static void generateSortTail(
  /* The bottom of the loop
  */
  sqlite3VdbeResolveLabel(v, addrContinue);
-
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
+
  if( p->selFlags & SF_UseSorter ){
+
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
+
  }else{
+
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
+
  }
  sqlite3VdbeResolveLabel(v, addrBreak);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
@@ -94187,6 +96087,7 @@ SQLITE_PRIVATE int sqlite3Select(
  int distinct;          /* Table to use for the distinct set */
  int rc = 1;            /* Value to return from this function */
  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
+
  int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite3 *db;           /* The database connection */
@@ -94245,7 +96146,11 @@ SQLITE_PRIVATE int sqlite3Select(
    Select *pSub = pItem->pSelect;
    int isAggSub;

-
    if( pSub==0 || pItem->isPopulated ) continue;
+
    if( pSub==0 ) continue;
+
    if( pItem->addrFillSub ){
+
      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+
      continue;
+
    }

    /* Increment Parse.nHeight by the height of the largest expression
    ** tree refered to by this, the parent select. The child select
@@ -94256,21 +96161,44 @@ SQLITE_PRIVATE int sqlite3Select(
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);

-
    /* Check to see if the subquery can be absorbed into the parent. */
    isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
    if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
+
      /* This subquery can be absorbed into its parent. */
      if( isAggSub ){
        isAgg = 1;
        p->selFlags |= SF_Aggregate;
      }
      i = -1;
    }else{
+
      /* Generate a subroutine that will fill an ephemeral table with
+
      ** the content of this subquery.  pItem->addrFillSub will point
+
      ** to the address of the generated subroutine.  pItem->regReturn
+
      ** is a register allocated to hold the subroutine return address
+
      */
+
      int topAddr;
+
      int onceAddr = 0;
+
      int retAddr;
+
      assert( pItem->addrFillSub==0 );
+
      pItem->regReturn = ++pParse->nMem;
+
      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
+
      pItem->addrFillSub = topAddr+1;
+
      VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
+
      if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
+
        /* If the subquery is no correlated and if we are not inside of
+
        ** a trigger, then we only need to compute the value of the subquery
+
        ** once. */
+
        int regOnce = ++pParse->nMem;
+
        onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
+
      }
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
-
      assert( pItem->isPopulated==0 );
      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
      sqlite3Select(pParse, pSub, &dest);
-
      pItem->isPopulated = 1;
      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+
      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
+
      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
+
      VdbeComment((v, "end %s", pItem->pTab->zName));
+
      sqlite3VdbeChangeP1(v, topAddr, retAddr);
+

    }
    if( /*pParse->nErr ||*/ db->mallocFailed ){
      goto select_end;
@@ -94313,16 +96241,6 @@ SQLITE_PRIVATE int sqlite3Select(
  }
#endif

-
  /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
-
  ** GROUP BY might use an index, DISTINCT never does.
-
  */
-
  assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
-
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
-
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
-
    pGroupBy = p->pGroupBy;
-
    p->selFlags &= ~SF_Distinct;
-
  }
-

  /* If there is both a GROUP BY and an ORDER BY clause and they are
  ** identical, then disable the ORDER BY clause since the GROUP BY
  ** will cause elements to come out in the correct order.  This is
@@ -94335,6 +96253,30 @@ SQLITE_PRIVATE int sqlite3Select(
    pOrderBy = 0;
  }

+
  /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and 
+
  ** if the select-list is the same as the ORDER BY list, then this query
+
  ** can be rewritten as a GROUP BY. In other words, this:
+
  **
+
  **     SELECT DISTINCT xyz FROM ... ORDER BY xyz
+
  **
+
  ** is transformed to:
+
  **
+
  **     SELECT xyz FROM ... GROUP BY xyz
+
  **
+
  ** The second form is preferred as a single index (or temp-table) may be 
+
  ** used for both the ORDER BY and DISTINCT processing. As originally 
+
  ** written the query must use a temp-table for at least one of the ORDER 
+
  ** BY and DISTINCT, and an index or separate temp-table for the other.
+
  */
+
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct 
+
   && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
+
  ){
+
    p->selFlags &= ~SF_Distinct;
+
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
+
    pGroupBy = p->pGroupBy;
+
    pOrderBy = 0;
+
  }
+

  /* If there is an ORDER BY clause, then this sorting
  ** index might end up being unused if the data can be 
  ** extracted in pre-sorted order.  If that is the case, then the
@@ -94365,27 +96307,30 @@ SQLITE_PRIVATE int sqlite3Select(
  iEnd = sqlite3VdbeMakeLabel(v);
  p->nSelectRow = (double)LARGEST_INT64;
  computeLimitRegisters(pParse, p, iEnd);
+
  if( p->iLimit==0 && addrSortIndex>=0 ){
+
    sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
+
    p->selFlags |= SF_UseSorter;
+
  }

  /* Open a virtual index to use for the distinct set.
  */
  if( p->selFlags & SF_Distinct ){
    KeyInfo *pKeyInfo;
-
    assert( isAgg || pGroupBy );
    distinct = pParse->nTab++;
    pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
-
    sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
-
                        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+
    addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
+
        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
    sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
  }else{
-
    distinct = -1;
+
    distinct = addrDistinctIndex = -1;
  }

  /* Aggregate and non-aggregate queries are handled differently */
  if( !isAgg && pGroupBy==0 ){
-
    /* This case is for non-aggregate queries
-
    ** Begin the database scan
-
    */
-
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
+
    ExprList *pDist = (isDistinct ? p->pEList : 0);
+

+
    /* Begin the database scan. */
+
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
    if( pWInfo==0 ) goto select_end;
    if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;

@@ -94394,14 +96339,56 @@ SQLITE_PRIVATE int sqlite3Select(
    ** into an OP_Noop.
    */
    if( addrSortIndex>=0 && pOrderBy==0 ){
-
      sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
+
      sqlite3VdbeChangeToNoop(v, addrSortIndex);
      p->addrOpenEphm[2] = -1;
    }

-
    /* Use the standard inner loop
-
    */
-
    assert(!isDistinct);
-
    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
+
    if( pWInfo->eDistinct ){
+
      VdbeOp *pOp;                /* No longer required OpenEphemeral instr. */
+
     
+
      assert( addrDistinctIndex>=0 );
+
      pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
+

+
      assert( isDistinct );
+
      assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED 
+
           || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE 
+
      );
+
      distinct = -1;
+
      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
+
        int iJump;
+
        int iExpr;
+
        int iFlag = ++pParse->nMem;
+
        int iBase = pParse->nMem+1;
+
        int iBase2 = iBase + pEList->nExpr;
+
        pParse->nMem += (pEList->nExpr*2);
+

+
        /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
+
        ** OP_Integer initializes the "first row" flag.  */
+
        pOp->opcode = OP_Integer;
+
        pOp->p1 = 1;
+
        pOp->p2 = iFlag;
+

+
        sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
+
        iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
+
        sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
+
        for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
+
          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
+
          sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
+
          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
+
          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+
        }
+
        sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
+

+
        sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
+
        assert( sqlite3VdbeCurrentAddr(v)==iJump );
+
        sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
+
      }else{
+
        pOp->opcode = OP_Noop;
+
      }
+
    }
+

+
    /* Use the standard inner loop. */
+
    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
                    pWInfo->iContinue, pWInfo->iBreak);

    /* End the database scan loop.
@@ -94418,6 +96405,8 @@ SQLITE_PRIVATE int sqlite3Select(
    int iAbortFlag;     /* Mem address which causes query abort if positive */
    int groupBySort;    /* Rows come from source in GROUP BY order */
    int addrEnd;        /* End of processing for this SELECT */
+
    int sortPTab = 0;   /* Pseudotable used to decode sorting results */
+
    int sortOut = 0;    /* Output register from the sorter */

    /* Remove any and all aliases between the result set and the
    ** GROUP BY clause.
@@ -94479,12 +96468,12 @@ SQLITE_PRIVATE int sqlite3Select(

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
-
      ** that we do not need it after all, the OpenEphemeral instruction
+
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
-
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, 
+
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);

@@ -94511,7 +96500,7 @@ SQLITE_PRIVATE int sqlite3Select(
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
-
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
+
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
      if( pWInfo==0 ) goto select_end;
      if( pGroupBy==0 ){
        /* The optimizer is able to deliver rows in group by order so
@@ -94565,11 +96554,14 @@ SQLITE_PRIVATE int sqlite3Select(
        }
        regRecord = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
-
        sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
+
        sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
        sqlite3ReleaseTempReg(pParse, regRecord);
        sqlite3ReleaseTempRange(pParse, regBase, nCol);
        sqlite3WhereEnd(pWInfo);
-
        sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
+
        sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
+
        sortOut = sqlite3GetTempReg(pParse);
+
        sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
+
        sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort"));
        sAggInfo.useSortingIdx = 1;
        sqlite3ExprCacheClear(pParse);
@@ -94582,9 +96574,13 @@ SQLITE_PRIVATE int sqlite3Select(
      */
      addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
      sqlite3ExprCacheClear(pParse);
+
      if( groupBySort ){
+
        sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
+
      }
      for(j=0; j<pGroupBy->nExpr; j++){
        if( groupBySort ){
-
          sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j);
+
          sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
+
          if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
        }else{
          sAggInfo.directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
@@ -94623,10 +96619,10 @@ SQLITE_PRIVATE int sqlite3Select(
      /* End of the loop
      */
      if( groupBySort ){
-
        sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
+
        sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
      }else{
        sqlite3WhereEnd(pWInfo);
-
        sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
+
        sqlite3VdbeChangeToNoop(v, addrSortingIdx);
      }

      /* Output the final row of result
@@ -94773,7 +96769,7 @@ SQLITE_PRIVATE int sqlite3Select(
        ** of output.
        */
        resetAccumulator(pParse, &sAggInfo);
-
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
+
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
        if( pWInfo==0 ){
          sqlite3ExprListDelete(db, pDel);
          goto select_end;
@@ -94952,6 +96948,8 @@ SQLITE_PRIVATE void sqlite3PrintSelect(Select *p, int indent){
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/
+
/* #include <stdlib.h> */
+
/* #include <string.h> */

#ifndef SQLITE_OMIT_GET_TABLE

@@ -95249,15 +97247,28 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
      goto trigger_cleanup;
    }
  }
+
  if( !pTableName || db->mallocFailed ){
+
    goto trigger_cleanup;
+
  }
+

+
  /* A long-standing parser bug is that this syntax was allowed:
+
  **
+
  **    CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
+
  **                                                 ^^^^^^^^
+
  **
+
  ** To maintain backwards compatibility, ignore the database
+
  ** name on pTableName if we are reparsing our of SQLITE_MASTER.
+
  */
+
  if( db->init.busy && iDb!=1 ){
+
    sqlite3DbFree(db, pTableName->a[0].zDatabase);
+
    pTableName->a[0].zDatabase = 0;
+
  }

  /* If the trigger name was unqualified, and the table is a temp table,
  ** then set iDb to 1 to create the trigger in the temporary database.
  ** If sqlite3SrcListLookup() returns 0, indicating the table does not
  ** exist, the error is caught by the block below.
  */
-
  if( !pTableName || db->mallocFailed ){
-
    goto trigger_cleanup;
-
  }
  pTab = sqlite3SrcListLookup(pParse, pTableName);
  if( db->init.busy==0 && pName2->n==0 && pTab
        && pTab->pSchema==db->aDb[1].pSchema ){
@@ -96555,7 +98566,9 @@ SQLITE_PRIVATE void sqlite3Update(
  /* Begin the database scan
  */
  sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
-
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
+
  pWInfo = sqlite3WhereBegin(
+
      pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
+
  );
  if( pWInfo==0 ) goto update_cleanup;
  okOnePass = pWInfo->okOnePass;

@@ -98581,6 +100594,7 @@ struct WhereCost {
#define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
#define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
#define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */
+
#define WHERE_DISTINCT     0x40000000  /* Correct order for DISTINCT */

/*
** Initialize a preallocated WhereClause structure.
@@ -98794,11 +100808,19 @@ static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
  Bitmask mask = 0;
  while( pS ){
+
    SrcList *pSrc = pS->pSrc;
    mask |= exprListTableUsage(pMaskSet, pS->pEList);
    mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
    mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
    mask |= exprTableUsage(pMaskSet, pS->pWhere);
    mask |= exprTableUsage(pMaskSet, pS->pHaving);
+
    if( ALWAYS(pSrc!=0) ){
+
      int i;
+
      for(i=0; i<pSrc->nSrc; i++){
+
        mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
+
        mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
+
      }
+
    }
    pS = pS->pPrior;
  }
  return mask;
@@ -99725,6 +101747,162 @@ static int referencesOtherTables(
  return 0;
}

+
/*
+
** This function searches the expression list passed as the second argument
+
** for an expression of type TK_COLUMN that refers to the same column and
+
** uses the same collation sequence as the iCol'th column of index pIdx.
+
** Argument iBase is the cursor number used for the table that pIdx refers
+
** to.
+
**
+
** If such an expression is found, its index in pList->a[] is returned. If
+
** no expression is found, -1 is returned.
+
*/
+
static int findIndexCol(
+
  Parse *pParse,                  /* Parse context */
+
  ExprList *pList,                /* Expression list to search */
+
  int iBase,                      /* Cursor for table associated with pIdx */
+
  Index *pIdx,                    /* Index to match column of */
+
  int iCol                        /* Column of index to match */
+
){
+
  int i;
+
  const char *zColl = pIdx->azColl[iCol];
+

+
  for(i=0; i<pList->nExpr; i++){
+
    Expr *p = pList->a[i].pExpr;
+
    if( p->op==TK_COLUMN
+
     && p->iColumn==pIdx->aiColumn[iCol]
+
     && p->iTable==iBase
+
    ){
+
      CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
+
      if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
+
        return i;
+
      }
+
    }
+
  }
+

+
  return -1;
+
}
+

+
/*
+
** This routine determines if pIdx can be used to assist in processing a
+
** DISTINCT qualifier. In other words, it tests whether or not using this
+
** index for the outer loop guarantees that rows with equal values for
+
** all expressions in the pDistinct list are delivered grouped together.
+
**
+
** For example, the query 
+
**
+
**   SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
+
**
+
** can benefit from any index on columns "b" and "c".
+
*/
+
static int isDistinctIndex(
+
  Parse *pParse,                  /* Parsing context */
+
  WhereClause *pWC,               /* The WHERE clause */
+
  Index *pIdx,                    /* The index being considered */
+
  int base,                       /* Cursor number for the table pIdx is on */
+
  ExprList *pDistinct,            /* The DISTINCT expressions */
+
  int nEqCol                      /* Number of index columns with == */
+
){
+
  Bitmask mask = 0;               /* Mask of unaccounted for pDistinct exprs */
+
  int i;                          /* Iterator variable */
+

+
  if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
+
  testcase( pDistinct->nExpr==BMS-1 );
+

+
  /* Loop through all the expressions in the distinct list. If any of them
+
  ** are not simple column references, return early. Otherwise, test if the
+
  ** WHERE clause contains a "col=X" clause. If it does, the expression
+
  ** can be ignored. If it does not, and the column does not belong to the
+
  ** same table as index pIdx, return early. Finally, if there is no
+
  ** matching "col=X" expression and the column is on the same table as pIdx,
+
  ** set the corresponding bit in variable mask.
+
  */
+
  for(i=0; i<pDistinct->nExpr; i++){
+
    WhereTerm *pTerm;
+
    Expr *p = pDistinct->a[i].pExpr;
+
    if( p->op!=TK_COLUMN ) return 0;
+
    pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
+
    if( pTerm ){
+
      Expr *pX = pTerm->pExpr;
+
      CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+
      CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
+
      if( p1==p2 ) continue;
+
    }
+
    if( p->iTable!=base ) return 0;
+
    mask |= (((Bitmask)1) << i);
+
  }
+

+
  for(i=nEqCol; mask && i<pIdx->nColumn; i++){
+
    int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
+
    if( iExpr<0 ) break;
+
    mask &= ~(((Bitmask)1) << iExpr);
+
  }
+

+
  return (mask==0);
+
}
+

+

+
/*
+
** Return true if the DISTINCT expression-list passed as the third argument
+
** is redundant. A DISTINCT list is redundant if the database contains a
+
** UNIQUE index that guarantees that the result of the query will be distinct
+
** anyway.
+
*/
+
static int isDistinctRedundant(
+
  Parse *pParse,
+
  SrcList *pTabList,
+
  WhereClause *pWC,
+
  ExprList *pDistinct
+
){
+
  Table *pTab;
+
  Index *pIdx;
+
  int i;                          
+
  int iBase;
+

+
  /* If there is more than one table or sub-select in the FROM clause of
+
  ** this query, then it will not be possible to show that the DISTINCT 
+
  ** clause is redundant. */
+
  if( pTabList->nSrc!=1 ) return 0;
+
  iBase = pTabList->a[0].iCursor;
+
  pTab = pTabList->a[0].pTab;
+

+
  /* If any of the expressions is an IPK column on table iBase, then return 
+
  ** true. Note: The (p->iTable==iBase) part of this test may be false if the
+
  ** current SELECT is a correlated sub-query.
+
  */
+
  for(i=0; i<pDistinct->nExpr; i++){
+
    Expr *p = pDistinct->a[i].pExpr;
+
    if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
+
  }
+

+
  /* Loop through all indices on the table, checking each to see if it makes
+
  ** the DISTINCT qualifier redundant. It does so if:
+
  **
+
  **   1. The index is itself UNIQUE, and
+
  **
+
  **   2. All of the columns in the index are either part of the pDistinct
+
  **      list, or else the WHERE clause contains a term of the form "col=X",
+
  **      where X is a constant value. The collation sequences of the
+
  **      comparison and select-list expressions must match those of the index.
+
  */
+
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+
    if( pIdx->onError==OE_None ) continue;
+
    for(i=0; i<pIdx->nColumn; i++){
+
      int iCol = pIdx->aiColumn[i];
+
      if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) 
+
       && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
+
      ){
+
        break;
+
      }
+
    }
+
    if( i==pIdx->nColumn ){
+
      /* This index implies that the DISTINCT qualifier is redundant. */
+
      return 1;
+
    }
+
  }
+

+
  return 0;
+
}

/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
@@ -99761,7 +101939,10 @@ static int isSortingIndex(
  struct ExprList_item *pTerm;    /* A term of the ORDER BY clause */
  sqlite3 *db = pParse->db;

-
  assert( pOrderBy!=0 );
+
  if( !pOrderBy ) return 0;
+
  if( wsFlags & WHERE_COLUMN_IN ) return 0;
+
  if( pIdx->bUnordered ) return 0;
+

  nTerm = pOrderBy->nExpr;
  assert( nTerm>0 );

@@ -100074,6 +102255,10 @@ static void bestAutomaticIndex(
  WhereTerm *pWCEnd;          /* End of pWC->a[] */
  Table *pTable;              /* Table tht might be indexed */

+
  if( pParse->nQueryLoop<=(double)1 ){
+
    /* There is no point in building an automatic index for a single scan */
+
    return;
+
  }
  if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
    /* Automatic indices are disabled at run-time */
    return;
@@ -100086,6 +102271,10 @@ static void bestAutomaticIndex(
    /* The NOT INDEXED clause appears in the SQL. */
    return;
  }
+
  if( pSrc->isCorrelated ){
+
    /* The source is a correlated sub-query. No point in indexing it. */
+
    return;
+
  }

  assert( pParse->nQueryLoop >= (double)1 );
  pTable = pSrc->pTab;
@@ -100154,8 +102343,7 @@ static void constructAutomaticIndex(
  v = pParse->pVdbe;
  assert( v!=0 );
  regIsInit = ++pParse->nMem;
-
  addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
-
  sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
+
  addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);

  /* Count the number of columns that will be added to the index
  ** and used to match WHERE clause constraints */
@@ -100302,6 +102490,7 @@ static sqlite3_index_info *allocateIndexInfo(
    testcase( pTerm->eOperator==WO_IN );
    testcase( pTerm->eOperator==WO_ISNULL );
    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    nTerm++;
  }

@@ -100352,6 +102541,7 @@ static sqlite3_index_info *allocateIndexInfo(
    testcase( pTerm->eOperator==WO_IN );
    testcase( pTerm->eOperator==WO_ISNULL );
    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    pIdxCons[j].iColumn = pTerm->u.leftColumn;
    pIdxCons[j].iTermOffset = i;
    pIdxCons[j].op = (u8)pTerm->eOperator;
@@ -101017,6 +103207,7 @@ static void bestBtreeIndex(
  Bitmask notReady,           /* Mask of cursors not available for indexing */
  Bitmask notValid,           /* Cursors not available for any purpose */
  ExprList *pOrderBy,         /* The ORDER BY clause */
+
  ExprList *pDistinct,        /* The select-list if query is DISTINCT */
  WhereCost *pCost            /* Lowest cost query plan */
){
  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
@@ -101157,7 +103348,8 @@ static void bestBtreeIndex(
    int nInMul = 1;               /* Number of distinct equalities to lookup */
    int estBound = 100;           /* Estimated reduction in search space */
    int nBound = 0;               /* Number of range constraints seen */
-
    int bSort = 0;                /* True if external sort required */
+
    int bSort = !!pOrderBy;       /* True if external sort required */
+
    int bDist = !!pDistinct;      /* True if index cannot help with DISTINCT */
    int bLookup = 0;              /* True if not a covering index */
    WhereTerm *pTerm;             /* A single term of the WHERE clause */
#ifdef SQLITE_ENABLE_STAT2
@@ -101221,17 +103413,20 @@ static void bestBtreeIndex(
    ** naturally scan rows in the required order, set the appropriate flags
    ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
    ** will scan rows in a different order, set the bSort variable.  */
-
    if( pOrderBy ){
-
      if( (wsFlags & WHERE_COLUMN_IN)==0
-
        && pProbe->bUnordered==0
-
        && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
-
                          nEq, wsFlags, &rev)
-
      ){
-
        wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
-
        wsFlags |= (rev ? WHERE_REVERSE : 0);
-
      }else{
-
        bSort = 1;
-
      }
+
    if( isSortingIndex(
+
          pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
+
    ){
+
      bSort = 0;
+
      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
+
      wsFlags |= (rev ? WHERE_REVERSE : 0);
+
    }
+

+
    /* If there is a DISTINCT qualifier and this index will scan rows in
+
    ** order of the DISTINCT expressions, clear bDist and set the appropriate
+
    ** flags in wsFlags. */
+
    if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
+
      bDist = 0;
+
      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
    }

    /* If currently calculating the cost of using an index (not the IPK
@@ -101266,12 +103461,13 @@ static void bestBtreeIndex(
    }

#ifdef SQLITE_ENABLE_STAT2
-
    /* If the constraint is of the form x=VALUE and histogram
+
    /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
+
    ** and we do not think that values of x are unique and if histogram
    ** data is available for column x, then it might be possible
    ** to get a better estimate on the number of rows based on
    ** VALUE and how common that value is according to the histogram.
    */
-
    if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
+
    if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
        testcase( pFirstTerm->eOperator==WO_EQ );
        testcase( pFirstTerm->eOperator==WO_ISNULL );
@@ -101348,6 +103544,9 @@ static void bestBtreeIndex(
    if( bSort ){
      cost += nRow*estLog(nRow)*3;
    }
+
    if( bDist ){
+
      cost += nRow*estLog(nRow)*3;
+
    }

    /**** Cost of using this index has now been computed ****/

@@ -101493,7 +103692,7 @@ static void bestIndex(
  }else
#endif
  {
-
    bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
+
    bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
  }
}

@@ -102455,7 +104654,7 @@ static Bitmask codeOneLoopStart(
      if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
        WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
        /* Loop through table entries that match term pOrTerm. */
-
        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
+
        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
                        WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
        if( pSubWInfo ){
@@ -102696,6 +104895,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  SrcList *pTabList,    /* A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+
  ExprList *pDistinct,  /* The select-list for DISTINCT queries - or NULL */
  u16 wctrlFlags        /* One of the WHERE_* flags defined in sqliteInt.h */
){
  int i;                     /* Loop counter */
@@ -102756,6 +104956,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pMaskSet = (WhereMaskSet*)&pWC[1];

+
  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+
  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+
  if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
+

  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.
  */
@@ -102823,6 +105027,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
    goto whereBeginError;
  }

+
  /* Check if the DISTINCT qualifier, if there is one, is redundant. 
+
  ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
+
  ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
+
  */
+
  if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
+
    pDistinct = 0;
+
    pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+
  }
+

  /* Chose the best index to use for each table in the FROM clause.
  **
  ** This loop fills in the following fields:
@@ -102906,6 +105119,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
        int doNotReorder;    /* True if this table should not be reordered */
        WhereCost sCost;     /* Cost information from best[Virtual]Index() */
        ExprList *pOrderBy;  /* ORDER BY clause for index to optimize */
+
        ExprList *pDist;     /* DISTINCT clause for index to optimize */
  
        doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
        if( j!=iFrom && doNotReorder ) break;
@@ -102916,6 +105130,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
        }
        mask = (isOptimal ? m : notReady);
        pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
+
        pDist = (i==0 ? pDistinct : 0);
        if( pTabItem->pIndex==0 ) nUnconstrained++;
  
        WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
@@ -102930,7 +105145,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
#endif
        {
          bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
-
                         &sCost);
+
              pDist, &sCost);
        }
        assert( isOptimal || (sCost.used&notReady)==0 );

@@ -102991,6 +105206,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
    if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
      *ppOrderBy = 0;
    }
+
    if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
+
      assert( pWInfo->eDistinct==0 );
+
      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+
    }
    andFlags &= bestPlan.plan.wsFlags;
    pLevel->plan = bestPlan.plan;
    testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
@@ -103325,6 +105544,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
+
/* #include <stdio.h> */


/*
@@ -104185,6 +106405,7 @@ struct yyParser {
typedef struct yyParser yyParser;

#ifndef NDEBUG
+
/* #include <stdio.h> */
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -106760,6 +108981,7 @@ SQLITE_PRIVATE void sqlite3Parser(
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
*/
+
/* #include <stdlib.h> */

/*
** The charMap() macro maps alphabetic characters into their
@@ -108152,6 +110374,16 @@ SQLITE_API int sqlite3_initialize(void){
#endif
#endif

+
  /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
+
  ** compile-time option.
+
  */
+
#ifdef SQLITE_EXTRA_INIT
+
  if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+
    int SQLITE_EXTRA_INIT(void);
+
    rc = SQLITE_EXTRA_INIT();
+
  }
+
#endif
+

  return rc;
}

@@ -111520,7 +113752,13 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
# define SQLITE_ENABLE_FTS3
#endif

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

+
/* If not building as part of the core, include sqlite3ext.h. */
+
#ifndef SQLITE_CORE
+
SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
+
#endif
+

/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
/************** Begin file fts3_tokenizer.h **********************************/
/*
@@ -112053,7 +114291,7 @@ struct Fts3Doclist {
  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
@@ -112253,19 +114491,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
/* 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(
@@ -112276,7 +114503,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);

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

-
#endif /* SQLITE_ENABLE_FTS3 */
+
#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

/************** End of fts3Int.h *********************************************/
@@ -112287,11 +114514,22 @@ SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, in
# define SQLITE_CORE 1
#endif

+
/* #include <assert.h> */
+
/* #include <stdlib.h> */
+
/* #include <stddef.h> */
+
/* #include <stdio.h> */
+
/* #include <string.h> */
+
/* #include <stdarg.h> */

#ifndef SQLITE_CORE 
  SQLITE_EXTENSION_INIT1
#endif

+
static int fts3EvalNext(Fts3Cursor *pCsr);
+
static int fts3EvalStart(Fts3Cursor *pCsr);
+
static int fts3TermSegReaderCursor(
+
    Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
+

/* 
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
@@ -112800,9 +115038,23 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
  return zRet;
}

+
/*
+
** This function interprets the string at (*pp) as a non-negative integer
+
** value. It reads the integer and sets *pnOut to the value read, then 
+
** sets *pp to point to the byte immediately following the last byte of
+
** the integer value.
+
**
+
** Only decimal digits ('0'..'9') may be part of an integer value. 
+
**
+
** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
+
** the output value undefined. Otherwise SQLITE_OK is returned.
+
**
+
** This function is used when parsing the "prefix=" FTS4 parameter.
+
*/
static int fts3GobbleInt(const char **pp, int *pnOut){
-
  const char *p = *pp;
-
  int nInt = 0;
+
  const char *p = *pp;            /* Iterator pointer */
+
  int nInt = 0;                   /* Output value */
+

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

-

+
/*
+
** This function is called to allocate an array of Fts3Index structures
+
** representing the indexes maintained by the current FTS table. FTS tables
+
** always maintain the main "terms" index, but may also maintain one or
+
** more "prefix" indexes, depending on the value of the "prefix=" parameter
+
** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
+
**
+
** Argument zParam is passed the value of the "prefix=" option if one was
+
** specified, or NULL otherwise.
+
**
+
** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
+
** the allocated array. *pnIndex is set to the number of elements in the
+
** array. If an error does occur, an SQLite error code is returned.
+
**
+
** Regardless of whether or not an error is returned, it is the responsibility
+
** of the caller to call sqlite3_free() on the output array to free it.
+
*/
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 **apIndex      /* OUT: Array of indexes for this table */
){
-
  struct Fts3Index *aIndex;
-
  int nIndex = 1;
+
  struct Fts3Index *aIndex;       /* Allocated array */
+
  int nIndex = 1;                 /* Number of entries in array */

  if( zParam && zParam[0] ){
    const char *p;
@@ -112831,7 +115098,7 @@ static int fts3PrefixParameter(
  }

  aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
-
  *apIndex = *apFree = aIndex;
+
  *apIndex = aIndex;
  *pnIndex = nIndex;
  if( !aIndex ){
    return SQLITE_NOMEM;
@@ -112888,8 +115155,7 @@ static int fts3InitVtab(
  sqlite3_tokenizer *pTokenizer = 0;        /* Tokenizer for this table */

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

  /* The results of parsing supported FTS4 key=value options: */
  int bNoDocsize = 0;             /* True to omit %_docsize table */
@@ -113026,7 +115292,7 @@ static int fts3InitVtab(
  }
  assert( pTokenizer );

-
  rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
+
  rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
  if( rc==SQLITE_ERROR ){
    assert( zPrefix );
    *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
@@ -113113,7 +115379,7 @@ static int fts3InitVtab(

fts3_init_out:
  sqlite3_free(zPrefix);
-
  sqlite3_free(aFree);
+
  sqlite3_free(aIndex);
  sqlite3_free(zCompress);
  sqlite3_free(zUncompress);
  sqlite3_free((void *)aCol);
@@ -113704,8 +115970,6 @@ static void fts3PoslistMerge(
}

/*
-
** nToken==1 searches for adjacent positions.
-
**
** This function is used to merge two position lists into one. When it is
** called, *pp1 and *pp2 must both point to position lists. A position-list is
** the part of a doclist that follows each document id. For example, if a row
@@ -113725,6 +115989,8 @@ static void fts3PoslistMerge(
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
** slots before it.
+
**
+
** e.g. nToken==1 searches for adjacent positions.
*/
static int fts3PoslistPhraseMerge(
  char **pp,                      /* IN/OUT: Preallocated output buffer */
@@ -113891,22 +116157,34 @@ static int fts3PoslistNearMerge(
}

/* 
-
** A pointer to an instance of this structure is used as the context 
-
** argument to sqlite3Fts3SegReaderIterate()
+
** An instance of this function is used to merge together the (potentially
+
** large number of) doclists for each term that matches a prefix query.
+
** See function fts3TermSelectMerge() for details.
*/
typedef struct TermSelect TermSelect;
struct TermSelect {
-
  int isReqPos;
-
  char *aaOutput[16];             /* Malloc'd output buffer */
-
  int anOutput[16];               /* Size of output in bytes */
+
  char *aaOutput[16];             /* Malloc'd output buffers */
+
  int anOutput[16];               /* Size each output buffer in bytes */
};

-

+
/*
+
** This function is used to read a single varint from a buffer. Parameter
+
** pEnd points 1 byte past the end of the buffer. When this function is
+
** called, if *pp points to pEnd or greater, then the end of the buffer
+
** has been reached. In this case *pp is set to 0 and the function returns.
+
**
+
** If *pp does not point to or past pEnd, then a single varint is read
+
** from *pp. *pp is then set to point 1 byte past the end of the read varint.
+
**
+
** If bDescIdx is false, the value read is added to *pVal before returning.
+
** If it is true, the value read is subtracted from *pVal before this 
+
** function returns.
+
*/
static void fts3GetDeltaVarint3(
-
  char **pp, 
-
  char *pEnd, 
-
  int bDescIdx,
-
  sqlite3_int64 *pVal
+
  char **pp,                      /* IN/OUT: Point to read varint from */
+
  char *pEnd,                     /* End of buffer */
+
  int bDescIdx,                   /* True if docids are descending */
+
  sqlite3_int64 *pVal             /* IN/OUT: Integer value */
){
  if( *pp>=pEnd ){
    *pp = 0;
@@ -113921,6 +116199,21 @@ static void fts3GetDeltaVarint3(
  }
}

+
/*
+
** This function is used to write a single varint to a buffer. The varint
+
** is written to *pp. Before returning, *pp is set to point 1 byte past the
+
** end of the value written.
+
**
+
** If *pbFirst is zero when this function is called, the value written to
+
** the buffer is that of parameter iVal. 
+
**
+
** If *pbFirst is non-zero when this function is called, then the value 
+
** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
+
** (if bDescIdx is non-zero).
+
**
+
** Before returning, this function always sets *pbFirst to 1 and *piPrev
+
** to the value of parameter iVal.
+
*/
static void fts3PutDeltaVarint3(
  char **pp,                      /* IN/OUT: Output pointer */
  int bDescIdx,                   /* True for descending docids */
@@ -113941,10 +116234,34 @@ static void fts3PutDeltaVarint3(
  *pbFirst = 1;
}

-
#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))

+
/*
+
** This macro is used by various functions that merge doclists. The two
+
** arguments are 64-bit docid values. If the value of the stack variable
+
** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). 
+
** Otherwise, (i2-i1).
+
**
+
** Using this makes it easier to write code that can merge doclists that are
+
** sorted in either ascending or descending order.
+
*/
+
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
+

+
/*
+
** This function does an "OR" merge of two doclists (output contains all
+
** positions contained in either argument doclist). If the docids in the 
+
** input doclists are sorted in ascending order, parameter bDescDoclist
+
** should be false. If they are sorted in ascending order, it should be
+
** passed a non-zero value.
+
**
+
** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
+
** containing the output doclist and SQLITE_OK is returned. In this case
+
** *pnOut is set to the number of bytes in the output doclist.
+
**
+
** If an error occurs, an SQLite error code is returned. The output values
+
** are undefined in this case.
+
*/
static int fts3DoclistOrMerge(
-
  int bDescIdx,                   /* True if arguments are desc */
+
  int bDescDoclist,               /* 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 */
@@ -113962,38 +116279,81 @@ static int fts3DoclistOrMerge(

  *paOut = 0;
  *pnOut = 0;
-
  aOut = sqlite3_malloc(n1+n2);
+

+
  /* Allocate space for the output. Both the input and output doclists
+
  ** are delta encoded. If they are in ascending order (bDescDoclist==0),
+
  ** then the first docid in each list is simply encoded as a varint. For
+
  ** each subsequent docid, the varint stored is the difference between the
+
  ** current and previous docid (a positive number - since the list is in
+
  ** ascending order).
+
  **
+
  ** The first docid written to the output is therefore encoded using the 
+
  ** same number of bytes as it is in whichever of the input lists it is
+
  ** read from. And each subsequent docid read from the same input list 
+
  ** consumes either the same or less bytes as it did in the input (since
+
  ** the difference between it and the previous value in the output must
+
  ** be a positive value less than or equal to the delta value read from 
+
  ** the input list). The same argument applies to all but the first docid
+
  ** read from the 'other' list. And to the contents of all position lists
+
  ** that will be copied and merged from the input to the output.
+
  **
+
  ** However, if the first docid copied to the output is a negative number,
+
  ** then the encoding of the first docid from the 'other' input list may
+
  ** be larger in the output than it was in the input (since the delta value
+
  ** may be a larger positive integer than the actual docid).
+
  **
+
  ** The space required to store the output is therefore the sum of the
+
  ** sizes of the two inputs, plus enough space for exactly one of the input
+
  ** docids to grow. 
+
  **
+
  ** A symetric argument may be made if the doclists are in descending 
+
  ** order.
+
  */
+
  aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
  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);
+
    sqlite3_int64 iDiff = DOCID_CMP(i1, i2);

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

  *paOut = aOut;
  *pnOut = (p-aOut);
+
  assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
  return SQLITE_OK;
}

+
/*
+
** This function does a "phrase" merge of two doclists. In a phrase merge,
+
** the output contains a copy of each position from the right-hand input
+
** doclist for which there is a position in the left-hand input doclist
+
** exactly nDist tokens before it.
+
**
+
** If the docids in the input doclists are sorted in ascending order,
+
** parameter bDescDoclist should be false. If they are sorted in ascending 
+
** order, it should be passed a non-zero value.
+
**
+
** The right-hand input doclist is overwritten by this function.
+
*/
static void fts3DoclistPhraseMerge(
-
  int bDescIdx,                   /* True if arguments are desc */
+
  int bDescDoclist,               /* 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 */
@@ -114016,26 +116376,26 @@ static void fts3DoclistPhraseMerge(
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);

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

-
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+
      fts3PutDeltaVarint3(&p, bDescDoclist, &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);
+
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }else if( iDiff<0 ){
      fts3PoslistCopy(0, &p1);
-
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
    }else{
      fts3PoslistCopy(0, &p2);
-
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }
  }

@@ -114052,7 +116412,7 @@ static void fts3DoclistPhraseMerge(
** the responsibility of the caller to free any doclists left in the
** TermSelect.aaOutput[] array.
*/
-
static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
+
static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
  char *aOut = 0;
  int nOut = 0;
  int i;
@@ -114093,24 +116453,25 @@ static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
}

/*
-
** This function is used as the sqlite3Fts3SegReaderIterate() callback when
-
** querying the full-text index for a doclist associated with a term or
-
** term-prefix.
+
** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
+
** as the first argument. The merge is an "OR" merge (see function
+
** fts3DoclistOrMerge() for details).
+
**
+
** This function is called with the doclist for each term that matches
+
** a queried prefix. It merges all these doclists into one, the doclist
+
** for the specified prefix. Since there can be a very large number of
+
** doclists to merge, the merging is done pair-wise using the TermSelect
+
** object.
+
**
+
** This function returns SQLITE_OK if the merge is successful, or an
+
** SQLite error code (SQLITE_NOMEM) if an error occurs.
*/
-
static int fts3TermSelectCb(
-
  Fts3Table *p,                   /* Virtual table object */
-
  void *pContext,                 /* Pointer to TermSelect structure */
-
  char *zTerm,
-
  int nTerm,
-
  char *aDoclist,
-
  int nDoclist
+
static int fts3TermSelectMerge(
+
  Fts3Table *p,                   /* FTS table handle */
+
  TermSelect *pTS,                /* TermSelect object to merge into */
+
  char *aDoclist,                 /* Pointer to doclist */
+
  int nDoclist                    /* Size of aDoclist in bytes */
){
-
  TermSelect *pTS = (TermSelect *)pContext;
-

-
  UNUSED_PARAMETER(p);
-
  UNUSED_PARAMETER(zTerm);
-
  UNUSED_PARAMETER(nTerm);
-

  if( pTS->aaOutput[0]==0 ){
    /* If this is the first term selected, copy the doclist to the output
    ** buffer using memcpy(). */
@@ -114181,6 +116542,13 @@ static int fts3SegReaderCursorAppend(
  return SQLITE_OK;
}

+
/*
+
** Add seg-reader objects to the Fts3MultiSegReader object passed as the
+
** 8th argument.
+
**
+
** This function returns SQLITE_OK if successful, or an SQLite error code
+
** otherwise.
+
*/
static int fts3SegReaderCursor(
  Fts3Table *p,                   /* FTS3 table handle */
  int iIndex,                     /* Index to search (from 0 to p->nIndex-1) */
@@ -114189,11 +116557,11 @@ static int fts3SegReaderCursor(
  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 */
+
  Fts3MultiSegReader *pCsr        /* Cursor object to populate */
){
-
  int rc = SQLITE_OK;
-
  int rc2;
-
  sqlite3_stmt *pStmt = 0;
+
  int rc = SQLITE_OK;             /* Error code */
+
  sqlite3_stmt *pStmt = 0;        /* Statement to iterate through segments */
+
  int rc2;                        /* Result of sqlite3_reset() */

  /* 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
@@ -114282,24 +116650,42 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
  );
}

+
/*
+
** In addition to its current configuration, have the Fts3MultiSegReader
+
** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
+
**
+
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+
*/
static int fts3SegReaderCursorAddZero(
-
  Fts3Table *p,
-
  const char *zTerm,
-
  int nTerm,
-
  Fts3MultiSegReader *pCsr
+
  Fts3Table *p,                   /* FTS virtual table handle */
+
  const char *zTerm,              /* Term to scan doclist of */
+
  int nTerm,                      /* Number of bytes in zTerm */
+
  Fts3MultiSegReader *pCsr        /* Fts3MultiSegReader to modify */
){
  return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
}

-

-
SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
+
/*
+
** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
+
** if isPrefix is true, to scan the doclist for all terms for which 
+
** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
+
** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
+
** an SQLite error code.
+
**
+
** It is the responsibility of the caller to free this object by eventually
+
** passing it to fts3SegReaderCursorFree() 
+
**
+
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+
** Output parameter *ppSegcsr is set to 0 if an error occurs.
+
*/
+
static int fts3TermSegReaderCursor(
  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 */
){
-
  Fts3MultiSegReader *pSegcsr;   /* Object to allocate and return */
+
  Fts3MultiSegReader *pSegcsr;    /* Object to allocate and return */
  int rc = SQLITE_NOMEM;          /* Return code */

  pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
@@ -114343,6 +116729,9 @@ SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
  return rc;
}

+
/*
+
** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
+
*/
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
  sqlite3Fts3SegReaderFinish(pSegcsr);
  sqlite3_free(pSegcsr);
@@ -114350,35 +116739,25 @@ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){

/*
** This function retreives the doclist for the specified term (or term
-
** prefix) from the database. 
-
**
-
** The returned doclist may be in one of two formats, depending on the 
-
** value of parameter isReqPos. If isReqPos is zero, then the doclist is
-
** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
-
** is non-zero, then the returned list is in the same format as is stored 
-
** in the database without the found length specifier at the start of on-disk
-
** doclists.
+
** prefix) from the database.
*/
static int fts3TermSelect(
  Fts3Table *p,                   /* Virtual table handle */
  Fts3PhraseToken *pTok,          /* Token to query for */
  int iColumn,                    /* Column to query (or -ve for all columns) */
-
  int isReqPos,                   /* True to include position lists in output */
  int *pnOut,                     /* OUT: Size of buffer at *ppOut */
  char **ppOut                    /* OUT: Malloced result buffer */
){
  int rc;                         /* Return code */
-
  Fts3MultiSegReader *pSegcsr;   /* Seg-reader cursor for this term */
-
  TermSelect tsc;                 /* Context object for fts3TermSelectCb() */
+
  Fts3MultiSegReader *pSegcsr;    /* Seg-reader cursor for this term */
+
  TermSelect tsc;                 /* Object for pair-wise doclist merging */
  Fts3SegFilter filter;           /* Segment term filter configuration */

  pSegcsr = pTok->pSegcsr;
  memset(&tsc, 0, sizeof(TermSelect));
-
  tsc.isReqPos = isReqPos;

-
  filter.flags = FTS3_SEGMENT_IGNORE_EMPTY 
+
  filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
        | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
-
        | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
        | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
  filter.iCol = iColumn;
  filter.zTerm = pTok->z;
@@ -114388,13 +116767,11 @@ static int fts3TermSelect(
  while( SQLITE_OK==rc
      && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) 
  ){
-
    rc = fts3TermSelectCb(p, (void *)&tsc, 
-
        pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
-
    );
+
    rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
  }

  if( rc==SQLITE_OK ){
-
    rc = fts3TermSelectMerge(p, &tsc);
+
    rc = fts3TermSelectFinishMerge(p, &tsc);
  }
  if( rc==SQLITE_OK ){
    *ppOut = tsc.aaOutput[0];
@@ -114420,24 +116797,15 @@ static int fts3TermSelect(
** that the doclist is simply a list of docids stored as delta encoded 
** varints.
*/
-
static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
+
static int fts3DoclistCountDocids(char *aList, int nList){
  int nDoc = 0;                   /* Return value */
  if( aList ){
    char *aEnd = &aList[nList];   /* Pointer to one byte after EOF */
    char *p = aList;              /* Cursor */
-
    if( !isPoslist ){
-
      /* The number of docids in the list is the same as the number of 
-
      ** varints. In FTS3 a varint consists of a single byte with the 0x80 
-
      ** bit cleared and zero or more bytes with the 0x80 bit set. So to
-
      ** count the varints in the buffer, just count the number of bytes
-
      ** with the 0x80 bit clear.  */
-
      while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
-
    }else{
-
      while( p<aEnd ){
-
        nDoc++;
-
        while( (*p++)&0x80 );     /* Skip docid varint */
-
        fts3PoslistCopy(0, &p);   /* Skip over position list */
-
      }
+
    while( p<aEnd ){
+
      nDoc++;
+
      while( (*p++)&0x80 );     /* Skip docid varint */
+
      fts3PoslistCopy(0, &p);   /* Skip over position list */
    }
  }

@@ -114467,7 +116835,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
      rc = SQLITE_OK;
    }
  }else{
-
    rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
+
    rc = fts3EvalNext((Fts3Cursor *)pCursor);
  }
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  return rc;
@@ -114544,7 +116912,7 @@ static int fts3FilterMethod(
    rc = sqlite3Fts3ReadLock(p);
    if( rc!=SQLITE_OK ) return rc;

-
    rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
+
    rc = fts3EvalStart(pCsr);

    sqlite3Fts3SegmentsClose(p);
    if( rc!=SQLITE_OK ) return rc;
@@ -114951,6 +117319,11 @@ static int fts3RenameMethod(
  return rc;
}

+
/*
+
** The xSavepoint() method.
+
**
+
** Flush the contents of the pending-terms table to disk.
+
*/
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  UNUSED_PARAMETER(iSavepoint);
  assert( ((Fts3Table *)pVtab)->inTransaction );
@@ -114958,6 +117331,12 @@ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
  return fts3SyncMethod(pVtab);
}
+

+
/*
+
** The xRelease() method.
+
**
+
** This is a no-op.
+
*/
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  UNUSED_PARAMETER(iSavepoint);
@@ -114967,6 +117346,12 @@ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  TESTONLY( p->mxSavepoint = iSavepoint-1 );
  return SQLITE_OK;
}
+

+
/*
+
** The xRollbackTo() method.
+
**
+
** Discard the contents of the pending terms table.
+
*/
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts3Table *p = (Fts3Table*)pVtab;
  UNUSED_PARAMETER(iSavepoint);
@@ -115116,18 +117501,6 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
  return rc;
}

-
#if !SQLITE_CORE
-
SQLITE_API int sqlite3_extension_init(
-
  sqlite3 *db, 
-
  char **pzErrMsg,
-
  const sqlite3_api_routines *pApi
-
){
-
  SQLITE_EXTENSION_INIT2(pApi)
-
  return sqlite3Fts3Init(db);
-
}
-
#endif
-

-

/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
** by pExpr. 
@@ -115144,11 +117517,11 @@ SQLITE_API int sqlite3_extension_init(
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
-
  Fts3Cursor *pCsr, 
-
  Fts3Expr *pExpr, 
+
  Fts3Cursor *pCsr,               /* FTS cursor handle */
+
  Fts3Expr *pExpr,                /* Allocate readers for this expression */
  int *pnToken,                   /* OUT: Total number of tokens in phrase. */
  int *pnOr,                      /* OUT: Total number of OR nodes in expr. */
-
  int *pRc
+
  int *pRc                        /* IN/OUT: Error code */
){
  if( pExpr && SQLITE_OK==*pRc ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
@@ -115157,7 +117530,7 @@ static void fts3EvalAllocateReaders(
      *pnToken += nToken;
      for(i=0; i<nToken; i++){
        Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
-
        int rc = sqlite3Fts3TermSegReaderCursor(pCsr, 
+
        int rc = fts3TermSegReaderCursor(pCsr, 
            pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
        );
        if( rc!=SQLITE_OK ){
@@ -115175,12 +117548,20 @@ static void fts3EvalAllocateReaders(
  }
}

+
/*
+
** Arguments pList/nList contain the doclist for token iToken of phrase p.
+
** It is merged into the main doclist stored in p->doclist.aAll/nAll.
+
**
+
** This function assumes that pList points to a buffer allocated using
+
** sqlite3_malloc(). This function takes responsibility for eventually
+
** freeing the buffer.
+
*/
static void fts3EvalPhraseMergeToken(
-
  Fts3Table *pTab,
-
  Fts3Phrase *p,
-
  int iToken,
-
  char *pList,
-
  int nList
+
  Fts3Table *pTab,                /* FTS Table pointer */
+
  Fts3Phrase *p,                  /* Phrase to merge pList/nList into */
+
  int iToken,                     /* Token pList/nList corresponds to */
+
  char *pList,                    /* Pointer to doclist */
+
  int nList                       /* Number of bytes in pList */
){
  assert( iToken!=p->iDoclistToken );

@@ -115229,9 +117610,15 @@ static void fts3EvalPhraseMergeToken(
  if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
}

+
/*
+
** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
+
** does not take deferred tokens into account.
+
**
+
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+
*/
static int fts3EvalPhraseLoad(
-
  Fts3Cursor *pCsr, 
-
  Fts3Phrase *p
+
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+
  Fts3Phrase *p                   /* Phrase object */
){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int iToken;
@@ -115244,7 +117631,7 @@ static int fts3EvalPhraseLoad(
    if( pToken->pSegcsr ){
      int nThis = 0;
      char *pThis = 0;
-
      rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
+
      rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
      if( rc==SQLITE_OK ){
        fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
      }
@@ -115255,14 +117642,22 @@ static int fts3EvalPhraseLoad(
  return rc;
}

+
/*
+
** This function is called on each phrase after the position lists for
+
** any deferred tokens have been loaded into memory. It updates the phrases
+
** current position list to include only those positions that are really
+
** instances of the phrase (after considering deferred tokens). If this
+
** means that the phrase does not appear in the current row, doclist.pList
+
** and doclist.nList are both zeroed.
+
**
+
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+
*/
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;
+
  int iToken;                     /* Used to iterate through phrase tokens */
+
  int rc = SQLITE_OK;             /* Return code */
+
  char *aPoslist = 0;             /* Position list for deferred tokens */
+
  int nPoslist = 0;               /* Number of bytes in aPoslist */
+
  int iPrev = -1;                 /* Token number of previous deferred token */

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

@@ -115308,6 +117703,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
  }

  if( iPrev>=0 ){
+
    int nMaxUndeferred = pPhrase->iDoclistToken;
    if( nMaxUndeferred<0 ){
      pPhrase->doclist.pList = aPoslist;
      pPhrase->doclist.nList = nPoslist;
@@ -115356,9 +117752,15 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
** 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.
+
**
+
** If parameter bOptOk is true, then the phrase may (or may not) use the
+
** incremental loading strategy. Otherwise, the entire doclist is loaded into
+
** memory within this call.
+
**
+
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
-
  int rc;
+
  int rc;                         /* Error code */
  Fts3PhraseToken *pFirst = &p->aToken[0];
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;

@@ -115386,7 +117788,13 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){

/*
** This function is used to iterate backwards (from the end to start) 
-
** through doclists.
+
** through doclists. It is used by this module to iterate through phrase
+
** doclists in reverse and by the fts3_write.c module to iterate through
+
** pending-terms lists when writing to databases with "order=desc".
+
**
+
** The doclist may be sorted in ascending (parameter bDescIdx==0) or 
+
** descending (parameter bDescIdx==1) order of docid. Regardless, this
+
** function iterates from the end of the doclist to the beginning.
*/
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
  int bDescIdx,                   /* True if the doclist is desc */
@@ -115451,9 +117859,9 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
** successfully advanced, *pbEof is set to 0.
*/
static int fts3EvalPhraseNext(
-
  Fts3Cursor *pCsr, 
-
  Fts3Phrase *p, 
-
  u8 *pbEof
+
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+
  Fts3Phrase *p,                  /* Phrase object to advance to next docid */
+
  u8 *pbEof                       /* OUT: Set to 1 if EOF */
){
  int rc = SQLITE_OK;
  Fts3Doclist *pDL = &p->doclist;
@@ -115499,10 +117907,10 @@ static int fts3EvalPhraseNext(

      /* 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
+
      ** edited in place by fts3EvalNearTrim(), 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().  */
+
      ** fts3EvalNearTrim().  */
      while( pIter<pEnd && *pIter==0 ) pIter++;

      pDL->pNextDocid = pIter;
@@ -115514,11 +117922,27 @@ static int fts3EvalPhraseNext(
  return rc;
}

+
/*
+
**
+
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+
** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
+
** expression. Also the Fts3Expr.bDeferred variable is set to true for any
+
** expressions for which all descendent tokens are deferred.
+
**
+
** If parameter bOptOk is zero, then it is guaranteed that the
+
** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
+
** each phrase in the expression (subject to deferred token processing).
+
** Or, if bOptOk is non-zero, then one or more tokens within the expression
+
** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
+
**
+
** If an error occurs within this function, *pRc is set to an SQLite error
+
** code before returning.
+
*/
static void fts3EvalStartReaders(
-
  Fts3Cursor *pCsr, 
-
  Fts3Expr *pExpr, 
-
  int bOptOk,
-
  int *pRc
+
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+
  Fts3Expr *pExpr,                /* Expression to initialize phrases in */
+
  int bOptOk,                     /* True to enable incremental loading */
+
  int *pRc                        /* IN/OUT: Error code */
){
  if( pExpr && SQLITE_OK==*pRc ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
@@ -115537,23 +117961,42 @@ static void fts3EvalStartReaders(
  }
}

+
/*
+
** An array of the following structures is assembled as part of the process
+
** of selecting tokens to defer before the query starts executing (as part
+
** of the xFilter() method). There is one element in the array for each
+
** token in the FTS expression.
+
**
+
** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
+
** to phrases that are connected only by AND and NEAR operators (not OR or
+
** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
+
** separately. The root of a tokens AND/NEAR cluster is stored in 
+
** Fts3TokenAndCost.pRoot.
+
*/
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;
+
  Fts3Expr *pRoot;                /* Root of NEAR/AND cluster */
+
  int nOvfl;                      /* Number of overflow pages to load doclist */
  int iCol;                       /* The column the token must match */
};

+
/*
+
** This function is used to populate an allocated Fts3TokenAndCost array.
+
**
+
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+
** Otherwise, if an error occurs during execution, *pRc is set to an
+
** SQLite error code.
+
*/
static void fts3EvalTokenCosts(
-
  Fts3Cursor *pCsr, 
-
  Fts3Expr *pRoot, 
-
  Fts3Expr *pExpr, 
-
  Fts3TokenAndCost **ppTC,
-
  Fts3Expr ***ppOr,
-
  int *pRc
+
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+
  Fts3Expr *pRoot,                /* Root of current AND/NEAR cluster */
+
  Fts3Expr *pExpr,                /* Expression to consider */
+
  Fts3TokenAndCost **ppTC,        /* Write new entries to *(*ppTC)++ */
+
  Fts3Expr ***ppOr,               /* Write new OR root to *(*ppOr)++ */
+
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==SQLITE_OK && pExpr ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
@@ -115585,19 +118028,30 @@ static void fts3EvalTokenCosts(
  }
}

+
/*
+
** Determine the average document (row) size in pages. If successful,
+
** write this value to *pnPage and return SQLITE_OK. Otherwise, return
+
** an SQLite error code.
+
**
+
** The average document size in pages is calculated by first calculating 
+
** determining the average size in bytes, B. If B is less than the amount
+
** of data that will fit on a single leaf page of an intkey table in
+
** this database, then the average docsize is 1. Otherwise, it is 1 plus
+
** the number of overflow pages consumed by a record B bytes in size.
+
*/
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.
-
     */
+
    ** 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;
@@ -115632,68 +118086,117 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
  return SQLITE_OK;
}

+
/*
+
** This function is called to select the tokens (if any) that will be 
+
** deferred. The array aTC[] has already been populated when this is
+
** called.
+
**
+
** This function is called once for each AND/NEAR cluster in the 
+
** expression. Each invocation determines which tokens to defer within
+
** the cluster with root node pRoot. See comments above the definition
+
** of struct Fts3TokenAndCost for more details.
+
**
+
** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
+
** called on each token to defer. Otherwise, an SQLite error code is
+
** returned.
+
*/
static int fts3EvalSelectDeferred(
-
  Fts3Cursor *pCsr,
-
  Fts3Expr *pRoot,
-
  Fts3TokenAndCost *aTC,
-
  int nTC
+
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+
  Fts3Expr *pRoot,                /* Consider tokens with this root node */
+
  Fts3TokenAndCost *aTC,          /* Array of expression tokens and costs */
+
  int nTC                         /* Number of entries in aTC[] */
){
-
  int nDocSize = 0;
-
  int nDocEst = 0;
-
  int rc = SQLITE_OK;
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
-
  int ii;
+
  int nDocSize = 0;               /* Number of pages per doc loaded */
+
  int rc = SQLITE_OK;             /* Return code */
+
  int ii;                         /* Iterator variable for various purposes */
+
  int nOvfl = 0;                  /* Total overflow pages used by doclists */
+
  int nToken = 0;                 /* Total number of tokens in cluster */

-
  int nOvfl = 0;
-
  int nTerm = 0;
+
  int nMinEst = 0;                /* The minimum count for any phrase so far. */
+
  int nLoad4 = 1;                 /* (Phrases that will be loaded)^4. */

+
  /* Count the tokens in this AND/NEAR cluster. If none of the doclists
+
  ** associated with the tokens spill onto overflow pages, or if there is
+
  ** only 1 token, exit early. No tokens to defer in this case. */
  for(ii=0; ii<nTC; ii++){
    if( aTC[ii].pRoot==pRoot ){
      nOvfl += aTC[ii].nOvfl;
-
      nTerm++;
+
      nToken++;
    }
  }
-
  if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
+
  if( nOvfl==0 || nToken<2 ) return SQLITE_OK;

+
  /* Obtain the average docsize (in pages). */
  rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
+
  assert( rc!=SQLITE_OK || nDocSize>0 );

-
  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) 
+
  /* Iterate through all tokens in this AND/NEAR cluster, in ascending order 
+
  ** of the number of overflow pages that will be loaded by the pager layer 
+
  ** to retrieve the entire doclist for the token from the full-text index.
+
  ** Load the doclists for tokens that are either:
+
  **
+
  **   a. The cheapest token in the entire query (i.e. the one visited by the
+
  **      first iteration of this loop), or
+
  **
+
  **   b. Part of a multi-token phrase.
+
  **
+
  ** After each token doclist is loaded, merge it with the others from the
+
  ** same phrase and count the number of documents that the merged doclist
+
  ** contains. Set variable "nMinEst" to the smallest number of documents in 
+
  ** any phrase doclist for which 1 or more token doclists have been loaded.
+
  ** Let nOther be the number of other phrases for which it is certain that
+
  ** one or more tokens will not be deferred.
+
  **
+
  ** Then, for each token, defer it if loading the doclist would result in
+
  ** loading N or more overflow pages into memory, where N is computed as:
+
  **
+
  **    (nMinEst + 4^nOther - 1) / (4^nOther)
+
  */
+
  for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
+
    int iTC;                      /* Used to iterate through aTC[] array. */
+
    Fts3TokenAndCost *pTC = 0;    /* Set to cheapest remaining token. */
+

+
    /* Set pTC to point to the cheapest remaining token. */
+
    for(iTC=0; iTC<nTC; iTC++){
+
      if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot 
+
       && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl) 
      ){
-
        pTC = &aTC[jj];
+
        pTC = &aTC[iTC];
      }
    }
    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{
+
    if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
+
      /* The number of overflow pages to load for this (and therefore all
+
      ** subsequent) tokens is greater than the estimated number of pages 
+
      ** that will be loaded if all subsequent tokens are deferred.
+
      */
+
      Fts3PhraseToken *pToken = pTC->pToken;
+
      rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
+
      fts3SegReaderCursorFree(pToken->pSegcsr);
+
      pToken->pSegcsr = 0;
+
    }else{
+
      nLoad4 = nLoad4*4;
+
      if( ii==0 || pTC->pPhrase->nToken>1 ){
+
        /* Either this is the cheapest token in the entire query, or it is
+
        ** part of a multi-token phrase. Either way, the entire doclist will
+
        ** (eventually) be loaded into memory. It may as well be now. */
        Fts3PhraseToken *pToken = pTC->pToken;
        int nList = 0;
        char *pList = 0;
-
        rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
+
        rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
        assert( rc==SQLITE_OK || pList==0 );
-

        if( rc==SQLITE_OK ){
-
          nDocEst = fts3DoclistCountDocids(1, pList, nList);
+
          int nCount;
          fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
+
          nCount = fts3DoclistCountDocids(
+
              pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
+
          );
+
          if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
        }
      }
-
    }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;
  }
@@ -115701,36 +118204,29 @@ static int fts3EvalSelectDeferred(
  return rc;
}

-
SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
+
/*
+
** This function is called from within the xFilter method. It initializes
+
** the full-text query currently stored in pCsr->pExpr. To iterate through
+
** the results of a query, the caller does:
+
**
+
**    fts3EvalStart(pCsr);
+
**    while( 1 ){
+
**      fts3EvalNext(pCsr);
+
**      if( pCsr->bEof ) break;
+
**      ... return row pCsr->iPrevId to the caller ...
+
**    }
+
*/
+
static int fts3EvalStart(Fts3Cursor *pCsr){
  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);
+
  fts3EvalAllocateReaders(pCsr, 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 ){
+
  /* Determine which, if any, tokens in the expression should be deferred. */
+
  if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
    Fts3TokenAndCost *aTC;
    Fts3Expr **apOr;
    aTC = (Fts3TokenAndCost *)sqlite3_malloc(
@@ -115746,7 +118242,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int b
      Fts3TokenAndCost *pTC = aTC;
      Fts3Expr **ppOr = apOr;

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

@@ -115761,11 +118257,14 @@ SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int b
    }
  }

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

-
static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
+
/*
+
** Invalidate the current position list for phrase pPhrase.
+
*/
+
static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
  if( pPhrase->doclist.bFreeList ){
    sqlite3_free(pPhrase->doclist.pList);
  }
@@ -115774,8 +118273,30 @@ static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
  pPhrase->doclist.bFreeList = 0;
}

-
static int fts3EvalNearTrim2(
-
  int nNear,
+
/*
+
** This function is called to edit the position list associated with
+
** the phrase object passed as the fifth argument according to a NEAR
+
** condition. For example:
+
**
+
**     abc NEAR/5 "def ghi"
+
**
+
** Parameter nNear is passed the NEAR distance of the expression (5 in
+
** the example above). When this function is called, *paPoslist points to
+
** the position list, and *pnToken is the number of phrase tokens in, the
+
** phrase on the other side of the NEAR operator to pPhrase. For example,
+
** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
+
** the position list associated with phrase "abc".
+
**
+
** All positions in the pPhrase position list that are not sufficiently
+
** close to a position in the *paPoslist position list are removed. If this
+
** leaves 0 positions, zero is returned. Otherwise, non-zero.
+
**
+
** Before returning, *paPoslist is set to point to the position lsit 
+
** associated with pPhrase. And *pnToken is set to the number of tokens in
+
** pPhrase.
+
*/
+
static int fts3EvalNearTrim(
+
  int nNear,                      /* NEAR distance. As in "NEAR/nNear". */
  char *aTmp,                     /* Temporary space to use */
  char **paPoslist,               /* IN/OUT: Position list */
  int *pnToken,                   /* IN/OUT: Tokens in phrase of *paPoslist */
@@ -115807,89 +118328,54 @@ static int fts3EvalNearTrim2(
  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.
+
** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
+
** Otherwise, it advances the expression passed as the second argument to
+
** point to the next matching row in the database. Expressions iterate through
+
** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
+
** or descending if it is non-zero.
+
**
+
** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
+
** successful, the following variables in pExpr are set:
+
**
+
**   Fts3Expr.bEof                (non-zero if EOF - there is no next row)
+
**   Fts3Expr.iDocid              (valid if bEof==0. The docid of the next row)
+
**
+
** If the expression is of type FTSQUERY_PHRASE, and the expression is not
+
** at EOF, then the following variables are populated with the position list
+
** for the phrase for the visited row:
+
**
+
**   FTs3Expr.pPhrase->doclist.nList        (length of pList in bytes)
+
**   FTs3Expr.pPhrase->doclist.pList        (pointer to position list)
+
**
+
** It says above that this function advances the expression to the next
+
** matching row. This is usually true, but there are the following exceptions:
+
**
+
**   1. Deferred tokens are not taken into account. If a phrase consists
+
**      entirely of deferred tokens, it is assumed to match every row in
+
**      the db. In this case the position-list is not populated at all. 
+
**
+
**      Or, if a phrase contains one or more deferred tokens and one or
+
**      more non-deferred tokens, then the expression is advanced to the 
+
**      next possible match, considering only non-deferred tokens. In other
+
**      words, if the phrase is "A B C", and "B" is deferred, the expression
+
**      is advanced to the next row that contains an instance of "A * C", 
+
**      where "*" may match any single token. The position list in this case
+
**      is populated as for "A * C" before returning.
+
**
+
**   2. NEAR is treated as AND. If the expression is "x NEAR y", it is 
+
**      advanced to point to the next row that matches "x AND y".
+
** 
+
** See fts3EvalTestDeferredAndNear() for details on testing if a row is
+
** really a match, taking into account deferred tokens and NEAR operators.
*/
-
#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
-

-
static void fts3EvalNext(
-
  Fts3Cursor *pCsr, 
-
  Fts3Expr *pExpr, 
-
  int *pRc
+
static void fts3EvalNextRow(
+
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+
  Fts3Expr *pExpr,                /* Expr. to advance to next matching row */
+
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==SQLITE_OK ){
+
    int bDescDoclist = pCsr->bDesc;         /* Used by DOCID_CMP() macro */
    assert( pExpr->bEof==0 );
    pExpr->bStart = 1;

@@ -115899,28 +118385,32 @@ static void fts3EvalNext(
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
        assert( !pLeft->bDeferred || !pRight->bDeferred );
+

        if( pLeft->bDeferred ){
-
          fts3EvalNext(pCsr, pRight, pRc);
+
          /* LHS is entirely deferred. So we assume it matches every row.
+
          ** Advance the RHS iterator to find the next row visited. */
+
          fts3EvalNextRow(pCsr, pRight, pRc);
          pExpr->iDocid = pRight->iDocid;
          pExpr->bEof = pRight->bEof;
        }else if( pRight->bDeferred ){
-
          fts3EvalNext(pCsr, pLeft, pRc);
+
          /* RHS is entirely deferred. So we assume it matches every row.
+
          ** Advance the LHS iterator to find the next row visited. */
+
          fts3EvalNextRow(pCsr, pLeft, pRc);
          pExpr->iDocid = pLeft->iDocid;
          pExpr->bEof = pLeft->bEof;
        }else{
-
          fts3EvalNext(pCsr, pLeft, pRc);
-
          fts3EvalNext(pCsr, pRight, pRc);
-

+
          /* Neither the RHS or LHS are deferred. */
+
          fts3EvalNextRow(pCsr, pLeft, pRc);
+
          fts3EvalNextRow(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);
+
              fts3EvalNextRow(pCsr, pLeft, pRc);
            }else{
-
              fts3EvalNext(pCsr, pRight, pRc);
+
              fts3EvalNextRow(pCsr, pRight, pRc);
            }
          }
-

          pExpr->iDocid = pLeft->iDocid;
          pExpr->bEof = (pLeft->bEof || pRight->bEof);
        }
@@ -115936,12 +118426,12 @@ static void fts3EvalNext(
        assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );

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

        pExpr->bEof = (pLeft->bEof && pRight->bEof);
@@ -115960,17 +118450,17 @@ static void fts3EvalNext(
        Fts3Expr *pRight = pExpr->pRight;

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

-
        fts3EvalNext(pCsr, pLeft, pRc);
+
        fts3EvalNextRow(pCsr, pLeft, pRc);
        if( pLeft->bEof==0 ){
          while( !*pRc 
              && !pRight->bEof 
              && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 
          ){
-
            fts3EvalNext(pCsr, pRight, pRc);
+
            fts3EvalNextRow(pCsr, pRight, pRc);
          }
        }
        pExpr->iDocid = pLeft->iDocid;
@@ -115980,7 +118470,7 @@ static void fts3EvalNext(

      default: {
        Fts3Phrase *pPhrase = pExpr->pPhrase;
-
        fts3EvalZeroPoslist(pPhrase);
+
        fts3EvalInvalidatePoslist(pPhrase);
        *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
        pExpr->iDocid = pPhrase->doclist.iDocid;
        break;
@@ -115989,15 +118479,113 @@ static void fts3EvalNext(
  }
}

-
static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
-
  int bHit = 1;
+
/*
+
** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
+
** cluster, then this function returns 1 immediately.
+
**
+
** Otherwise, it checks if the current row really does match the NEAR 
+
** expression, using the data currently stored in the position lists 
+
** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. 
+
**
+
** If the current row is a match, the position list associated with each
+
** phrase in the NEAR expression is edited in place to contain only those
+
** phrase instances sufficiently close to their peers to satisfy all NEAR
+
** constraints. In this case it returns 1. If the NEAR expression does not 
+
** match the current row, 0 is returned. The position lists may or may not
+
** be edited if 0 is returned.
+
*/
+
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 - it's the way the parser in fts3_expr.c works.
+
  */
+
  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 = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+
      }
+
  
+
      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+
      nToken = pExpr->pRight->pPhrase->nToken;
+
      for(p=pExpr->pLeft; p && res; p=p->pLeft){
+
        int nNear = p->pParent->nNear;
+
        Fts3Phrase *pPhrase = (
+
            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+
        );
+
        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+
      }
+
    }
+

+
    sqlite3_free(aTmp);
+
  }
+

+
  return res;
+
}
+

+
/*
+
** This function is a helper function for fts3EvalTestDeferredAndNear().
+
** Assuming no error occurs or has occurred, It returns non-zero if the
+
** expression passed as the second argument matches the row that pCsr 
+
** currently points to, or zero if it does not.
+
**
+
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+
** If an error occurs during execution of this function, *pRc is set to 
+
** the appropriate SQLite error code. In this case the returned value is 
+
** undefined.
+
*/
+
static int fts3EvalTestExpr(
+
  Fts3Cursor *pCsr,               /* FTS cursor handle */
+
  Fts3Expr *pExpr,                /* Expr to test. May or may not be root. */
+
  int *pRc                        /* IN/OUT: Error code */
+
){
+
  int bHit = 1;                   /* Return value */
  if( *pRc==SQLITE_OK ){
    switch( pExpr->eType ){
      case FTSQUERY_NEAR:
      case FTSQUERY_AND:
        bHit = (
-
            fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
-
         && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
+
            fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
+
         && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
         && fts3EvalNearTest(pExpr, pRc)
        );

@@ -116023,27 +118611,27 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
          Fts3Expr *p;
          for(p=pExpr; p->pPhrase==0; p=p->pLeft){
            if( p->pRight->iDocid==pCsr->iPrevId ){
-
              fts3EvalZeroPoslist(p->pRight->pPhrase);
+
              fts3EvalInvalidatePoslist(p->pRight->pPhrase);
            }
          }
          if( p->iDocid==pCsr->iPrevId ){
-
            fts3EvalZeroPoslist(p->pPhrase);
+
            fts3EvalInvalidatePoslist(p->pPhrase);
          }
        }

        break;

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

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

@@ -116054,7 +118642,7 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
          Fts3Phrase *pPhrase = pExpr->pPhrase;
          assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
          if( pExpr->bDeferred ){
-
            fts3EvalZeroPoslist(pPhrase);
+
            fts3EvalInvalidatePoslist(pPhrase);
          }
          *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
          bHit = (pPhrase->doclist.pList!=0);
@@ -116070,27 +118658,49 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
}

/*
-
** Return 1 if both of the following are true:
+
** This function is called as the second part of each xNext operation when
+
** iterating through the results of a full-text query. At this point the
+
** cursor points to a row that matches the query expression, with the
+
** following caveats:
+
**
+
**   * Up until this point, "NEAR" operators in the expression have been
+
**     treated as "AND".
+
**
+
**   * Deferred tokens have not yet been considered.
+
**
+
** If *pRc is not SQLITE_OK when this function is called, it immediately
+
** returns 0. Otherwise, it tests whether or not after considering NEAR
+
** operators and deferred tokens the current row is still a match for the
+
** expression. It returns 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.
+
**      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){
+
static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
  int rc = *pRc;
  int bMiss = 0;
  if( rc==SQLITE_OK ){
+

+
    /* If there are one or more deferred tokens, load the current row into
+
    ** memory and scan it to determine the position list for each deferred
+
    ** token. Then, see if this row is really a match, considering deferred
+
    ** tokens and NEAR operators (neither of which were taken into account
+
    ** earlier, by fts3EvalNextRow()). 
+
    */
    if( pCsr->pDeferred ){
      rc = fts3CursorSeek(0, pCsr);
      if( rc==SQLITE_OK ){
        rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
      }
    }
-
    bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
+
    bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
+

+
    /* Free the position-lists accumulated for each deferred token above. */
    sqlite3Fts3FreeDeferredDoclists(pCsr);
    *pRc = rc;
  }
@@ -116101,7 +118711,7 @@ static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
** Advance to the next document that matches the FTS expression in
** Fts3Cursor.pExpr.
*/
-
SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
+
static int fts3EvalNext(Fts3Cursor *pCsr){
  int rc = SQLITE_OK;             /* Return Code */
  Fts3Expr *pExpr = pCsr->pExpr;
  assert( pCsr->isEof==0 );
@@ -116113,19 +118723,19 @@ SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
        sqlite3_reset(pCsr->pStmt);
      }
      assert( sqlite3_data_count(pCsr->pStmt)==0 );
-
      fts3EvalNext(pCsr, pExpr, &rc);
+
      fts3EvalNextRow(pCsr, pExpr, &rc);
      pCsr->isEof = pExpr->bEof;
      pCsr->isRequireSeek = 1;
      pCsr->isMatchinfoNeeded = 1;
      pCsr->iPrevId = pExpr->iDocid;
-
    }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
+
    }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
  }
  return rc;
}

/*
** Restart interation for expression pExpr so that the next call to
-
** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental 
+
** fts3EvalNext() 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
@@ -116141,7 +118751,7 @@ static void fts3EvalRestart(
    Fts3Phrase *pPhrase = pExpr->pPhrase;

    if( pPhrase ){
-
      fts3EvalZeroPoslist(pPhrase);
+
      fts3EvalInvalidatePoslist(pPhrase);
      if( pPhrase->bIncr ){
        assert( pPhrase->nToken==1 );
        assert( pPhrase->aToken[0].pSegcsr );
@@ -116257,14 +118867,14 @@ static int fts3EvalGatherStats(
        assert( sqlite3_data_count(pCsr->pStmt)==0 );

        /* Advance to the next document */
-
        fts3EvalNext(pCsr, pRoot, &rc);
+
        fts3EvalNextRow(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) 
+
           && fts3EvalTestDeferredAndNear(pCsr, &rc) 
      );

      if( rc==SQLITE_OK && pCsr->isEof==0 ){
@@ -116286,10 +118896,10 @@ static int fts3EvalGatherStats(
      */
      fts3EvalRestart(pCsr, pRoot, &rc);
      do {
-
        fts3EvalNext(pCsr, pRoot, &rc);
+
        fts3EvalNextRow(pCsr, pRoot, &rc);
        assert( pRoot->bEof==0 );
      }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
-
      fts3EvalLoadDeferred(pCsr, &rc);
+
      fts3EvalTestDeferredAndNear(pCsr, &rc);
    }
  }
  return rc;
@@ -116420,7 +119030,7 @@ SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
  if( pPhrase ){
    int i;
    sqlite3_free(pPhrase->doclist.aAll);
-
    fts3EvalZeroPoslist(pPhrase);
+
    fts3EvalInvalidatePoslist(pPhrase);
    memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
    for(i=0; i<pPhrase->nToken; i++){
      fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
@@ -116429,6 +119039,20 @@ SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
  }
}

+
#if !SQLITE_CORE
+
/*
+
** Initialize API pointer table, if required.
+
*/
+
SQLITE_API int sqlite3_extension_init(
+
  sqlite3 *db, 
+
  char **pzErrMsg,
+
  const sqlite3_api_routines *pApi
+
){
+
  SQLITE_EXTENSION_INIT2(pApi)
+
  return sqlite3Fts3Init(db);
+
}
+
#endif
+

#endif

/************** End of fts3.c ************************************************/
@@ -116448,6 +119072,8 @@ SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

+
/* #include <string.h> */
+
/* #include <assert.h> */

typedef struct Fts3auxTable Fts3auxTable;
typedef struct Fts3auxCursor Fts3auxCursor;
@@ -116986,6 +119612,8 @@ SQLITE_API int sqlite3_fts3_enable_parentheses = 0;
*/
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10

+
/* #include <string.h> */
+
/* #include <assert.h> */

/*
** isNot:
@@ -117687,6 +120315,7 @@ SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){

#ifdef SQLITE_TEST

+
/* #include <stdio.h> */

/*
** Function to query the hash-table of tokenizers (see README.tokenizers).
@@ -117897,6 +120526,9 @@ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

+
/* #include <assert.h> */
+
/* #include <stdlib.h> */
+
/* #include <string.h> */


/*
@@ -118277,6 +120909,10 @@ SQLITE_PRIVATE void *sqlite3Fts3HashInsert(
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

+
/* #include <assert.h> */
+
/* #include <stdlib.h> */
+
/* #include <stdio.h> */
+
/* #include <string.h> */


/*
@@ -118918,12 +121554,10 @@ SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
-
#ifndef SQLITE_CORE
-
  SQLITE_EXTENSION_INIT1
-
#endif
-

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

+
/* #include <assert.h> */
+
/* #include <string.h> */

/*
** Implementation of the SQL scalar function for accessing the underlying 
@@ -119099,6 +121733,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(

#ifdef SQLITE_TEST

+
/* #include <tcl.h> */
+
/* #include <string.h> */

/*
** Implementation of a special SQL scalar function for testing tokenizers 
@@ -119410,6 +122046,10 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable(
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

+
/* #include <assert.h> */
+
/* #include <stdlib.h> */
+
/* #include <stdio.h> */
+
/* #include <string.h> */


typedef struct simple_tokenizer {
@@ -119635,6 +122275,9 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(

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

+
/* #include <string.h> */
+
/* #include <assert.h> */
+
/* #include <stdlib.h> */

/*
** When full-text index nodes are loaded from disk, the buffer that they
@@ -122896,6 +125539,8 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){

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

+
/* #include <string.h> */
+
/* #include <assert.h> */

/*
** Characters that may appear in the second argument to matchinfo().
@@ -124483,6 +127128,8 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo(
#else
#endif

+
/* #include <string.h> */
+
/* #include <assert.h> */

#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
@@ -127697,6 +130344,7 @@ SQLITE_API int sqlite3_extension_init(
#include <unicode/ustring.h>
#include <unicode/ucol.h>

+
/* #include <assert.h> */

#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
@@ -128176,8 +130824,12 @@ SQLITE_API int sqlite3_extension_init(
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#ifdef SQLITE_ENABLE_ICU

+
/* #include <assert.h> */
+
/* #include <string.h> */

#include <unicode/ubrk.h>
+
/* #include <unicode/ucol.h> */
+
/* #include <unicode/ustring.h> */
#include <unicode/utf16.h>

typedef struct IcuTokenizer IcuTokenizer;
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.7.1"
-
#define SQLITE_VERSION_NUMBER 3007007
-
#define SQLITE_SOURCE_ID      "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"
+
#define SQLITE_VERSION        "3.7.8"
+
#define SQLITE_VERSION_NUMBER 3007008
+
#define SQLITE_SOURCE_ID      "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -741,6 +741,37 @@ struct sqlite3_io_methods {
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
+
**
+
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
+
** retry counts and intervals for certain disk I/O operations for the
+
** windows [VFS] in order to work to provide robustness against
+
** anti-virus programs.  By default, the windows VFS will retry file read,
+
** file write, and file delete opertions up to 10 times, with a delay
+
** of 25 milliseconds before the first retry and with the delay increasing
+
** by an additional 25 milliseconds with each subsequent retry.  This
+
** opcode allows those to values (10 retries and 25 milliseconds of delay)
+
** to be adjusted.  The values are changed for all database connections
+
** within the same process.  The argument is a pointer to an array of two
+
** integers where the first integer i the new retry count and the second
+
** integer is the delay.  If either integer is negative, then the setting
+
** is not changed but instead the prior value of that setting is written
+
** into the array entry, allowing the current retry settings to be
+
** interrogated.  The zDbName parameter is ignored.
+
**
+
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
+
** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
+
** write ahead log and shared memory files used for transaction control
+
** are automatically deleted when the latest connection to the database
+
** closes.  Setting persistent WAL mode causes those files to persist after
+
** close.  Persisting the files is useful when other processes that do not
+
** have write permission on the directory containing the database file want
+
** to read the database file, as the WAL and shared memory files must exist
+
** in order for the database to be readable.  The fourth parameter to
+
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
+
** WAL mode.  If the integer is -1, then it is overwritten with the current
+
** WAL persistence setting.
+
** 
*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
@@ -750,7 +781,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8
-

+
#define SQLITE_FCNTL_WIN32_AV_RETRY   9
+
#define SQLITE_FCNTL_PERSIST_WAL     10

/*
** CAPI3REF: Mutex Handle
@@ -1178,16 +1210,10 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** order to verify that SQLite recovers gracefully from such
** conditions.
**
-
** The xMalloc and xFree methods must work like the
-
** malloc() and free() functions from the standard C library.
-
** The xRealloc method must work like realloc() from the standard C library
-
** with the exception that if the second argument to xRealloc is zero,
-
** xRealloc must be a no-op - it must not perform any allocation or
-
** deallocation.  ^SQLite guarantees that the second argument to
+
** The xMalloc, xRealloc, and xFree methods must work like the
+
** malloc(), realloc() and free() functions from the standard C library.
+
** ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.
-
** And so in cases where xRoundup always returns a positive number,
-
** xRealloc can perform exactly as the standard library realloc() and
-
** still be in compliance with this specification.
**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc.  The allocated size